aboutsummaryrefslogtreecommitdiff
path: root/NvBlast/tools
diff options
context:
space:
mode:
authorBryan Galdrikian <[email protected]>2017-02-21 12:07:59 -0800
committerBryan Galdrikian <[email protected]>2017-02-21 12:07:59 -0800
commit446ce137c6823ba9eff273bdafdaf266287c7c98 (patch)
treed20aab3e2ed08d7b3ca71c2f40db6a93ea00c459 /NvBlast/tools
downloadblast-1.0.0-beta.tar.xz
blast-1.0.0-beta.zip
first commitv1.0.0-beta
Diffstat (limited to 'NvBlast/tools')
-rw-r--r--NvBlast/tools/ApexImporter/src/ApexDestructibleObjExporter.cpp314
-rw-r--r--NvBlast/tools/ApexImporter/src/ApexDestructibleObjExporter.h47
-rw-r--r--NvBlast/tools/ApexImporter/src/Main.cpp298
-rw-r--r--NvBlast/tools/ArtistTools/source/ArtistTools/main.cpp6
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/BlastPlugin.cpp1736
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/BlastPlugin.h192
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/FoundationHolder.h138
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/ProjectParams.cpp2162
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/ProjectParams.h210
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D11/PluginBlastDx11.cpp23
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D11/PluginBlastDx11.h16
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D12/PluginBlastDx12.cpp20
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D12/PluginBlastDx12.h16
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Render/Interface/PluginBlast.cpp69
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Render/Interface/PluginBlast.h21
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/Sample.h95
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAsset.cpp60
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAsset.h99
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetBoxes.cpp84
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetBoxes.h56
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModel.cpp64
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModel.h57
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSimple.cpp56
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSimple.h47
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSkinned.cpp47
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSkinned.h46
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastController.cpp555
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastController.h246
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamily.cpp588
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamily.h224
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyBoxes.cpp92
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyBoxes.h37
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSimple.cpp638
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSimple.h72
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSkinned.cpp167
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSkinned.h63
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFractureTool.cpp171
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFractureTool.h41
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastModel.cpp167
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastModel.h60
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastReplay.cpp160
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastReplay.h75
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/Application.cpp66
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/Application.h57
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/DeviceManager.cpp801
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/DeviceManager.h179
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleController.cpp63
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleController.h57
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleManager.cpp1267
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleManager.h302
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/physx/PhysXController.cpp825
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/physx/PhysXController.h296
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ConvexRenderMesh.cpp82
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ConvexRenderMesh.h34
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/CustomRenderMesh.cpp96
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/CustomRenderMesh.h41
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/DebugRenderBuffer.h50
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Mesh.cpp13
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Mesh.h54
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/PrimitiveRenderMesh.cpp284
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/PrimitiveRenderMesh.h81
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderMaterial.cpp277
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderMaterial.h132
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderUtils.h78
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderable.cpp55
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderable.h151
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderer.cpp736
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderer.h251
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererHBAO.cpp81
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererHBAO.h40
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererShadow.cpp417
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererShadow.h82
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ResourceManager.cpp246
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ResourceManager.h97
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ShaderUtils.h99
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/SkinnedRenderMesh.cpp217
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/SkinnedRenderMesh.h82
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SampleAssetListParser.cpp272
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SampleAssetListParser.h20
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp1510
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.h99
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/CommonUIController.cpp621
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/CommonUIController.h106
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/DamageToolController.cpp294
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/DamageToolController.h129
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/EditionToolController.cpp156
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/EditionToolController.h62
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/GizmoToolController.cpp1210
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/GizmoToolController.h124
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/SelectionToolController.cpp445
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/SelectionToolController.h82
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/imgui_impl_dx11.cpp583
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/imgui_impl_dx11.h25
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/PxInputDataFromPxFileBuf.h51
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleProfiler.cpp223
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleProfiler.h79
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleTime.h58
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/UIHelpers.h56
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/Utils.cpp13
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/Utils.h91
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastCompositePanel.cpp306
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastCompositePanel.h59
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.cpp1804
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.h284
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastToolBar.cpp523
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastToolBar.h94
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/CollisionToolsDlg.cpp54
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/CollisionToolsDlg.h39
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/DefaultDamagePanel.cpp104
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/DefaultDamagePanel.h38
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FileReferencesPanel.cpp148
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FileReferencesPanel.h41
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FiltersDockWidget.cpp389
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FiltersDockWidget.h104
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureCutoutSettingsPanel.cpp155
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureCutoutSettingsPanel.h52
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureGeneralPanel.cpp63
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureGeneralPanel.h36
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureShellCutSettingsPanel.cpp40
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureShellCutSettingsPanel.h30
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureSliceSettingsPanel.cpp105
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureSliceSettingsPanel.h38
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVisualizersPanel.cpp36
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVisualizersPanel.h28
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVoronoiSettingsPanel.cpp354
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVoronoiSettingsPanel.h79
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/GeneralPanel.cpp281
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/GeneralPanel.h52
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialAssignmentsPanel.cpp265
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialAssignmentsPanel.h40
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialLibraryPanel.cpp473
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialLibraryPanel.h72
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/NoiseToolsDlg.cpp39
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/NoiseToolsDlg.h33
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/QtUtil.cpp155
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/QtUtil.h37
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SourceAssetOpenDlg.cpp82
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SourceAssetOpenDlg.h38
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SupportPanel.cpp49
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SupportPanel.h36
-rw-r--r--NvBlast/tools/ArtistTools/source/BlastPlugin/blastplugin_global.h11
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Anim/AnimUtil.cpp419
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Anim/AnimUtil.h217
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Anim/FbxUtil.cpp1023
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Anim/FbxUtil.h64
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Backdoor/backdoor.cpp263
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Backdoor/backdoor.h52
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/CoreLib.cpp1460
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/CoreLib.h121
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Parameters/FoundationHolder.h138
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/PluginInterface.h137
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Buffer.cpp31
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Buffer.h65
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11GPUProfiler.cpp138
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11GPUProfiler.h56
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderInterface.cpp890
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderInterface.h90
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderShader.cpp256
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderShader.h72
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RendererWindow.cpp319
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RendererWindow.h43
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Shaders.cpp225
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Shaders.h43
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11ShadowMap.cpp208
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11ShadowMap.h72
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11TextureResource.cpp29
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11TextureResource.h64
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Util.cpp333
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Util.h69
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Wrapper.cpp33
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Wrapper.h14
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/RenderPluginDx11.cpp315
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/RenderPluginDx11.h83
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Buffer.cpp31
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Buffer.h81
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12GPUProfiler.cpp222
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12GPUProfiler.h63
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderContext.cpp564
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderContext.h254
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderInterface.cpp467
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderInterface.h74
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderShader.cpp384
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderShader.h85
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderTarget.cpp371
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderTarget.h110
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RendererWindow.cpp141
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RendererWindow.h29
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Shaders.cpp231
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Shaders.h42
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12ShadowMap.cpp99
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12ShadowMap.h68
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12TextureResource.cpp29
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12TextureResource.h89
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Util.cpp386
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Util.h68
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Wrapper.cpp33
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Wrapper.h14
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/RenderPluginDx12.cpp343
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/RenderPluginDx12.h83
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/GPUProfiler.cpp87
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/GPUProfiler.h61
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/BoneGeometryData.h305
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/LightGeometryData.h269
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/WindGeometryData.h2513
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderInterface.cpp351
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderInterface.h175
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderPlugin.cpp86
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderPlugin.h124
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderResources.cpp47
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderResources.h72
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/LightShaderParam.h83
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/MeshShaderParam.h142
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/ShadowMap.cpp36
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/ShadowMap.h48
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/SimpleRenderable.cpp493
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Render/SimpleRenderable.h75
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/Camera.cpp867
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/Camera.h128
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/Gamepad.cpp1310
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/Gamepad.h68
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/GlobalSettings.cpp310
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/GlobalSettings.h172
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/Light.cpp744
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/Light.h152
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/MeshData.cpp108
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/MeshData.h74
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/Mouse.cpp105
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/Mouse.h103
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/SimpleScene.cpp1312
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Scene/SimpleScene.h184
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/Automate.cpp530
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/Automate.h23
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/CoreLibUtils.h65
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/MathUtil.cpp327
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/MathUtil.h557
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/Profiler.cpp82
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/Profiler.h51
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/Settings.cpp767
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/Settings.h392
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/Stats.cpp76
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/Stats.h54
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/Timer.cpp80
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/Timer.h68
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/ViewerOutput.cpp75
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Utils/ViewerOutput.h136
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.cpp1448
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.h208
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.cpp106
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.h31
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/D3DWidget.cpp151
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/D3DWidget.h51
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.cpp263
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.h47
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.cpp177
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.h80
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.cpp906
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.h100
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.cpp93
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.h39
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.cpp190
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.h51
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/OutputWindow.cpp22
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/OutputWindow.h22
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.cpp17
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.h284
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBoxInt.h15
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/TipListView.cpp42
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/TipListView.h26
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/Window/UIGlobal.h37
-rw-r--r--NvBlast/tools/ArtistTools/source/CoreLib/corelib_global.h20
-rw-r--r--NvBlast/tools/AuthoringTool/src/AuthoringTool.cpp403
-rw-r--r--NvBlast/tools/AuthoringTool/src/FractureProcessor.cpp264
-rw-r--r--NvBlast/tools/AuthoringTool/src/FractureProcessor.h64
-rw-r--r--NvBlast/tools/AuthoringTool/src/SimpleRandomGenerator.h27
-rw-r--r--NvBlast/tools/CMakeLists.txt95
-rw-r--r--NvBlast/tools/CurveEditor/source/Attribute.h109
-rw-r--r--NvBlast/tools/CurveEditor/source/Common.h10
-rw-r--r--NvBlast/tools/CurveEditor/source/Curve.h204
-rw-r--r--NvBlast/tools/CurveEditor/source/CurveEditorMainWindow.h217
-rw-r--r--NvBlast/tools/CurveEditor/source/GraphEditorTestApp/CurveEditorTestApp.cpp342
-rw-r--r--NvBlast/tools/CurveEditor/source/GraphEditorTestApp/CurveEditorTestApp.h49
-rw-r--r--NvBlast/tools/CurveEditor/source/GraphEditorTestApp/main.cpp10
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Curve/BezierSpline.cpp143
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Curve/BezierSpline.h57
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Curve/CatmullRomSpline.cpp205
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Curve/CatmullRomSpline.h44
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Curve/Curve.cpp1114
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Curve/Spline.cpp151
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Curve/Spline.h43
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Window/AlphaDialog.cpp181
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Window/AlphaDialog.h47
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Window/ColorWidget.cpp1724
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Window/ColorWidget.h126
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Window/CurveEditorMainWindow.cpp1530
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Window/CurveWidget.cpp1229
-rw-r--r--NvBlast/tools/CurveEditor/source/Internal/Window/CurveWidget.h158
-rw-r--r--NvBlast/tools/DataConverter/src/Main.cpp88
-rw-r--r--NvBlast/tools/common/BlastDataExporter.cpp106
-rw-r--r--NvBlast/tools/common/BlastDataExporter.h78
-rw-r--r--NvBlast/tools/common/FbxFileReader.cpp170
-rw-r--r--NvBlast/tools/common/FbxFileReader.h23
-rw-r--r--NvBlast/tools/common/FbxFileWriter.cpp645
-rw-r--r--NvBlast/tools/common/FbxFileWriter.h49
-rw-r--r--NvBlast/tools/common/FbxUtils.cpp30
-rw-r--r--NvBlast/tools/common/FbxUtils.h20
-rw-r--r--NvBlast/tools/common/IMeshFileReader.h21
-rw-r--r--NvBlast/tools/common/IMeshFileWriter.h41
-rw-r--r--NvBlast/tools/common/Log.cpp59
-rw-r--r--NvBlast/tools/common/Log.h122
-rw-r--r--NvBlast/tools/common/ObjFileReader.cpp63
-rw-r--r--NvBlast/tools/common/ObjFileReader.h16
-rw-r--r--NvBlast/tools/common/ObjFileWriter.cpp142
-rw-r--r--NvBlast/tools/common/ObjFileWriter.h26
-rw-r--r--NvBlast/tools/common/Utils.cpp166
-rw-r--r--NvBlast/tools/common/Utils.h113
-rw-r--r--NvBlast/tools/compiler/cmake/ApexImporter.cmake82
-rw-r--r--NvBlast/tools/compiler/cmake/AuthoringTool.cmake98
-rw-r--r--NvBlast/tools/compiler/cmake/DataConverter.cmake60
-rw-r--r--NvBlast/tools/compiler/cmake/Windows/ApexImporter.cmake22
-rw-r--r--NvBlast/tools/compiler/cmake/Windows/AuthoringTool.cmake22
-rw-r--r--NvBlast/tools/compiler/cmake/Windows/CMakeLists.txt58
-rw-r--r--NvBlast/tools/compiler/cmake/Windows/DataConverter.cmake22
322 files changed, 70903 insertions, 0 deletions
diff --git a/NvBlast/tools/ApexImporter/src/ApexDestructibleObjExporter.cpp b/NvBlast/tools/ApexImporter/src/ApexDestructibleObjExporter.cpp
new file mode 100644
index 0000000..0c90ac1
--- /dev/null
+++ b/NvBlast/tools/ApexImporter/src/ApexDestructibleObjExporter.cpp
@@ -0,0 +1,314 @@
+#include "ApexDestructibleObjExporter.h"
+
+#include "Log.h"
+
+#include "PsFastXml.h"
+#include "PsFileBuffer.h"
+#include "PxInputDataFromPxFileBuf.h"
+#include <PxVec2.h>
+#include <PxVec3.h>
+#include <map>
+#include <FbxFileWriter.h>
+#include <ObjFileWriter.h>
+
+
+using namespace nvidia;
+using namespace Nv::Blast;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Material Parser
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const float VEC_EPS = 1e-4;
+
+class MaterialXmlParser : public physx::shdfnd::FastXml::Callback
+{
+public:
+ std::string textureFile;
+
+protected:
+ // encountered a comment in the XML
+ virtual bool processComment(const char* /*comment*/)
+ {
+ return true;
+ }
+
+ virtual bool processClose(const char* /*element*/, unsigned int /*depth*/, bool& /*isError*/)
+ {
+ return true;
+ }
+
+ // return true to continue processing the XML document, false to skip.
+ virtual bool processElement(const char* elementName, // name of the element
+ const char* elementData, // element data, null if none
+ const physx::shdfnd::FastXml::AttributePairs& attr,
+ int /*lineno*/) // line number in the source XML file
+ {
+ PX_UNUSED(attr);
+ if (::strcmp(elementName, "sampler2D") == 0)
+ {
+ int nameIndex = -1;
+ for (int i = 0; i < attr.getNbAttr(); i += 2)
+ {
+ if (::strcmp(attr.getKey(i), "name") == 0)
+ {
+ nameIndex = i;
+ break;
+ }
+ }
+
+ if (::strcmp(attr.getValue(nameIndex), "diffuseTexture") == 0)
+ {
+ textureFile = elementData;
+ }
+ }
+
+ return true;
+ }
+};
+
+std::string getTextureFromMaterial(const char* materialPath)
+{
+ PsFileBuffer fileBuffer(materialPath, general_PxIOStream2::PxFileBuf::OPEN_READ_ONLY);
+ PxInputDataFromPxFileBuf inputData(fileBuffer);
+ MaterialXmlParser parser;
+ physx::shdfnd::FastXml* xml = physx::shdfnd::createFastXml(&parser);
+ xml->processXml(inputData, false);
+
+ xml->release();
+
+ // trim folders
+ std::string textureFile = parser.textureFile.substr(parser.textureFile.find_last_of("/\\") + 1);
+
+ return textureFile;
+}
+
+
+bool ApexDestructibleGeometryExporter::exportToFile(NvBlastAsset* asset, const DestructibleAsset& apexAsset, const std::string& name, const std::vector<uint32_t>& chunkReorderInvMap, bool toFbx, bool toObj, bool fbxascii, bool toUe4)
+{
+ const RenderMeshAsset* rAsset = apexAsset.getRenderMeshAsset();
+ uint32_t submeshCount = rAsset->getSubmeshCount();
+ std::vector<std::string> materialPathes;
+ // gather materials
+ {
+ for (uint32_t submeshIndex = 0; submeshIndex < submeshCount; ++submeshIndex)
+ {
+ const char* materialName = rAsset->getMaterialName(submeshIndex);
+ std::ostringstream materialPath;
+ materialPath << m_materialsDir << "\\" << materialName;
+ std::string texturePath = getTextureFromMaterial(materialPath.str().c_str());
+ materialPathes.push_back(texturePath);
+ }
+ }
+ struct vc3Comp
+ {
+ bool operator()(const PxVec3& a, const PxVec3& b) const
+ {
+ if (a.x + VEC_EPS < b.x) return true;
+ if (a.x - VEC_EPS > b.x) return false;
+ if (a.y + VEC_EPS < b.y) return true;
+ if (a.y - VEC_EPS > b.y) return false;
+ if (a.z + VEC_EPS < b.z) return true;
+ return false;
+ }
+ };
+ struct vc2Comp
+ {
+ bool operator()(const PxVec2& a, const PxVec2& b) const
+ {
+ if (a.x + VEC_EPS < b.x) return true;
+ if (a.x - VEC_EPS > b.x) return false;
+ if (a.y + VEC_EPS < b.y) return true;
+ return false;
+ }
+ };
+
+ std::vector<PxVec3> compressedPositions;
+ std::vector<PxVec3> compressedNormals;
+ std::vector<PxVec2> compressedTextures;
+
+ std::vector<uint32_t> positionsMapping;
+ std::vector<uint32_t> normalsMapping;
+ std::vector<uint32_t> texturesMapping;
+
+ std::map<PxVec3, uint32_t, vc3Comp> posMap;
+ std::map<PxVec3, uint32_t, vc3Comp> normMap;
+ std::map<PxVec2, uint32_t, vc2Comp> texMap;
+
+
+ // gather data for export
+ {
+ for (uint32_t submeshIndex = 0; submeshIndex < submeshCount; ++submeshIndex)
+ {
+ const RenderSubmesh& currentSubmesh = rAsset->getSubmesh(submeshIndex);
+ uint32_t indexCount = currentSubmesh.getVertexBuffer().getVertexCount();
+ const VertexFormat& fmt = currentSubmesh.getVertexBuffer().getFormat();
+ // Find position buffer index
+ uint32_t bufferId = 0;
+ {
+ for (; bufferId < fmt.getBufferCount(); ++bufferId)
+ {
+ if (fmt.getBufferSemantic(bufferId) != RenderVertexSemantic::POSITION)
+ continue;
+ else
+ break;
+ }
+ if (bufferId == fmt.getBufferCount())
+ {
+ lout() << "Can't find positions buffer" << std::endl;
+ return false;
+ }
+ }
+ const PxVec3* posistions = reinterpret_cast<const PxVec3*>(currentSubmesh.getVertexBuffer().getBuffer(bufferId));
+ uint32_t oldSize = (uint32_t)positionsMapping.size();
+ positionsMapping.resize(oldSize + indexCount);
+ for (uint32_t i = 0; i < indexCount; ++i)
+ {
+ auto it = posMap.find(posistions[i]);
+ if (it == posMap.end())
+ {
+ posMap[posistions[i]] = (uint32_t)compressedPositions.size();
+ positionsMapping[oldSize + i] = (uint32_t)compressedPositions.size();
+ compressedPositions.push_back(posistions[i]);
+ }
+ else
+ {
+ positionsMapping[oldSize + i] = it->second;
+ }
+ }
+ }
+
+ for (uint32_t submeshIndex = 0; submeshIndex < submeshCount; ++submeshIndex)
+ {
+ const RenderSubmesh& currentSubmesh = rAsset->getSubmesh(submeshIndex);
+ uint32_t indexCount = currentSubmesh.getVertexBuffer().getVertexCount();
+ const VertexFormat& fmt = currentSubmesh.getVertexBuffer().getFormat();
+ // Find normal buffer index
+ uint32_t bufferId = 0;
+ {
+ for (; bufferId < fmt.getBufferCount(); ++bufferId)
+ {
+ if (fmt.getBufferSemantic(bufferId) != RenderVertexSemantic::NORMAL)
+ continue;
+ else
+ break;
+ }
+ if (bufferId == fmt.getBufferCount())
+ {
+ lout() << "Can't find positions buffer" << std::endl;
+ return false;
+ }
+ }
+ const PxVec3* normals = reinterpret_cast<const PxVec3*>(currentSubmesh.getVertexBuffer().getBuffer(bufferId));
+ uint32_t oldSize = (uint32_t)normalsMapping.size();
+ normalsMapping.resize(oldSize + indexCount);
+ for (uint32_t i = 0; i < indexCount; ++i)
+ {
+ auto it = normMap.find(normals[i]);
+ if (it == normMap.end())
+ {
+ normMap[normals[i]] = (uint32_t)compressedNormals.size();
+ normalsMapping[oldSize + i] = (uint32_t)compressedNormals.size();
+ compressedNormals.push_back(normals[i]);
+ }
+ else
+ {
+ normalsMapping[oldSize + i] = it->second;
+ }
+ }
+
+ }
+ for (uint32_t submeshIndex = 0; submeshIndex < submeshCount; ++submeshIndex)
+ {
+ const RenderSubmesh& currentSubmesh = rAsset->getSubmesh(submeshIndex);
+ uint32_t indexCount = currentSubmesh.getVertexBuffer().getVertexCount();
+ const VertexFormat& fmt = currentSubmesh.getVertexBuffer().getFormat();
+
+ // Find texture coords buffer index
+ uint32_t bufferId = 0;
+ {
+ for (; bufferId < fmt.getBufferCount(); ++bufferId)
+ {
+ if (fmt.getBufferSemantic(bufferId) != RenderVertexSemantic::TEXCOORD0)
+ continue;
+ else
+ break;
+ }
+ if (bufferId == fmt.getBufferCount())
+ {
+ lout() << "Can't find positions buffer" << std::endl;
+ return false;
+ }
+ }
+ const PxVec2* texCoord = reinterpret_cast<const PxVec2*>(currentSubmesh.getVertexBuffer().getBuffer(bufferId));
+ uint32_t oldSize = (uint32_t)texturesMapping.size();
+ texturesMapping.resize(oldSize + indexCount);
+ for (uint32_t i = 0; i < indexCount; ++i)
+ {
+ auto it = texMap.find(texCoord[i]);
+ if (it == texMap.end())
+ {
+ texMap[texCoord[i]] = (uint32_t)compressedTextures.size();
+ texturesMapping[oldSize + i] = (uint32_t)compressedTextures.size();
+ compressedTextures.push_back(texCoord[i]);
+ }
+ else
+ {
+ texturesMapping[oldSize + i] = it->second;
+ }
+ }
+
+ }
+
+ uint32_t apexChunkCount = apexAsset.getChunkCount();
+ uint32_t chunkCount = static_cast<uint32_t>(chunkReorderInvMap.size());
+
+ std::vector<std::vector<std::vector<int32_t> > > pInd(chunkCount);
+ std::vector<std::vector<std::vector<int32_t> > > tInd(chunkCount);
+ std::vector<std::vector<std::vector<int32_t> > > nInd(chunkCount);
+
+
+ for (uint32_t chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex)
+ {
+ uint32_t apexChunkIndex = chunkReorderInvMap[chunkIndex];
+ if (apexChunkIndex >= apexChunkCount)
+ {
+ continue;
+ }
+ uint32_t part = apexAsset.getPartIndex(apexChunkIndex);
+ uint32_t offset = 0;
+ for (uint32_t submeshIndex = 0; submeshIndex < submeshCount; ++submeshIndex)
+ {
+ const RenderSubmesh& currentSubmesh = rAsset->getSubmesh(submeshIndex);
+ const uint32_t* indexArray = currentSubmesh.getIndexBuffer(part);
+ uint32_t indexCount = currentSubmesh.getIndexCount(part);
+ pInd[chunkIndex].push_back(std::vector<int32_t>());
+ tInd[chunkIndex].push_back(std::vector<int32_t>());
+ nInd[chunkIndex].push_back(std::vector<int32_t>());
+
+ for (uint32_t i = 0; i < indexCount;++i)
+ {
+ pInd[chunkIndex].back().push_back(positionsMapping[indexArray[i] + offset]);
+ tInd[chunkIndex].back().push_back(texturesMapping[indexArray[i] + offset]);
+ nInd[chunkIndex].back().push_back(normalsMapping[indexArray[i] + offset]);
+ }
+ offset += currentSubmesh.getVertexBuffer().getVertexCount();
+ }
+ }
+
+ if (toObj)
+ {
+ ObjFileWriter writer;
+ writer.saveToFile(asset, name, m_exportDir, compressedPositions, compressedNormals, compressedTextures, pInd, nInd, tInd, materialPathes, submeshCount);
+ }
+ if (toFbx)
+ {
+ FbxFileWriter writer;
+ writer.bOutputFBXAscii = fbxascii;
+ writer.setConvertToUE4(toUe4);
+ writer.saveToFile(asset, name, m_exportDir, compressedPositions, compressedNormals, compressedTextures, pInd, nInd, tInd, materialPathes, submeshCount);
+ }
+ }
+
+ return true;
+}
diff --git a/NvBlast/tools/ApexImporter/src/ApexDestructibleObjExporter.h b/NvBlast/tools/ApexImporter/src/ApexDestructibleObjExporter.h
new file mode 100644
index 0000000..cd6f238
--- /dev/null
+++ b/NvBlast/tools/ApexImporter/src/ApexDestructibleObjExporter.h
@@ -0,0 +1,47 @@
+#ifndef OBJ_APEX_EXPORTER_H
+#define OBJ_APEX_EXPORTER_H
+
+#include <string>
+#include <vector>
+#include "DestructibleAsset.h"
+
+
+
+
+namespace physx
+{
+ class PxVec3;
+ class PxVec2;
+}
+
+struct NvBlastAsset;
+
+namespace Nv
+{
+namespace Blast
+{
+
+class ApexDestructibleGeometryExporter
+{
+public:
+ ApexDestructibleGeometryExporter(std::string materialsDir, std::string exportDir) : m_materialsDir(materialsDir), m_exportDir(exportDir)
+ {}
+
+ bool exportToFile(NvBlastAsset* asset, const nvidia::apex::DestructibleAsset& apexAsset, const std::string& name, const std::vector<uint32_t>& chunkReorderInvMap, bool toFbx, bool toObj, bool fbxascii, bool toUe4);
+
+private:
+ ApexDestructibleGeometryExporter& operator=(const ApexDestructibleGeometryExporter&)
+ {
+ return *this;
+ }
+ const std::string m_materialsDir;
+ const std::string m_exportDir;
+
+};
+
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif //OBJ_EXPORTER_H
diff --git a/NvBlast/tools/ApexImporter/src/Main.cpp b/NvBlast/tools/ApexImporter/src/Main.cpp
new file mode 100644
index 0000000..157e923
--- /dev/null
+++ b/NvBlast/tools/ApexImporter/src/Main.cpp
@@ -0,0 +1,298 @@
+
+#if NV_VC
+#pragma warning(push)
+#pragma warning(disable: 4996) // 'fopen' unsafe warning, from NxFileBuffer.h
+#endif
+
+#include "PxPhysicsAPI.h"
+#include "Apex.h"
+#include <ModuleDestructible.h>
+#include <DestructibleAsset.h>
+#include "NullRenderer.h"
+#include "NvBlastExtApexImportTool.h"
+#include "Log.h"
+#include <string>
+#include <iostream>
+#include "tclap/CmdLine.h"
+#include "ApexDestructibleObjExporter.h"
+#include "NvBlastTkFramework.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlastExtPxManager.h"
+#include <BlastDataExporter.h>
+#include "windows.h"
+#include <NvBlastTkAsset.h>
+#define DEFAULT_INPUT_FILE "../../../tools/ApexImporter/resources/assets/table.apb"
+#define DEFAULT_OUTPUT_DIR "C:/TestFracturer/"
+#define DEFAULT_ASSET_NAME "table"
+
+using namespace Nv::Blast;
+using namespace Nv::Blast::ApexImporter;
+
+void loggingCallback(int type, const char* msg, const char* file, int line)
+{
+ if (type == NvBlastMessage::Info)
+ lout() << Log::TYPE_INFO << msg << " FILE:" << file << " Line: " << line << "\n";
+ else
+ lout() << Log::TYPE_ERROR << msg << " FILE:" << file << " Line: " << line << "\n";
+}
+
+bool isDirectoryExist(std::string path)
+{
+ DWORD attributes = GetFileAttributesA(path.c_str());
+ if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ return true;
+ }
+ return false;
+}
+
+bool mkDirRecursively(std::string path)
+{
+ if (isDirectoryExist(path))
+ {
+ return true;
+ }
+ auto indx = path.find_first_of("\\/");
+ while (indx != std::string::npos)
+ {
+ std::string subfolder = path.substr(0, indx);
+ CreateDirectory(subfolder.c_str(), NULL);
+ indx = path.find_first_of("\\/", indx + 1);
+ }
+ return isDirectoryExist(path);
+}
+
+// Create an Asset from the APEX destructible asset
+void run(const std::string& inFilepath, const std::string& outDir, const std::string& assetName, uint32_t mode, bool llFlag, bool tkFlag, bool extPxFlag, bool obj, bool fbx, bool fbxascii, bool ue4)
+{
+ std::string inputDir = inFilepath.substr(0, inFilepath.find_last_of("/\\"));
+
+ // load APEX
+ ApexImportTool blast(loggingCallback);
+
+ lout() << Log::TYPE_INFO << "ApexImportTool initialization" << std::endl;
+ blast.initialize();
+ if (!blast.isValid())
+ {
+ lout() << Log::TYPE_ERROR << "Failed to create BlastSDK" << std::endl;
+ return;
+ }
+
+ // load asset
+ lout() << Log::TYPE_INFO << "Loading asset: " << inFilepath << std::endl;
+ physx::PxFileBuf* apexAssetStream = nvidia::apex::GetApexSDK()->createStream(inFilepath.c_str(), physx::PxFileBuf::OPEN_READ_ONLY);
+ nvidia::apex::DestructibleAsset* apexAsset = blast.loadAssetFromFile(apexAssetStream);
+ if (!apexAsset)
+ {
+ return;
+ }
+ apexAssetStream->release();
+
+ ApexImporterConfig config;
+ config.infSearchMode = static_cast<ApexImporterConfig::InterfaceSearchMode>(mode);
+
+ std::vector<uint32_t> chunkReorderInvMap;
+ TkFrameworkDesc frameworkDesc =
+ {
+ nvidia::apex::GetApexSDK()->getErrorCallback(),
+ nvidia::apex::GetApexSDK()->getAllocator()
+ };
+ TkFramework* framework = NvBlastTkFrameworkCreate(frameworkDesc);
+ if (framework == nullptr)
+ {
+ lout() << Log::TYPE_ERROR << "Failed to create TkFramework" << std::endl;
+ return;
+ }
+
+ std::vector<NvBlastChunkDesc> chunkDesc;
+ std::vector<NvBlastBondDesc> bondDescs;
+ std::vector<uint32_t> flags;
+
+ std::vector<ExtPxAssetDesc::ChunkDesc> physicsChunks;
+ std::vector<ExtPxAssetDesc::SubchunkDesc> physicsSubchunks;
+
+ bool result = blast.importApexAsset(chunkReorderInvMap, apexAsset, chunkDesc, bondDescs, flags, config);
+ if (!result)
+ {
+ lout() << Log::TYPE_ERROR << "Failed to build Blast asset data" << std::endl;
+ return;
+ };
+
+ result = blast.getCollisionGeometry(apexAsset, static_cast<uint32_t>(chunkDesc.size()), chunkReorderInvMap, flags, physicsChunks, physicsSubchunks);
+ if (!result)
+ {
+ lout() << Log::TYPE_ERROR << "Failed to build physics data" << std::endl;
+ return;
+ };
+
+
+ // save asset
+ lout() << Log::TYPE_INFO << "Saving blast asset: " << outDir << std::endl;
+ BlastDataExporter blExpr(framework, nvidia::apex::GetApexSDK()->getCookingInterface(), loggingCallback);
+ NvBlastAsset* llAsset = blExpr.createLlBlastAsset(bondDescs, chunkDesc);
+
+ std::cout <<"Chunk count: " << NvBlastAssetGetChunkCount(llAsset, NULL) << std::endl;
+
+ if (llAsset == nullptr && (llFlag || fbx))
+ {
+ lout() << Log::TYPE_ERROR << "Failed to build low-level asset" << std::endl;
+ return;
+ }
+
+ if (llFlag)
+ {
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << "/" << assetName << ".llasset";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+ blExpr.saveBlastLLAsset(outBlastFilePath, llAsset);
+ std::cout << "Wrote NvBlastAsset to " << outBlastFilePath << std::endl;
+ }
+ if (tkFlag)
+ {
+ TkAsset* tkAsset = blExpr.createTkBlastAsset(bondDescs, chunkDesc);
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << "/" << assetName << ".tkasset";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+ blExpr.saveBlastTkAsset(outBlastFilePath, tkAsset);
+ std::cout << "Wrote TkAsset to " << outBlastFilePath << std::endl;
+ tkAsset->release();
+ }
+ if (extPxFlag)
+ {
+ ExtPxAsset* pxAsset = blExpr.createExtBlastAsset(bondDescs, chunkDesc, physicsChunks);
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << "/" << assetName << ".bpxa";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+ blExpr.saveBlastExtAsset(outBlastFilePath, pxAsset);
+ std::cout << "Wrote ExtPxAsset to " << outBlastFilePath << std::endl;
+ pxAsset->release();
+ }
+
+ lout() << Log::TYPE_INFO << "Saving model file: " << outDir << std::endl;
+ ApexDestructibleGeometryExporter objSaver(inputDir, outDir);
+ objSaver.exportToFile(llAsset, *apexAsset, assetName, chunkReorderInvMap, fbx, obj, fbxascii, ue4);
+ _aligned_free(llAsset);
+}
+
+
+int main(int argc, const char* const* argv)
+{
+ try
+ {
+ // setup cmd line
+ TCLAP::CmdLine cmd("Blast SDK: APEX Importer", ' ', "0.1");
+
+ TCLAP::ValueArg<std::string> infileArg("f", "file", "File to load", true, DEFAULT_INPUT_FILE, "infile");
+ cmd.add(infileArg);
+
+ TCLAP::ValueArg<std::string> outDirArg("o", "outputDir", "Output directory", false, DEFAULT_OUTPUT_DIR, "output directory");
+ cmd.add(outDirArg);
+
+ TCLAP::ValueArg<std::string> outAssetName("n", "outAssetName", "Output asset name", true, DEFAULT_ASSET_NAME, "output asset name");
+ cmd.add(outAssetName);
+
+
+ TCLAP::ValueArg<uint32_t> interfaceSearchMode("m", "mode", "Interface search mode", false, 0, "0 - EXACT, 1 - FORCED, for detailed description see docs.");
+ cmd.add(interfaceSearchMode);
+
+ TCLAP::SwitchArg debugSwitch("d", "debug", "Print debug output", cmd, false);
+
+ TCLAP::SwitchArg bpxaOutputArg("", "bpxa", "Output ExtPxAsset to the output directory (ext: bpxa)", false);
+ cmd.add(bpxaOutputArg);
+
+ TCLAP::SwitchArg tkOutputArg("", "tk", "Output TkAsset to the output directory (ext: tkasset)", false);
+ cmd.add(tkOutputArg);
+
+ TCLAP::SwitchArg llOutputArg("", "ll", "Output LL Blast asset to the output directory (ext: llasset)", false);
+ cmd.add(llOutputArg);
+
+ TCLAP::SwitchArg ue4OutputArg("", "ue4", "Output FBX with UE4 coordinate system", false);
+ cmd.add(ue4OutputArg);
+
+ TCLAP::SwitchArg fbxAsciiArg("", "fbxascii", "Output FBX as an ascii file (defaults to binary output)", false);
+ cmd.add(fbxAsciiArg);
+
+ TCLAP::SwitchArg objOutputArg("", "obj", "Output a OBJ mesh to the output directory", false);
+ cmd.add(objOutputArg);
+
+ TCLAP::SwitchArg fbxOutputArg("", "fbx", "Output a FBX mesh to the output directory", false);
+ cmd.add(fbxOutputArg);
+
+
+ // parse cmd input
+ cmd.parse(argc, argv);
+
+ bool bOutputBPXA = bpxaOutputArg.getValue();
+ bool bOutputTK = tkOutputArg.getValue();
+ bool bOutputLL = llOutputArg.getValue();
+
+ bool bUE4CoordSystem = ue4OutputArg.isSet();
+ bool bOutputFBXAscii = fbxAsciiArg.isSet();
+
+ bool bOutputObjFile = objOutputArg.isSet();
+ bool bOutputFbxFile = fbxOutputArg.isSet();
+
+
+ // Did we specify no output formats?
+ if (!bpxaOutputArg.isSet() && !tkOutputArg.isSet() && !llOutputArg.isSet())
+ {
+ std::cout << "Didn't specify an output format on the command line, so defaulting to outputting BPXA" << std::endl;
+ bOutputBPXA = true;
+ }
+ // Did we specify no geometry output formats?
+ if (!bOutputObjFile && !bOutputFbxFile)
+ {
+ std::cout << "Didn't specify an output geometry format on the command line, so defaulting to outputting .OBJ" << std::endl;
+ bOutputObjFile = true;
+ }
+
+ // get cmd parse results
+ std::string infile = infileArg.getValue();
+ std::string outDir;
+ std::string assetName = outAssetName.getValue();
+
+ /**
+ Set output dir, make sure that it exist.
+ */
+ if (outDirArg.isSet())
+ {
+ outDir = outDirArg.getValue();
+ std::string temp = outDir + '/';
+ if (!isDirectoryExist(outDir.data()))
+ {
+ std::cout << "Output directory doesn't exist. It will be created." << std::endl;
+ if (!mkDirRecursively(temp.data()))
+ {
+ std::cout << "Directory creation failed!" << std::endl;
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ auto idx = infile.find_last_of("/\\");
+ if (idx == 0 || idx == std::string::npos)
+ {
+ outDir = ".";
+ }
+ else
+ {
+ outDir = infile.substr(0, idx);
+ }
+ }
+
+ bool debug = debugSwitch.getValue();
+ int mode = interfaceSearchMode.getValue();
+ // do stuff
+ if (debug)
+ lout().setMinVerbosity(Log::MOST_VERBOSE);
+
+ run(infile, outDir, assetName, mode, bOutputLL, bOutputTK, bOutputBPXA, bOutputObjFile, bOutputFbxFile, bOutputFBXAscii, bUE4CoordSystem);
+ }
+ catch (TCLAP::ArgException &e) // catch any exceptions
+ {
+ lout() << Log::TYPE_ERROR << "error: " << e.error() << " for arg " << e.argId() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/NvBlast/tools/ArtistTools/source/ArtistTools/main.cpp b/NvBlast/tools/ArtistTools/source/ArtistTools/main.cpp
new file mode 100644
index 0000000..74c9d89
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/ArtistTools/main.cpp
@@ -0,0 +1,6 @@
+#include "CoreLib.h"
+
+int main(int argc, char *argv[])
+{
+ return CoreLib::Inst()->CoreMain(argc, argv);
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/BlastPlugin.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/BlastPlugin.cpp
new file mode 100644
index 0000000..78aa6d0
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/BlastPlugin.cpp
@@ -0,0 +1,1736 @@
+#include <QtCore/QtPlugin>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtWidgets/QMenuBar>
+#include <QtWidgets/QToolBar>
+#include <QtWidgets/QTabWidget>
+#include <QtWidgets/QAction>
+#include <QtWidgets/QMessageBox>
+#include <QtWidgets/QFileDialog>
+#include <QtGui/QDesktopServices>
+#include <QtWidgets/QPushButton>
+#include <QtCore/QVariant>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QButtonGroup>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QComboBox>
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QGridLayout>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QHeaderView>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QSpacerItem>
+#include <QtWidgets/QVBoxLayout>
+#include <QtWidgets/QWidget>
+
+#include "PluginBlast.h"
+#include "BlastPlugin.h"
+#include "SlideSpinBox.h"
+#include "Utils.h"
+#include "CorelibUtils.h"
+#include "Settings.h"
+#include "GlobalSettings.h"
+#include "SimpleScene.h"
+#include "Camera.h"
+#include "Light.h"
+#include "ProjectParams.h"
+#include "FoundationHolder.h"
+#include "AppMainWindow.h"
+#include "ViewerOutput.h"
+#include "ExpandablePanel.h"
+#include "DisplayMeshesPanel.h"
+#include "PluginBlast.h"
+#include "BlastToolbar.h"
+#include "MaterialLibraryPanel.h"
+#include "MaterialAssignmentsPanel.h"
+#include "FileReferencesPanel.h"
+#include "GeneralPanel.h"
+#include "BlastCompositePanel.h"
+#include "BlastSceneTree.h"
+#include "FiltersDockWidget.h"
+#include "DefaultDamagePanel.h"
+#include "FiltersDockWidget.h"
+#include "FractureCutoutSettingsPanel.h"
+#include "FractureGeneralPanel.h"
+#include "FractureShellCutSettingsPanel.h"
+#include "FractureSliceSettingsPanel.h"
+#include "FractureVisualizersPanel.h"
+#include "FractureVoronoiSettingsPanel.h"
+#include "SupportPanel.h"
+#include "BlastSceneTree.h"
+#include "FiltersDockWidget.h"
+
+// A singleton, sort of... To pass the events from WindowProc to the object.
+DeviceManager* g_DeviceManagerInstance = NULL;
+
+HWND g_hWnd = 0;
+
+DeviceManager* GetDeviceManager()
+{
+ return g_DeviceManagerInstance;
+}
+
+QString BlastPlugin::GetPluginName()
+{
+ return BlastPluginName;
+}
+
+bool BlastPlugin::CoreLib_RunApp()
+{
+ return true;
+}
+
+bool BlastPlugin::LoadRenderPlugin(std::string api)
+{
+ return PluginBlast::Create(api);
+}
+
+bool BlastPlugin::GetBoneNames(std::vector<std::string>& BoneNames)
+{
+ return true;
+}
+
+bool BlastPlugin::MainToolbar_updateValues()
+{
+ return true;
+}
+
+bool BlastPlugin::CurveEditor_updateValues(int _paramId, float* _values)
+{
+ return true;
+}
+
+bool BlastPlugin::CurveEditor_onUpdateValues(int _paramId, float* _values)
+{
+ return true;
+}
+
+bool BlastPlugin::DisplayMeshesPanel_updateValues()
+{
+ return true;
+}
+bool BlastPlugin::DisplayMeshesPanel_EmitToggleSignal(unsigned int id, bool visible)
+{
+ return true;
+}
+
+bool BlastPlugin::Camera_LoadParameters(void* ptr, Camera* pCamera)
+{
+ nvidia::parameterized::BlastProjectParametersNS::Camera_Type* param =
+ static_cast<nvidia::parameterized::BlastProjectParametersNS::Camera_Type*>(ptr);
+
+ pCamera->_zup = param->flags == 1;
+ pCamera->_fov = param->fov;
+ pCamera->_aspectRatio = param->aspectRatio;
+ pCamera->_znear = param->znear;
+ pCamera->_zfar = param->zfar;
+ pCamera->_isPerspective = param->isPerspective;
+ memcpy(&pCamera->_eye, &param->eye, sizeof(pCamera->_eye));
+ memcpy(&pCamera->_at, &param->at, sizeof(pCamera->_at));
+ pCamera->_lookDistance = param->lookDistance;
+ memcpy(&pCamera->_orientation, &param->orientation, sizeof(pCamera->_orientation));
+ memcpy(&pCamera->_viewMatrix, &param->viewMatrix, sizeof(pCamera->_viewMatrix));
+ memcpy(&pCamera->_projectionMatrix, &param->projectionMatrix, sizeof(pCamera->_projectionMatrix));
+
+ return true;
+}
+
+bool BlastPlugin::Camera_SaveParameters(void * ptr, Camera* pCamera)
+{
+ nvidia::parameterized::BlastProjectParametersNS::Camera_Type* outParam =
+ static_cast<nvidia::parameterized::BlastProjectParametersNS::Camera_Type*>(ptr);
+
+ outParam->flags = (pCamera->_zup ? 1 : 2);
+ outParam->fov = pCamera->_fov;
+ outParam->aspectRatio = pCamera->_aspectRatio;
+ outParam->znear = pCamera->_znear;
+ outParam->zfar = pCamera->_zfar;
+ outParam->width = 0;
+ outParam->height = 0;
+ outParam->isPerspective = pCamera->_isPerspective;
+ memcpy(&outParam->eye, &pCamera->_eye, sizeof(outParam->eye));
+ memcpy(&outParam->at, &pCamera->_at, sizeof(outParam->at));
+ outParam->lookDistance = pCamera->_lookDistance;
+ memcpy(&outParam->orientation, &pCamera->_orientation, sizeof(outParam->orientation));
+ memcpy(&outParam->viewMatrix, &pCamera->_viewMatrix, sizeof(outParam->viewMatrix));
+ memcpy(&outParam->projectionMatrix, &pCamera->_projectionMatrix, sizeof(outParam->projectionMatrix));
+ return true;
+}
+
+bool BlastPlugin::Gamepad_ToggleSimulation()
+{
+ return true;
+}
+
+bool BlastPlugin::Gamepad_LoadSamples(QString fn)
+{
+ return true;
+}
+
+bool BlastPlugin::Gamepad_ResetScene()
+{
+ return true;
+}
+
+bool BlastPlugin::Gamepad_StartAnimation()
+{
+ return true;
+}
+
+bool BlastPlugin::GamepadHandler_ShowHair()
+{
+ return true;
+}
+
+bool BlastPlugin::GamepadHandler_SpinWindStrength(float windStrength)
+{
+ return true;
+}
+
+bool BlastPlugin::Gamepad_ResetAnimation()
+{
+ return true;
+}
+
+bool BlastPlugin::Gamepad_PlayPauseAnimation()
+{
+ return true;
+}
+
+bool BlastPlugin::Light_loadParameters(NvParameterized::Handle& handle, Light* pLight)
+{
+ if (pLight == nullptr)
+ return false;
+
+ NvParameterized::NvParameters* params = static_cast<NvParameterized::NvParameters*>(handle.getInterface());
+ size_t offset = 0;
+ nvidia::parameterized::BlastProjectParametersNS::Light_Type* param = nullptr;
+ params->getVarPtr(handle, (void*&)param, offset);
+
+ pLight->m_enable = param->enable;
+ pLight->m_useShadows = param->useShadows;
+ pLight->m_visualize = param->visualize;
+ pLight->m_intensity = param->intensity;
+
+ memcpy(&pLight->m_color, &param->color, sizeof(atcore_float3));
+
+ atcore_float3 axisX, axisY, axisZ, lightPos;
+ memcpy(&axisX, &param->lightAxisX, sizeof(atcore_float3));
+ memcpy(&axisY, &param->lightAxisY, sizeof(atcore_float3));
+ memcpy(&axisZ, &param->lightAxisZ, sizeof(atcore_float3));
+ memcpy(&lightPos, &param->lightPos, sizeof(atcore_float3));
+
+ pLight->SetShadowMapResolution(param->shadowMapResolution);
+
+ pLight->m_lightCamera.SetEye(lightPos);
+ pLight->m_lightCamera.SetViewMatrix(axisX, axisY, axisZ);
+ pLight->m_lightCamera.BuildViewMatrix();
+ return true;
+}
+
+bool BlastPlugin::Light_saveParameters(NvParameterized::Handle& handle, Light* pLight)
+{
+ if (pLight == nullptr)
+ return false;
+
+ NvParameterized::NvParameters* params = static_cast<NvParameterized::NvParameters*>(handle.getInterface());
+ size_t offset = 0;
+ nvidia::parameterized::BlastProjectParametersNS::Light_Type* param = nullptr;
+ params->getVarPtr(handle, (void*&)param, offset);
+ memset((void*)param, 0, sizeof(nvidia::parameterized::BlastProjectParametersNS::Light_Type));
+
+ param->enable = pLight->m_enable;
+ param->useShadows = pLight->m_useShadows;
+ param->visualize = pLight->m_visualize;
+ param->intensity = pLight->m_intensity;
+
+ param->shadowMapResolution = pLight->m_shadowMapResolutionIndex;
+
+ memcpy(&param->color, &pLight->m_color, sizeof(atcore_float3));
+
+ {
+ atcore_float3 axisX = pLight->m_lightCamera.GetXAxis();
+ atcore_float3 axisY = pLight->m_lightCamera.GetYAxis();
+ atcore_float3 axisZ = pLight->m_lightCamera.GetZAxis();
+ atcore_float3 lightPos = pLight->m_lightCamera.GetEye();
+
+ memcpy(&param->lightAxisX, &axisX, sizeof(atcore_float3));
+ memcpy(&param->lightAxisY, &axisY, sizeof(atcore_float3));
+ memcpy(&param->lightAxisZ, &axisZ, sizeof(atcore_float3));
+ memcpy(&param->lightPos, &lightPos, sizeof(atcore_float3));
+ }
+ return true;
+}
+
+bool BlastPlugin::SimpleScene_SimpleScene()
+{
+ return true;
+}
+
+
+#include "Timer.h"
+Timer g_fpsTimer;
+
+#include "D3DWidget.h"
+#include "SampleManager.h"
+
+#include <QtWidgets/QShortcut>
+
+bool BlastPlugin::SimpleScene_Initialize(int backdoor)
+{
+ if (!CreateProjectParamsContext())
+ return false;
+
+ D3DWidget* d3dWidget = AppMainWindow::Inst().GetRenderWidget();
+ g_hWnd = (HWND)d3dWidget->winId();
+
+ RECT rc;
+ GetClientRect((HWND)g_hWnd, &rc);
+ int wBuf = rc.right - rc.left;
+ int hBuf = rc.bottom - rc.top;
+
+ DeviceCreationParameters deviceParams;
+ deviceParams.swapChainFormat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+ deviceParams.swapChainSampleCount = 4;
+ deviceParams.startFullscreen = false;
+ deviceParams.hWnd = g_hWnd;
+ deviceParams.backBufferWidth = wBuf;
+ deviceParams.backBufferHeight = hBuf;
+#if defined(DEBUG) | defined(_DEBUG)
+ deviceParams.createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG;
+#endif
+ deviceParams.featureLevel = D3D_FEATURE_LEVEL_11_0;
+
+ DeviceManager* pDeviceManager = new DeviceManager;
+ //pDeviceManager->CreateWindowDeviceAndSwapChain(deviceParams);
+ RenderPlugin* pPlugin = RenderPlugin::Instance();
+ D3DHandles handles;
+ pDeviceManager->SetWindowHandle(g_hWnd);
+ pDeviceManager->SetWindowDeviceAndSwapChain(pPlugin->GetDeviceHandles(handles));
+ g_DeviceManagerInstance = pDeviceManager;
+ SimpleScene::Inst()->SetDeviceManager(pDeviceManager);
+
+ SampleManager* pSampleManager = new SampleManager(pDeviceManager);
+ SimpleScene::Inst()->SetSampleManager(pSampleManager);
+
+ // post build will copy samples\resources to bin\resources. If debug in VS, need set working directory to binary's folder
+
+ pSampleManager->init();
+
+ QShortcut* shortCut;
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_K), d3dWidget);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_damagetool()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_Q), d3dWidget);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_selecttool()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_W), d3dWidget);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_Translate()));
+ shortCut = new QShortcut(QKeySequence(Qt::Key_E), d3dWidget);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_Rotation()));
+ shortCut = new QShortcut(QKeySequence(Qt::Key_R), d3dWidget);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_Scale()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_L), d3dWidget);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_edittool()));
+
+ _chunkContextMenu = new QMenu();
+ action_Make_Support = new QAction(tr("Make Support"), d3dWidget);
+ _chunkContextMenu->addAction(action_Make_Support);
+ connect(action_Make_Support, SIGNAL(triggered()), this, SLOT(slot_Make_Support()));
+
+ action_Make_Static_Support = new QAction(tr("Make Static Support"), d3dWidget);
+ _chunkContextMenu->addAction(action_Make_Static_Support);
+ connect(action_Make_Static_Support, SIGNAL(triggered()), this, SLOT(slot_Make_Static_Support()));
+
+ action_Remove_Support = new QAction(tr("Remove Support"), d3dWidget);
+ _chunkContextMenu->addAction(action_Remove_Support);
+ connect(action_Remove_Support, SIGNAL(triggered()), this, SLOT(slot_Remove_Support()));
+
+ _bondContextMenu = new QMenu();
+ action_Bond_Chunks = new QAction(tr("Bond Chunks"), d3dWidget);
+ _bondContextMenu->addAction(action_Bond_Chunks);
+ connect(action_Bond_Chunks, SIGNAL(triggered()), this, SLOT(slot_Bond_Chunks()));
+
+ action_Bond_Chunks_with_Joints = new QAction(tr("Bond Chunks With Joints"), d3dWidget);
+ _bondContextMenu->addAction(action_Bond_Chunks_with_Joints);
+ connect(action_Bond_Chunks_with_Joints, SIGNAL(triggered()), this, SLOT(slot_Bond_Chunks_with_Joints()));
+
+ action_Remove_all_Bonds = new QAction(tr("Remove All Bonds"), d3dWidget);
+ _bondContextMenu->addAction(action_Remove_all_Bonds);
+ connect(action_Remove_all_Bonds, SIGNAL(triggered()), this, SLOT(slot_Remove_all_Bonds()));
+
+ return true;
+}
+bool BlastPlugin::SimpleScene_Shutdown()
+{
+ SampleManager& sm = SimpleScene::Inst()->GetSampleManager();
+ sm.free();
+ //SimpleScene::Inst()->SetSampleManager(NV_NULL);
+
+ ReleaseProjectParamsContext();
+
+ g_DeviceManagerInstance = NV_NULL;
+
+ return true;
+}
+
+//#include "SceneController.h"
+bool BlastPlugin::SimpleScene_Clear()
+{
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ sampleManager.clearScene();
+// SceneController& sceneController = sampleManager.getSceneController();
+// sceneController.ClearScene();
+
+ BlastProject::ins().clear();
+
+ return true;
+}
+
+bool BlastPlugin::SimpleScene_Draw_DX12()
+{
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+#include <Stats.h>
+namespace
+{
+ Stats g_StatsCPU;
+ Stats g_StatsGPU;
+
+ Stats g_FrameStatsCPU;
+ Stats g_FrameStatsGPU;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void BlastPlugin::ResetFrameTimer()
+{
+ g_StatsCPU.reset();
+ g_StatsGPU.reset();
+}
+
+void BlastPlugin::DrawHUD()
+{
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ if (!globalSettings.m_showHUD)
+ return;
+
+ // finish frame timer
+ g_FrameStatsCPU.add(g_StatsCPU);
+ g_FrameStatsGPU.add(g_StatsGPU);
+
+ wchar_t sz[1000];
+
+ RenderInterface::TxtHelperBegin();
+ RenderInterface::TxtHelperSetInsertionPos(2, 0);
+ RenderInterface::TxtHelperSetForegroundColor(1.0f, 1.0f, 1.0f, 1.0f);
+
+ if (RenderInterface::GetDeviceInfoString(sz))
+ RenderInterface::TxtHelperDrawTextLine(sz);
+
+ {
+ // const NvHair::BuildInfo& buildInfo = GetHairSDK()->getBuildInfo();
+
+ // char releaseVersion[NvHair::BuildInfo::VERSION_BUFFER_SIZE];
+ // buildInfo.m_versionToStringFunc(buildInfo.m_releaseVersion, releaseVersion);
+
+ swprintf_s(sz, 1000, L"Lib build: %S Release version: %S\n", "n.a.", "1.0.0");
+ RenderInterface::TxtHelperDrawTextLine(sz);
+ }
+
+ swprintf_s(sz, 1000, L"Current frame time %3.2f[%d-%d:%2.2f]\n",
+ globalSettings.m_frameTime,
+ (int)globalSettings.m_frameStartTime,
+ (int)globalSettings.m_frameEndTime,
+ globalSettings.m_animationSpeed);
+
+ RenderInterface::TxtHelperDrawTextLine(sz);
+
+ bool computeProfile = globalSettings.m_computeProfile;
+
+ //FurCharacter& character = SimpleScene::Inst()->GetFurCharacter();
+ //std::vector<HairInstance*> validInstances;
+ //character.GetValidHairInstances(validInstances);
+
+ if (globalSettings.m_computeStatistics && globalSettings.m_showHUD)
+ {
+
+ //for (int i = 0; i < validInstances.size(); i++)
+ //{
+ // HairInstance* pHairInstance = validInstances[i];
+
+ // NvHair::Stats& hairStats = pHairInstance->m_hairStats;
+
+ // int totalHairs = hairStats.m_numHairs;
+ // int totalFaces = hairStats.m_numFaces;
+
+ // float averageNumCVsPerHair = hairStats.m_averageNumCvsPerHair;
+ // float averageDensity = hairStats.m_averageDensity;
+ // float averageHairsPerFace = hairStats.m_averageHairsPerFace;
+ // float distanceLODFactor = hairStats.m_distanceLodFactor;
+ // float detailLODFactor = hairStats.m_detailLodFactor;
+ // float camDistance = hairStats.m_camDistance;
+
+ // int m = pHairInstance->getDescriptor().m_splineMultiplier;
+ // float vertsPerHair = m * (averageNumCVsPerHair - 1.0f) + 1;
+ // float totalLines = totalHairs * vertsPerHair;
+
+ // const char* hairName = pHairInstance->m_assetName.c_str();
+ // std::wstring hairNameW;
+ // std::copy(hairName, hairName + strlen(hairName), back_inserter(hairNameW));
+
+ // swprintf_s(sz, 1000, L"Asset Name (%s), %d hairs, %d faces, %.1f lines",
+ // hairNameW.c_str(), totalHairs, totalFaces, totalLines);
+ // RenderInterface::TxtHelperDrawTextLine(sz);
+
+ // swprintf_s(sz, 1000, L" average density %.2f, avg hairs per face %.2f, avg CVs per hair %2.1f, avg render vertices per hair %3.1f",
+ // averageDensity, averageHairsPerFace, averageNumCVsPerHair, vertsPerHair);
+ // RenderInterface::TxtHelperDrawTextLine(sz);
+
+ // swprintf_s(sz, 1000, L" distance LOD Factor: %.2f, detail LOD Factor: %.2f, camera distance: %.2f",
+ // distanceLODFactor, detailLODFactor, camDistance);
+ // RenderInterface::TxtHelperDrawTextLine(sz);
+ //}
+ }
+
+ if (globalSettings.m_showFPS)
+ {
+ static double fps = 0;
+ static double lastFrames = GlobalSettings::Inst().m_renderFrameCnt;
+ Timer& g_fpsTimer = SimpleScene::Inst()->GetTimer();
+ static double lastFpsTime = g_fpsTimer.GetTimeInSeconds();
+ static int numFrames = 1;
+
+ static Stats lastStatsCPU;
+ static Stats lastStatsGPU;
+
+ Stats& statsGPU = g_FrameStatsGPU;
+ Stats& statsCPU = g_FrameStatsCPU;
+
+ double currentFpsTime = g_fpsTimer.GetTimeInSeconds();
+ if ((currentFpsTime - lastFpsTime) > 1.0)
+ {
+ double currentFrames = GlobalSettings::Inst().m_renderFrameCnt;
+ numFrames = currentFrames - lastFrames;
+
+ fps = numFrames / (currentFpsTime - lastFpsTime);
+
+ lastFrames = currentFrames;
+ lastFpsTime = currentFpsTime;
+
+ lastStatsGPU = statsGPU;
+ lastStatsCPU = statsCPU;
+
+ lastStatsGPU.average((float)numFrames);
+ lastStatsCPU.average((float)numFrames);
+
+ statsGPU.reset();
+ statsCPU.reset();
+ }
+
+ if (globalSettings.m_computeProfile)
+ {
+ swprintf_s(sz, 1000, L"Render time (GPU/CPU): Total %.2f/%.2fms, Hair %.2f/%.2fms, Mesh %.2f/%.2fms, Shadow %.2f/%.2fms, Stats %.2f/%.2fms",
+ lastStatsGPU.m_totalRenderTime, lastStatsCPU.m_totalRenderTime,
+ lastStatsGPU.m_hairRenderTime, lastStatsCPU.m_hairRenderTime,
+ lastStatsGPU.m_meshRenderTime, lastStatsCPU.m_meshRenderTime,
+ lastStatsGPU.m_shadowRenderTime, lastStatsCPU.m_shadowRenderTime,
+ lastStatsGPU.m_hairStatsTime, lastStatsCPU.m_hairStatsTime);
+
+ RenderInterface::TxtHelperDrawTextLine(sz);
+
+ swprintf_s(sz, 1000, L"Update time (GPU/CPU): Total %.2f/%.2fms, Hair Update %.2f/%.2fms, Mesh Skinning %.2f/%.2fms, Sim %.2f/%.2fms",
+ lastStatsGPU.m_totalUpdateTime, lastStatsCPU.m_totalUpdateTime,
+ lastStatsGPU.m_hairSkinningTime, lastStatsCPU.m_hairSkinningTime,
+ lastStatsGPU.m_meshSkinningTime, lastStatsCPU.m_meshSkinningTime,
+ lastStatsGPU.m_hairSimulationTime, lastStatsCPU.m_hairSimulationTime);
+ RenderInterface::TxtHelperDrawTextLine(sz);
+
+ {
+ float cpuMeshTime = lastStatsCPU.m_meshRenderTime + lastStatsCPU.m_meshSkinningTime;
+ float gpuMeshTime = lastStatsGPU.m_meshRenderTime + lastStatsGPU.m_meshSkinningTime;
+
+ float cpuHairTime = lastStatsCPU.m_totalRenderTime + lastStatsCPU.m_totalUpdateTime - cpuMeshTime;
+ float gpuHairTime = lastStatsGPU.m_totalRenderTime + lastStatsGPU.m_totalUpdateTime - gpuMeshTime;
+
+ float gpuFPS = 1000.0f / gpuHairTime;
+ RenderInterface::TxtHelperSetForegroundColor(0.2f, 1.0f, 0.2f, 1.0f);
+ swprintf_s(sz, 1000, L"Hair: GPU Fps %.2f, GPU time %.2fms, CPU time %.2fms",
+ gpuFPS, gpuHairTime, cpuHairTime);
+ RenderInterface::TxtHelperDrawTextLine(sz);
+ }
+
+ float gpuTime = lastStatsGPU.m_totalRenderTime + lastStatsGPU.m_totalUpdateTime;
+ float gpuFPS = 1000.0f / gpuTime;
+ RenderInterface::TxtHelperSetForegroundColor(1.0f, 0.5f, 0.5f, 1.0f);
+ swprintf_s(sz, 1000, L"Total: GPU Fps %.2f, GPU time %.2fms, CPU time %.2fms",
+ gpuFPS,
+ lastStatsGPU.m_totalRenderTime + lastStatsGPU.m_totalUpdateTime,
+ lastStatsCPU.m_totalRenderTime + lastStatsCPU.m_totalUpdateTime
+ );
+ RenderInterface::TxtHelperDrawTextLine(sz);
+
+ }
+ else
+ {
+ swprintf_s(sz, 1000, L"Fps %.2f", fps);
+ RenderInterface::TxtHelperDrawTextLine(sz);
+ }
+ }
+
+ RenderInterface::TxtHelperEnd();
+}
+
+bool BlastPlugin::SimpleScene_Draw_DX11()
+{
+ BlastPlugin::DrawHUD();
+ return true;
+}
+
+bool BlastPlugin::SimpleScene_FitCamera(atcore_float3& center, atcore_float3& extents)
+{
+ return true;
+}
+bool BlastPlugin::SimpleScene_DrawGround()
+{
+ return true;
+}
+bool BlastPlugin::SimpleScene_DrawWind()
+{
+ return true;
+}
+bool BlastPlugin::SimpleScene_DrawAxis()
+{
+ return true;
+}
+
+#include <Shlwapi.h>
+#include <FbxUtil.h>
+#include <MeshData.h>
+#include <PxVec2.h>
+#include <SourceAssetOpenDlg.h>
+bool BlastPlugin::SimpleScene_LoadSceneFromFbx(const char* d, const char* f)
+{
+ SourceAssetOpenDlg dlg(false, &AppMainWindow::Inst());
+ int res = dlg.exec();
+ if (res != QDialog::Accepted || dlg.getFile().isEmpty())
+ return false;
+
+ QFileInfo fileInfo(dlg.getFile());
+ std::string dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ std::string fbxName = fileInfo.fileName().toLocal8Bit();
+
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ char fbxFilePath[MAX_PATH];
+
+ float sceneUnit = globalSettings.getSceneUnitInCentimeters();
+
+ PathCombineA(fbxFilePath, dir.c_str(), fbxName.c_str());
+
+ AppMainWindow::Inst().setProgress("Initializing FBX loader", 0);
+ FbxUtil::Initialize(fbxFilePath, sceneUnit);
+
+ char rootBoneName[MAX_PATH];
+ int upAxis = 0;
+
+ FbxUtil::GetGlobalSettings(
+ &globalSettings.m_frameStartTime,
+ &globalSettings.m_frameEndTime,
+ &globalSettings.m_animationFps,
+ &upAxis, rootBoneName);
+
+ if (upAxis == 1)
+ SimpleScene::Inst()->ResetUpDir(false);
+ else if (upAxis = 2)
+ SimpleScene::Inst()->ResetUpDir(true);
+
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+
+ int numMeshes = 0;
+ char* meshNames = 0;
+ char* skinned = 0;
+ FbxUtil::GetMeshInfo(&numMeshes, &meshNames, &skinned);
+ if (numMeshes > 1)
+ {
+ //return false;
+ }
+
+ // to do later when numMeshes is more than one
+ numMeshes = 1;
+
+ for (int i = 0; i < numMeshes; i++)
+ {
+ const char* meshName = meshNames + i * 128;
+
+ MeshDesc meshDesc;
+ FbxUtil::CreateMeshDescriptor(meshName, meshDesc);
+
+ MeshMaterial* materials = 0;
+ int numMaterials = 0;
+ FbxUtil::GetMeshMaterials(meshName, &numMaterials, &materials);
+
+ SkinData skinData;
+ FbxUtil::InitializeSkinData(meshName, skinData);
+
+ meshDesc.UpdateNormal(false);
+
+ std::vector<physx::PxVec3> positions;
+ std::vector<physx::PxVec3> normals;
+ std::vector<physx::PxVec2> uv;
+ std::vector<unsigned int> indices;
+
+ for (uint32_t i = 0; i < meshDesc.m_NumVertices; ++i)
+ {
+ atcore_float3 pos = meshDesc.m_pVertices[i];
+ atcore_float3 vertexNormal = meshDesc.m_pVertexNormals[i];
+ atcore_float2 texcoord = meshDesc.m_pTexCoords[i];
+
+ positions.push_back(physx::PxVec3(pos.x, pos.y, pos.z));
+ normals.push_back(physx::PxVec3(vertexNormal.x, vertexNormal.y, vertexNormal.z));
+ uv.push_back(physx::PxVec2(texcoord.x, texcoord.y));
+ }
+
+ for (uint32_t i = 0; i < meshDesc.m_NumTriangles; ++i)
+ {
+ indices.push_back(meshDesc.m_pIndices[i * 3 + 0]);
+ indices.push_back(meshDesc.m_pIndices[i * 3 + 1]);
+ indices.push_back(meshDesc.m_pIndices[i * 3 + 2]);
+ }
+
+ sampleManager.createAsset(meshName, positions, normals, uv, indices);
+
+ physx::PxTransform t(physx::PxIdentity);
+ {
+ QVector3D Position = dlg.getPosition();
+ t.p = physx::PxVec3(Position.x(), Position.y(), Position.z());
+
+ QVector3D RotationAxis = dlg.getRotationAxis();
+ physx::PxVec3 Axis = physx::PxVec3(RotationAxis.x(), RotationAxis.y(), RotationAxis.z());
+ Axis = Axis.getNormalized();
+ float RotationDegree = dlg.getRotationDegree();
+ float DEGREE_TO_RAD = acos(-1.0) / 180.0;
+ RotationDegree = RotationDegree * DEGREE_TO_RAD;
+ t.q = physx::PxQuat(RotationDegree, Axis);
+ }
+ sampleManager.addModelAsset(meshName, dlg.getSkinned(), t, !dlg.isAppend());
+ }
+
+ FbxUtil::Release();
+
+ globalSettings.m_sceneLoaded = true;
+ globalSettings.m_animationIndex = 1;
+ globalSettings.m_firstFrame = true;
+
+ globalSettings.resetAnimation();
+
+ return true;
+}
+
+bool BlastPlugin::SimpleScene_LoadProject(const char* dir, const char* file)
+{
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+ SimpleScene* pScene = SimpleScene::Inst();
+ nvidia::parameterized::BlastProjectParametersNS::ParametersStruct params;
+ if (!ProjectParamsLoad(globalSettings.getAbsoluteFilePath().c_str(), pScene))
+ return false;
+
+ return true;
+}
+bool BlastPlugin::SimpleScene_SaveProject(const char* dir, const char* file)
+{
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+ SimpleScene* pScene = SimpleScene::Inst();
+
+ QString saveFilePath = globalSettings.getAbsoluteFilePath().c_str();
+ QString tempFilePath = utils::GetTempFilePath().c_str();
+ if (ProjectParamsSave(tempFilePath.toUtf8().data(), pScene))
+ {
+ if (!utils::RenameFile(tempFilePath.toUtf8().data(), saveFilePath.toUtf8().data(), true /* overwrite */))
+ {
+ return false;
+ }
+ pScene->SetProjectModified(false);
+ return true;
+ }
+
+ return false;
+}
+bool BlastPlugin::SimpleScene_LoadParameters(NvParameterized::Interface* iface)
+{
+ nvidia::parameterized::BlastProjectParameters* params = static_cast<nvidia::parameterized::BlastProjectParameters*>(iface);
+
+ nvidia::parameterized::BlastProjectParametersNS::ParametersStruct& srcDesc = params->parameters();
+ copy(BlastProject::ins().getParams(), srcDesc);
+
+ for (int i = 0; i < srcDesc.blast.blastAssets.arraySizes[0]; ++i)
+ {
+ BPPAsset& asset = srcDesc.blast.blastAssets.buf[i];
+ QFileInfo fileInfo(asset.path.buf);
+ QByteArray tmp = fileInfo.baseName().toUtf8();
+ const char* fileName = tmp.data();
+ physx::PxTransform t(physx::PxIdentity);
+ BPPAssetInstance* instance = BlastProject::ins().getAssetInstance(asset.path.buf, 0);
+ if (instance != nullptr)
+ {
+ nvidia::NvVec3& postion = instance->transform.position;
+ nvidia::NvVec4& rotation = instance->transform.rotation;
+ t.p = physx::PxVec3(postion.x, postion.y, postion.z);
+ t.q = physx::PxQuat(rotation.x, rotation.y, rotation.z, rotation.w);
+ }
+ SimpleScene::Inst()->GetSampleManager().addModelAsset(fileName, false, t, true);
+ }
+
+ SimpleScene* pScene = SimpleScene::Inst();
+
+ if (pScene->m_pCamera)
+ {
+ pScene->m_pCamera->LoadParameters(&srcDesc.camera);
+ }
+
+ pScene->LoadCameraBookmarks(iface);
+
+ if (pScene->m_pWindCamera)
+ {
+ pScene->m_pWindCamera->LoadParameters(&srcDesc.windCamera);
+ }
+
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ // Load scene settings
+ globalSettings.m_repeatAnimation = srcDesc.scene.repeatAnimation;
+ globalSettings.m_animationSpeed = srcDesc.scene.animationSpeed;
+ globalSettings.m_showGrid = srcDesc.scene.showGrid;
+ globalSettings.m_showAxis = srcDesc.scene.showAxis;
+ globalSettings.m_zup = srcDesc.scene.upAxis == 1;
+ globalSettings.m_sceneUnitIndex = srcDesc.scene.sceneUnitIndex;
+
+ // Load render settings
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle("renderer", handle) == NvParameterized::ERROR_NONE)
+ {
+ globalSettings.m_computeStatistics = srcDesc.renderer.showStatistics;
+ globalSettings.m_showGraphicsMesh = srcDesc.renderer.showGraphicsMesh;
+ globalSettings.m_useLighting = srcDesc.renderer.useLighting;
+ globalSettings.m_showSkinnedMeshOnly = srcDesc.renderer.showSkinnedMeshOnly;
+ globalSettings.m_renderFps = srcDesc.renderer.renderFps;
+ globalSettings.m_simulationFps = srcDesc.renderer.simulationFps;
+
+ Light::LoadParameters(handle);
+ }
+
+ //// Load fbx paths
+ //if (iface->getParameterHandle("fbxFilePaths", handle) == NvParameterized::ERROR_NONE)
+ //{
+ // int arraySize;
+ // handle.getArraySize(arraySize);
+ // char** strArray = new char*[arraySize];
+ // handle.getParamStringArray(strArray, arraySize);
+ // for (int idx = 0; idx < arraySize; ++idx)
+ // {
+ // pScene->LoadSceneFromFbx(
+ // globalSettings.m_projectFileDir.c_str(),
+ // strArray[idx]);
+ // }
+ // delete[] strArray;
+ //}
+
+ //// get fur character mesh setting
+ //if (false == pScene->GetFurCharacter().LoadMeshParameters(handle))
+ // return false;
+
+ //// Load apx paths (hair instances)
+ //if (iface->getParameterHandle("apxFilePaths", handle) == NvParameterized::ERROR_NONE)
+ //{
+ // if (false == pScene->GetFurCharacter().LoadHairParameters(handle))
+ // return false;
+ //}
+
+ BlastProject::ins().loadUserPreset();
+ return true;
+}
+bool BlastPlugin::SimpleScene_SaveParameters(NvParameterized::Interface* iface)
+{
+ nvidia::parameterized::BlastProjectParameters* params = static_cast<nvidia::parameterized::BlastProjectParameters*>(iface);
+ nvidia::parameterized::BlastProjectParametersNS::ParametersStruct& targetDesc = params->parameters();
+ memset(&targetDesc, sizeof(BPParams), 0);
+ BPParams& srcParams = BlastProject::ins().getParams();
+ copy(targetDesc, srcParams);
+
+ SimpleScene* pScene = SimpleScene::Inst();
+
+ if (pScene->m_pCamera)
+ pScene->m_pCamera->SaveParameters(&targetDesc.camera);
+
+ pScene->SaveCameraBookmarks(iface);
+
+ if (pScene->m_pWindCamera)
+ pScene->m_pWindCamera->SaveParameters(&targetDesc.windCamera);
+
+ // Save scene settings
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ targetDesc.scene.repeatAnimation = globalSettings.m_repeatAnimation;
+ targetDesc.scene.animationSpeed = globalSettings.m_animationSpeed;
+ targetDesc.scene.showGrid = globalSettings.m_showGrid;
+ targetDesc.scene.showAxis = globalSettings.m_showAxis;
+ targetDesc.scene.upAxis = (globalSettings.m_zup) ? 1 : 2;
+ targetDesc.scene.sceneUnitIndex = globalSettings.m_sceneUnitIndex;
+
+ // Save render settings
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle("renderer", handle) == NvParameterized::ERROR_NONE)
+ {
+ targetDesc.renderer.renderFps = globalSettings.m_renderFps;
+ targetDesc.renderer.simulationFps = globalSettings.m_simulationFps;
+ targetDesc.renderer.showStatistics = globalSettings.m_computeStatistics;
+ targetDesc.renderer.showGraphicsMesh = globalSettings.m_showGraphicsMesh;
+ targetDesc.renderer.useLighting = globalSettings.m_useLighting;
+ targetDesc.renderer.showSkinnedMeshOnly = globalSettings.m_showSkinnedMeshOnly;
+
+ Light::SaveParameters(handle);
+ }
+
+ //if (iface->getParameterHandle("renderer.textureFilePath", handle) == NvParameterized::ERROR_NONE)
+ //{
+ // std::string textureFilePath = globalSettings.getRelativePath(globalSettings.m_backgroundTextureFilePath.c_str());
+ // handle.setParamString(textureFilePath.c_str());
+ //}
+
+ //// save hair path
+ //if (iface->getParameterHandle("apxFilePaths", handle) == NvParameterized::ERROR_NONE)
+ // character.SaveHairParameters(handle);
+
+ return true;
+}
+
+bool BlastPlugin::SimpleScene_LoadCameraBookmarks(NvParameterized::Interface* iface)
+{
+ return true;
+}
+
+bool BlastPlugin::SimpleScene_SaveCameraBookmarks(NvParameterized::Interface* iface)
+{
+ SimpleScene* pScene = SimpleScene::Inst();
+
+ nvidia::parameterized::BlastProjectParameters* params = static_cast<nvidia::parameterized::BlastProjectParameters*>(iface);
+ nvidia::parameterized::BlastProjectParametersNS::ParametersStruct& srcDesc = params->parameters();
+ nvidia::parameterized::BlastProjectParametersNS::CameraBookmark_DynamicArray1D_Type& bookmarks = srcDesc.cameraBookmarks;
+
+ NvParameterized::Handle cameraBookmarksHandle(iface);
+ if (iface->getParameterHandle("cameraBookmarks", cameraBookmarksHandle) != NvParameterized::ERROR_NONE)
+ return false;
+
+ int numCameraBookmarks = pScene->m_cameraBookmarks.size();
+ cameraBookmarksHandle.resizeArray(numCameraBookmarks);
+
+ for (int idx = 0; idx < numCameraBookmarks; ++idx)
+ {
+ NvParameterized::Handle cameraBookmarkHandle(cameraBookmarksHandle);
+ if (cameraBookmarksHandle.getChildHandle(idx, cameraBookmarkHandle) == NvParameterized::ERROR_NONE)
+ {
+ NvParameterized::Handle tempHandle(cameraBookmarkHandle);
+ CameraBookmark& bookmark = pScene->m_cameraBookmarks[idx];
+
+ if (ParamGetChild(cameraBookmarkHandle, tempHandle, "name"))
+ {
+ tempHandle.setParamString(bookmark.name.toStdString().c_str());
+ }
+
+ bookmark.camera.SaveParameters((void*)&(bookmarks.buf[idx].camera));
+ }
+ }
+
+ return true;
+}
+
+bool BlastPlugin::D3DWidget_resizeEvent(QResizeEvent* e)
+{
+ DeviceManager& deviceManager = SimpleScene::Inst()->GetDeviceManager();
+
+ int w = e->size().width();
+ int h = e->size().height();
+ WPARAM wParam = MAKEWPARAM(w, h);
+ LPARAM lParam = MAKELPARAM(w, h);
+ deviceManager.MsgProc(g_hWnd, WM_SIZE, wParam, lParam);
+
+ return true;
+}
+
+bool BlastPlugin::D3DWidget_paintEvent(QPaintEvent* e)
+{
+ SampleManager& pSampleManager = SimpleScene::Inst()->GetSampleManager();
+ pSampleManager.run();
+
+ if (pSampleManager.m_bNeedRefreshTree)
+ {
+ _blastSceneTree->updateValues();
+ pSampleManager.m_bNeedRefreshTree = false;
+ }
+
+ return true;
+}
+
+bool BlastPlugin::D3DWidget_mousePressEvent(QMouseEvent* e)
+{
+ UINT uMsg = WM_LBUTTONDOWN;
+ if (e->button() == Qt::RightButton)
+ {
+ uMsg = WM_RBUTTONDOWN;
+ }
+ else if (e->button() == Qt::MidButton)
+ {
+ uMsg = WM_MBUTTONDOWN;
+ }
+
+ int x = e->x();
+ int y = e->y();
+ WPARAM wParam = MAKEWPARAM(x, y);
+ LPARAM lParam = MAKELPARAM(x, y);
+
+ DeviceManager& deviceManager = SimpleScene::Inst()->GetDeviceManager();
+ deviceManager.MsgProc(g_hWnd, uMsg, wParam, lParam);
+
+ return true;
+}
+
+bool BlastPlugin::D3DWidget_mouseReleaseEvent(QMouseEvent* e)
+{
+ UINT uMsg = WM_LBUTTONUP;
+ if (e->button() == Qt::RightButton)
+ {
+ uMsg = WM_RBUTTONUP;
+ }
+ else if (e->button() == Qt::MidButton)
+ {
+ uMsg = WM_MBUTTONUP;
+ }
+
+ int x = e->x();
+ int y = e->y();
+ WPARAM wParam = MAKEWPARAM(x, y);
+ LPARAM lParam = MAKELPARAM(x, y);
+
+ DeviceManager& deviceManager = SimpleScene::Inst()->GetDeviceManager();
+ deviceManager.MsgProc(g_hWnd, uMsg, wParam, lParam);
+
+ return true;
+}
+
+bool BlastPlugin::D3DWidget_mouseMoveEvent(QMouseEvent* e)
+{
+ DeviceManager& deviceManager = SimpleScene::Inst()->GetDeviceManager();
+
+ int x = e->x();
+ int y = e->y();
+ WPARAM wParam = MAKEWPARAM(x, y);
+ LPARAM lParam = MAKELPARAM(x, y);
+ deviceManager.MsgProc(g_hWnd, WM_MOUSEMOVE, wParam, lParam);
+
+ return true;
+}
+
+bool BlastPlugin::D3DWidget_wheelEvent(QWheelEvent * e)
+{
+ DeviceManager& deviceManager = SimpleScene::Inst()->GetDeviceManager();
+
+ int delta = e->delta();
+ WPARAM wParam = MAKEWPARAM(delta, delta);
+ LPARAM lParam = MAKELPARAM(delta, delta);
+ deviceManager.MsgProc(g_hWnd, WM_MOUSEWHEEL, wParam, lParam);
+
+ return true;
+}
+
+bool BlastPlugin::D3DWidget_keyPressEvent(QKeyEvent* e)
+{ return true; }
+bool BlastPlugin::D3DWidget_keyReleaseEvent(QKeyEvent* e)
+{ return true; }
+bool BlastPlugin::D3DWidget_dragEnterEvent(QDragEnterEvent *e)
+{ return true; }
+bool BlastPlugin::D3DWidget_dragMoveEvent(QDragMoveEvent *e)
+{ return true; }
+bool BlastPlugin::D3DWidget_dragLeaveEvent(QDragLeaveEvent *e)
+{ return true; }
+bool BlastPlugin::D3DWidget_dropEvent(QDropEvent *e)
+{ return true; }
+
+bool BlastPlugin::D3DWidget_contextMenuEvent(QContextMenuEvent *e)
+{
+ QPoint pos = QCursor::pos();
+
+ std::map<BlastAsset*, std::vector<uint32_t>> selectedAssetChunks = SampleManager::ins()->getSelectedChunks();
+ if (1 == selectedAssetChunks.size())
+ {
+ std::map<BlastAsset*, std::vector<uint32_t>>::iterator itr = selectedAssetChunks.begin();
+ BlastAsset* asset = itr->first;
+ std::vector<uint32_t> selectChunks = itr->second;
+
+ std::vector<BlastChunkNode*> chunkNodes = BlastTreeData::ins().getChunkNodeByBlastChunk(asset, selectChunks);
+ if (1 == chunkNodes.size())
+ {
+ _chunkContextMenu->exec(pos);
+ }
+ else if (1 < chunkNodes.size())
+ {
+ bool allSupportChunk = true;
+ for (size_t i = 0; i < chunkNodes.size(); ++i)
+ {
+ BlastChunkNode* chunkNode = chunkNodes[i];
+ if (eChunk != chunkNode->getType())
+ {
+ allSupportChunk = false;
+ break;
+ }
+ }
+
+ if (allSupportChunk)
+ {
+ _bondContextMenu->exec(QCursor::pos());
+ }
+ }
+ }
+ e->accept();
+ return true;
+}
+
+#ifdef NV_ARTISTTOOLS
+bool BlastPlugin::D3D11Shaders_InitializeShadersD3D11(std::map<int, D3D11RenderShader*>& ShaderMap)
+{
+ return PluginBlast::Instance()->D3D11Shaders_InitializeShadersD3D11(ShaderMap);
+}
+#endif // NV_ARTISTTOOLS
+
+bool BlastPlugin::AppMainWindow_AppMainWindow()
+{
+ _mainToolbar = 0;
+ _materialLibraryPanel = 0;
+ _materialAssignmentsPanel = 0;
+ _fileReferencesPanel = 0;
+ _generalPanel = 0;
+ _defaultDamagePanel = 0;
+ _fractureCutoutSettingsPanel = 0;
+ _fractureGeneralPanel = 0;
+ _fractureShellCutSettingPanel = 0;
+ _fractureSliceSettingsPanel = 0;
+ _fractureVisualizersPanel = 0;
+ _fractureVoronoiSettingsPanel = 0;
+ _supportPanel = 0;
+ _blastSceneTree = 0;
+ _filtersDockWidget = 0;
+
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_InitMenuItems(QMenuBar* pMenuBar)
+{
+ QMenu *pMenu = pMenuBar->addMenu("&Blast");
+ QAction *act;
+
+ act = new QAction("Open project file", this);
+ act->setShortcut(QKeySequence::Open);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_openProject()));
+ pMenu->addAction(act);
+
+ act = new QAction("Save project file", this);
+ act->setShortcut(QKeySequence::Save);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveProject()));
+ pMenu->addAction(act);
+
+ act = new QAction("Save project file as...", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveProjectAs()));
+ pMenu->addAction(act);
+
+ pMenu->addSeparator();
+
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_InitMainTab(QWidget *displayScrollAreaContents, QVBoxLayout *displayScrollAreaLayout, int idx)
+{
+ ExpandablePanel* panel = new ExpandablePanel(displayScrollAreaContents);
+ displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Display Mesh Materials");
+
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_InitPluginTab(QTabWidget* sideBarTab)
+{
+ {
+ QWidget *tabMaterial;
+ QGridLayout *gridLayoutMaterial;
+ QFrame *materialEditorArea;
+ QVBoxLayout *materialEditorAreaLayout;
+ QScrollArea *materialScrollArea;
+ QWidget *materialScrollAreaContents;
+ QVBoxLayout *materialScrollAreaLayout;
+ QSpacerItem *verticalSpacerMaterial;
+
+ tabMaterial = new QWidget();
+ tabMaterial->setObjectName(QStringLiteral("tabMaterial"));
+ gridLayoutMaterial = new QGridLayout(tabMaterial);
+ gridLayoutMaterial->setSpacing(6);
+ gridLayoutMaterial->setContentsMargins(11, 11, 11, 11);
+ gridLayoutMaterial->setObjectName(QStringLiteral("gridLayoutMaterial"));
+ gridLayoutMaterial->setContentsMargins(0, 0, 0, 0);
+ materialEditorArea = new QFrame(tabMaterial);
+ materialEditorArea->setObjectName(QStringLiteral("materialEditorArea"));
+ materialEditorAreaLayout = new QVBoxLayout(materialEditorArea);
+ materialEditorAreaLayout->setSpacing(6);
+ materialEditorAreaLayout->setContentsMargins(11, 11, 11, 11);
+ materialEditorAreaLayout->setObjectName(QStringLiteral("materialEditorAreaLayout"));
+ materialEditorAreaLayout->setContentsMargins(2, 2, 2, 2);
+
+ gridLayoutMaterial->addWidget(materialEditorArea, 1, 0, 1, 1);
+
+ materialScrollArea = new QScrollArea(tabMaterial);
+ materialScrollArea->setObjectName(QStringLiteral("materialScrollArea"));
+ materialScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ materialScrollArea->setWidgetResizable(true);
+ materialScrollAreaContents = new QWidget();
+ materialScrollAreaContents->setObjectName(QStringLiteral("materialScrollAreaContents"));
+ materialScrollAreaContents->setGeometry(QRect(0, 0, 359, 481));
+ materialScrollAreaLayout = new QVBoxLayout(materialScrollAreaContents);
+ materialScrollAreaLayout->setSpacing(3);
+ materialScrollAreaLayout->setContentsMargins(11, 11, 11, 11);
+ materialScrollAreaLayout->setObjectName(QStringLiteral("materialScrollAreaLayout"));
+ materialScrollAreaLayout->setContentsMargins(2, 2, 2, 2);
+ verticalSpacerMaterial = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ materialScrollAreaLayout->addItem(verticalSpacerMaterial);
+
+ materialScrollArea->setWidget(materialScrollAreaContents);
+
+ gridLayoutMaterial->addWidget(materialScrollArea, 0, 0, 1, 1);
+
+ sideBarTab->addTab(tabMaterial, QString());
+
+ sideBarTab->setTabText(sideBarTab->indexOf(tabMaterial), QApplication::translate("AppMainWindowClass", "Materials", 0));
+
+ ExpandablePanel* panel = 0;
+ int pannelCnt = 0;
+
+ panel = new ExpandablePanel(materialScrollAreaContents);
+ _materialLibraryPanel = new MaterialLibraryPanel(panel);
+ panel->AddContent(_materialLibraryPanel);
+ materialScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Material Library");
+
+ panel = new ExpandablePanel(materialScrollAreaContents);
+ _materialAssignmentsPanel = new MaterialAssignmentsPanel(panel);
+ panel->AddContent(_materialAssignmentsPanel);
+ materialScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Material Assignments");
+ }
+
+ {
+ QWidget *tabBlast;
+ QGridLayout *gridLayout;
+ QFrame *blastMaterialEditorArea;
+ QVBoxLayout *blastMaterialEditorAreaLayout;
+ QScrollArea *blastScrollArea;
+ QWidget *blastScrollAreaContents;
+ QVBoxLayout *blastScrollAreaLayout;
+ QSpacerItem *verticalSpacer;
+
+ tabBlast = new QWidget();
+ tabBlast->setObjectName(QStringLiteral("tabBlast"));
+ gridLayout = new QGridLayout(tabBlast);
+ gridLayout->setSpacing(6);
+ gridLayout->setContentsMargins(11, 11, 11, 11);
+ gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setContentsMargins(0, 0, 0, 0);
+ blastMaterialEditorArea = new QFrame(tabBlast);
+ blastMaterialEditorArea->setObjectName(QStringLiteral("blastMaterialEditorArea"));
+ blastMaterialEditorAreaLayout = new QVBoxLayout(blastMaterialEditorArea);
+ blastMaterialEditorAreaLayout->setSpacing(6);
+ blastMaterialEditorAreaLayout->setContentsMargins(11, 11, 11, 11);
+ blastMaterialEditorAreaLayout->setObjectName(QStringLiteral("blastMaterialEditorAreaLayout"));
+ blastMaterialEditorAreaLayout->setContentsMargins(2, 2, 2, 2);
+
+ gridLayout->addWidget(blastMaterialEditorArea, 1, 0, 1, 1);
+
+ blastScrollArea = new QScrollArea(tabBlast);
+ blastScrollArea->setObjectName(QStringLiteral("blastScrollArea"));
+ blastScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ blastScrollArea->setWidgetResizable(true);
+ blastScrollAreaContents = new QWidget();
+ blastScrollAreaContents->setObjectName(QStringLiteral("blastScrollAreaContents"));
+ blastScrollAreaContents->setGeometry(QRect(0, 0, 359, 481));
+ blastScrollAreaLayout = new QVBoxLayout(blastScrollAreaContents);
+ blastScrollAreaLayout->setSpacing(3);
+ blastScrollAreaLayout->setContentsMargins(11, 11, 11, 11);
+ blastScrollAreaLayout->setObjectName(QStringLiteral("blastScrollAreaLayout"));
+ blastScrollAreaLayout->setContentsMargins(2, 2, 2, 2);
+ verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ blastScrollAreaLayout->addItem(verticalSpacer);
+
+ blastScrollArea->setWidget(blastScrollAreaContents);
+
+ gridLayout->addWidget(blastScrollArea, 0, 0, 1, 1);
+
+ sideBarTab->addTab(tabBlast, QString());
+
+ sideBarTab->setTabText(sideBarTab->indexOf(tabBlast), QApplication::translate("AppMainWindowClass", "Blast", 0));
+
+ ExpandablePanel* panel = 0;
+ int pannelCnt = 0;
+
+ panel = new ExpandablePanel(blastScrollAreaContents);
+ _fileReferencesPanel = new FileReferencesPanel(panel);
+ panel->AddContent(_fileReferencesPanel);
+ blastScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("File References");
+
+ panel = new ExpandablePanel(blastScrollAreaContents);
+ _generalPanel = new GeneralPanel(panel);
+ panel->AddContent(_generalPanel);
+ blastScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("General");
+
+ panel = new ExpandablePanel(blastScrollAreaContents);
+ _supportPanel = new SupportPanel(panel);
+ panel->AddContent(_supportPanel);
+ blastScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Support");
+
+ panel = new ExpandablePanel(blastScrollAreaContents);
+ _blastCompositePanel = new BlastCompositePanel(panel);
+ panel->AddContent(_blastCompositePanel);
+ blastScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Blast Composite");
+
+ panel = new ExpandablePanel(blastScrollAreaContents);
+ _fractureGeneralPanel = new FractureGeneralPanel(panel);
+ panel->AddContent(_fractureGeneralPanel);
+ blastScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Fracture General");
+
+ panel = new ExpandablePanel(blastScrollAreaContents);
+ _fractureCutoutSettingsPanel = new FractureCutoutSettingsPanel(panel);
+ panel->AddContent(_fractureCutoutSettingsPanel);
+ blastScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Cutout Projection Settings");
+
+ panel = new ExpandablePanel(blastScrollAreaContents);
+ _fractureShellCutSettingPanel = new FractureShellCutSettingsPanel(panel);
+ panel->AddContent(_fractureShellCutSettingPanel);
+ blastScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Shell Cut Settings");
+
+ panel = new ExpandablePanel(blastScrollAreaContents);
+ _fractureSliceSettingsPanel = new FractureSliceSettingsPanel(panel);
+ panel->AddContent(_fractureSliceSettingsPanel);
+ blastScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Slice Settings");
+
+ panel = new ExpandablePanel(blastScrollAreaContents);
+ _fractureVoronoiSettingsPanel = new FractureVoronoiSettingsPanel(panel);
+ panel->AddContent(_fractureVoronoiSettingsPanel);
+ blastScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Voronoi Settings");
+
+ panel = new ExpandablePanel(blastScrollAreaContents);
+ _fractureVisualizersPanel = new FractureVisualizersPanel(panel);
+ panel->AddContent(_fractureVisualizersPanel);
+ blastScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Visualizers");
+ }
+
+ {
+ QWidget *tabDamage;
+ QGridLayout *gridLayoutDamage;
+ QFrame *damageEditorArea;
+ QVBoxLayout *damageEditorAreaLayout;
+ QScrollArea *damageScrollArea;
+ QWidget *damageScrollAreaContents;
+ QVBoxLayout *damageScrollAreaLayout;
+ QSpacerItem *verticalSpacerDamage;
+
+ tabDamage = new QWidget();
+ tabDamage->setObjectName(QStringLiteral("tabDamage"));
+ gridLayoutDamage = new QGridLayout(tabDamage);
+ gridLayoutDamage->setSpacing(6);
+ gridLayoutDamage->setContentsMargins(11, 11, 11, 11);
+ gridLayoutDamage->setObjectName(QStringLiteral("gridLayoutDamage"));
+ gridLayoutDamage->setContentsMargins(0, 0, 0, 0);
+ damageEditorArea = new QFrame(tabDamage);
+ damageEditorArea->setObjectName(QStringLiteral("damageEditorArea"));
+ damageEditorAreaLayout = new QVBoxLayout(damageEditorArea);
+ damageEditorAreaLayout->setSpacing(6);
+ damageEditorAreaLayout->setContentsMargins(11, 11, 11, 11);
+ damageEditorAreaLayout->setObjectName(QStringLiteral("damageEditorAreaLayout"));
+ damageEditorAreaLayout->setContentsMargins(2, 2, 2, 2);
+
+ gridLayoutDamage->addWidget(damageEditorArea, 1, 0, 1, 1);
+
+ damageScrollArea = new QScrollArea(tabDamage);
+ damageScrollArea->setObjectName(QStringLiteral("damageScrollArea"));
+ damageScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ damageScrollArea->setWidgetResizable(true);
+ damageScrollAreaContents = new QWidget();
+ damageScrollAreaContents->setObjectName(QStringLiteral("damageScrollAreaContents"));
+ damageScrollAreaContents->setGeometry(QRect(0, 0, 359, 481));
+ damageScrollAreaLayout = new QVBoxLayout(damageScrollAreaContents);
+ damageScrollAreaLayout->setSpacing(3);
+ damageScrollAreaLayout->setContentsMargins(11, 11, 11, 11);
+ damageScrollAreaLayout->setObjectName(QStringLiteral("damageScrollAreaLayout"));
+ damageScrollAreaLayout->setContentsMargins(2, 2, 2, 2);
+ verticalSpacerDamage = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ damageScrollAreaLayout->addItem(verticalSpacerDamage);
+
+ damageScrollArea->setWidget(damageScrollAreaContents);
+
+ gridLayoutDamage->addWidget(damageScrollArea, 0, 0, 1, 1);
+
+ sideBarTab->addTab(tabDamage, QString());
+
+ sideBarTab->setTabText(sideBarTab->indexOf(tabDamage), QApplication::translate("AppMainWindowClass", "Damage", 0));
+
+ ExpandablePanel* panel = 0;
+ int pannelCnt = 0;
+
+ panel = new ExpandablePanel(damageScrollAreaContents);
+ _defaultDamagePanel = new DefaultDamagePanel(panel);
+ panel->AddContent(_defaultDamagePanel);
+ damageScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Default Damage");
+ }
+
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_InitUI()
+{
+ AppMainWindow* mainWindow = &AppMainWindow::Inst();
+ _mainToolbar = new BlastToolbar(mainWindow);
+ _mainToolbar->setAllowedAreas(Qt::TopDockWidgetArea);
+ _mainToolbar->setFeatures(_mainToolbar->features()&~QDockWidget::DockWidgetClosable);
+ mainWindow->addDockWidget(Qt::TopDockWidgetArea, _mainToolbar);
+
+ _filtersDockWidget = new FiltersDockWidget(mainWindow);
+ _filtersDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea);
+ _filtersDockWidget->setFeatures(_filtersDockWidget->features()&~QDockWidget::DockWidgetClosable);
+ mainWindow->addDockWidget(Qt::LeftDockWidgetArea, _filtersDockWidget);
+
+ _blastSceneTree = new BlastSceneTree(mainWindow);
+ _blastSceneTree->setAllowedAreas(Qt::LeftDockWidgetArea);
+ _blastSceneTree->setFeatures(_blastSceneTree->features()&~QDockWidget::DockWidgetClosable);
+ _blastSceneTree->addObserver(_defaultDamagePanel);
+ mainWindow->addDockWidget(Qt::LeftDockWidgetArea, _blastSceneTree);
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_updateUI()
+{
+ if (_mainToolbar)
+ _mainToolbar->updateValues();
+
+ if (_filtersDockWidget)
+ _filtersDockWidget->updateValues();
+
+ if (_blastSceneTree)
+ _blastSceneTree->updateValues();
+
+ if (_materialLibraryPanel)
+ _materialLibraryPanel->updateValues();
+
+ if (_materialAssignmentsPanel)
+ _materialAssignmentsPanel->updateValues();
+
+ if (_fileReferencesPanel)
+ _fileReferencesPanel->updateValues();
+
+ if (_generalPanel)
+ _generalPanel->updateValues();
+
+ if (_blastCompositePanel)
+ _blastCompositePanel->updateValues();
+
+ if (_fractureCutoutSettingsPanel)
+ _fractureCutoutSettingsPanel->updateValues();
+
+ if (_fractureGeneralPanel)
+ _fractureGeneralPanel->updateValues();
+
+ if (_fractureShellCutSettingPanel)
+ _fractureShellCutSettingPanel->updateValues();
+
+ if (_fractureSliceSettingsPanel)
+ _fractureSliceSettingsPanel->updateValues();
+
+ if (_fractureVisualizersPanel)
+ _fractureVisualizersPanel->updateValues();
+
+ if (_fractureVoronoiSettingsPanel)
+ _fractureVoronoiSettingsPanel->updateValues();
+
+ if (_supportPanel)
+ _supportPanel->updateValues();
+
+ if (_defaultDamagePanel)
+ _defaultDamagePanel->updateValues();
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_updatePluginUI()
+{
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_processDragAndDrop(QString fname)
+{
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_closeEvent(QCloseEvent *event)
+{
+ if (!menu_saveProject())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+bool BlastPlugin::AppMainWindow_InitToolbar(QWidget *pQWidget, QVBoxLayout* pLayout)
+{
+ //_mainToolbar = new BlastToolbar(pQWidget);
+ //pLayout->insertWidget(0, _mainToolbar);
+// connect(_mainToolbar->getUI().btnFileOpen, SIGNAL(clicked()), this, SLOT(menu_openProject()));
+
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_shortcut_expert(bool mode)
+{
+ if (_mainToolbar)
+ _mainToolbar->setVisible(mode);
+
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_updateMainToolbar()
+{
+ if (_mainToolbar)
+ _mainToolbar->updateValues();
+
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_menu_about()
+{
+ return true;
+}
+
+bool BlastPlugin::AppMainWindow_menu_opendoc()
+{
+ QString appDir = QApplication::applicationDirPath();
+ QString docsFile = QFileInfo(appDir + "/../../docs/User_Guide/Nvidia Blast.chm").absoluteFilePath();
+
+ QUrl docsUrl = QUrl::fromLocalFile(docsFile);
+ QUrl url = QUrl::fromUserInput(QString("http://docs.nvidia.com/gameworks/content/artisttools/blast/index.html"));
+ QDesktopServices::openUrl(url);
+
+ return true;
+}
+
+#if USE_CURVE_EDITOR
+#include "CurveEditorMainWindow.h"
+
+bool BlastPlugin::AppMainWindow_UpdateCurveEditor()
+{
+ return true;
+}
+bool BlastPlugin::AppMainWindow_ShowCurveEditor(int paramId)
+{
+ return true;
+}
+bool BlastPlugin::AppMainWindow_onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute)
+{
+ return true;
+}
+bool BlastPlugin::AppMainWindow_onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute)
+{
+ return true;
+}
+bool BlastPlugin::AppMainWindow_onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex)
+{
+ return true;
+}
+#endif
+
+bool BlastPlugin::menu_openProject()
+{
+ AppMainWindow& window = AppMainWindow::Inst();
+ QString lastDir = window._lastFilePath;
+ QString fileName = QFileDialog::getOpenFileName(&window, "Open Blast Project File", lastDir, "Blast Project File (*.blastProj)");
+
+ return window.openProject(fileName);
+}
+
+bool BlastPlugin::menu_saveProject()
+{
+ char message[1024];
+
+ std::string projectFilePath = GlobalSettings::Inst().getAbsoluteFilePath();
+ std::string projectFileName = GlobalSettings::Inst().m_projectFileName;
+ if (projectFileName != "")
+ {
+ if (SimpleScene::Inst()->SaveProject(
+ GlobalSettings::Inst().m_projectFileDir.c_str(),
+ GlobalSettings::Inst().m_projectFileName.c_str()
+ ) == false)
+ {
+ QMessageBox messageBox;
+
+ sprintf(message, "Project file %s could not be saved!", (const char*)projectFilePath.c_str());
+ messageBox.critical(0, "Error", message);
+ messageBox.setFixedSize(500, 200);
+ char message[1024];
+ sprintf(message, "Failed to save project file(\"%s\")", (const char*)projectFilePath.c_str());
+ viewer_err(message);
+ return false;
+ }
+
+ sprintf(message, "Project file %s was saved.", (const char*)projectFilePath.c_str());
+
+ /*
+ QMessageBox messageBox;
+ messageBox.information(0, "Info", message);
+ messageBox.setFixedSize(500,200);
+ */
+ viewer_msg(message);
+ return true;
+ }
+ else
+ {
+ return menu_saveProjectAs();
+ }
+ return false;
+}
+
+bool BlastPlugin::menu_saveProjectAs()
+{
+ AppMainWindow& window = AppMainWindow::Inst();
+
+ char message[1024];
+
+ QString lastDir = window._lastFilePath;
+ QString fileName = QFileDialog::getSaveFileName(&window, "Save Blast Project File", lastDir, "Blast Project File (*.blastProj)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->SaveProject(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ sprintf(message, "Project file %s could not be saved!", (const char*)file);
+ messageBox.critical(0, "Error", message);
+ messageBox.setFixedSize(500, 200);
+ return false;
+ }
+
+ sprintf(message, "Project file %s was saved.", (const char*)file);
+
+ /*
+ QMessageBox messageBox;
+ messageBox.information(0, "Info", message);
+ messageBox.setFixedSize(500,200);
+ */
+
+ viewer_msg(message);
+
+ window._lastFilePath = fileInfo.absoluteDir().absolutePath();
+ return true;
+ }
+ return false;
+}
+
+bool BlastPlugin::shortcut_damagetool()
+{
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ sampleManager.setBlastToolType(BTT_Damage);
+ return true;
+}
+
+bool BlastPlugin::shortcut_selecttool()
+{
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ sampleManager.setBlastToolType(BTT_Select);
+ return true;
+}
+
+bool BlastPlugin::shortcut_Translate()
+{
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ sampleManager.setBlastToolType(BTT_Translate);
+ return true;
+}
+
+bool BlastPlugin::shortcut_Rotation()
+{
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ sampleManager.setBlastToolType(BTT_Rotation);
+ return true;
+}
+
+bool BlastPlugin::shortcut_Scale()
+{
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ sampleManager.setBlastToolType(BTT_Scale);
+ return true;
+}
+
+bool BlastPlugin::shortcut_edittool()
+{
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ sampleManager.setBlastToolType(BTT_Edit);
+ return true;
+}
+
+bool BlastPlugin::slot_Make_Support()
+{
+ BlastSceneTree::ins()->makeSupport();
+ return true;
+}
+
+bool BlastPlugin::slot_Make_Static_Support()
+{
+ BlastSceneTree::ins()->makeStaticSupport();
+ return true;
+}
+
+bool BlastPlugin::slot_Remove_Support()
+{
+ BlastSceneTree::ins()->removeSupport();
+ return true;
+}
+
+bool BlastPlugin::slot_Bond_Chunks()
+{
+ BlastSceneTree::ins()->bondChunks();
+ return true;
+}
+
+bool BlastPlugin::slot_Bond_Chunks_with_Joints()
+{
+ BlastSceneTree::ins()->bondChunksWithJoints();
+ return true;
+}
+
+bool BlastPlugin::slot_Remove_all_Bonds()
+{
+ BlastSceneTree::ins()->removeAllBonds();
+ return true;
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/BlastPlugin.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/BlastPlugin.h
new file mode 100644
index 0000000..21a5499
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/BlastPlugin.h
@@ -0,0 +1,192 @@
+#ifndef BLASTPLUGIN_H
+#define BLASTPLUGIN_H
+
+#include <QtCore/QObject>
+#include <QtCore/QtPlugin>
+#include "PluginInterface.h"
+#include "UIGlobal.h"
+
+class QMenu;
+class QAction;
+class QDoubleSpinBox;
+class QComboBox;
+class QCheckBox;
+class QVBoxLayout;
+class BlastToolbar;
+class FileReferencesPanel;
+class GeneralPanel;
+class BlastCompositePanel;
+class DefaultDamagePanel;
+class MaterialLibraryPanel;
+class MaterialAssignmentsPanel;
+class FractureCutoutSettingsPanel;
+class FractureGeneralPanel;
+class FractureShellCutSettingsPanel;
+class FractureSliceSettingsPanel;
+class FractureVisualizersPanel;
+class FractureVoronoiSettingsPanel;
+class SupportPanel;
+class BlastSceneTree;
+class FiltersDockWidget;
+
+class Camera;
+class Light;
+namespace NvParameterized
+{
+ class Interface;
+ class Handle;
+}
+class D3D11RenderShader;
+
+#define BlastPluginName "BlastPlugin"
+
+class BlastPlugin : public QObject, public PluginInterface
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID PluginInterface_iid FILE "blastplugin.json")
+ Q_INTERFACES(PluginInterface)
+
+public:
+ virtual QString GetPluginName();
+
+ virtual bool CoreLib_RunApp();
+
+ virtual bool LoadRenderPlugin(std::string api);
+
+ virtual bool GetBoneNames(std::vector<std::string>& BoneNames);
+
+ virtual bool MainToolbar_updateValues();
+
+ virtual bool CurveEditor_updateValues(int _paramId, float* _values);
+ virtual bool CurveEditor_onUpdateValues(int _paramId, float* _values);
+
+ virtual bool DisplayMeshesPanel_updateValues();
+ virtual bool DisplayMeshesPanel_EmitToggleSignal(unsigned int id, bool visible);
+
+ virtual bool Camera_LoadParameters(void* ptr, Camera* pCamera);
+ virtual bool Camera_SaveParameters(void * ptr, Camera* pCamera);
+
+ virtual bool Gamepad_ToggleSimulation();
+ virtual bool Gamepad_LoadSamples(QString fn);
+ virtual bool Gamepad_ResetScene();
+ virtual bool Gamepad_StartAnimation();
+ virtual bool GamepadHandler_ShowHair();
+ virtual bool GamepadHandler_SpinWindStrength(float windStrength);
+ virtual bool Gamepad_ResetAnimation();
+ virtual bool Gamepad_PlayPauseAnimation();
+
+ virtual bool Light_loadParameters(NvParameterized::Handle& handle, Light* pLight);
+ virtual bool Light_saveParameters(NvParameterized::Handle& handle, Light* pLight);
+
+ virtual bool SimpleScene_SimpleScene();
+ virtual bool SimpleScene_Initialize(int backdoor);
+ virtual bool SimpleScene_Shutdown();
+ virtual bool SimpleScene_Clear();
+ virtual bool SimpleScene_Draw_DX12();
+ virtual bool SimpleScene_Draw_DX11();
+ virtual bool SimpleScene_FitCamera(atcore_float3& center, atcore_float3& extents);
+ virtual bool SimpleScene_DrawGround();
+ virtual bool SimpleScene_DrawWind();
+ virtual bool SimpleScene_DrawAxis();
+ virtual bool SimpleScene_LoadSceneFromFbx(const char* dir, const char* fbxName);
+ virtual bool SimpleScene_LoadProject(const char* dir, const char* file);
+ virtual bool SimpleScene_SaveProject(const char* dir, const char* file);
+ virtual bool SimpleScene_LoadParameters(NvParameterized::Interface* iface);
+ virtual bool SimpleScene_SaveParameters(NvParameterized::Interface* iface);
+ virtual bool SimpleScene_LoadCameraBookmarks(NvParameterized::Interface* iface);
+ virtual bool SimpleScene_SaveCameraBookmarks(NvParameterized::Interface* iface);
+
+ virtual bool D3DWidget_resizeEvent(QResizeEvent* e);
+ virtual bool D3DWidget_paintEvent(QPaintEvent* e);
+ virtual bool D3DWidget_mousePressEvent(QMouseEvent* e);
+ virtual bool D3DWidget_mouseReleaseEvent(QMouseEvent* e);
+ virtual bool D3DWidget_mouseMoveEvent(QMouseEvent* e);
+ virtual bool D3DWidget_wheelEvent(QWheelEvent * e);
+ virtual bool D3DWidget_keyPressEvent(QKeyEvent* e);
+ virtual bool D3DWidget_keyReleaseEvent(QKeyEvent* e);
+ virtual bool D3DWidget_dragEnterEvent(QDragEnterEvent *e);
+ virtual bool D3DWidget_dragMoveEvent(QDragMoveEvent *e);
+ virtual bool D3DWidget_dragLeaveEvent(QDragLeaveEvent *e);
+ virtual bool D3DWidget_dropEvent(QDropEvent *e);
+ virtual bool D3DWidget_contextMenuEvent(QContextMenuEvent *e);
+
+ virtual bool D3D11Shaders_InitializeShadersD3D11(std::map<int, D3D11RenderShader*>& ShaderMap);
+
+ virtual bool AppMainWindow_AppMainWindow();
+ virtual bool AppMainWindow_InitMenuItems(QMenuBar* pMenuBar);
+ virtual bool AppMainWindow_InitMainTab(QWidget *displayScrollAreaContents, QVBoxLayout *displayScrollAreaLayout, int idx);
+ virtual bool AppMainWindow_InitPluginTab(QTabWidget* pTabWidget);
+ virtual bool AppMainWindow_InitUI();
+ virtual bool AppMainWindow_updateUI();
+ virtual bool AppMainWindow_updatePluginUI();
+ virtual bool AppMainWindow_processDragAndDrop(QString fname);
+ virtual bool AppMainWindow_closeEvent(QCloseEvent *event);
+ virtual bool AppMainWindow_InitToolbar(QWidget *pQWidget, QVBoxLayout* pLayout);
+ virtual bool AppMainWindow_shortcut_expert(bool mode);
+ virtual bool AppMainWindow_updateMainToolbar();
+
+ virtual bool AppMainWindow_menu_about();
+ virtual bool AppMainWindow_menu_opendoc();
+#if USE_CURVE_EDITOR
+ virtual bool AppMainWindow_UpdateCurveEditor();
+ virtual bool AppMainWindow_ShowCurveEditor(int paramId);
+ virtual bool AppMainWindow_onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute);
+ virtual bool AppMainWindow_onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute);
+ virtual bool AppMainWindow_onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex);
+#endif
+ BlastToolbar* GetMainToolbar() { return _mainToolbar; }
+
+public:
+ static void DrawHUD();
+
+ /////////////////////////////////////////////////////////////////////
+ // profiler and timer
+ static void ResetFrameTimer();
+
+public slots:
+ bool menu_openProject();
+ bool menu_saveProject();
+ bool menu_saveProjectAs();
+ bool shortcut_damagetool();
+ bool shortcut_selecttool();
+ bool shortcut_Translate();
+ bool shortcut_Rotation();
+ bool shortcut_Scale();
+ bool shortcut_edittool();
+
+ bool slot_Make_Support();
+ bool slot_Make_Static_Support();
+ bool slot_Remove_Support();
+ bool slot_Bond_Chunks();
+ bool slot_Bond_Chunks_with_Joints();
+ bool slot_Remove_all_Bonds();
+
+private:
+ BlastToolbar* _mainToolbar;
+ MaterialLibraryPanel* _materialLibraryPanel;
+ MaterialAssignmentsPanel* _materialAssignmentsPanel;
+ FileReferencesPanel* _fileReferencesPanel;
+ GeneralPanel* _generalPanel;
+ BlastCompositePanel* _blastCompositePanel;
+ DefaultDamagePanel* _defaultDamagePanel;
+ FractureCutoutSettingsPanel* _fractureCutoutSettingsPanel;
+ FractureGeneralPanel* _fractureGeneralPanel;
+ FractureShellCutSettingsPanel* _fractureShellCutSettingPanel;
+ FractureSliceSettingsPanel* _fractureSliceSettingsPanel;
+ FractureVisualizersPanel* _fractureVisualizersPanel;
+ FractureVoronoiSettingsPanel* _fractureVoronoiSettingsPanel;
+ SupportPanel* _supportPanel;
+ BlastSceneTree* _blastSceneTree;
+ FiltersDockWidget* _filtersDockWidget;
+
+ QMenu* _chunkContextMenu;
+ QMenu* _bondContextMenu;
+ QAction* action_Make_Support;
+ QAction* action_Make_Static_Support;
+ QAction* action_Remove_Support;
+ QAction* action_Bond_Chunks;
+ QAction* action_Bond_Chunks_with_Joints;
+ QAction* action_Remove_all_Bonds;
+};
+
+#endif // HAIRWORKSPLUGIN_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/FoundationHolder.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/FoundationHolder.h
new file mode 100644
index 0000000..5ec7868
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/FoundationHolder.h
@@ -0,0 +1,138 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "NvErrorCallback.h"
+#include "NsGlobals.h"
+#include "NsVersionNumber.h"
+
+class DefaultErrorCallback : public nvidia::NvErrorCallback
+{
+public:
+ DefaultErrorCallback(void)
+ {
+ }
+
+ virtual void reportError(nvidia::NvErrorCode::Enum code, const char* message, const char* file, int line)
+ {
+ NV_UNUSED(code);
+ printf("PhysX: %s : %s : %d\r\n", message, file, line);
+ }
+private:
+};
+
+class DefaultAllocator : public nvidia::NvAllocatorCallback
+{
+public:
+ DefaultAllocator(void)
+ {
+ }
+
+ ~DefaultAllocator(void)
+ {
+ }
+
+ virtual void* allocate(size_t size, const char* typeName, const char* filename, int line)
+ {
+ NV_UNUSED(typeName);
+ NV_UNUSED(filename);
+ NV_UNUSED(line);
+ void *ret = ::_aligned_malloc(size, 16);
+ return ret;
+ }
+
+ virtual void deallocate(void* ptr)
+ {
+ ::_aligned_free(ptr);
+ }
+private:
+};
+
+
+#if 0
+class FoundationHolder
+{
+ NvFoundation* mFoundation;
+ FoundationHolder()
+ :mFoundation(nullptr)
+ {
+ }
+
+ ~FoundationHolder()
+ {
+ if (mFoundation)
+ {
+ // to-do
+ // we should release foundation. but Hair SDK could release it first.
+ //mFoundation->release();
+ mFoundation = nullptr;
+ }
+ }
+
+public:
+
+ static NvFoundation* GetFoundation()
+ {
+ static FoundationHolder fh;
+ if (fh.mFoundation == nullptr)
+ {
+ static DefaultAllocator sDefaultAllocator;
+ static DefaultErrorCallback sDefaultErrorCallback;
+ fh.mFoundation = NvCreateFoundation(NV_FOUNDATION_VERSION, sDefaultAllocator, sDefaultErrorCallback);
+ assert(fh.mFoundation != nullptr);
+ }
+ return fh.mFoundation;
+ }
+};
+
+#else
+
+class FoundationHolder
+{
+ bool m_isInitialized;
+ public:
+ static void GetFoundation()
+ {
+ static FoundationHolder s_holder;
+ if (!s_holder.m_isInitialized)
+ {
+ static DefaultAllocator sDefaultAllocator;
+ static DefaultErrorCallback sDefaultErrorCallback;
+ nvidia::shdfnd::initializeSharedFoundation(NV_FOUNDATION_VERSION, sDefaultAllocator, sDefaultErrorCallback);
+
+ s_holder.m_isInitialized = true;
+ }
+ }
+ ~FoundationHolder()
+ {
+ //nvidia::terminateSharedFoundation();
+ }
+};
+
+#endif
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/ProjectParams.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/ProjectParams.cpp
new file mode 100644
index 0000000..36d78cc
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/ProjectParams.cpp
@@ -0,0 +1,2162 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2013 NVIDIA Corporation. All rights reserved.
+
+#include "NvParameterized.h"
+#include "XmlSerializer.h"
+#include "NsFileBuffer.h"
+#include "NvTraits.h"
+#include "NsMemoryBuffer.h"
+
+#include "BlastProjectParameters.h"
+#include "SimpleScene.h"
+#include "ProjectParams.h"
+
+#include "NvErrorCallback.h"
+#include "NsGlobals.h"
+#include "NsVersionNumber.h"
+#include <QtXml\QtXml>
+#include <QtWidgets/QMessageBox>
+#include "AppMainWindow.h"
+#include "FoundationHolder.h"
+
+using namespace nvidia;
+using namespace nvidia::parameterized;
+
+
+struct ProjectParamsContext* g_projectParamsContext = nullptr;
+const char* USER_PRESET_PATH = ".\\BlastUserPreset.userPreset";
+
+struct ProjectParamsContext
+{
+ //NvFoundation* mFoundation;
+ NvParameterized::Traits* mTraits;
+ BlastProjectParametersFactory* mBlastProjectParametersFactory;
+};
+
+void freeString(NvParameterized::DummyStringStruct& str)
+{
+ delete[] str.buf;
+ str.buf = nullptr;
+}
+
+void freeBlast(BPPGraphicsMesh& data)
+{
+ freeString(data.name);
+}
+
+void freeBlast(BPPChunk& data)
+{
+ freeString(data.name);
+ freeString(data.asset);
+}
+
+void freeBlast(BPPBond& data)
+{
+ freeString(data.name);
+ freeString(data.asset);
+}
+
+void freeBlast(BPPAsset& data)
+{
+ freeString(data.path);
+}
+
+void freeBlast(BPPAssetInstance& data)
+{
+ freeString(data.name);
+ freeString(data.source);
+}
+
+void freeBlast(BPPComposite& data)
+{
+ freeString(data.composite);
+
+ freeBlast(data.blastAssetInstances);
+ freeBlast(data.landmarks);
+}
+
+void freeBlast(BPPBlast& data)
+{
+ freeString(data.fileReferences.fbxSourceAsset);
+ freeString(data.fileReferences.fbx);
+ freeString(data.fileReferences.blast);
+ freeString(data.fileReferences.collision);
+
+ freeBlast(data.composite);
+ freeBlast(data.blastAssets);
+ freeBlast(data.chunks);
+ freeBlast(data.bonds);
+}
+
+void freeBlast(BPPLandmark& data)
+{
+ freeString(data.name);
+}
+
+void freeBlast(BPPStringArray& data)
+{
+ for (int i = 0; i < data.arraySizes[0]; ++i)
+ {
+ freeString(data.buf[i]);
+ }
+
+ delete[] data.buf;
+ data.buf = nullptr;
+ data.arraySizes[0] = 0;
+}
+
+void freeBlast(BPPGraphicsMeshArray& data)
+{
+ for (int i = 0; i < data.arraySizes[0]; ++i)
+ {
+ freeBlast(data.buf[i]);
+ }
+
+ delete[] data.buf;
+ data.buf = nullptr;
+ data.arraySizes[0] = 0;
+}
+
+void freeBlast(BPPChunkArray& data)
+{
+ for (int i = 0; i < data.arraySizes[0]; ++i)
+ {
+ freeBlast(data.buf[i]);
+ }
+
+ delete[] data.buf;
+ data.buf = nullptr;
+ data.arraySizes[0] = 0;
+}
+
+void freeBlast(BPPBondArray& data)
+{
+ for (int i = 0; i < data.arraySizes[0]; ++i)
+ {
+ freeBlast(data.buf[i]);
+ }
+
+ delete[] data.buf;
+ data.buf = nullptr;
+ data.arraySizes[0] = 0;
+}
+
+void freeBlast(BPPAssetArray& data)
+{
+ for (int i = 0; i < data.arraySizes[0]; ++i)
+ {
+ freeBlast(data.buf[i]);
+ }
+
+ delete[] data.buf;
+ data.buf = nullptr;
+ data.arraySizes[0] = 0;
+}
+
+void freeBlast(BPPAssetInstanceArray& data)
+{
+ for (int i = 0; i < data.arraySizes[0]; ++i)
+ {
+ freeBlast(data.buf[i]);
+ }
+
+ delete[] data.buf;
+ data.buf = nullptr;
+ data.arraySizes[0] = 0;
+}
+
+void freeBlast(BPPLandmarkArray& data)
+{
+ for (int i = 0; i < data.arraySizes[0]; ++i)
+ {
+ freeBlast(data.buf[i]);
+ }
+
+ delete[] data.buf;
+ data.buf = nullptr;
+ data.arraySizes[0] = 0;
+}
+
+void copy(NvParameterized::DummyStringStruct& dest, const char* source)
+{
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ //dest.isAllocated = false;
+
+ if (source != nullptr)
+ {
+ dest.buf = new char[strlen(source) + 1];
+ strcpy(const_cast<char*>(dest.buf), source);
+ //dest.isAllocated = true;
+ }
+}
+
+void copy(NvParameterized::DummyStringStruct& dest, NvParameterized::DummyStringStruct& source)
+{
+ copy(dest, source.buf);
+}
+
+void copy(BPPStringArray& dest, BPPStringArray& source)
+{
+ {
+ for (int i = 0; i < dest.arraySizes[0]; ++i)
+ {
+ delete[] dest.buf[i].buf;
+ }
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+ }
+
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new NvParameterized::DummyStringStruct[source.arraySizes[0]];
+
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ NvParameterized::DummyStringStruct& destItem = dest.buf[i];
+ NvParameterized::DummyStringStruct& sourceItem = source.buf[i];
+
+ destItem.buf = nullptr;
+
+ copy(destItem, sourceItem);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPGraphicsMaterialArray& dest, BPPGraphicsMaterialArray& source)
+{
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new BPPGraphicsMaterial[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ BPPGraphicsMaterial& destItem = dest.buf[i];
+ BPPGraphicsMaterial& sourceItem = source.buf[i];
+
+ init(destItem);
+
+ copy(destItem, sourceItem);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPGraphicsMeshArray& dest, BPPGraphicsMeshArray& source)
+{
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new BPPGraphicsMesh[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ BPPGraphicsMesh& destItem = dest.buf[i];
+ BPPGraphicsMesh& sourceItem = source.buf[i];
+
+ destItem.name.buf = nullptr;
+
+ copy(destItem.name, sourceItem.name);
+ destItem.visible = sourceItem.visible;
+ copy(destItem.materialAssignments, sourceItem.materialAssignments);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPBookmarkArray& dest, BPPBookmarkArray& source)
+{
+ {
+ int count = dest.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ delete[] dest.buf[i].name.buf;
+ }
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+ }
+
+ {
+ int count = source.arraySizes[0];
+ dest.arraySizes[0] = count;
+ if (count > 0)
+ {
+ dest.buf = new BPPCameraBookmark[count];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPCameraBookmark& destItem = dest.buf[i];
+ BPPCameraBookmark& sourceItem = source.buf[i];
+
+ destItem.name.buf = nullptr;
+
+ copy(destItem.name, sourceItem.name);
+ destItem.camera = sourceItem.camera;
+ }
+ }
+ }
+}
+
+void copy(BPPLightArray& dest, BPPLightArray& source)
+{
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new BPPLight[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ BPPLight& destItem = dest.buf[i];
+ BPPLight& sourceItem = source.buf[i];
+
+ destItem.name.buf = nullptr;
+
+ copy(destItem.name, sourceItem.name);
+ copy(destItem, sourceItem);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPChunkArray& dest, BPPChunkArray& source)
+{
+ freeBlast(dest);
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new BPPChunk[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ BPPChunk& destItem = dest.buf[i];
+ BPPChunk& sourceItem = source.buf[i];
+
+ destItem.name.buf = nullptr;
+ destItem.asset.buf = nullptr;
+
+ copy(destItem, sourceItem);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPBondArray& dest, BPPBondArray& source)
+{
+ freeBlast(dest);
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new BPPBond[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ BPPBond& destItem = dest.buf[i];
+ BPPBond& sourceItem = source.buf[i];
+
+ destItem.name.buf = nullptr;
+ destItem.asset.buf = nullptr;
+ destItem.support.healthMask.buf = nullptr;
+
+ copy(destItem, sourceItem);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPProjectileArray& dest, BPPProjectileArray& source)
+{
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new BPPProjectile[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ BPPProjectile& destItem = dest.buf[i];
+ BPPProjectile& sourceItem = source.buf[i];
+
+ destItem.name.buf = nullptr;
+
+ copy(destItem, sourceItem);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPAssetArray& dest, BPPAssetArray& source)
+{
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new BPPAsset[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ BPPAsset& destItem = dest.buf[i];
+ BPPAsset& sourceItem = source.buf[i];
+
+ destItem.path.buf = nullptr;
+ destItem.activePreset.buf = nullptr;
+
+ copy(destItem, sourceItem);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPAssetInstanceArray& dest, BPPAssetInstanceArray& source)
+{
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new BPPAssetInstance[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ BPPAssetInstance& destItem = dest.buf[i];
+ BPPAssetInstance& sourceItem = source.buf[i];
+
+ destItem.name.buf = nullptr;
+ destItem.source.buf = nullptr;
+
+ copy(destItem, sourceItem);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPLandmarkArray& dest, BPPLandmarkArray& source)
+{
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new BPPLandmark[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ BPPLandmark& destItem = dest.buf[i];
+ BPPLandmark& sourceItem = source.buf[i];
+
+ destItem.name.buf = nullptr;
+
+ copy(destItem, sourceItem);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPU32Array& dest, BPPU32Array& source)
+{
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new uint32_t[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ uint32_t& destItem = dest.buf[i];
+ uint32_t& sourceItem = source.buf[i];
+
+ destItem = sourceItem;
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPFilterPresetArray& dest, BPPFilterPresetArray& source)
+{
+ delete[] dest.buf;
+ dest.buf = nullptr;
+ dest.arraySizes[0] = 0;
+
+ if (source.arraySizes[0] > 0)
+ {
+ dest.buf = new BPPFilterPreset[source.arraySizes[0]];
+ for (int i = 0; i < source.arraySizes[0]; ++i)
+ {
+ BPPFilterPreset& destItem = dest.buf[i];
+ BPPFilterPreset& sourceItem = source.buf[i];
+
+ destItem.name.buf = nullptr;
+ destItem.depthFilters.buf = nullptr;
+
+ copy(destItem, sourceItem);
+ }
+ dest.arraySizes[0] = source.arraySizes[0];
+ }
+}
+
+void copy(BPPLight& dest, BPPLight& source)
+{
+ copy(dest.name, source.name);
+ dest.enable = source.enable;
+ dest.useShadows = source.useShadows;
+ dest.lockToRoot = source.lockToRoot;
+ dest.visualize = source.visualize;
+ dest.type = source.type;
+ dest.shadowMapResolution = source.shadowMapResolution;
+ dest.color = source.color;
+ dest.diffuseColor = source.diffuseColor;
+ dest.ambientColor = source.ambientColor;
+ dest.specularColor = source.specularColor;
+ dest.intensity = source.intensity;
+ dest.distance = source.distance;
+ dest.spotFalloffStart = source.spotFalloffStart;
+ dest.spotFalloffEnd = source.spotFalloffEnd;
+ dest.lightAxisX = source.lightAxisX;
+ dest.lightAxisY = source.lightAxisY;
+ dest.lightAxisZ = source.lightAxisZ;
+ dest.lightPos = source.lightPos;
+}
+
+void copy(BPPGraphicsMaterial& dest, BPPGraphicsMaterial& source)
+{
+ copy(dest.name, source.name);
+ dest.useTextures = source.useTextures;
+ copy(dest.diffuseTextureFilePath, source.diffuseTextureFilePath);
+ copy(dest.specularTextureFilePath, source.specularTextureFilePath);
+ copy(dest.normalTextureFilePath, source.normalTextureFilePath);
+ dest.diffuseColor = source.diffuseColor;
+ dest.specularColor = source.specularColor;
+ dest.specularShininess = source.specularShininess;
+}
+
+void copy(BPPGraphicsMesh& dest, BPPGraphicsMesh& source)
+{
+ copy(dest.name, source.name);
+ dest.visible = source.visible;
+ copy(dest.materialAssignments, source.materialAssignments);
+}
+
+void copy(BPPMaterialAssignments& dest, BPPMaterialAssignments& source)
+{
+ dest.materialIndexes[0] = source.materialIndexes[0];
+ dest.materialIndexes[1] = source.materialIndexes[1];
+ dest.materialIndexes[2] = source.materialIndexes[2];
+ dest.materialIndexes[3] = source.materialIndexes[3];
+}
+
+void copy(BPPProjectile& dest, BPPProjectile& source)
+{
+ copy(dest.name, source.name);
+ dest.visible = source.visible;
+}
+
+void copy(BPPSupportStructure& dest, BPPSupportStructure& source)
+{
+ copy(dest.healthMask, source.healthMask);
+ dest.bondStrength = source.bondStrength;
+ dest.enableJoint = source.enableJoint;
+}
+
+void copy(BPPChunk& dest, BPPChunk& source)
+{
+ dest.ID = source.ID;
+ dest.parentID = source.parentID;
+ copy(dest.name, source.name);
+ copy(dest.asset, source.asset);
+ dest.visible = source.visible;
+ dest.support = source.support;
+ dest.staticFlag = source.staticFlag;
+}
+
+void copy(BPPBond& dest, BPPBond& source)
+{
+ copy(dest.name, source.name);
+ copy(dest.asset, source.asset);
+ dest.visible = source.visible;
+ dest.fromChunk = source.fromChunk;
+ dest.toChunk = source.toChunk;
+ copy(dest.support, source.support);
+}
+
+void copy(BPPLandmark& dest, BPPLandmark& source)
+{
+ copy(dest.name, source.name);
+ dest.visible = source.visible;
+ dest.enable = source.enable;
+ dest.radius = source.radius;
+}
+
+void copy(BPPRenderer& dest, BPPRenderer& source)
+{
+ dest.renderFps = source.renderFps;
+ dest.frameStartTime = source.frameStartTime;
+ dest.frameEndTime = source.frameEndTime;
+ dest.animationFps = source.animationFps;
+ dest.animate = source.animate;
+ dest.simulate = source.simulate;
+ dest.resetSimulationOnLoop = source.resetSimulationOnLoop;
+ dest.simulationFps = source.simulationFps;
+ dest.showGraphicsMesh = source.showGraphicsMesh;
+ dest.visualizeGrowthMesh = source.visualizeGrowthMesh;
+ dest.visualizeLight = source.visualizeLight;
+ dest.visualizeWind = source.visualizeWind;
+ dest.showStatistics = source.showStatistics;
+ dest.renderStyle = source.renderStyle;
+ dest.colorizeOption = source.colorizeOption;
+ dest.showWireframe = source.showWireframe;
+ dest.lockRootBone = source.lockRootBone;
+ dest.controlTextureOption = source.controlTextureOption;
+ dest.useLighting = source.useLighting;
+ dest.showSkinnedMeshOnly = source.showSkinnedMeshOnly;
+ dest.lightDir = source.lightDir;
+ dest.ambientColor = source.ambientColor;
+ dest.windDir = source.windDir;
+ dest.windStrength = source.windStrength;
+ dest.lightIntensity = source.lightIntensity;
+ dest.gravityDir = source.gravityDir;
+ dest.gravityScale = source.gravityScale;
+
+ copy(dest.textureFilePath, source.textureFilePath);
+ copy(dest.lights, source.lights);
+}
+
+void copy(BPPStressSolver& dest, BPPStressSolver& source)
+{
+ dest.solverMode = source.solverMode;
+ dest.linearFactor = source.linearFactor;
+ dest.angularFactor = source.angularFactor;
+ dest.meanError = source.meanError;
+ dest.varianceError = source.varianceError;
+ dest.bondsPerFrame = source.bondsPerFrame;
+ dest.bondsIterations = source.bondsIterations;
+}
+
+void copy(BPPAsset& dest, BPPAsset& source)
+{
+ copy(dest.path, source.path);
+ dest.visible = source.visible;
+ dest.stressSolver = source.stressSolver;
+ copy(dest.activePreset, source.activePreset);
+ dest.defaultDamage = source.defaultDamage;
+}
+
+void copy(BPPAssetInstance& dest, BPPAssetInstance& source)
+{
+ copy(dest.name, source.name);
+ dest.visible = source.visible;
+ copy(dest.source, source.source);
+ dest.transform = source.transform;
+}
+
+void copy(BPPComposite& dest, BPPComposite& source)
+{
+ copy(dest.composite, source.composite);
+ dest.visible = source.visible;
+ copy(dest.blastAssetInstances, source.blastAssetInstances);
+ dest.bondThreshold = source.bondThreshold;
+ dest.bondStrength = source.bondStrength;
+ copy(dest.landmarks, source.landmarks);
+}
+
+void copy(BPPBlast& dest, BPPBlast& source)
+{
+ copy(dest.fileReferences.fbxSourceAsset, source.fileReferences.fbxSourceAsset);
+ copy(dest.fileReferences.fbx, source.fileReferences.fbx);
+ copy(dest.fileReferences.blast, source.fileReferences.blast);
+ copy(dest.fileReferences.collision, source.fileReferences.collision);
+
+ copy(dest.composite, source.composite);
+ copy(dest.blastAssets, source.blastAssets);
+ copy(dest.chunks, source.chunks);
+ copy(dest.bonds, source.bonds);
+ copy(dest.projectiles, source.projectiles);
+ copy(dest.graphicsMeshes, source.graphicsMeshes);
+
+ copy(dest.userPreset, source.userPreset);
+ copy(dest.healthMask, source.healthMask);
+}
+
+void copy(BPPFilter& dest, BPPFilter& source)
+{
+ dest.activeFilter = source.activeFilter;
+ copy(dest.filters, source.filters);
+}
+
+void copy(BPPVoronoi& dest, BPPVoronoi& source)
+{
+ dest.numSites = source.numSites;
+ dest.siteGeneration = source.siteGeneration;
+ dest.gridSize = source.gridSize;
+ dest.gridScale = source.gridScale;
+ dest.amplitude = source.amplitude;
+
+ dest.frequency = source.frequency;
+ copy(dest.paintMasks, source.paintMasks);
+ dest.activePaintMask = source.activePaintMask;
+ copy(dest.meshCutters, source.meshCutters);
+ dest.activeMeshCutter = source.activeMeshCutter;
+ dest.fractureInsideCutter = source.fractureInsideCutter;
+ dest.fractureOutsideCutter = source.fractureOutsideCutter;
+ copy(dest.textureSites, source.textureSites);
+ dest.numTextureSites = source.numTextureSites;
+}
+
+void copy(BPPCutoutProjection& dest, BPPCutoutProjection& source)
+{
+ copy(dest.textures, source.textures);
+ dest.cutoutType = source.cutoutType;
+ dest.pixelThreshold = source.pixelThreshold;
+ dest.tiled = source.tiled;
+ dest.invertU = source.invertU;
+ dest.invertV = source.invertV;
+}
+
+void copy(BPPFracture& dest, BPPFracture& source)
+{
+ dest.activeFractureMethod = source.activeFractureMethod;
+ dest.general = source.general;
+ dest.visualization = source.visualization;
+ dest.shellCut = source.shellCut;
+ copy(dest.voronoi, source.voronoi);
+ dest.slice = source.slice;
+ copy(dest.cutoutProjection, source.cutoutProjection);
+}
+
+void copy(BPPFilterPreset& dest, BPPFilterPreset& source)
+{
+ copy(dest.name, source.name);
+ copy(dest.depthFilters, source.depthFilters);
+}
+
+void copy(BPParams& dest, BPParams& source)
+{
+ dest.camera = source.camera;
+ copy(dest.cameraBookmarks, source.cameraBookmarks);
+ dest.lightCamera = source.camera;
+ dest.windCamera = source.camera;
+ copy(dest.graphicsMaterials, source.graphicsMaterials);
+ dest.scene = source.scene;
+ copy(dest.renderer, source.renderer);
+ copy(dest.blast, source.blast);
+ copy(dest.filter, source.filter);
+ copy(dest.fracture, source.fracture);
+
+ copy(dest.blast.userPreset, USER_PRESET_PATH);
+}
+
+void merge(BPPChunkArray& dest, BPPChunkArray& source)
+{
+ if (source.arraySizes[0] > 0)
+ {
+ BPPChunk* oriDestArray = dest.buf;
+ int oriCount = dest.arraySizes[0];
+ int srcCount = source.arraySizes[0];
+ dest.buf = new BPPChunk[oriCount + srcCount];
+ int i = 0;
+ for (; i < oriCount; ++i)
+ {
+ BPPChunk& destItem = dest.buf[i];
+ BPPChunk& oriItem = oriDestArray[i];
+
+ destItem.name.buf = nullptr;
+ destItem.asset.buf = nullptr;
+ copy(destItem, oriItem);
+ }
+ for (int j = 0; j < srcCount; ++j, ++i)
+ {
+ BPPChunk& destItem = dest.buf[i];
+ BPPChunk& sourceItem = source.buf[j];
+
+ destItem.name.buf = nullptr;
+ destItem.asset.buf = nullptr;
+ copy(destItem, sourceItem);
+ }
+ for (int m = 0; m < oriCount; ++m)
+ {
+ freeBlast(oriDestArray[m]);
+ }
+ delete[] oriDestArray;
+ dest.arraySizes[0] = oriCount + srcCount;
+ }
+}
+
+void merge(BPPBondArray& dest, BPPBondArray& source)
+{
+ if (source.arraySizes[0] > 0)
+ {
+ BPPBond* oriDestArray = dest.buf;
+ int oriCount = dest.arraySizes[0];
+ int srcCount = source.arraySizes[0];
+ dest.buf = new BPPBond[oriCount + srcCount];
+ int i = 0;
+ for (; i < oriCount; ++i)
+ {
+ BPPBond& destItem = dest.buf[i];
+ BPPBond& oriItem = oriDestArray[i];
+
+ destItem.name.buf = nullptr;
+ destItem.asset.buf = nullptr;
+ destItem.support.healthMask.buf = nullptr;
+ copy(destItem, oriItem);
+ }
+ for (int j = 0; j < srcCount; ++j, ++i)
+ {
+ BPPBond& destItem = dest.buf[i];
+ BPPBond& sourceItem = source.buf[j];
+
+ destItem.name.buf = nullptr;
+ destItem.asset.buf = nullptr;
+ destItem.support.healthMask.buf = nullptr;
+ copy(destItem, sourceItem);
+ }
+ for (int m = 0; m < oriCount; ++m)
+ {
+ freeBlast(oriDestArray[m]);
+ }
+ delete[] oriDestArray;
+ dest.arraySizes[0] = oriCount + srcCount;
+ }
+}
+
+void init(BPPStressSolver& param)
+{
+ param.solverMode = -1;
+ param.linearFactor = 0;
+ param.angularFactor = 0;
+ param.meanError = 0;
+ param.varianceError = 0;
+ param.bondsPerFrame = 0;
+ param.bondsIterations = 0;
+}
+
+void init(BPPGraphicsMaterial& param)
+{
+ param.name.buf = nullptr;
+ param.useTextures = false;
+ param.diffuseTextureFilePath.buf = nullptr;
+ param.specularTextureFilePath.buf = nullptr;
+ param.normalTextureFilePath.buf = nullptr;
+ param.specularShininess = 0.0;
+}
+
+void init(BPParams& params)
+{
+ //memset(&params, sizeof(BPParams), 0);
+
+ //params.cameraBookmarks.buf = nullptr;
+ //for (int i = 0; i < 4; ++i)
+ // params.renderer.lights.buf[i].name.buf =
+}
+
+StressSolverUserPreset::StressSolverUserPreset(const char* inName)
+ : name(inName)
+{
+ name = name;
+ stressSolver.solverMode = -1;
+ stressSolver.linearFactor = 0;
+ stressSolver.angularFactor = 0;
+ stressSolver.meanError = 0;
+ stressSolver.varianceError = 0;
+ stressSolver.bondsPerFrame = 0;
+ stressSolver.bondsIterations = 0;
+}
+
+BlastProject& BlastProject::ins()
+{
+ static BlastProject _ins;
+ return _ins;
+}
+
+BlastProject::~BlastProject()
+{
+ delete[] _projectParams.cameraBookmarks.buf;
+}
+
+void BlastProject::clear()
+{
+ freeBlast(_projectParams.blast);
+}
+
+bool BlastProject::isGraphicsMaterialNameExist(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return false;
+
+ BPPGraphicsMaterialArray& theArray = _projectParams.graphicsMaterials;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ BPPGraphicsMaterial& item = theArray.buf[i];
+ if (nvidia::shdfnd::strcmp(item.name.buf, name) == 0)
+ return true;
+ }
+ return false;
+}
+
+BPPGraphicsMaterial* BlastProject::addGraphicsMaterial(const char* name, const char* diffuseTexture)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return nullptr;
+
+ BPPGraphicsMaterialArray& theArray = _projectParams.graphicsMaterials;
+ BPPGraphicsMaterial* oldBuf = theArray.buf;
+ theArray.buf = new BPPGraphicsMaterial[theArray.arraySizes[0] + 1];
+
+ int i = 0;
+ for (; i < theArray.arraySizes[0]; ++i)
+ {
+ BPPGraphicsMaterial& newItem = theArray.buf[i];
+ BPPGraphicsMaterial& oldItem = oldBuf[i];
+ newItem.useTextures = false;
+ newItem.name.buf = nullptr;
+ newItem.diffuseTextureFilePath.buf = nullptr;
+ newItem.specularTextureFilePath.buf = nullptr;
+ newItem.normalTextureFilePath.buf = nullptr;
+ newItem.specularShininess = 0.0;
+ copy(newItem, oldItem);
+ }
+
+ BPPGraphicsMaterial& newItem = theArray.buf[i];
+ newItem.name.buf = nullptr;
+ newItem.useTextures = false;
+ newItem.diffuseTextureFilePath.buf = nullptr;
+ newItem.specularTextureFilePath.buf = nullptr;
+ newItem.normalTextureFilePath.buf = nullptr;
+ newItem.specularShininess = 0.0;
+ copy(newItem.name, name);
+ if (diffuseTexture != nullptr)
+ {
+ copy(newItem.diffuseTextureFilePath, diffuseTexture);
+ }
+ theArray.arraySizes[0] += 1;
+
+ delete[] oldBuf;
+
+ return &newItem;
+}
+
+void BlastProject::removeGraphicsMaterial(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0 || !isGraphicsMaterialNameExist(name))
+ return;
+
+ BPPGraphicsMaterialArray& theArray = _projectParams.graphicsMaterials;
+ BPPGraphicsMaterial* oldBuf = theArray.buf;
+
+ theArray.buf = new BPPGraphicsMaterial[theArray.arraySizes[0] - 1];
+ int index = 0;
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(oldBuf[i].name.buf, name) != 0)
+ {
+ BPPGraphicsMaterial& newItem = theArray.buf[index++];
+ BPPGraphicsMaterial& oldItem = oldBuf[i];
+ newItem.useTextures = false;
+ newItem.name.buf = nullptr;
+ newItem.diffuseTextureFilePath.buf = nullptr;
+ newItem.specularTextureFilePath.buf = nullptr;
+ newItem.normalTextureFilePath.buf = nullptr;
+ copy(newItem, oldItem);
+ }
+ }
+ theArray.arraySizes[0] -= 1;
+ delete[] oldBuf;
+}
+
+void BlastProject::renameGraphicsMaterial(const char* oldName, const char* newName)
+{
+ if (oldName == nullptr || newName == nullptr)
+ return;
+
+ BPPGraphicsMaterialArray& theArray = _projectParams.graphicsMaterials;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(theArray.buf[i].name.buf, oldName) == 0)
+ {
+ copy(theArray.buf[i].name, newName);
+ return;
+ }
+ }
+}
+
+std::vector<BPPAsset*> BlastProject::getSelectedBlastAssets(void)
+{
+ std::vector<BPPAsset*> assets;
+ return assets;
+}
+
+bool BlastProject::isAssetInstanceNameExist(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return false;
+
+ BPPAssetInstanceArray& theArray = _projectParams.blast.composite.blastAssetInstances;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ BPPAssetInstance& item = theArray.buf[i];
+ if (nvidia::shdfnd::strcmp(item.name.buf, name) == 0)
+ return true;
+ }
+ return false;
+}
+
+BPPAssetInstance* BlastProject::getAssetInstance(const char* assetPath, int instanceIndex)
+{
+ if (assetPath == nullptr || strlen(assetPath) == 0 || instanceIndex < 0)
+ {
+ return nullptr;
+ }
+
+ BPPAssetInstanceArray& instanceArray = _projectParams.blast.composite.blastAssetInstances;
+ if (instanceIndex < instanceArray.arraySizes[0])
+ {
+ BPPAssetInstance& assetInstance = instanceArray.buf[instanceIndex];
+ if (nvidia::shdfnd::strcmp(assetPath, assetInstance.source.buf) == 0)
+ return &assetInstance;
+ }
+
+ return nullptr;
+}
+
+BPPAssetInstance* BlastProject::addAssetInstance(int blastAssetIndex, const char* instanceName)
+{
+ if (instanceName == nullptr)
+ return nullptr;
+
+ BPPAssetArray& assetArray = _projectParams.blast.blastAssets;
+ if (blastAssetIndex < 0 && blastAssetIndex > assetArray.arraySizes[0])
+ return nullptr;
+
+ BPPComposite& composite = _projectParams.blast.composite;
+ BPPAssetInstanceArray& theArray = composite.blastAssetInstances;
+
+ BPPAssetInstance* oldBuf = theArray.buf;
+ theArray.buf = new BPPAssetInstance[theArray.arraySizes[0] + 1];
+
+ int i = 0;
+ for (; i < theArray.arraySizes[0]; ++i)
+ {
+ BPPAssetInstance& newItem = theArray.buf[i];
+ BPPAssetInstance& oldItem = oldBuf[i];
+
+ newItem.name.buf = nullptr;
+ newItem.source.buf = nullptr;
+ copy(newItem, oldItem);
+ }
+
+ BPPAssetInstance& newItem = theArray.buf[i];
+ newItem.name.buf = nullptr;
+ newItem.source.buf = nullptr;
+ copy(newItem.name, instanceName);
+ copy(newItem.source, assetArray.buf[blastAssetIndex].path);
+ newItem.visible = true;
+
+ delete[] oldBuf;
+
+ return &newItem;
+}
+
+void BlastProject::removeAssetInstance(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0 || !isAssetInstanceNameExist(name))
+ return;
+
+ BPPAssetInstanceArray& theArray = _projectParams.blast.composite.blastAssetInstances;
+ BPPAssetInstance* oldBuf = theArray.buf;
+
+ theArray.buf = new BPPAssetInstance[theArray.arraySizes[0] - 1];
+ int index = 0;
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(oldBuf[i].name.buf, name) != 0)
+ {
+ BPPAssetInstance& newItem = theArray.buf[index++];
+ BPPAssetInstance& oldItem = oldBuf[i];
+ newItem.name.buf = nullptr;
+ newItem.source.buf = nullptr;
+ copy(newItem, oldItem);
+ }
+ }
+ theArray.arraySizes[0] -= 1;
+ delete[] oldBuf;
+}
+
+BPPChunk* BlastProject::getChunk(BPPAsset& asset, int id)
+{
+ BPPChunkArray& chunkArray = _projectParams.blast.chunks;
+
+ int count = chunkArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPChunk& chunk = chunkArray.buf[i];
+ if (chunk.ID == id && (nvidia::shdfnd::strcmp(chunk.asset.buf, asset.path.buf) == 0))
+ return &chunk;
+ }
+
+ return nullptr;
+}
+
+std::vector<BPPChunk*> BlastProject::getChildrenChunks(BPPAsset& asset, int parentID)
+{
+ std::vector<BPPChunk*> chunks;
+
+ BPPChunkArray& chunkArray = _projectParams.blast.chunks;
+
+ int count = chunkArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPChunk& chunk = chunkArray.buf[i];
+ if (chunk.parentID == parentID && (nvidia::shdfnd::strcmp(chunk.asset.buf, asset.path.buf) == 0))
+ chunks.push_back(&chunk);
+ }
+
+ return chunks;
+}
+
+std::vector<BPPChunk*> BlastProject::getChildrenChunks(BPPAsset& asset)
+{
+ std::vector<BPPChunk*> chunks;
+
+ BPPChunkArray& chunkArray = _projectParams.blast.chunks;
+
+ int count = chunkArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPChunk& chunk = chunkArray.buf[i];
+ if (nvidia::shdfnd::strcmp(chunk.asset.buf, asset.path.buf) == 0)
+ chunks.push_back(&chunk);
+ }
+
+ return chunks;
+}
+
+std::vector<BPPBond*> BlastProject::getBondsByChunk(BPPAsset& asset, int chunkID)
+{
+ std::vector<BPPBond*> bonds;
+ BPPBondArray& bondArray = _projectParams.blast.bonds;
+ int count = bondArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPBond& bond = bondArray.buf[i];
+ if ((nvidia::shdfnd::strcmp(bond.asset.buf, asset.path.buf) == 0))
+ {
+ if (bond.fromChunk == chunkID)
+ bonds.push_back(&bond);
+ else if (bond.toChunk == chunkID)
+ bonds.push_back(&bond);
+ }
+ }
+
+ return bonds;
+}
+
+bool BlastProject::isLandmarkNameExist(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return false;
+
+ BPPLandmarkArray& theArray = _projectParams.blast.composite.landmarks;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ BPPLandmark& item = theArray.buf[i];
+ if (nvidia::shdfnd::strcmp(item.name.buf, name) == 0)
+ return true;
+ }
+ return false;
+}
+
+BPPLandmark* BlastProject::addLandmark(const char* name)
+{
+ if (name == nullptr)
+ return nullptr;
+
+ BPPLandmarkArray& theArray = _projectParams.blast.composite.landmarks;
+ BPPLandmark* oldBuf = theArray.buf;
+ theArray.buf = new BPPLandmark[theArray.arraySizes[0] + 1];
+
+ int i = 0;
+ for (; i < theArray.arraySizes[0]; ++i)
+ {
+ BPPLandmark& newItem = theArray.buf[i];
+ BPPLandmark& oldItem = oldBuf[i];
+
+ newItem.name.buf = nullptr;
+ copy(newItem, oldItem);
+ }
+
+ BPPLandmark& newItem = theArray.buf[i];
+ newItem.name.buf = nullptr;
+ copy(newItem.name, name);
+ newItem.visible = true;
+ newItem.enable = true;
+ newItem.radius = 0.0;
+ theArray.arraySizes[0] += 1;
+
+ delete[] oldBuf;
+
+ return &newItem;
+}
+
+void BlastProject::removeLandmark(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0 || !isLandmarkNameExist(name))
+ return ;
+
+ BPPLandmarkArray& theArray = _projectParams.blast.composite.landmarks;
+ BPPLandmark* oldBuf = theArray.buf;
+
+ theArray.buf = new BPPLandmark[theArray.arraySizes[0] - 1];
+ int index = 0;
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(oldBuf[i].name.buf, name) != 0)
+ {
+ BPPLandmark& newItem = theArray.buf[index++];
+ BPPLandmark& oldItem = oldBuf[i];
+ newItem.name.buf = nullptr;
+ copy(newItem, oldItem);
+ }
+ }
+ theArray.arraySizes[0] -= 1;
+ delete[] oldBuf;
+}
+
+BPPLandmark* BlastProject::getLandmark(const char* name)
+{
+ if (name == nullptr)
+ return nullptr;
+
+ BPPLandmarkArray& theArray = _projectParams.blast.composite.landmarks;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(theArray.buf[i].name.buf, name) == 0)
+ return &theArray.buf[i];
+ }
+
+ return nullptr;
+}
+
+void BlastProject::renameLandmark(const char* oldName, const char* newName)
+{
+ if (oldName == nullptr || newName == nullptr)
+ return ;
+
+ BPPLandmarkArray& theArray = _projectParams.blast.composite.landmarks;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(theArray.buf[i].name.buf, oldName) == 0)
+ {
+ copy(theArray.buf[i].name, newName);
+ return;
+ }
+ }
+}
+
+bool BlastProject::isUserPresetNameExist(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return false;
+
+ for (size_t i = 0; i < _userPresets.size(); ++i)
+ {
+ StressSolverUserPreset& item = _userPresets[i];
+ if (item.name == name)
+ return true;
+ }
+
+ return false;
+}
+
+std::vector<StressSolverUserPreset>& BlastProject::getUserPresets()
+{
+ return _userPresets;
+}
+
+void BlastProject::addUserPreset(const char* name)
+{
+ _userPresets.push_back(StressSolverUserPreset(name));
+}
+
+void BlastProject::saveUserPreset()
+{
+ QFile file(_projectParams.blast.userPreset.buf);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
+ {
+ return;
+ }
+ QTextStream out(&file);
+
+ QDomDocument xmlDoc;
+ QDomElement rootElm = xmlDoc.createElement(QObject::tr("UserPreSet"));
+ xmlDoc.appendChild(rootElm);
+
+ for (size_t i = 0; i < _userPresets.size(); ++i)
+ {
+ _saveStressSolverPreset(rootElm, _userPresets[i]);
+ }
+
+ // 4 is count of indent
+ xmlDoc.save(out, 4);
+}
+
+void BlastProject::loadUserPreset()
+{
+ QFile file(_projectParams.blast.userPreset.buf);
+
+ if (!file.open(QIODevice::ReadOnly))
+ {
+ return;
+ }
+
+ QDomDocument xmlDoc;
+ if (!xmlDoc.setContent(&file))
+ {
+ file.close();
+ return;
+ }
+ file.close();
+
+ if (xmlDoc.isNull() || xmlDoc.documentElement().tagName() != QObject::tr("UserPreSet"))
+ {
+ QMessageBox::warning(&AppMainWindow::Inst(), QObject::tr("Warning"), QObject::tr("The file you selected is empty or not a blast user preset file."));
+ return;
+ }
+
+ QDomNodeList elms = xmlDoc.documentElement().elementsByTagName(QObject::tr("StressSolverPreset"));
+ for (int i = 0; i < elms.count(); ++i)
+ {
+ StressSolverUserPreset preset("");
+ _userPresets.push_back(preset);
+ _loadStressSolverPreset(elms.at(i).toElement(), _userPresets[i]);
+ }
+
+}
+
+bool BlastProject::isFilterPresetNameExist(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return false;
+
+ BPPFilterPresetArray& theArray = _projectParams.filter.filters;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ BPPFilterPreset& item = theArray.buf[i];
+ if (nvidia::shdfnd::strcmp(item.name.buf, name) == 0)
+ return true;
+ }
+ return false;
+}
+
+std::vector<BPPFilterPreset*> BlastProject::getFilterPresets()
+{
+ std::vector<BPPFilterPreset*> presets;
+ return presets;
+}
+
+void BlastProject::addFilterPreset(const char* name)
+{
+ if (name == nullptr)
+ return;
+
+ BPPFilterPresetArray& theArray = _projectParams.filter.filters;
+ BPPFilterPreset* oldBuf = theArray.buf;
+ theArray.buf = new BPPFilterPreset[theArray.arraySizes[0] + 1];
+
+ int i = 0;
+ for (; i < theArray.arraySizes[0]; ++i)
+ {
+ BPPFilterPreset& newItem = theArray.buf[i];
+ BPPFilterPreset& oldItem = oldBuf[i];
+
+ newItem.name.buf = nullptr;
+ newItem.depthFilters.buf = nullptr;
+ newItem.depthFilters.arraySizes[0] = 0;
+ copy(newItem, oldItem);
+ }
+
+ BPPFilterPreset& newItem = theArray.buf[i];
+ newItem.name.buf = nullptr;
+ newItem.depthFilters.buf = nullptr;
+ newItem.depthFilters.arraySizes[0] = 0;
+ copy(newItem.name, name);
+ theArray.arraySizes[0] += 1;
+
+ delete[] oldBuf;
+}
+
+void BlastProject::removeFilterPreset(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0 || !isFilterPresetNameExist(name))
+ return;
+
+ BPPFilterPresetArray& theArray = _projectParams.filter.filters;
+ BPPFilterPreset* oldBuf = theArray.buf;
+
+ theArray.buf = new BPPFilterPreset[theArray.arraySizes[0] - 1];
+ int index = 0;
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(oldBuf[i].name.buf, name) != 0)
+ {
+ BPPFilterPreset& newItem = theArray.buf[index++];
+ BPPFilterPreset& oldItem = oldBuf[i];
+ newItem.name.buf = nullptr;
+ newItem.depthFilters.buf = nullptr;
+ newItem.depthFilters.arraySizes[0] = 0;
+ copy(newItem, oldItem);
+ }
+ }
+ theArray.arraySizes[0] -= 1;
+ delete[] oldBuf;
+}
+
+BPPFilterPreset* BlastProject::getFilterPreset(const char* name)
+{
+ if (name == nullptr)
+ return nullptr;
+
+ BPPFilterPresetArray& theArray = _projectParams.filter.filters;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(theArray.buf[i].name.buf, name) == 0)
+ return &theArray.buf[i];
+ }
+
+ return nullptr;
+}
+
+void BlastProject::renameFilterPreset(const char* oldName, const char* newName)
+{
+ if (oldName == nullptr || newName == nullptr)
+ return;
+
+ BPPFilterPresetArray& theArray = _projectParams.filter.filters;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(theArray.buf[i].name.buf, oldName) == 0)
+ {
+ copy(theArray.buf[i].name, newName);
+ return;
+ }
+ }
+}
+
+void BlastProject::addFilterDepth(const char* filterName, int depth)
+{
+ if (filterName == nullptr || depth < 0)
+ return;
+
+ BPPFilterPresetArray& theArray = _projectParams.filter.filters;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(theArray.buf[i].name.buf, filterName) == 0)
+ {
+ BPPU32Array& depthArray = theArray.buf[i].depthFilters;
+ for (int j = 0; j < depthArray.arraySizes[0]; ++j)
+ {
+ if (depthArray.buf[j] == depth)
+ return;
+ }
+
+ uint32_t* oldBuf = depthArray.buf;
+ depthArray.buf = new uint32_t[theArray.arraySizes[0] + 1];
+
+ int m = 0, n = 0;
+ for (; n < depthArray.arraySizes[0];)
+ {
+ if (oldBuf[n] < depth)
+ {
+ depthArray.buf[m++] = oldBuf[n++];
+ }
+ else
+ {
+ if (m == n)
+ depthArray.buf[m++] = depth;
+ else
+ depthArray.buf[m++] = oldBuf[n++];
+ }
+ }
+
+ if (m == n)
+ {
+ depthArray.buf[m] = depth;
+ }
+ depthArray.arraySizes[0] += 1;
+ return;
+ }
+ }
+}
+
+void BlastProject::removeFilterDepth(const char* filterName, int depth)
+{
+ if (filterName == nullptr || depth < 0)
+ return;
+
+ BPPFilterPresetArray& theArray = _projectParams.filter.filters;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(theArray.buf[i].name.buf, filterName) == 0)
+ {
+ bool foundDepth = false;
+ BPPU32Array& depthArray = theArray.buf[i].depthFilters;
+ for (int j = 0; j < depthArray.arraySizes[0]; ++j)
+ {
+ if (depthArray.buf[j] == depth)
+ {
+ foundDepth = true;
+ break;
+ }
+ }
+
+ if (!foundDepth)
+ return;
+
+ uint32_t* oldBuf = depthArray.buf;
+ depthArray.buf = new uint32_t[theArray.arraySizes[0] - 1];
+
+ int m = 0, n = 0;
+ for (; n < depthArray.arraySizes[0];)
+ {
+ if (oldBuf[n] != depth)
+ {
+ depthArray.buf[m++] = oldBuf[n++];
+ }
+ else
+ {
+ depthArray.buf[m] = depthArray.buf[n++];
+ }
+ }
+
+ depthArray.arraySizes[0] -= 1;
+ return;
+ }
+ }
+}
+
+bool BlastProject::isCutoutTextureNameExist(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return false;
+
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.cutoutProjection.textures;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ NvParameterized::DummyStringStruct& item = theArray.buf[i];
+ if (nvidia::shdfnd::strcmp(item.buf, name) == 0)
+ return true;
+ }
+ return false;
+}
+
+void BlastProject::addCutoutTexture(const char* name)
+{
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.cutoutProjection.textures;
+ _addStringItem(theArray, name);
+}
+
+void BlastProject::removeCutoutTexture(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0 || !isCutoutTextureNameExist(name))
+ return;
+
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.cutoutProjection.textures;
+ _removeStringItem(theArray, name);
+}
+
+bool BlastProject::isPaintMaskNameExist(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return false;
+
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.voronoi.paintMasks;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ NvParameterized::DummyStringStruct& item = theArray.buf[i];
+ if (nvidia::shdfnd::strcmp(item.buf, name) == 0)
+ return true;
+ }
+ return false;
+}
+
+void BlastProject::addPaintMasks(const char* name)
+{
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.voronoi.paintMasks;
+ _addStringItem(theArray, name);
+}
+
+void BlastProject::removePaintMasks(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0 || !isPaintMaskNameExist(name))
+ return;
+
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.voronoi.paintMasks;
+ _removeStringItem(theArray, name);
+}
+
+bool BlastProject::isMeshCutterNameExist(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return false;
+
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.voronoi.meshCutters;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ NvParameterized::DummyStringStruct& item = theArray.buf[i];
+ if (nvidia::shdfnd::strcmp(item.buf, name) == 0)
+ return true;
+ }
+ return false;
+}
+
+void BlastProject::addMeshCutter(const char* name)
+{
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.voronoi.meshCutters;
+ _addStringItem(theArray, name);
+}
+
+void BlastProject::removeMeshCutter(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0 || !isMeshCutterNameExist(name))
+ return;
+
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.voronoi.meshCutters;
+ _removeStringItem(theArray, name);
+}
+
+bool BlastProject::isVoronoiTextureNameExist(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return false;
+
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.voronoi.textureSites;
+
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ NvParameterized::DummyStringStruct& item = theArray.buf[i];
+ if (nvidia::shdfnd::strcmp(item.buf, name) == 0)
+ return true;
+ }
+ return false;
+}
+
+void BlastProject::addVoronoiTexture(const char* name)
+{
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.voronoi.textureSites;
+ _addStringItem(theArray, name);
+}
+
+void BlastProject::removeVoronoiTexture(const char* name)
+{
+ if (name == nullptr || strlen(name) == 0 || !isVoronoiTextureNameExist(name))
+ return;
+
+ BPPStringArray& theArray = BlastProject::ins().getParams().fracture.voronoi.textureSites;
+ _removeStringItem(theArray, name);
+}
+
+BlastProject::BlastProject()
+{
+ _projectParams.cameraBookmarks.buf = nullptr;
+ _projectParams.cameraBookmarks.arraySizes[0] = 0;
+
+ _projectParams.graphicsMaterials.buf = nullptr;
+ _projectParams.graphicsMaterials.arraySizes[0] = 0;
+
+ _projectParams.renderer.textureFilePath.buf = nullptr;
+
+ _projectParams.renderer.lights.buf = new BPPLight[4];
+ _projectParams.renderer.lights.arraySizes[0] = 4;
+
+ for (int i = 0; i < 4; ++i)
+ {
+ _projectParams.renderer.lights.buf[i].name.buf = nullptr;
+ }
+
+ _projectParams.blast.fileReferences.blast.buf = nullptr;
+ _projectParams.blast.fileReferences.fbx.buf = nullptr;
+ _projectParams.blast.fileReferences.fbxSourceAsset.buf = nullptr;
+ _projectParams.blast.fileReferences.collision.buf = nullptr;
+
+ _projectParams.blast.composite.composite.buf = nullptr;
+ _projectParams.blast.composite.blastAssetInstances.buf = nullptr;
+ _projectParams.blast.composite.blastAssetInstances.arraySizes[0] = 0;
+
+ _projectParams.blast.composite.landmarks.buf = nullptr;
+ _projectParams.blast.composite.landmarks.arraySizes[0] = 0;
+
+ _projectParams.blast.blastAssets.buf = nullptr;
+ _projectParams.blast.blastAssets.arraySizes[0] = 0;
+
+ _projectParams.blast.projectiles.buf = nullptr;
+ _projectParams.blast.projectiles.arraySizes[0] = 0;
+
+ _projectParams.blast.graphicsMeshes.buf = nullptr;
+ _projectParams.blast.graphicsMeshes.arraySizes[0] = 0;
+
+ _projectParams.blast.userPreset.buf = nullptr;
+ _projectParams.blast.healthMask.buf = nullptr;
+
+ _projectParams.filter.filters.buf = nullptr;
+ _projectParams.filter.filters.arraySizes[0] = 0;
+
+ _projectParams.fracture.voronoi.paintMasks.buf = nullptr;
+ _projectParams.fracture.voronoi.paintMasks.arraySizes[0] = 0;
+
+ _projectParams.fracture.voronoi.meshCutters.buf = nullptr;
+ _projectParams.fracture.voronoi.meshCutters.arraySizes[0] = 0;
+
+ _projectParams.fracture.voronoi.textureSites.buf = nullptr;
+ _projectParams.fracture.voronoi.textureSites.arraySizes[0] = 0;
+
+ _projectParams.fracture.cutoutProjection.textures.buf = nullptr;
+ _projectParams.fracture.cutoutProjection.textures.arraySizes[0] = 0;
+}
+
+void BlastProject::_saveStressSolverPreset(QDomElement& parentElm, StressSolverUserPreset& stressSolverUserPreset)
+{
+ QDomElement newElm = parentElm.ownerDocument().createElement(QObject::tr("StressSolverPreset"));
+ parentElm.appendChild(newElm);
+ newElm.setAttribute(QObject::tr("Name"), stressSolverUserPreset.name.c_str());
+ _saveStressSolver(newElm, stressSolverUserPreset.stressSolver);
+}
+
+void BlastProject::_saveStressSolver(QDomElement& parentElm, BPPStressSolver& stressSolver)
+{
+ QDomElement newElm = parentElm.ownerDocument().createElement(QObject::tr("StressSolver"));
+ parentElm.appendChild(newElm);
+ newElm.setAttribute(QObject::tr("SolverMode"), stressSolver.solverMode);
+ newElm.setAttribute(QObject::tr("LinearFactor"), stressSolver.linearFactor);
+ newElm.setAttribute(QObject::tr("AngularFactor"), stressSolver.angularFactor);
+ newElm.setAttribute(QObject::tr("MeanError"), stressSolver.meanError);
+ newElm.setAttribute(QObject::tr("VarianceError"), stressSolver.varianceError);
+ newElm.setAttribute(QObject::tr("BondsPerFrame"), stressSolver.bondsPerFrame);
+ newElm.setAttribute(QObject::tr("BondsIterations"), stressSolver.bondsIterations);
+}
+
+void BlastProject::_loadStressSolverPreset(QDomElement& parentElm, StressSolverUserPreset& stressSolverUserPreset)
+{
+ stressSolverUserPreset.name = parentElm.attribute(QObject::tr("Name")).toUtf8().data();
+
+ QDomElement stressSolverElm = parentElm.firstChildElement(QObject::tr("StressSolver"));
+ _loadStressSolver(stressSolverElm, stressSolverUserPreset.stressSolver);
+}
+
+void BlastProject::_loadStressSolver(QDomElement& parentElm, BPPStressSolver& stressSolver)
+{
+ stressSolver.solverMode = parentElm.attribute(QObject::tr("SolverMode")).toInt();
+ stressSolver.linearFactor = parentElm.attribute(QObject::tr("LinearFactor")).toFloat();
+ stressSolver.angularFactor = parentElm.attribute(QObject::tr("AngularFactor")).toFloat();
+ stressSolver.meanError = parentElm.attribute(QObject::tr("MeanError")).toFloat();
+ stressSolver.varianceError = parentElm.attribute(QObject::tr("VarianceError")).toFloat();
+ stressSolver.bondsPerFrame = parentElm.attribute(QObject::tr("BondsPerFrame")).toUInt();
+ stressSolver.bondsIterations = parentElm.attribute(QObject::tr("BondsIterations")).toUInt();
+}
+
+void BlastProject::_addStringItem(BPPStringArray& theArray, const char* name)
+{
+ if (name == nullptr)
+ return;
+
+ NvParameterized::DummyStringStruct* oldBuf = theArray.buf;
+ theArray.buf = new NvParameterized::DummyStringStruct[theArray.arraySizes[0] + 1];
+
+ int i = 0;
+ for (; i < theArray.arraySizes[0]; ++i)
+ {
+ NvParameterized::DummyStringStruct& newItem = theArray.buf[i];
+ NvParameterized::DummyStringStruct& oldItem = oldBuf[i];
+ newItem.buf = nullptr;
+ copy(newItem, oldItem);
+ }
+
+ NvParameterized::DummyStringStruct& newItem = theArray.buf[i];
+ newItem.buf = nullptr;
+ copy(newItem, name);
+ theArray.arraySizes[0] += 1;
+
+ delete[] oldBuf;
+}
+
+void BlastProject::_removeStringItem(BPPStringArray& theArray, const char* name)
+{
+ if (name == nullptr || strlen(name) == 0)
+ return;
+
+ bool nameExist = false;
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ NvParameterized::DummyStringStruct& item = theArray.buf[i];
+ if (nvidia::shdfnd::strcmp(item.buf, name) == 0)
+ {
+ nameExist = true;
+ break;
+ }
+ }
+
+ if (!nameExist)
+ return;
+
+ NvParameterized::DummyStringStruct* oldBuf = theArray.buf;
+
+ theArray.buf = new NvParameterized::DummyStringStruct[theArray.arraySizes[0] - 1];
+ int index = 0;
+ for (int i = 0; i < theArray.arraySizes[0]; ++i)
+ {
+ if (nvidia::shdfnd::strcmp(oldBuf[i].buf, name) != 0)
+ {
+ NvParameterized::DummyStringStruct& newItem = theArray.buf[index++];
+ NvParameterized::DummyStringStruct& oldItem = oldBuf[i];
+ newItem.buf = nullptr;
+ copy(newItem, oldItem);
+ }
+ }
+ theArray.arraySizes[0] -= 1;
+ delete[] oldBuf;
+}
+
+static bool LoadParamVec2Array(NvParameterized::Interface* iface,
+ const char* paramName,
+ nvidia::NvVec2** outValue)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ int arraySize;
+ handle.getArraySize(arraySize);
+ *outValue = new nvidia::NvVec2[arraySize];
+ handle.getParamVec2Array((nvidia::NvVec2*)*outValue, arraySize);
+ return true;
+ }
+ return false;
+}
+
+static bool LoadParamVec3Array(NvParameterized::Interface* iface,
+ const char* paramName,
+ nvidia::NvVec3** outValue)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ int arraySize;
+ handle.getArraySize(arraySize);
+ *outValue = new nvidia::NvVec3[arraySize];
+ handle.getParamVec3Array((nvidia::NvVec3*)*outValue, arraySize);
+ return true;
+ }
+ return false;
+}
+
+static bool LoadParamVec4Array(NvParameterized::Interface* iface,
+ const char* paramName,
+ nvidia::NvVec4** outValue)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ int arraySize;
+ handle.getArraySize(arraySize);
+ *outValue = new nvidia::NvVec4[arraySize];
+ handle.getParamVec4Array((nvidia::NvVec4*)*outValue, arraySize);
+ return true;
+ }
+ return false;
+}
+
+static bool LoadParamU8Array(NvParameterized::Interface* iface,
+ const char* paramName,
+ NvUInt8** outValue)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ int arraySize;
+ handle.getArraySize(arraySize);
+ *outValue = new NvUInt8[arraySize];
+ handle.getParamU8Array((NvUInt8*)*outValue, arraySize);
+ return true;
+ }
+ return false;
+}
+
+static bool LoadParamU32Array(NvParameterized::Interface* iface,
+ const char* paramName,
+ NvUInt32** outValue)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ int arraySize;
+ handle.getArraySize(arraySize);
+ *outValue = new NvUInt32[arraySize];
+ handle.getParamU32Array((NvUInt32*)*outValue, arraySize);
+ return true;
+ }
+ return false;
+}
+
+static bool LoadParamString(NvParameterized::Interface* iface,
+ const char* paramName,
+ char* outString)
+{
+ if (outString == NV_NULL)
+ {
+ return false;
+ }
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ const char* var;
+ handle.getParamString(var);
+ if (var)
+ {
+ strcpy(outString, var);
+ }
+ else
+ {
+ outString[0] = '\0';
+ }
+ return true;
+ }
+ return false;
+}
+
+static bool SaveParamVec2Array(NvParameterized::Interface* iface,
+ const char* paramName,
+ const nvidia::NvVec2* value,
+ int arraySize)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ handle.resizeArray(arraySize);
+ handle.setParamVec2Array((nvidia::NvVec2*)value, arraySize);
+ return true;
+ }
+ return false;
+}
+
+static bool SaveParamVec3Array(NvParameterized::Interface* iface,
+ const char* paramName,
+ const nvidia::NvVec3* value,
+ int arraySize)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ handle.resizeArray(arraySize);
+ handle.setParamVec3Array((nvidia::NvVec3*)value, arraySize);
+ return true;
+ }
+ return false;
+}
+
+static bool SaveParamVec4Array(NvParameterized::Interface* iface,
+ const char* paramName,
+ const nvidia::NvVec4* value,
+ int arraySize)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ handle.resizeArray(arraySize);
+ handle.setParamVec4Array((nvidia::NvVec4*)value, arraySize);
+ return true;
+ }
+ return false;
+}
+
+static bool SaveParamU8Array(NvParameterized::Interface* iface,
+ const char* paramName,
+ const NvUInt8* value,
+ int arraySize)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ handle.resizeArray(arraySize);
+ handle.setParamU8Array((NvUInt8*)value, arraySize);
+ return true;
+ }
+ return false;
+}
+
+static bool SaveParamU32Array(NvParameterized::Interface* iface,
+ const char* paramName,
+ const NvUInt32* value,
+ int arraySize)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ handle.resizeArray(arraySize);
+ handle.setParamU32Array((NvUInt32*)value, arraySize);
+ return true;
+ }
+ return false;
+}
+
+static bool SaveParamString(NvParameterized::Interface* iface,
+ const char* paramName,
+ const char* inString)
+{
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle(paramName, handle) == NvParameterized::ERROR_NONE)
+ {
+ handle.setParamString(inString);
+ return true;
+ }
+ return false;
+}
+
+bool CreateProjectParamsContext()
+{
+ FoundationHolder::GetFoundation();
+
+ ProjectParamsContext* context = new ProjectParamsContext;
+ g_projectParamsContext = context;
+ if (context == nullptr)
+ return false;
+
+ //context->mFoundation = FoundationHolder::GetFoundation();
+ //assert(context->mFoundation != NV_NULL);
+ context->mTraits = NvParameterized::createTraits();
+ context->mBlastProjectParametersFactory = new BlastProjectParametersFactory;
+ context->mTraits->registerFactory(*context->mBlastProjectParametersFactory);
+ return true;
+}
+
+void ReleaseProjectParamsContext()
+{
+ g_projectParamsContext->mTraits->release();
+ delete g_projectParamsContext->mBlastProjectParametersFactory;
+ delete g_projectParamsContext;
+}
+
+bool ProjectParamsLoad(const char* filePath,
+ SimpleScene* scene)
+{
+ if (g_projectParamsContext == NV_NULL) return false;
+ NvFileBuf* stream = new NvFileBufferBase(filePath, NvFileBuf::OPEN_READ_ONLY);
+ if (!stream || !stream->isOpen())
+ {
+ // file open error
+ if (stream) stream->release();
+ return false;
+ }
+ NvParameterized::Serializer::DeserializedData data;
+ NvParameterized::Serializer::ErrorType serError = NvParameterized::Serializer::ERROR_NONE;
+ NvParameterized::XmlSerializer serializer(g_projectParamsContext->mTraits);
+ bool isUpdated;
+ serError = serializer.deserialize(*stream, data, isUpdated);
+ if (data.size() < 1)
+ {
+ if (stream) stream->release();
+ return false;
+ }
+
+ scene->Clear();
+
+ for (int idx = 0; idx < (int)data.size(); ++idx) {
+ NvParameterized::Interface* iface = data[idx];
+ if (::strcmp(iface->className(), BlastProjectParameters::staticClassName()) == 0)
+ {
+ scene->LoadParameters(iface);
+ }
+ }
+ stream->release();
+ return true;
+}
+
+bool ProjectParamsSave(const char* filePath,
+ SimpleScene* scene)
+{
+ if (g_projectParamsContext == NV_NULL) return false;
+ NvParameterized::XmlSerializer serializer(g_projectParamsContext->mTraits);
+ NvFileBuf* stream = new NvFileBufferBase(filePath, NvFileBuf::OPEN_WRITE_ONLY);
+ if (!stream || !stream->isOpen())
+ {
+ // file open error
+ if (stream) stream->release();
+ return false;
+ }
+ NvParameterized::Traits* traits = g_projectParamsContext->mTraits;
+ int numObjects = 0;
+ const int kMaxObjects = 1;
+ NvParameterized::Interface* objects[kMaxObjects];
+
+ if (1)
+ {
+ BlastProjectParameters* params = new BlastProjectParameters(traits);
+ objects[numObjects++] = params;
+ NvParameterized::Interface* iface = static_cast<NvParameterized::Interface*>(params);
+ scene->SaveParameters(iface);
+ }
+
+ NV_ASSERT(numObjects <= kMaxObjects);
+ NvParameterized::Serializer::ErrorType serError = NvParameterized::Serializer::ERROR_NONE;
+ bool isUpdate = false;
+ serError = serializer.serialize(*stream, (const NvParameterized::Interface**)&objects[0], numObjects, isUpdate);
+ //for (int idx = 0; idx < numObjects; ++idx)
+ //{
+ // delete objects[idx];
+ //}
+ stream->release();
+ return true;
+}
+
+// Utility function to get the child parameter handle from the parent handle.
+bool ParamGetChild(NvParameterized::Handle& parentHandle, NvParameterized::Handle& outChildHandle, const char* childName)
+{
+ if (parentHandle.getChildHandle(parentHandle.getInterface(), childName, outChildHandle) == NvParameterized::ERROR_NONE)
+ {
+ return true;
+ }
+ return false;
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/ProjectParams.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/ProjectParams.h
new file mode 100644
index 0000000..fa7adf7
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Parameters/ProjectParams.h
@@ -0,0 +1,210 @@
+#pragma once
+
+#include "BlastProjectParameters.h"
+#include <QtCore/QVector>
+
+class QDomElement;
+
+typedef nvidia::parameterized::BlastProjectParametersNS::ParametersStruct BPParams;
+typedef nvidia::parameterized::BlastProjectParametersNS::GraphicsMaterial_Type BPPGraphicsMaterial;
+typedef nvidia::parameterized::BlastProjectParametersNS::MaterialAssignments_Type BPPMaterialAssignments;
+typedef nvidia::parameterized::BlastProjectParametersNS::GraphicsMesh_Type BPPGraphicsMesh;
+typedef nvidia::parameterized::BlastProjectParametersNS::Light_Type BPPLight;
+typedef nvidia::parameterized::BlastProjectParametersNS::Camera_Type BPPCamera;
+typedef nvidia::parameterized::BlastProjectParametersNS::CameraBookmark_Type BPPCameraBookmark;
+typedef nvidia::parameterized::BlastProjectParametersNS::Scene_Type BPPScene;
+typedef nvidia::parameterized::BlastProjectParametersNS::Renderer_Type BPPRenderer;
+typedef nvidia::parameterized::BlastProjectParametersNS::BlastFileReferences_Type BPPFileReferences;
+typedef nvidia::parameterized::BlastProjectParametersNS::StressSolver_Type BPPStressSolver;
+typedef nvidia::parameterized::BlastProjectParametersNS::SupportStructure_Type BPPSupportStructure;
+typedef nvidia::parameterized::BlastProjectParametersNS::Bond_Type BPPBond;
+typedef nvidia::parameterized::BlastProjectParametersNS::Chunk_Type BPPChunk;
+typedef nvidia::parameterized::BlastProjectParametersNS::DefaultDamage_Type BPPDefaultDamage;
+typedef nvidia::parameterized::BlastProjectParametersNS::BlastAsset_Type BPPAsset;
+typedef nvidia::parameterized::BlastProjectParametersNS::BlastAssetInstance_Type BPPAssetInstance;
+typedef nvidia::parameterized::BlastProjectParametersNS::Projectile_Type BPPProjectile;
+typedef nvidia::parameterized::BlastProjectParametersNS::Landmark_Type BPPLandmark;
+typedef nvidia::parameterized::BlastProjectParametersNS::BlastComposite_Type BPPComposite;
+typedef nvidia::parameterized::BlastProjectParametersNS::Blast_Type BPPBlast;
+typedef nvidia::parameterized::BlastProjectParametersNS::FractureGeneral_Type BPPFractureGeneral;
+typedef nvidia::parameterized::BlastProjectParametersNS::FractureVisualization_Type BPPFractureVisualization;
+typedef nvidia::parameterized::BlastProjectParametersNS::ShellCut_Type BPPShellCut;
+typedef nvidia::parameterized::BlastProjectParametersNS::Voronoi_Type BPPVoronoi;
+typedef nvidia::parameterized::BlastProjectParametersNS::Slice_Type BPPSlice;
+typedef nvidia::parameterized::BlastProjectParametersNS::CutoutProjection_Type BPPCutoutProjection;
+typedef nvidia::parameterized::BlastProjectParametersNS::Fracture_Type BPPFracture;
+typedef nvidia::parameterized::BlastProjectParametersNS::FilterPreset_Type BPPFilterPreset;
+typedef nvidia::parameterized::BlastProjectParametersNS::Filter_Type BPPFilter;
+
+typedef nvidia::parameterized::BlastProjectParametersNS::CameraBookmark_DynamicArray1D_Type BPPBookmarkArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::STRING_DynamicArray1D_Type BPPStringArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::GraphicsMaterial_DynamicArray1D_Type BPPGraphicsMaterialArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::GraphicsMesh_DynamicArray1D_Type BPPGraphicsMeshArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::Light_DynamicArray1D_Type BPPLightArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::Chunk_DynamicArray1D_Type BPPChunkArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::Bond_DynamicArray1D_Type BPPBondArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::Projectile_DynamicArray1D_Type BPPProjectileArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::BlastAsset_DynamicArray1D_Type BPPAssetArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::BlastAssetInstance_DynamicArray1D_Type BPPAssetInstanceArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::Landmark_DynamicArray1D_Type BPPLandmarkArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::FilterPreset_DynamicArray1D_Type BPPFilterPresetArray;
+typedef nvidia::parameterized::BlastProjectParametersNS::U32_DynamicArray1D_Type BPPU32Array;
+
+void freeString(NvParameterized::DummyStringStruct& str);
+void freeBlast(BPPGraphicsMesh& data);
+void freeBlast(BPPChunk& data);
+void freeBlast(BPPBond& data);
+void freeBlast(BPPAsset& data);
+void freeBlast(BPPAssetInstance& data);
+void freeBlast(BPPComposite& data);
+void freeBlast(BPPBlast& data);
+void freeBlast(BPPLandmark& data);
+
+void freeBlast(BPPStringArray& data);
+void freeBlast(BPPGraphicsMeshArray& data);
+void freeBlast(BPPChunkArray& data);
+void freeBlast(BPPBondArray& data);
+void freeBlast(BPPAssetArray& data);
+void freeBlast(BPPAssetInstanceArray& data);
+void freeBlast(BPPLandmarkArray& data);
+
+void copy(NvParameterized::DummyStringStruct& dest, const char* source);
+void copy(NvParameterized::DummyStringStruct& dest, NvParameterized::DummyStringStruct& source);
+void copy(BPPStringArray& dest, BPPStringArray& source);
+void copy(BPPGraphicsMaterialArray& dest, BPPGraphicsMaterialArray& source);
+void copy(BPPGraphicsMeshArray& dest, BPPGraphicsMeshArray& source);
+void copy(BPPBookmarkArray& dest, BPPBookmarkArray& source);
+void copy(BPPLightArray& dest, BPPLightArray& source);
+void copy(BPPChunkArray& dest, BPPChunkArray& source);
+void copy(BPPBondArray& dest, BPPBondArray& source);
+void copy(BPPProjectileArray& dest, BPPProjectileArray& source);
+void copy(BPPAssetArray& dest, BPPAssetArray& source);
+void copy(BPPAssetInstanceArray& dest, BPPAssetInstanceArray& source);
+void copy(BPPLandmarkArray& dest, BPPLandmarkArray& source);
+void copy(BPPU32Array& dest, BPPU32Array& source);
+void copy(BPPFilterPresetArray& dest, BPPFilterPresetArray& source);
+
+void copy(BPPLight& dest, BPPLight& source);
+void copy(BPPRenderer& dest, BPPRenderer& source);
+void copy(BPPGraphicsMaterial& dest, BPPGraphicsMaterial& source);
+void copy(BPPGraphicsMesh& dest, BPPGraphicsMesh& source);
+void copy(BPPMaterialAssignments& dest, BPPMaterialAssignments& source);
+void copy(BPPChunk& dest, BPPChunk& source);
+void copy(BPPBond& dest, BPPBond& source);
+void copy(BPPProjectile& dest, BPPProjectile& source);
+void copy(BPPSupportStructure& dest, BPPSupportStructure& source);
+void copy(BPPLandmark& dest, BPPLandmark& source);
+void copy(BPPStressSolver& dest, BPPStressSolver& source);
+void copy(BPPAsset& dest, BPPAsset& source);
+void copy(BPPAssetInstance& dest, BPPAssetInstance& source);
+void copy(BPPComposite& dest, BPPComposite& source);
+void copy(BPPBlast& dest, BPPBlast& source);
+void copy(BPPFilter& dest, BPPFilter& source);
+void copy(BPPVoronoi& dest, BPPVoronoi& source);
+void copy(BPPCutoutProjection& dest, BPPCutoutProjection& source);
+void copy(BPPFracture& dest, BPPFracture& source);
+void copy(BPPFilterPreset& dest, BPPFilterPreset& source);
+void copy(BPParams& dest, BPParams& source);
+
+void merge(BPPChunkArray& dest, BPPChunkArray& source);
+void merge(BPPBondArray& dest, BPPBondArray& source);
+
+void init(BPPStressSolver& param);
+void init(BPPGraphicsMaterial& param);
+void init(BPParams& params);
+
+struct StressSolverUserPreset
+{
+ StressSolverUserPreset(const char* inName);
+ std::string name;
+ BPPStressSolver stressSolver;
+};
+
+class BlastProject
+{
+public:
+
+ static BlastProject& ins();
+ ~BlastProject();
+
+ BPParams& getParams() { return _projectParams; }
+
+ void clear();
+
+ bool isGraphicsMaterialNameExist(const char* name);
+ BPPGraphicsMaterial* addGraphicsMaterial(const char* name, const char* diffuseTexture);
+ void removeGraphicsMaterial(const char* name);
+ void renameGraphicsMaterial(const char* oldName, const char* newName);
+
+ std::vector<BPPAsset*> getSelectedBlastAssets(void);
+
+ bool isAssetInstanceNameExist(const char* name);
+ BPPAssetInstance* getAssetInstance(const char* assetPath, int instanceIndex);
+ BPPAssetInstance* addAssetInstance(int blastAssetIndex, const char* instanceName);
+ void removeAssetInstance(const char* name);
+
+ BPPChunk* getChunk(BPPAsset& asset, int id);
+ std::vector<BPPChunk*> getChildrenChunks(BPPAsset& asset, int parentID);
+ std::vector<BPPChunk*> getChildrenChunks(BPPAsset& asset);
+ std::vector<BPPBond*> getBondsByChunk(BPPAsset& asset, int chunkID);
+
+ bool isLandmarkNameExist(const char* name);
+ BPPLandmark* addLandmark(const char* name);
+ void removeLandmark(const char* name);
+ BPPLandmark* getLandmark(const char* name);
+ void renameLandmark(const char* oldName, const char* newName);
+
+ bool isUserPresetNameExist(const char* name);
+ std::vector<StressSolverUserPreset>& getUserPresets();
+ void addUserPreset(const char* name);
+ void saveUserPreset();
+ void loadUserPreset();
+
+ bool isFilterPresetNameExist(const char* name);
+ std::vector<BPPFilterPreset*> getFilterPresets();
+ void addFilterPreset(const char* name);
+ void removeFilterPreset(const char* name);
+ BPPFilterPreset* getFilterPreset(const char* name);
+ void renameFilterPreset(const char* oldName, const char* newName);
+ void addFilterDepth(const char* filterName, int depth);
+ void removeFilterDepth(const char* filterName, int depth);
+
+ bool isCutoutTextureNameExist(const char* name);
+ void addCutoutTexture(const char* name);
+ void removeCutoutTexture(const char* name);
+
+ bool isPaintMaskNameExist(const char* name);
+ void addPaintMasks(const char* name);
+ void removePaintMasks(const char* name);
+
+ bool isMeshCutterNameExist(const char* name);
+ void addMeshCutter(const char* name);
+ void removeMeshCutter(const char* name);
+
+ bool isVoronoiTextureNameExist(const char* name);
+ void addVoronoiTexture(const char* name);
+ void removeVoronoiTexture(const char* name);
+
+private:
+ BlastProject();
+ void _saveStressSolverPreset(QDomElement& parentElm, StressSolverUserPreset& stressSolverUserPreset);
+ void _saveStressSolver(QDomElement& parentElm, BPPStressSolver& stressSolver);
+ void _loadStressSolverPreset(QDomElement& parentElm, StressSolverUserPreset& stressSolverUserPreset);
+ void _loadStressSolver(QDomElement& parentElm, BPPStressSolver& stressSolver);
+
+ void _addStringItem(BPPStringArray& theArray, const char* name);
+ void _removeStringItem(BPPStringArray& theArray, const char* name);
+
+private:
+ BPParams _projectParams;
+ std::vector<StressSolverUserPreset> _userPresets;
+};
+
+bool CreateProjectParamsContext();
+void ReleaseProjectParamsContext();
+bool ProjectParamsLoad(const char* filePath,
+ class SimpleScene* scene);
+bool ProjectParamsSave(const char* filePath,
+ class SimpleScene* scene);
+
+bool ParamGetChild(NvParameterized::Handle& parentHandle, NvParameterized::Handle& outChildHandle, const char* childName);
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D11/PluginBlastDx11.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D11/PluginBlastDx11.cpp
new file mode 100644
index 0000000..1c37502
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D11/PluginBlastDx11.cpp
@@ -0,0 +1,23 @@
+#include "PluginBlastDx11.h"
+#include "D3D11RenderShader.h"
+#include "D3D11RenderInterface.h"
+#include "LightShaderParam.h"
+
+PluginBlast* CreateRenderBlast(void)
+{
+ return new PluginBlastDx11;
+}
+
+PluginBlastDx11::PluginBlastDx11()
+{
+}
+
+PluginBlastDx11::~PluginBlastDx11()
+{
+}
+
+// D3D11Shaders
+bool PluginBlastDx11::D3D11Shaders_InitializeShadersD3D11(std::map<int, D3D11RenderShader*>& ShaderMap)
+{
+ return true;
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D11/PluginBlastDx11.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D11/PluginBlastDx11.h
new file mode 100644
index 0000000..ed9dbe1
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D11/PluginBlastDx11.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "PluginBlast.h"
+
+extern "C" PLUGINBTRENDER_EXPORT PluginBlast* CreateRenderBlast(void);
+
+class PluginBlastDx11 : public PluginBlast
+{
+public:
+ PluginBlastDx11();
+ ~PluginBlastDx11();
+
+ // D3D11Shaders
+ virtual bool D3D11Shaders_InitializeShadersD3D11(std::map<int, D3D11RenderShader*>& ShaderMap);
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D12/PluginBlastDx12.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D12/PluginBlastDx12.cpp
new file mode 100644
index 0000000..670f17b
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D12/PluginBlastDx12.cpp
@@ -0,0 +1,20 @@
+#include "PluginBlastDx12.h"
+
+PluginBlast* CreateRenderBlast(void)
+{
+ return new PluginBlastDx12;
+}
+
+PluginBlastDx12::PluginBlastDx12()
+{
+}
+
+PluginBlastDx12::~PluginBlastDx12()
+{
+}
+
+// D3D11Shaders
+bool PluginBlastDx12::D3D11Shaders_InitializeShadersD3D11(std::map<int, D3D11RenderShader*>& ShaderMap)
+{
+ return true;
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D12/PluginBlastDx12.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D12/PluginBlastDx12.h
new file mode 100644
index 0000000..fab6b4e
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/D3D12/PluginBlastDx12.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "PluginBlast.h"
+
+extern "C" PLUGINBTRENDER_EXPORT PluginBlast* CreateRenderBlast(void);
+
+class PluginBlastDx12 : public PluginBlast
+{
+public:
+ PluginBlastDx12();
+ ~PluginBlastDx12();
+
+ // D3D11Shaders
+ virtual bool D3D11Shaders_InitializeShadersD3D11(std::map<int, D3D11RenderShader*>& ShaderMap);
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/Interface/PluginBlast.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/Interface/PluginBlast.cpp
new file mode 100644
index 0000000..3a9c9c9
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/Interface/PluginBlast.cpp
@@ -0,0 +1,69 @@
+#include "PluginBlast.h"
+
+PluginBlast* g_Plugin = nullptr;
+
+PluginBlast::PluginBlast()
+{
+}
+
+PluginBlast::~PluginBlast()
+{
+}
+
+typedef PluginBlast*(*Func)(void);
+
+bool PluginBlast::Create(std::string strApi)
+{
+ if ("" == strApi)
+ return false;
+
+ std::string pluginDll = "";
+ HMODULE module = NULL;
+ Func CreateFunc = NULL;
+
+#ifdef NV_ARTISTTOOLS
+ pluginDll = "RenderBlast";
+#else
+ pluginDll = "FurRender";
+#endif
+
+ pluginDll.append(strApi);
+
+#ifdef _WIN64
+ pluginDll.append(".win64");
+#else
+ pluginDll.append(".win32");
+#endif
+
+#ifdef _DEBUG
+ pluginDll.append(".d");
+#else
+#endif
+
+ pluginDll.append(".dll");
+
+ module = LoadLibraryA(pluginDll.c_str());
+ if (NULL == module)
+ return false;
+
+ CreateFunc = (Func)GetProcAddress(module, "CreateRenderBlast");
+ if (NULL == CreateFunc)
+ return false;
+
+ g_Plugin = CreateFunc();
+ return (NULL != g_Plugin);
+}
+
+PluginBlast* PluginBlast::Instance()
+{
+ return g_Plugin;
+}
+
+void PluginBlast::Destroy()
+{
+ if (nullptr == g_Plugin)
+ return;
+
+ delete g_Plugin;
+ g_Plugin = nullptr;
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/Interface/PluginBlast.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/Interface/PluginBlast.h
new file mode 100644
index 0000000..a67fd89
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Render/Interface/PluginBlast.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "RenderPlugin.h"
+#include "blastplugin_global.h"
+
+class PLUGINBT_EXPORT PluginBlast
+{
+public:
+ static bool Create(std::string api);
+ static PluginBlast* Instance();
+ static void Destroy();
+
+ ~PluginBlast();
+
+ // D3D11Shaders
+ virtual bool D3D11Shaders_InitializeShadersD3D11(std::map<int, D3D11RenderShader*>& ShaderMap) = 0;
+
+protected:
+ PluginBlast();
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/Sample.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/Sample.h
new file mode 100644
index 0000000..c9fa503
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/Sample.h
@@ -0,0 +1,95 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SAMPLE_H
+#define SAMPLE_H
+
+#include "PxTransform.h"
+#include <string>
+#include <vector>
+
+
+struct AssetList
+{
+ struct BoxAsset
+ {
+ BoxAsset() : staticHeight(-std::numeric_limits<float>().infinity()),
+ jointAllBonds(false), extents(20, 20, 20)
+ {}
+
+ struct Level
+ {
+ Level() :x(0), y(0), z(0), isSupport(0) {};
+
+ int x, y, z;
+ bool isSupport;
+ };
+
+ std::string id;
+ std::string name;
+ physx::PxVec3 extents;
+ float staticHeight;
+ bool jointAllBonds;
+ std::vector<Level> levels;
+ };
+
+ struct ModelAsset
+ {
+ ModelAsset() : isSkinned(false), transform(physx::PxIdentity)
+ {}
+
+ std::string id;
+ std::string file;
+ std::string name;
+ physx::PxTransform transform;
+ bool isSkinned;
+ };
+
+ struct CompositeAsset
+ {
+ CompositeAsset() : transform(physx::PxIdentity)
+ {}
+
+ struct AssetRef
+ {
+ std::string id;
+ physx::PxTransform transform;
+ };
+
+ struct Joint
+ {
+ int32_t assetIndices[2];
+ uint32_t chunkIndices[2];
+ physx::PxVec3 attachPositions[2];
+ };
+
+ std::string id;
+ std::string name;
+ physx::PxTransform transform;
+ std::vector<AssetRef> assetRefs;
+ std::vector<Joint> joints;
+ };
+
+ std::vector<ModelAsset> models;
+ std::vector<CompositeAsset> composites;
+ std::vector<BoxAsset> boxes;
+};
+
+struct SampleConfig
+{
+ std::wstring sampleName;
+ std::string assetsFile;
+ std::vector<std::string> additionalResourcesDir;
+ AssetList additionalAssetList;
+};
+
+int runSample(const SampleConfig& config);
+
+#endif //SAMPLE_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAsset.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAsset.cpp
new file mode 100644
index 0000000..01f8fd6
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAsset.cpp
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastAsset.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlastTkAsset.h"
+#include <map>
+
+BlastAsset::BlastAsset(Renderer& renderer)
+ : m_renderer(renderer)
+{
+}
+
+void BlastAsset::validate()
+{
+}
+
+size_t BlastAsset::getBlastAssetSize() const
+{
+ return m_pxAsset->getTkAsset().getDataSize();
+}
+
+std::vector<uint32_t> BlastAsset::getChunkIndexesByDepth(uint32_t depth) const
+{
+ const TkAsset& tkAsset = m_pxAsset->getTkAsset();
+ const NvBlastChunk* pNvBlastChunk = tkAsset.getChunks();
+ uint32_t chunkCount = tkAsset.getChunkCount();
+
+ std::map<uint32_t, uint32_t> indexDepthMap;
+ indexDepthMap.insert(std::make_pair(0, 0));
+ for (size_t i = 1; i < chunkCount; ++i)
+ {
+ int depth = 0;
+ const NvBlastChunk* curChunk = pNvBlastChunk + i;
+ while (-1 != curChunk->parentChunkIndex)
+ {
+ ++depth;
+ curChunk = pNvBlastChunk + curChunk->parentChunkIndex;
+ }
+ indexDepthMap.insert(std::make_pair(i, depth));
+ }
+
+ std::vector<uint32_t> indexes;
+ for (std::map<uint32_t, uint32_t>::iterator itr = indexDepthMap.begin(); itr != indexDepthMap.end(); ++itr)
+ {
+ if (itr->second == depth)
+ {
+ indexes.push_back(itr->first);
+ }
+ }
+
+ return indexes;
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAsset.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAsset.h
new file mode 100644
index 0000000..b2e2f38
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAsset.h
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_ASSET_H
+#define BLAST_ASSET_H
+
+#include <memory>
+#include <vector>
+#include "PxTransform.h"
+#include "NvBlastTypes.h"
+
+using namespace physx;
+
+class Renderer;
+class BlastFamily;
+class PhysXController;
+
+namespace Nv
+{
+namespace Blast
+{
+class ExtPxFamily;
+class ExtPxAsset;
+class ExtPxManager;
+class TkGroup;
+}
+}
+
+using namespace Nv::Blast;
+
+// Add By Lixu Begin
+typedef BlastFamily* BlastFamilyPtr;
+// Add By Lixu End
+
+
+class BlastAsset
+{
+public:
+ //////// ctor ////////
+
+ BlastAsset(Renderer& renderer);
+ virtual ~BlastAsset() {}
+
+
+ //////// desc ////////
+
+ /**
+ Descriptor with actor initial settings.
+ */
+ struct ActorDesc
+ {
+ NvBlastID id;
+ PxTransform transform;
+ TkGroup* group;
+ };
+
+
+ //////// abstract ////////
+
+ virtual BlastFamilyPtr createFamily(PhysXController& physXConroller, ExtPxManager& pxManager, const ActorDesc& desc) = 0;
+
+
+ //////// data getters ////////
+
+ const ExtPxAsset* getPxAsset() const
+ {
+ return m_pxAsset;
+ }
+
+ size_t getBlastAssetSize() const;
+
+ std::vector<uint32_t> getChunkIndexesByDepth(uint32_t depth) const;
+
+protected:
+ //////// internal operations ////////
+
+ void validate();
+
+
+ //////// input data ////////
+
+ Renderer& m_renderer;
+
+
+ //////// internal data ////////
+
+ ExtPxAsset* m_pxAsset;
+};
+
+
+
+#endif //BLAST_ASSET_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetBoxes.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetBoxes.cpp
new file mode 100644
index 0000000..dfa0138
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetBoxes.cpp
@@ -0,0 +1,84 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastAssetBoxes.h"
+#include "BlastFamilyBoxes.h"
+#include "NvBlastExtPxAsset.h"
+#include "PxPhysics.h"
+#include "cooking/PxCooking.h"
+
+
+BlastAssetBoxes::BlastAssetBoxes(TkFramework& framework, PxPhysics& physics, PxCooking& cooking, Renderer& renderer, const Desc& desc)
+ : BlastAsset(renderer)
+{
+ // generate boxes slices procedurally
+ CubeAssetGenerator::generate(m_generatorAsset, desc.generatorSettings);
+
+ // asset desc / tk asset
+ ExtPxAssetDesc assetDesc;
+ assetDesc.chunkDescs = &m_generatorAsset.solverChunks[0];
+ assetDesc.chunkCount = (uint32_t)m_generatorAsset.solverChunks.size();
+ assetDesc.bondDescs = m_generatorAsset.solverBonds.size() > 0 ? &m_generatorAsset.solverBonds[0] : nullptr;
+ assetDesc.bondCount = (uint32_t)m_generatorAsset.solverBonds.size();
+ std::vector<uint8_t> bondFlags(assetDesc.bondCount);
+ std::fill(bondFlags.begin(), bondFlags.end(), desc.jointAllBonds ? 1 : 0);
+ assetDesc.bondFlags = bondFlags.data();
+
+ // box convex
+ PxVec3 vertices[8] = { { -1, -1, -1 }, { -1, -1, 1 }, { -1, 1, -1 }, { -1, 1, 1 }, { 1, -1, -1 }, { 1, -1, 1 }, { 1, 1, -1 }, { 1, 1, 1 } };
+ PxConvexMeshDesc convexMeshDesc;
+ convexMeshDesc.points.count = 8;
+ convexMeshDesc.points.data = vertices;
+ convexMeshDesc.points.stride = sizeof(PxVec3);
+ convexMeshDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
+ m_boxMesh = cooking.createConvexMesh(convexMeshDesc, physics.getPhysicsInsertionCallback());
+
+ // prepare chunks
+ const uint32_t chunkCount = (uint32_t)m_generatorAsset.solverChunks.size();
+ std::vector<ExtPxAssetDesc::ChunkDesc> pxChunks(chunkCount);
+ std::vector<ExtPxAssetDesc::SubchunkDesc> pxSubchunks;
+ pxSubchunks.reserve(chunkCount);
+ for (uint32_t i = 0; i < m_generatorAsset.solverChunks.size(); i++)
+ {
+ uint32_t chunkID = m_generatorAsset.solverChunks[i].userData;
+ GeneratorAsset::BlastChunkCube& cube = m_generatorAsset.chunks[chunkID];
+ PxVec3 position = *reinterpret_cast<PxVec3*>(&cube.position);
+ PxVec3 extents = *reinterpret_cast<PxVec3*>(&cube.extents);
+ ExtPxAssetDesc::ChunkDesc& chunk = pxChunks[chunkID];
+ ExtPxAssetDesc::SubchunkDesc subchunk =
+ {
+ PxTransform(position),
+ PxConvexMeshGeometry(m_boxMesh, PxMeshScale(extents / 2))
+ };
+ pxSubchunks.push_back(subchunk);
+ chunk.subchunks = &pxSubchunks.back();
+ chunk.subchunkCount = 1;
+ chunk.isStatic = (position.y - (extents.y - desc.generatorSettings.extents.y) / 2) <= desc.staticHeight;
+ }
+
+ // create asset
+ assetDesc.pxChunks = pxChunks.data();
+ m_pxAsset = ExtPxAsset::create(assetDesc, framework);
+
+ validate();
+}
+
+
+BlastAssetBoxes::~BlastAssetBoxes()
+{
+ m_boxMesh->release();
+ m_pxAsset->release();
+}
+
+
+BlastFamilyPtr BlastAssetBoxes::createFamily(PhysXController& physXConroller, ExtPxManager& pxManager, const ActorDesc& desc)
+{
+ return BlastFamilyPtr(new BlastFamilyBoxes(physXConroller, pxManager, m_renderer, *this, desc));
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetBoxes.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetBoxes.h
new file mode 100644
index 0000000..518e93d
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetBoxes.h
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_ASSET_BOXES_H
+#define BLAST_ASSET_BOXES_H
+
+#include "BlastAsset.h"
+#include "AssetGenerator.h"
+#include "PxConvexMesh.h"
+
+
+namespace physx
+{
+class PxPhysics;
+class PxCooking;
+}
+
+namespace Nv
+{
+namespace Blast
+{
+class TkFramework;
+}
+}
+
+
+class BlastAssetBoxes : public BlastAsset
+{
+public:
+ struct Desc
+ {
+ CubeAssetGenerator::Settings generatorSettings;
+ float staticHeight;
+ bool jointAllBonds;
+ };
+
+ BlastAssetBoxes(TkFramework& framework, PxPhysics& physics, PxCooking& cooking, Renderer& renderer, const Desc& desc);
+ virtual ~BlastAssetBoxes();
+
+ BlastFamilyPtr createFamily(PhysXController& physXConroller, ExtPxManager& pxManager, const ActorDesc& desc);
+
+private:
+ PxConvexMesh* m_boxMesh;
+ GeneratorAsset m_generatorAsset;
+};
+
+
+
+#endif //BLAST_ASSET_BOXES_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModel.cpp
new file mode 100644
index 0000000..c42215e
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModel.cpp
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastAssetModel.h"
+#include "Renderer.h"
+#include "BlastController.h"
+#include "Utils.h"
+#include "ResourceManager.h"
+#include "PsFileBuffer.h"
+#include "NvBlastExtPxAsset.h"
+#include <sstream>
+
+
+BlastAssetModel::BlastAssetModel(TkFramework& framework, PxPhysics& physics, PxCooking& cooking, Renderer& renderer, const char* modelName)
+ : BlastAsset(renderer)
+{
+ ResourceManager& resourceManager = m_renderer.getResourceManager();
+
+ // Physics Asset
+ std::ostringstream blastFileName;
+ blastFileName << modelName << ".bpxa";
+ std::string path;
+ if (resourceManager.findFile(blastFileName.str(), path))
+ {
+ PsFileBuffer fileBuf(path.c_str(), PxFileBuf::OPEN_READ_ONLY);
+ m_pxAsset = ExtPxAsset::deserialize(fileBuf, framework, physics);
+ ASSERT_PRINT(m_pxAsset != nullptr, "can't load bpxa file");
+ }
+ else
+ {
+ ASSERT_PRINT(false, "wrong blastFilename");
+ }
+
+ // load obj file
+ std::ostringstream objFileName;
+ objFileName << modelName << ".obj";
+ if (resourceManager.findFile(objFileName.str(), path))
+ {
+ m_model = BlastModel::loadFromFileTinyLoader(path.c_str());
+ if (!m_model)
+ {
+ ASSERT_PRINT(false, "obj load failed");
+ }
+ }
+ else
+ {
+ ASSERT_PRINT(false, "wrong objFileName");
+ }
+
+ validate();
+}
+
+
+BlastAssetModel::~BlastAssetModel()
+{
+ m_pxAsset->release();
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModel.h
new file mode 100644
index 0000000..8132911
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModel.h
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_ASSET_MODEL_H
+#define BLAST_ASSET_MODEL_H
+
+#include "BlastAsset.h"
+#include "BlastModel.h"
+
+
+namespace physx
+{
+class PxPhysics;
+class PxCooking;
+}
+
+namespace Nv
+{
+namespace Blast
+{
+class TkFramework;
+}
+}
+
+
+class BlastAssetModel : public BlastAsset
+{
+public:
+ //////// ctor ////////
+
+ BlastAssetModel(TkFramework& framework, PxPhysics& physics, PxCooking& cooking, Renderer& renderer, const char* modelName);
+ virtual ~BlastAssetModel();
+
+
+ //////// data getters ////////
+
+ const BlastModel& getModel() const
+ {
+// Add By Lixu Begin
+ return *m_model;
+// Add By Lixu End
+ }
+
+private:
+ //////// private internal data ////////
+
+ BlastModelPtr m_model;
+};
+
+#endif //BLAST_ASSET_MODEL_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSimple.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSimple.cpp
new file mode 100644
index 0000000..56c7441
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSimple.cpp
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+
+#include "BlastAssetModelSimple.h"
+#include "BlastFamilyModelSimple.h"
+#include "CustomRenderMesh.h"
+#include "Renderer.h"
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// BlastAssetModelSimple
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+BlastAssetModelSimple::BlastAssetModelSimple(TkFramework& framework, PxPhysics& physics, PxCooking& cooking, Renderer& renderer, const char* modelName)
+ : BlastAssetModel(framework, physics, cooking, renderer, modelName)
+{
+ // prepare materials
+// Add By Lixu Begin
+ for (const BlastModel::Material& material : getModel().materials)
+ {
+ if (material.diffuseTexture.empty())
+ m_renderMaterials.push_back(RenderMaterial::getDefaultRenderMaterial());
+ else
+ m_renderMaterials.push_back(new RenderMaterial(material.name.c_str(), renderer.getResourceManager(), "model_simple_textured_ex", material.diffuseTexture.c_str()));
+ }
+// Add By Lixu End
+ validate();
+}
+
+
+BlastAssetModelSimple::~BlastAssetModelSimple()
+{
+ // release materials
+ for (RenderMaterial* r : m_renderMaterials)
+ {
+ if (r == RenderMaterial::getDefaultRenderMaterial())
+ {
+ continue;
+ }
+ SAFE_DELETE(r);
+ }
+}
+
+
+BlastFamilyPtr BlastAssetModelSimple::createFamily(PhysXController& physXConroller, ExtPxManager& pxManager, const ActorDesc& desc)
+{
+ return BlastFamilyPtr(new BlastFamilyModelSimple(physXConroller, pxManager, m_renderer, *this, desc));
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSimple.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSimple.h
new file mode 100644
index 0000000..7e61616
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSimple.h
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_ASSET_MODEL_SIMPLE_H
+#define BLAST_ASSET_MODEL_SIMPLE_H
+
+#include "BlastAssetModel.h"
+
+
+class RenderMaterial;
+
+class BlastAssetModelSimple : public BlastAssetModel
+{
+public:
+ //////// ctor ////////
+
+ BlastAssetModelSimple(TkFramework& framework, PxPhysics& physics, PxCooking& cooking, Renderer& renderer, const char* modelName);
+ virtual ~BlastAssetModelSimple();
+
+
+ //////// interface implementation ////////
+
+ virtual BlastFamilyPtr createFamily(PhysXController& physXConroller, ExtPxManager& pxManager, const ActorDesc& desc);
+
+
+ //////// data getters ////////
+
+ const std::vector<RenderMaterial*>& getRenderMaterials() const
+ {
+ return m_renderMaterials;
+ }
+
+
+private:
+ //////// private internal data ////////
+
+ std::vector<RenderMaterial*> m_renderMaterials;
+};
+
+#endif //BLAST_ASSET_MODEL_SIMPLE_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSkinned.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSkinned.cpp
new file mode 100644
index 0000000..5cf3a0d
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSkinned.cpp
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastAssetModelSkinned.h"
+#include "BlastFamilyModelSkinned.h"
+#include "RenderMaterial.h"
+#include "Renderer.h"
+
+
+BlastAssetModelSkinned::BlastAssetModelSkinned(TkFramework& framework, PxPhysics& physics, PxCooking& cooking, Renderer& renderer, const char* modelName)
+ : BlastAssetModel(framework, physics, cooking, renderer, modelName)
+{
+// Add By Lixu Begin
+ int index = 0;
+ char materialName[50];
+ for (const BlastModel::Material& material : getModel().materials)
+ {
+ sprintf(materialName, "%s_Material%d", modelName, index++);
+
+ if (material.diffuseTexture.empty())
+ m_renderMaterials.push_back(new RenderMaterial(modelName, renderer.getResourceManager(), "model_skinned"));
+ else
+ m_renderMaterials.push_back(new RenderMaterial(modelName, renderer.getResourceManager(), "model_skinned_textured", material.diffuseTexture.c_str()));
+ }
+// Add By Lixu End
+ validate();
+}
+
+BlastAssetModelSkinned::~BlastAssetModelSkinned()
+{
+ for (RenderMaterial* r : m_renderMaterials)
+ {
+ SAFE_DELETE(r);
+ }
+}
+
+BlastFamilyPtr BlastAssetModelSkinned::createFamily(PhysXController& physXConroller, ExtPxManager& pxManager, const ActorDesc& desc)
+{
+ return BlastFamilyPtr(new BlastFamilyModelSkinned(physXConroller, pxManager, m_renderer, *this, desc));
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSkinned.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSkinned.h
new file mode 100644
index 0000000..149c8e8
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastAssetModelSkinned.h
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_ASSET_MODEL_SKINNED_H
+#define BLAST_ASSET_MODEL_SKINNED_H
+
+#include "BlastAssetModel.h"
+
+class RenderMaterial;
+
+class BlastAssetModelSkinned : public BlastAssetModel
+{
+public:
+ //////// ctor ////////
+
+ BlastAssetModelSkinned(TkFramework& framework, PxPhysics& physics, PxCooking& cooking, Renderer& renderer, const char* modelName);
+ virtual ~BlastAssetModelSkinned();
+
+
+ //////// interface implementation ////////
+
+ BlastFamilyPtr createFamily(PhysXController& physXConroller, ExtPxManager& pxManager, const ActorDesc& desc);
+
+
+ //////// public getter ////////
+
+ const std::vector<RenderMaterial*>& getRenderMaterials() const
+ {
+ return m_renderMaterials;
+ }
+
+
+private:
+ //////// internal data ////////
+
+ std::vector<RenderMaterial*> m_renderMaterials;
+};
+
+#endif //BLAST_ASSET_MODEL_SKINNED_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastController.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastController.cpp
new file mode 100644
index 0000000..4061931
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastController.cpp
@@ -0,0 +1,555 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastController.h"
+#include "BlastFamily.h"
+#include "BlastAsset.h"
+#include "BlastReplay.h"
+#include "PhysXController.h"
+#include "SampleTime.h"
+#include "SampleProfiler.h"
+#include "Utils.h"
+#include "Renderer.h"
+
+#include "NvBlast.h"
+#include "NvBlastExtPxManager.h"
+#include "NvBlastExtPxFamily.h"
+#include "NvBlastExtPxActor.h"
+
+#include "NvBlastTkFramework.h"
+
+#include "PsString.h"
+#include "PxTaskManager.h"
+#include "PxDefaultCpuDispatcher.h"
+#include "PxRigidBody.h"
+#include "PxScene.h"
+#include "PxRigidDynamic.h"
+#include "PxDistanceJoint.h"
+
+#include <sstream>
+#include <numeric>
+#include <cstdlib>
+
+#include "imgui.h"
+
+// Add By Lixu Begin
+#include "BlastSceneTree.h"
+// Add By Lixu End
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// AllocatorCallback
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class BlastAllocatorCallback : public PxAllocatorCallback
+{
+public:
+ virtual void* allocate(size_t size, const char* typeName, const char* filename, int line) override
+ {
+ NV_UNUSED(typeName);
+ NV_UNUSED(filename);
+ NV_UNUSED(line);
+ return malloc(size);
+ }
+
+ virtual void deallocate(void* ptr) override
+ {
+ free(ptr);
+ }
+};
+BlastAllocatorCallback g_allocatorCallback;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// ErrorCallback
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class BlastErrorCallback : public PxErrorCallback
+{
+public:
+ virtual void reportError(PxErrorCode::Enum code, const char* msg, const char* file, int line) override
+ {
+ std::stringstream str;
+ str << "NvBlastTk ";
+ bool critical = false;
+ switch (code)
+ {
+ case PxErrorCode::eNO_ERROR: critical = false; break;
+ case PxErrorCode::eDEBUG_INFO: str << "[Debug Info]"; critical = false; break;
+ case PxErrorCode::eDEBUG_WARNING: str << "[Debug Warning]"; critical = false; break;
+ case PxErrorCode::eINVALID_PARAMETER: str << "[Invalid Parameter]"; critical = true; break;
+ case PxErrorCode::eINVALID_OPERATION: str << "[Invalid Operation]"; critical = true; break;
+ case PxErrorCode::eOUT_OF_MEMORY: str << "[Out of] Memory"; critical = true; break;
+ case PxErrorCode::eINTERNAL_ERROR: str << "[Internal Error]"; critical = true; break;
+ case PxErrorCode::eABORT: str << "[Abort]"; critical = true; break;
+ case PxErrorCode::ePERF_WARNING: str << "[Perf Warning]"; critical = false; break;
+ default: PX_ALWAYS_ASSERT();
+ }
+ str << file << "(" << line << "): " << msg << "\n";
+
+ std::string message = str.str();
+ shdfnd::printString(message.c_str());
+ PX_ASSERT_WITH_MESSAGE(!critical, message.c_str());
+ }
+};
+BlastErrorCallback g_errorCallback;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Joint creation
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static physx::PxJoint* createPxJointCallback(ExtPxActor* actor0, const physx::PxTransform& localFrame0, ExtPxActor* actor1, const physx::PxTransform& localFrame1, physx::PxPhysics& physics, TkJoint& joint)
+{
+ PxDistanceJoint* pxJoint = PxDistanceJointCreate(physics, actor0 ? &actor0->getPhysXActor() : nullptr, localFrame0, actor1 ? &actor1->getPhysXActor() : nullptr, localFrame1);
+ pxJoint->setMaxDistance(1.0f);
+ return pxJoint;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Controller
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+BlastController::BlastController()
+: m_eventCallback(nullptr), debugRenderMode(BlastFamily::DEBUG_RENDER_DISABLED), m_impactDamageEnabled(true),
+m_impactDamageToStressEnabled(false), m_rigidBodyLimitEnabled(true), m_rigidBodyLimit(40000), m_blastAssetsSize(0), debugRenderScale(0.01f)
+{
+ m_extImpactDamageManagerSettings.fragility = 500.0f;
+
+ m_impactDamageToStressFactor = 0.01f;
+ m_draggingToStressFactor = 100.0f;
+}
+
+
+BlastController::~BlastController()
+{
+}
+
+void BlastController::reinitialize()
+{
+ onSampleStop();
+ onSampleStart();
+}
+
+void BlastController::onSampleStart()
+{
+ TkFrameworkDesc desc;
+ desc.allocatorCallback = &g_allocatorCallback;
+ desc.errorCallback = &g_errorCallback;
+ m_tkFramework = NvBlastTkFrameworkCreate(desc);
+
+ m_replay = new BlastReplay();
+
+ m_taskManager = PxTaskManager::createTaskManager(g_errorCallback, getPhysXController().getCPUDispatcher(), 0);
+
+ TkGroupDesc gdesc;
+ gdesc.pxTaskManager = m_taskManager;
+ m_tkGroup = m_tkFramework->createGroup(gdesc);
+
+ m_extPxManager = ExtPxManager::create(getPhysXController().getPhysics(), *m_tkFramework, createPxJointCallback);
+ m_extPxManager->setActorCountLimit(m_rigidBodyLimitEnabled ? m_rigidBodyLimit : 0);
+ m_extImpactDamageManager = ExtImpactDamageManager::create(m_extPxManager, m_extImpactDamageManagerSettings);
+ m_eventCallback = new EventCallback(m_extImpactDamageManager);
+
+ setImpactDamageEnabled(m_impactDamageEnabled, true);
+}
+
+
+void BlastController::onSampleStop()
+{
+ removeAllFamilies();
+
+ m_extImpactDamageManager->release();
+ m_extPxManager->release();
+ SAFE_DELETE(m_eventCallback);
+
+ m_tkGroup->release();
+
+ delete m_replay;
+
+ m_tkFramework->release();
+
+ m_taskManager->release();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Impact damage
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void BlastController::setImpactDamageEnabled(bool enabled, bool forceUpdate)
+{
+ if (m_impactDamageEnabled != enabled || forceUpdate)
+ {
+ m_impactDamageEnabled = enabled;
+ getPhysXController().getPhysXScene().setSimulationEventCallback(m_impactDamageEnabled ? m_eventCallback : nullptr);
+ refreshImpactDamageSettings();
+ }
+}
+
+bool BlastController::customImpactDamageFunction(void* data, ExtPxActor* actor, physx::PxShape* shape, physx::PxVec3 position, physx::PxVec3 force)
+{
+ return reinterpret_cast<BlastController*>(data)->stressDamage(actor, position, force);
+}
+
+bool BlastController::stressDamage(ExtPxActor *actor, physx::PxVec3 position, physx::PxVec3 force)
+{
+ if (actor->getTkActor().getGraphNodeCount() > 1)
+ {
+ void* userData = actor->getFamily().userData;
+ if (userData)
+ {
+ ExtStressSolver* solver = reinterpret_cast<ExtStressSolver*>(userData);
+ solver->applyImpulse(*actor, position, force * m_impactDamageToStressFactor);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void BlastController::refreshImpactDamageSettings()
+{
+ m_extImpactDamageManagerSettings.damageFunction = m_impactDamageToStressEnabled ? customImpactDamageFunction : nullptr;
+ m_extImpactDamageManagerSettings.damageFunctionData = this;
+ m_extImpactDamageManager->setSettings(m_extImpactDamageManagerSettings);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Stress
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void BlastController::updateDraggingStress()
+{
+ auto physxController = getPhysXController();
+ auto actor = physxController.getDraggingActor();
+ if (actor)
+ {
+ ExtPxActor* pxActor = m_extPxManager->getActorFromPhysXActor(*actor);
+ if (pxActor && pxActor->getTkActor().getGraphNodeCount() > 1 && pxActor->getPhysXActor().getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)
+ {
+ void* userData = pxActor->getFamily().userData;
+ if (userData)
+ {
+ ExtStressSolver* solver = reinterpret_cast<ExtStressSolver*>(userData);
+ PxTransform t(pxActor->getPhysXActor().getGlobalPose().getInverse());
+ PxVec3 dragVector = t.rotate(physxController.getDragVector());
+ const float factor = dragVector.magnitudeSquared() * m_draggingToStressFactor;
+ solver->applyImpulse(*pxActor, physxController.getDragActorHookLocalPoint(), dragVector.getNormalized() * factor);
+ }
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Stats
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+uint32_t BlastController::getActorCount() const
+{
+ return std::accumulate(m_families.begin(), m_families.end(), (uint32_t)0, [](uint32_t sum, const BlastFamilyPtr& a)
+ {
+ return sum += a->getActorCount();
+ });
+}
+
+uint32_t BlastController::getTotalVisibleChunkCount() const
+{
+ return std::accumulate(m_families.begin(), m_families.end(), (uint32_t)0, [](uint32_t sum, const BlastFamilyPtr& a)
+ {
+ return sum += a->getTotalVisibleChunkCount();
+ });
+}
+
+size_t BlastController::getFamilySize() const
+{
+ return std::accumulate(m_families.begin(), m_families.end(), (size_t)0, [](size_t sum, const BlastFamilyPtr& a)
+ {
+ return sum += a->getFamilySize();
+ });
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Time
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const double Time::s_secondsPerTick = Time::getTickDuration();
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Controller events
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void BlastController::Animate(double dt)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ PROFILER_BEGIN("Apply Impact Damage");
+ m_extImpactDamageManager->applyDamage();
+ PROFILER_END();
+
+ updateDraggingStress();
+
+ m_replay->update();
+
+ Time blastTime;
+ for (uint32_t i = 0; i < m_families.size(); ++i)
+ {
+ if (m_families[i])
+ {
+ m_families[i]->updatePreSplit(dt);
+ }
+ }
+
+ fillDebugRender();
+
+ PROFILER_BEGIN("Tk Group Process/Sync");
+ m_tkGroup->process();
+ m_tkGroup->sync(true);
+ PROFILER_END();
+
+ TkGroupStats gstats;
+ m_tkGroup->getStats(gstats);
+
+ this->m_lastBlastTimers.blastDamageMaterial = NvBlastTicksToSeconds(gstats.timers.material);
+ this->m_lastBlastTimers.blastDamageFracture = NvBlastTicksToSeconds(gstats.timers.fracture);
+ this->m_lastBlastTimers.blastSplitIsland = NvBlastTicksToSeconds(gstats.timers.island);
+ this->m_lastBlastTimers.blastSplitPartition = NvBlastTicksToSeconds(gstats.timers.partition);
+ this->m_lastBlastTimers.blastSplitVisibility = NvBlastTicksToSeconds(gstats.timers.visibility);
+
+ for (uint32_t i = 0; i < m_families.size(); ++i)
+ {
+ if (m_families[i])
+ {
+ m_families[i]->updateAfterSplit(dt);
+ }
+ }
+
+// Add By Lixu Begin
+ BlastSceneTree* pBlastSceneTree = BlastSceneTree::ins();
+ bool needUpdateUI = false;
+
+ std::map<BlastAsset*, std::vector<BlastFamily*>>& AssetFamiliesMap = getManager()->getAssetFamiliesMap();
+ std::map<BlastAsset*, std::vector<BlastFamily*>>::iterator itAsset;
+ std::vector<BlastFamily*>::iterator itFamily;
+ uint32_t assetIndex = 0;
+ for (itAsset = AssetFamiliesMap.begin(); itAsset != AssetFamiliesMap.end(); itAsset++)
+ {
+ std::vector<BlastFamily*>& BlastFamilies = itAsset->second;
+ for (itFamily = BlastFamilies.begin(); itFamily != BlastFamilies.end(); itFamily++)
+ {
+ BlastFamily* pFamily = *itFamily;
+
+ std::map<uint32_t, bool>& VisibleChangedChunks = pFamily->getVisibleChangedChunks();
+ std::map<uint32_t, bool>::iterator itChunk;
+ for (itChunk = VisibleChangedChunks.begin(); itChunk != VisibleChangedChunks.end(); itChunk++)
+ {
+ pBlastSceneTree->updateVisible(assetIndex, itChunk->first, itChunk->second);
+ }
+ pFamily->clearVisibleChangedChunks();
+
+ needUpdateUI = needUpdateUI || VisibleChangedChunks.size() > 0;
+ }
+
+ assetIndex++;
+ }
+
+ if (needUpdateUI)
+ {
+ pBlastSceneTree->updateValues(false);
+ }
+// Add By Lixu End
+}
+
+
+void BlastController::drawUI()
+{
+ // impact damage
+ bool impactEnabled = getImpactDamageEnabled();
+ if (ImGui::Checkbox("Impact Damage", &impactEnabled))
+ {
+ setImpactDamageEnabled(impactEnabled);
+ }
+
+ if (ImGui::DragFloat("Fragility", &m_extImpactDamageManagerSettings.fragility))
+ {
+ refreshImpactDamageSettings();
+ }
+
+ if (ImGui::Checkbox("Impact Damage To Stress Solver", &m_impactDamageToStressEnabled))
+ {
+ refreshImpactDamageSettings();
+ }
+
+ ImGui::DragFloat("Impact Damage To Stress Factor", &m_impactDamageToStressFactor, 0.001f, 0.0f, 1000.0f, "%.4f");
+ ImGui::DragFloat("Dragging To Stress Factor", &m_draggingToStressFactor, 0.1f, 0.0f, 1000.0f, "%.3f");
+
+ ImGui::Checkbox("Limit Rigid Body Count", &m_rigidBodyLimitEnabled);
+ if (m_rigidBodyLimitEnabled)
+ {
+ ImGui::DragInt("Rigid Body Limit", (int*)&m_rigidBodyLimit, 100, 1000, 100000);
+ }
+ m_extPxManager->setActorCountLimit(m_rigidBodyLimitEnabled ? m_rigidBodyLimit : 0);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// actor management
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+BlastFamilyPtr BlastController::spawnFamily(BlastAsset* blastAsset, const BlastAsset::ActorDesc& desc)
+{
+ BlastFamilyPtr actor = blastAsset->createFamily(getPhysXController(), *m_extPxManager, desc);
+ m_families.push_back(actor);
+ recalculateAssetsSize();
+ m_replay->addFamily(&actor->getFamily()->getTkFamily());
+ return actor;
+}
+
+void BlastController::removeFamily(BlastFamilyPtr actor)
+{
+ m_replay->removeFamily(&actor->getFamily()->getTkFamily());
+ m_families.erase(std::remove(m_families.begin(), m_families.end(), actor), m_families.end());
+ recalculateAssetsSize();
+ getPhysXController().resetDragging();
+// Add By Lixu Begin
+ delete actor;
+// Add By Lixu End
+}
+
+void BlastController::removeAllFamilies()
+{
+ while (!m_families.empty())
+ {
+ removeFamily(m_families.back());
+ }
+ m_replay->reset();
+}
+
+// Add By Lixu Begin
+#include "SceneController.h"
+// Add By Lixu End
+void BlastController::recalculateAssetsSize()
+{
+
+// Add By Lixu Begin
+ std::map<BlastAsset*, std::vector<BlastFamily*>>& AssetFamiliesMap = getManager()->getAssetFamiliesMap();
+ std::map<BlastAsset*, AssetList::ModelAsset>& AssetDescMap = getManager()->getAssetDescMap();
+ std::map<BlastAsset*, std::vector<BlastFamily*>>::iterator it;
+ for (it = AssetFamiliesMap.begin(); it != AssetFamiliesMap.end(); it++)
+ {
+ std::vector<BlastFamily*>& fs = it->second;
+ fs.clear();
+ }
+ AssetFamiliesMap.clear();
+ AssetDescMap.clear();
+
+ SceneController& sceneController = getManager()->getSceneController();
+ int familiesSize = m_families.size();
+ for (int i = 0; i < familiesSize; i++)
+ {
+ BlastFamilyPtr pBlastFamily = m_families[i];
+ BlastAsset* pBlastAsset = (BlastAsset*)&pBlastFamily->getBlastAsset();
+ AssetFamiliesMap[pBlastAsset].push_back(&*m_families[i]);
+ if (AssetDescMap.find(pBlastAsset) == AssetDescMap.end())
+ {
+ AssetList::ModelAsset desc;
+ if (sceneController.GetAssetDesc(pBlastAsset, desc))
+ {
+ AssetDescMap[pBlastAsset] = desc;
+ }
+ }
+
+ AssetList::ModelAsset& m = AssetDescMap[pBlastAsset];
+ pBlastFamily->initTransform(m.transform);
+ }
+// Add By Lixu End
+
+ std::set<const BlastAsset*> uniquedAssets;
+ m_blastAssetsSize = 0;
+ for (uint32_t i = 0; i < m_families.size(); ++i)
+ {
+ if (uniquedAssets.find(&m_families[i]->getBlastAsset()) == uniquedAssets.end())
+ {
+ m_blastAssetsSize += m_families[i]->getBlastAsset().getBlastAssetSize();
+ uniquedAssets.insert(&m_families[i]->getBlastAsset());
+ }
+ }
+}
+
+void BlastController::blast(PxVec3 worldPos, float damageRadius, float explosiveImpulse, std::function<void(ExtPxActor*)> damageFunction)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ for (uint32_t i = 0; i < m_families.size(); ++i)
+ {
+ if (m_families[i])
+ {
+ m_families[i]->blast(worldPos, damageRadius, explosiveImpulse, damageFunction);
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// context/log
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void BlastController::blastLog(int type, const char* msg, const char* file, int line)
+{
+ std::stringstream str;
+ bool critical = false;
+ switch (type)
+ {
+ case NvBlastMessage::Error: str << "[NvBlast ERROR] "; critical = true; break;
+ case NvBlastMessage::Warning: str << "[NvBlast WARNING] "; critical = true; break;
+ case NvBlastMessage::Info: str << "[NvBlast INFO] "; critical = false; break;
+ case NvBlastMessage::Debug: str << "[NvBlast DEBUG] "; critical = false; break;
+ }
+ str << file << "(" << line << "): " << msg << "\n";
+
+ std::string message = str.str();
+ shdfnd::printString(message.c_str());
+ PX_ASSERT_WITH_MESSAGE(!critical, message.c_str());
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// debug render
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void BlastController::fillDebugRender()
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ m_debugRenderBuffer.clear();
+
+ if (debugRenderMode != BlastFamily::DEBUG_RENDER_DISABLED)
+ {
+ getPhysXController().getPhysXScene().setVisualizationParameter(PxVisualizationParameter::eSCALE, 1);
+ for (uint32_t i = 0; i < m_families.size(); ++i)
+ {
+ m_families[i]->fillDebugRender(m_debugRenderBuffer, debugRenderMode, debugRenderScale);
+ }
+ }
+ else
+ {
+ getPhysXController().getPhysXScene().setVisualizationParameter(PxVisualizationParameter::eSCALE, 0);
+ }
+
+ getRenderer().queueRenderBuffer(&m_debugRenderBuffer);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastController.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastController.h
new file mode 100644
index 0000000..98f5c24
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastController.h
@@ -0,0 +1,246 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_CONTROLLER_H
+#define BLAST_CONTROLLER_H
+
+#include "SampleManager.h"
+#include "BlastFamily.h"
+#include "DebugRenderBuffer.h"
+#include "PxSimulationEventCallback.h"
+#include "NvBlastExtImpactDamageManager.h"
+
+using namespace physx;
+
+class BlastAsset;
+class BlastReplay;
+
+namespace physx
+{
+class PxTaskManager;
+}
+namespace Nv
+{
+namespace Blast
+{
+class TkFramework;
+}
+}
+
+
+struct BlastTimers
+{
+ double blastDamageMaterial;
+ double blastDamageFracture;
+ double blastSplitIsland;
+ double blastSplitPartition;
+ double blastSplitVisibility;
+};
+
+/**
+Blast Controller. Entry point for all blast related code, keeps blast actors and controls them.
+*/
+class BlastController : public ISampleController
+{
+public:
+ //////// ctor ////////
+
+ BlastController();
+ virtual ~BlastController();
+
+ void reinitialize();
+
+ //////// controller callbacks ////////
+
+ virtual void onSampleStart();
+ virtual void onSampleStop();
+
+ virtual void Animate(double dt);
+ void drawUI();
+
+
+ //////// public API ////////
+
+ void blast(PxVec3 worldPos, float damageRadius, float explosiveImpulse, std::function<void(ExtPxActor*)> damageFunction);
+
+ bool stressDamage(ExtPxActor *actor, PxVec3 position, PxVec3 force);
+
+ BlastFamilyPtr spawnFamily(BlastAsset* blastAsset, const BlastAsset::ActorDesc& desc);
+ void removeFamily(BlastFamilyPtr actor);
+ void removeAllFamilies();
+
+
+ //////// public static ////////
+
+ static void blastLog(int type, const char* msg, const char* file, int line);
+
+
+ //////// public getters/setters ////////
+
+ TkFramework& getTkFramework() const
+ {
+ return *m_tkFramework;
+ }
+
+ TkGroup* getTkGroup() const
+ {
+ return m_tkGroup;
+ }
+
+ ExtPxManager& getExtPxManager() const
+ {
+ return *m_extPxManager;
+ }
+
+ ExtImpactDamageManager* getExtImpactDamageManager() const
+ {
+ return m_extImpactDamageManager;
+ }
+
+ BlastReplay* getReplay() const
+ {
+ return m_replay;
+ }
+
+ uint32_t getActorCount() const;
+
+ uint32_t getTotalVisibleChunkCount() const;
+
+ size_t getFamilySize() const;
+
+ size_t getBlastAssetsSize() const
+ {
+ return m_blastAssetsSize;
+ }
+
+ const BlastTimers& getLastBlastTimers() const
+ {
+ return m_lastBlastTimers;
+ }
+
+ bool getImpactDamageEnabled() const
+ {
+ return m_impactDamageEnabled;
+ }
+
+ void setImpactDamageEnabled(bool enabled, bool forceUpdate = false);
+
+ ExtStressSolverSettings& getStressSolverSettings()
+ {
+ return m_extStressSolverSettings;
+ }
+
+// Add By Lixu Begin
+ std::vector<BlastFamilyPtr>& getFamilies()
+ {
+ return m_families;
+ }
+// Add By Lixu End
+
+ float getLastStressDelta() const;
+
+ //////// public variables for UI ////////
+
+ BlastFamily::DebugRenderMode debugRenderMode;
+ float debugRenderScale;
+
+
+ //////// Filter shader enum ////////
+
+ enum FilterDataAttributes
+ {
+ SUPPRESS_CONTACT_NOTIFY = 1,
+ };
+
+private:
+ //////// impact damage event callback ////////
+
+ class EventCallback : public PxSimulationEventCallback
+ {
+ public:
+ EventCallback(ExtImpactDamageManager* manager) : m_manager(manager) {}
+
+ // implemented
+ virtual void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, uint32_t nbPairs)
+ {
+ m_manager->onContact(pairHeader, pairs, nbPairs);
+ }
+
+ private:
+ // unused
+ void onConstraintBreak(PxConstraintInfo*, PxU32) {}
+ void onWake(PxActor**, PxU32) {}
+ void onSleep(PxActor**, PxU32) {}
+ void onTrigger(PxTriggerPair*, PxU32) {}
+ void onAdvance(const PxRigidBody*const*, const PxTransform*, const PxU32) {}
+
+ // data
+ ExtImpactDamageManager* m_manager;
+ };
+
+
+ //////// private methods ////////
+
+ void updateDraggingStress();
+
+ void refreshImpactDamageSettings();
+
+ void fillDebugRender();
+
+ void recalculateAssetsSize();
+
+ static bool customImpactDamageFunction(void* data, ExtPxActor* actor, PxShape* shape, PxVec3 position, PxVec3 force);
+
+
+ //////// used controllers ////////
+
+ Renderer& getRenderer() const
+ {
+ return getManager()->getRenderer();
+ }
+
+ PhysXController& getPhysXController() const
+ {
+ return getManager()->getPhysXController();
+ }
+
+
+ //////// internal data ////////
+
+ PxTaskManager* m_taskManager;
+ TkFramework* m_tkFramework;
+ TkGroup* m_tkGroup;
+ ExtPxManager* m_extPxManager;
+ ExtImpactDamageManager* m_extImpactDamageManager;
+ ExtImpactSettings m_extImpactDamageManagerSettings;
+ EventCallback* m_eventCallback;
+ ExtStressSolverSettings m_extStressSolverSettings;
+
+ std::vector<BlastFamilyPtr> m_families;
+ DebugRenderBuffer m_debugRenderBuffer;
+
+ bool m_impactDamageEnabled;
+ bool m_impactDamageToStressEnabled;
+
+ float m_impactDamageToStressFactor;
+ float m_draggingToStressFactor;
+
+ bool m_rigidBodyLimitEnabled;
+ uint32_t m_rigidBodyLimit;
+
+ BlastReplay* m_replay;
+
+ BlastTimers m_lastBlastTimers;
+
+ size_t m_blastAssetsSize;
+};
+
+
+#endif
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamily.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamily.cpp
new file mode 100644
index 0000000..f947cbd
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamily.cpp
@@ -0,0 +1,588 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastFamily.h"
+#include "SampleProfiler.h"
+#include "PhysXController.h"
+#include "RenderUtils.h"
+#include "SampleTime.h"
+#include "UIHelpers.h"
+
+#include "NvBlast.h"
+#include "NvBlastTkFamily.h"
+#include "NvBlastTkActor.h"
+#include "NvBlastTkAsset.h"
+#include "NvBlastTkJoint.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlastExtPxActor.h"
+#include "NvBlastExtPxFamily.h"
+#include "NvBlastExtPxManager.h"
+
+#include "PxRigidDynamic.h"
+#include "PxScene.h"
+#include "PxJoint.h"
+
+
+const float RIGIDBODY_DENSITY = 2000.0f;
+
+const float BlastFamily::BOND_HEALTH_MAX = 1.0f;
+
+BlastFamily::BlastFamily(PhysXController& physXController, ExtPxManager& pxManager, const BlastAsset& blastAsset)
+ : m_physXController(physXController)
+ , m_pxManager(pxManager)
+ , m_blastAsset(blastAsset)
+ , m_listener(this)
+ , m_totalVisibleChunkCount(0)
+ , m_stressSolver(nullptr)
+{
+ m_settings.stressSolverEnabled = false;
+ m_settings.stressDamageEnabled = false;
+
+ m_settings.material = { 3.0f, 0.1f, 0.2f, 1.5f + 1e-5f, 0.95f };;
+}
+
+BlastFamily::~BlastFamily()
+{
+ if (m_stressSolver)
+ {
+ m_stressSolver->release();
+ }
+
+ m_pxFamily->unsubscribe(m_listener);
+
+ m_pxFamily->release();
+}
+
+void BlastFamily::initialize(const BlastAsset::ActorDesc& desc)
+{
+ ExtPxFamilyDesc familyDesc;
+ familyDesc.actorDesc.initialBondHealths = nullptr;
+ familyDesc.actorDesc.initialSupportChunkHealths = nullptr;
+ familyDesc.actorDesc.uniformInitialBondHealth = BOND_HEALTH_MAX;
+ familyDesc.actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
+ familyDesc.group = desc.group;
+ familyDesc.pxAsset = m_blastAsset.getPxAsset();
+ m_pxFamily = m_pxManager.createFamily(familyDesc);
+
+ m_tkFamily = &m_pxFamily->getTkFamily();
+ m_tkFamily->setID(desc.id);
+ m_tkFamily->setMaterial(&m_settings.material);
+
+ m_familySize = NvBlastFamilyGetSize(m_tkFamily->getFamilyLL(), nullptr);
+
+ m_pxFamily->subscribe(m_listener);
+
+ ExtPxSpawnSettings spawnSettings = {
+ &m_physXController.getPhysXScene(),
+ m_physXController.getDefaultMaterial(),
+ RIGIDBODY_DENSITY
+ };
+ m_pxFamily->spawn(desc.transform, PxVec3(1.0f), spawnSettings);
+
+ reloadStressSolver();
+}
+
+void BlastFamily::updatePreSplit(float dt)
+{
+ PROFILER_BEGIN("Stress Solver");
+ // update stress
+ m_stressSolveTime = 0;
+ if (m_stressSolver)
+ {
+ Time t;
+ m_stressSolver->update(m_settings.stressDamageEnabled);
+ m_stressSolveTime += t.getElapsedSeconds();
+ }
+ PROFILER_END();
+
+ // collect potential actors to health update
+ m_actorsToUpdateHealth.clear();
+ for (const ExtPxActor* actor : m_actors)
+ {
+ if (actor->getTkActor().isPending())
+ {
+ m_actorsToUpdateHealth.emplace(actor);
+ }
+ }
+}
+
+void BlastFamily::updateAfterSplit(float dt)
+{
+ PROFILER_BEGIN("Actor Health Update");
+ for (const ExtPxActor* actor : m_actors)
+ {
+ onActorUpdate(*actor);
+
+ // update health if neccessary
+ if (m_actorsToUpdateHealth.find(actor) != m_actorsToUpdateHealth.end())
+ {
+ onActorHealthUpdate(*actor);
+ }
+ }
+ PROFILER_END();
+
+ PROFILER_BEGIN("Actor Misc Update");
+ onUpdate();
+ PROFILER_END();
+
+ m_pxFamily->postSplitUpdate();
+}
+
+void BlastFamily::processActorCreated(ExtPxFamily&, ExtPxActor& actor)
+{
+ m_totalVisibleChunkCount += actor.getChunkCount();
+ m_actors.emplace(&actor);
+
+ onActorCreated(actor);
+ onActorHealthUpdate(actor);
+}
+
+void BlastFamily::processActorDestroyed(ExtPxFamily&, ExtPxActor& actor)
+{
+ m_totalVisibleChunkCount -= actor.getChunkCount();
+ m_physXController.notifyRigidDynamicDestroyed(&actor.getPhysXActor());
+
+ onActorDestroyed(actor);
+
+ m_actors.erase(m_actors.find(&actor));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Data Helpers
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+uint32_t BlastFamily::getActorCount() const
+{
+ return (uint32_t)m_tkFamily->getActorCount();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// UI
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void BlastFamily::drawUI()
+{
+ // Blast Material
+ ImGui::Spacing();
+ ImGui::Text("Blast Material:");
+ ImGui::DragFloat("singleChunkThreshold", &m_settings.material.singleChunkThreshold);
+ ImGui::DragFloat("graphChunkThreshold", &m_settings.material.graphChunkThreshold);
+ ImGui::DragFloat("bondNormalThreshold", &m_settings.material.bondNormalThreshold);
+ ImGui::DragFloat("bondTangentialThreshold", &m_settings.material.bondTangentialThreshold);
+ ImGui::DragFloat("damageAttenuation", &m_settings.material.damageAttenuation);
+
+ ImGui::Spacing();
+
+ // Stress Solver Settings
+ if (ImGui::Checkbox("Stress Solver Enabled", &m_settings.stressSolverEnabled))
+ {
+ reloadStressSolver();
+ }
+
+ if (m_settings.stressSolverEnabled)
+ {
+ // Settings
+ bool changed = false;
+
+ changed |= ImGui::DragInt("Bond Iterations Per Frame", (int*)&m_settings.stressSolverSettings.bondIterationsPerFrame, 100, 0, 500000);
+ changed |= ImGui::DragFloat("Stress Linear Factor", &m_settings.stressSolverSettings.stressLinearFactor, 0.00001f, 0.0f, 10.0f, "%.6f");
+ changed |= ImGui::DragFloat("Stress Angular Factor", &m_settings.stressSolverSettings.stressAngularFactor, 0.00001f, 0.0f, 10.0f, "%.6f");
+ changed |= ImGui::SliderInt("Graph Reduction Level", (int*)&m_settings.stressSolverSettings.graphReductionLevel, 0, 32);
+ if (changed)
+ {
+ refreshStressSolverSettings();
+ }
+
+ ImGui::Checkbox("Stress Damage Enabled", &m_settings.stressDamageEnabled);
+
+ if (ImGui::Button("Recalculate Stress"))
+ {
+ resetStress();
+ }
+ }
+}
+
+void BlastFamily::drawStatsUI()
+{
+ ImGui::PushStyleColor(ImGuiCol_Text, ImColor(10, 255, 10, 255));
+ const ExtStressSolver* stressSolver = m_stressSolver;
+ if (stressSolver)
+ {
+ const float errorLinear = stressSolver->getStressErrorLinear();
+ const float errorAngular = stressSolver->getStressErrorAngular();
+
+ ImGui::Text("Stress Bond Count: %d", stressSolver->getBondCount());
+ ImGui::Text("Stress Iterations: %d (+%d)", stressSolver->getIterationCount(), stressSolver->getIterationsPerFrame());
+ ImGui::Text("Stress Frames: %d", stressSolver->getFrameCount());
+ ImGui::Text("Stress Error Lin / Ang: %.4f / %.4f", errorLinear, errorAngular);
+ ImGui::Text("Stress Solve Time: %.3f ms", m_stressSolveTime * 1000);
+
+ // plot errors
+ {
+ static float scale = 1.0f;
+ scale = stressSolver->getFrameCount() <= 1 ? 1.0f : scale;
+ scale = std::max<float>(scale, errorLinear);
+ scale = std::max<float>(scale, errorAngular);
+
+ static PlotLinesInstance<> linearErrorPlot;
+ linearErrorPlot.plot("Stress Linear Error", errorLinear, "error/frame", 0.0f, 1.0f * scale);
+ static PlotLinesInstance<> angularErrorPlot;
+ angularErrorPlot.plot("Stress Angular Error", errorAngular, "error/frame", 0.0f, 1.0f * scale);
+ }
+ }
+ else
+ {
+ ImGui::Text("No Stress Solver");
+ }
+ ImGui::PopStyleColor();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Stress Solver
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void BlastFamily::setSettings(const Settings& settings)
+{
+ bool reloadStressSolverNeeded = (m_settings.stressSolverEnabled != settings.stressSolverEnabled);
+
+ m_settings = settings;
+ refreshStressSolverSettings();
+
+ if (reloadStressSolverNeeded)
+ {
+ reloadStressSolver();
+ }
+
+ m_tkFamily->setMaterial(&m_settings.material);
+}
+
+void BlastFamily::refreshStressSolverSettings()
+{
+ if (m_stressSolver)
+ {
+ m_stressSolver->setSettings(m_settings.stressSolverSettings);
+ }
+}
+
+void BlastFamily::resetStress()
+{
+ m_stressSolver->reset();
+}
+
+void BlastFamily::reloadStressSolver()
+{
+ if (m_stressSolver)
+ {
+ m_stressSolver->release();
+ m_stressSolver = nullptr;
+ }
+
+ if (m_settings.stressSolverEnabled)
+ {
+ m_stressSolver = ExtStressSolver::create(*m_pxFamily, m_settings.stressSolverSettings);
+ m_pxFamily->userData = m_stressSolver;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// debug render
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const DirectX::XMFLOAT4 BOND_NORMAL_COLOR(0.0f, 0.8f, 1.0f, 1.0f);
+const DirectX::XMFLOAT4 BOND_INVISIBLE_COLOR(0.65f, 0.16f, 0.16f, 1.0f);
+const DirectX::XMFLOAT4 BOND_IMPULSE_LINEAR_COLOR(0.0f, 1.0f, 0.0f, 1.0f);
+const DirectX::XMFLOAT4 BOND_IMPULSE_ANGULAR_COLOR(1.0f, 0.0f, 0.0f, 1.0f);
+const DirectX::XMFLOAT4 JOINT_COLOR(0.5f, 0.6f, 7.0f, 1.0f);
+
+
+inline void pushCentroid(std::vector<PxDebugLine>& lines, PxVec3 pos, PxU32 color, const float& area, const PxVec3& normal)
+{
+ // draw square of area 'area' rotated by normal
+ {
+ // build world rotation
+ PxVec3 n0(0, 0, 1);
+ PxVec3 n1 = normal;
+ PxVec3 axis = n0.cross(n1);
+ float d = n0.dot(n1);
+ PxQuat q(axis.x, axis.y, axis.z, 1.f + d);
+ q.normalize();
+ float e = PxSqrt(1.0f / 2.0f);
+ float r = PxSqrt(area);
+
+ // transform all 4 square points
+ PxTransform t(pos, q);
+ PxVec3 p0 = t.transform(PxVec3(-e, e, 0) * r);
+ PxVec3 p1 = t.transform(PxVec3( e, e, 0) * r);
+ PxVec3 p2 = t.transform(PxVec3( e, -e, 0) * r);
+ PxVec3 p3 = t.transform(PxVec3(-e, -e, 0) * r);
+
+ // push square edges
+ lines.push_back(PxDebugLine(p0, p1, color));
+ lines.push_back(PxDebugLine(p3, p2, color));
+ lines.push_back(PxDebugLine(p1, p2, color));
+ lines.push_back(PxDebugLine(p0, p3, color));
+ }
+
+ // draw normal
+ lines.push_back(PxDebugLine(pos, pos + normal * 0.5f, XMFLOAT4ToU32Color(BOND_NORMAL_COLOR)));
+}
+
+inline DirectX::XMFLOAT4 bondHealthColor(float healthFraction)
+{
+ const DirectX::XMFLOAT4 BOND_HEALTHY_COLOR(0.0f, 1.0f, 0.0f, 1.0f);
+ const DirectX::XMFLOAT4 BOND_MID_COLOR(1.0f, 1.0f, 0.0f, 1.0f);
+ const DirectX::XMFLOAT4 BOND_BROKEN_COLOR(1.0f, 0.0f, 0.0f, 1.0f);
+
+ return healthFraction < 0.5 ? XMFLOAT4Lerp(BOND_BROKEN_COLOR, BOND_MID_COLOR, 2.0f * healthFraction) : XMFLOAT4Lerp(BOND_MID_COLOR, BOND_HEALTHY_COLOR, 2.0f * healthFraction - 1.0f);
+}
+
+void BlastFamily::fillDebugRender(DebugRenderBuffer& debugRenderBuffer, DebugRenderMode mode, float renderScale)
+{
+ const NvBlastChunk* chunks = m_tkFamily->getAsset()->getChunks();
+ const NvBlastBond* bonds = m_tkFamily->getAsset()->getBonds();
+ const NvBlastSupportGraph graph = m_tkFamily->getAsset()->getGraph();
+
+ for (const ExtPxActor* pxActor : m_actors)
+ {
+ TkActor& actor = pxActor->getTkActor();
+ uint32_t lineStartIndex = (uint32_t)debugRenderBuffer.m_lines.size();
+
+ uint32_t nodeCount = actor.getGraphNodeCount();
+ if (nodeCount == 0) // subsupport chunks don't have graph nodes
+ continue;
+
+ std::vector<uint32_t> nodes(actor.getGraphNodeCount());
+ actor.getGraphNodeIndices(nodes.data(), static_cast<uint32_t>(nodes.size()));
+
+ if (DEBUG_RENDER_HEALTH_GRAPH <= mode && mode <= DEBUG_RENDER_HEALTH_GRAPH_CENTROIDS)
+ {
+ const float* bondHealths = actor.getBondHealths();
+
+ const ExtPxChunk* pxChunks = m_blastAsset.getPxAsset()->getChunks();
+
+ for (uint32_t node0 : nodes)
+ {
+ const uint32_t chunkIndex0 = graph.chunkIndices[node0];
+ const NvBlastChunk& blastChunk0 = chunks[chunkIndex0];
+ const ExtPxChunk& assetChunk0 = pxChunks[chunkIndex0];
+
+ for (uint32_t adjacencyIndex = graph.adjacencyPartition[node0]; adjacencyIndex < graph.adjacencyPartition[node0 + 1]; adjacencyIndex++)
+ {
+ uint32_t node1 = graph.adjacentNodeIndices[adjacencyIndex];
+ const uint32_t chunkIndex1 = graph.chunkIndices[node1];
+ const NvBlastChunk& blastChunk1 = chunks[chunkIndex1];
+ const ExtPxChunk& assetChunk1 = pxChunks[chunkIndex1];
+ if (node0 > node1)
+ continue;
+
+ bool invisibleBond = assetChunk0.subchunkCount == 0 || assetChunk1.subchunkCount == 0;
+
+ // health
+ uint32_t bondIndex = graph.adjacentBondIndices[adjacencyIndex];
+ float healthVal = PxClamp(bondHealths[bondIndex] / BOND_HEALTH_MAX, 0.0f, 1.0f);
+
+ DirectX::XMFLOAT4 color = bondHealthColor(healthVal);
+
+ const NvBlastBond& solverBond = bonds[bondIndex];
+ const PxVec3& centroid = reinterpret_cast<const PxVec3&>(solverBond.centroid);
+
+ // centroid
+ if (mode == DEBUG_RENDER_HEALTH_GRAPH_CENTROIDS || mode == DEBUG_RENDER_CENTROIDS)
+ {
+ const PxVec3& normal = reinterpret_cast<const PxVec3&>(solverBond.normal);
+ pushCentroid(debugRenderBuffer.m_lines, centroid, XMFLOAT4ToU32Color(invisibleBond ? BOND_INVISIBLE_COLOR : color), solverBond.area, normal.getNormalized());
+ }
+
+ // chunk connection (bond)
+ if ((mode == DEBUG_RENDER_HEALTH_GRAPH || mode == DEBUG_RENDER_HEALTH_GRAPH_CENTROIDS) && !invisibleBond)
+ {
+ const PxVec3& c0 = reinterpret_cast<const PxVec3&>(blastChunk0.centroid);
+ const PxVec3& c1 = reinterpret_cast<const PxVec3&>(blastChunk1.centroid);
+ debugRenderBuffer.m_lines.push_back(PxDebugLine(c0, c1, XMFLOAT4ToU32Color(color)));
+ }
+ }
+ }
+ }
+
+ // stress
+ if (DEBUG_RENDER_STRESS_GRAPH <= mode && mode <= DEBUG_RENDER_STRESS_GRAPH_BONDS_IMPULSES)
+ {
+ if (m_stressSolver)
+ {
+ m_stressSolver->fillDebugRender(nodes, debugRenderBuffer.m_lines, (ExtStressSolver::DebugRenderMode)(mode - DEBUG_RENDER_STRESS_GRAPH), renderScale);
+ }
+ }
+
+ // transform all added lines from local to global
+ PxTransform localToGlobal = pxActor->getPhysXActor().getGlobalPose();
+ for (uint32_t i = lineStartIndex; i < debugRenderBuffer.m_lines.size(); i++)
+ {
+ PxDebugLine& line = debugRenderBuffer.m_lines[i];
+ line.pos0 = localToGlobal.transform(line.pos0);
+ line.pos1 = localToGlobal.transform(line.pos1);
+ }
+ }
+
+ // joints debug render
+ if (mode == DEBUG_RENDER_JOINTS)
+ {
+ for (const ExtPxActor* pxActor : m_actors)
+ {
+ TkActor& actor = pxActor->getTkActor();
+ const uint32_t jointCount = actor.getJointCount();
+ if (jointCount > 0)
+ {
+ std::vector<TkJoint*> joints(jointCount);
+ actor.getJoints(joints.data(), jointCount);
+ for (auto joint : joints)
+ {
+ PxJoint* pxJoint = reinterpret_cast<PxJoint*>(joint->userData);
+ if (pxJoint)
+ {
+ PxRigidActor *actor0, *actor1;
+ pxJoint->getActors(actor0, actor1);
+ auto lp0 = pxJoint->getLocalPose(PxJointActorIndex::eACTOR0);
+ auto lp1 = pxJoint->getLocalPose(PxJointActorIndex::eACTOR1);
+ PxVec3 p0 = actor0 ? actor0->getGlobalPose().transform(lp0).p : lp0.p;
+ PxVec3 p1 = actor1 ? actor1->getGlobalPose().transform(lp1).p : lp1.p;
+ debugRenderBuffer.m_lines.push_back(PxDebugLine(p0, p1, XMFLOAT4ToU32Color(JOINT_COLOR)));
+ }
+ }
+ }
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// action!!!
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class BlastOverlapCallback : public PxOverlapCallback
+{
+public:
+ BlastOverlapCallback(ExtPxManager& pxManager, std::set<ExtPxActor*>& actorBuffer)
+ : m_pxManager(pxManager), m_actorBuffer(actorBuffer), PxOverlapCallback(m_hitBuffer, sizeof(m_hitBuffer) / sizeof(m_hitBuffer[0])) {}
+
+ PxAgain processTouches(const PxOverlapHit* buffer, PxU32 nbHits)
+ {
+ for (PxU32 i = 0; i < nbHits; ++i)
+ {
+ PxRigidDynamic* rigidDynamic = buffer[i].actor->is<PxRigidDynamic>();
+ if (rigidDynamic)
+ {
+ ExtPxActor* actor = m_pxManager.getActorFromPhysXActor(*rigidDynamic);
+ if (actor != nullptr)
+ {
+ m_actorBuffer.insert(actor);
+ }
+ }
+ }
+ return true;
+ }
+
+private:
+ ExtPxManager& m_pxManager;
+ std::set<ExtPxActor*>& m_actorBuffer;
+ PxOverlapHit m_hitBuffer[1000];
+};
+
+void BlastFamily::blast(PxVec3 worldPos, float damageRadius, float explosiveImpulse, std::function<void(ExtPxActor*)> damageFunction)
+{
+// Add By Lixu Begin
+ const ExtPxAsset* pExtPxAsset = m_blastAsset.getPxAsset();
+ const TkAsset& tkAsset = pExtPxAsset->getTkAsset();
+ uint32_t bondCount = tkAsset.getBondCount();
+ if (bondCount == 0)
+ {
+ return;
+ }
+// Add By Lixu End
+
+ std::set<ExtPxActor*> actorsToDamage;
+#if 1
+ BlastOverlapCallback overlapCallback(m_pxManager, actorsToDamage);
+ m_physXController.getPhysXScene().overlap(PxSphereGeometry(damageRadius), PxTransform(worldPos), overlapCallback);
+#else
+ for (std::map<NvBlastActor*, PhysXController::Actor*>::iterator it = m_actorsMap.begin(); it != m_actorsMap.end(); it++)
+ {
+ actorsToDamage.insert(it->first);
+ }
+#endif
+
+ for (auto actor : actorsToDamage)
+ {
+ damageFunction(actor);
+ }
+
+ if (explosiveImpulse > 0.0f)
+ {
+ explode(worldPos, damageRadius, explosiveImpulse);
+ }
+}
+
+
+class ExplodeOverlapCallback : public PxOverlapCallback
+{
+public:
+ ExplodeOverlapCallback(PxVec3 worldPos, float radius, float explosiveImpulse)
+ : m_worldPos(worldPos)
+ , m_radius(radius)
+ , m_explosiveImpulse(explosiveImpulse)
+ , PxOverlapCallback(m_hitBuffer, sizeof(m_hitBuffer) / sizeof(m_hitBuffer[0])) {}
+
+ PxAgain processTouches(const PxOverlapHit* buffer, PxU32 nbHits)
+ {
+ for (PxU32 i = 0; i < nbHits; ++i)
+ {
+ PxRigidActor* actor = buffer[i].actor;
+ PxRigidDynamic* rigidDynamic = actor->is<PxRigidDynamic>();
+ if (rigidDynamic && !(rigidDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC))
+ {
+ if (m_actorBuffer.find(rigidDynamic) == m_actorBuffer.end())
+ {
+ m_actorBuffer.insert(rigidDynamic);
+ PxVec3 dr = rigidDynamic->getGlobalPose().transform(rigidDynamic->getCMassLocalPose()).p - m_worldPos;
+ float distance = dr.magnitude();
+ float factor = PxClamp(1.0f - (distance * distance) / (m_radius * m_radius), 0.0f, 1.0f);
+ float impulse = factor * m_explosiveImpulse * RIGIDBODY_DENSITY;
+ PxVec3 vel = dr.getNormalized() * impulse / rigidDynamic->getMass();
+ rigidDynamic->setLinearVelocity(rigidDynamic->getLinearVelocity() + vel);
+ }
+ }
+ }
+ return true;
+ }
+
+private:
+ PxOverlapHit m_hitBuffer[1000];
+ float m_explosiveImpulse;
+ std::set<PxRigidDynamic*> m_actorBuffer;
+ PxVec3 m_worldPos;
+ float m_radius;
+};
+
+void BlastFamily::explode(PxVec3 worldPos, float damageRadius, float explosiveImpulse)
+{
+ ExplodeOverlapCallback overlapCallback(worldPos, damageRadius, explosiveImpulse);
+ m_physXController.getPhysXScene().overlap(PxSphereGeometry(damageRadius), PxTransform(worldPos), overlapCallback);
+
+}
+
+// Add By Lixu Begin
+bool BlastFamily::find(ExtPxActor* actor)
+{
+ std::set<ExtPxActor*>::iterator it = m_actors.find(actor);
+ return it != m_actors.end();
+}
+// Add By Lixu End
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamily.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamily.h
new file mode 100644
index 0000000..b4611a9
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamily.h
@@ -0,0 +1,224 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_FAMILY_H
+#define BLAST_FAMILY_H
+
+#include "BlastAsset.h"
+#include "NvBlastExtPxListener.h"
+#include "NvBlastExtStressSolver.h"
+#include "NvBlastExtDamageShaders.h"
+#include <functional>
+#include <set>
+#include <map>
+
+
+class DebugRenderBuffer;
+// Add By Lixu Begin
+class RenderMaterial;
+// Add By Lixu End
+
+namespace Nv
+{
+namespace Blast
+{
+class TkFamily;
+class ExtPxManager;
+}
+}
+
+
+/**
+BlastFamily class represents 1 spawned BlastAsset, contains and manipulates all physx/blast actors spawned by fracturing it.
+Abstract class, internal actor management functions are implementation dependent and so pure virtual.
+*/
+class BlastFamily
+{
+public:
+
+ //////// public API ////////
+
+ void blast(PxVec3 worldPos, float damageRadius, float explosiveImpulse, std::function<void(ExtPxActor*)> damageFunction);
+ void explode(PxVec3 worldPos, float damageRadius, float explosiveImpulse);
+
+ void updatePreSplit(float dt);
+ void updateAfterSplit(float dt);
+
+ void drawUI();
+ void drawStatsUI();
+
+// Add By Lixu Begin
+ bool find(ExtPxActor* actor);
+ virtual void setActorSelected(const ExtPxActor& actor, bool selected) {}
+ virtual std::vector<uint32_t> getSelectedChunks() { return std::vector<uint32_t>(); }
+ virtual void clearChunksSelected() {}
+ virtual void setChunkSelected(uint32_t chunk, bool selected) {}
+ virtual void setChunkSelected(std::vector<uint32_t> depths, bool selected) {}
+ virtual bool getChunkSelected(uint32_t chunk) { return false; }
+ virtual void setActorScale(const ExtPxActor& actor, PxMat44& scale, bool replace) {}
+ virtual bool isChunkVisible(uint32_t chunkIndex) { return false; }
+ virtual void setChunkVisible(uint32_t chunkIndex, bool bVisible) {}
+ virtual void setChunkVisible(std::vector<uint32_t> depths, bool bVisible) {}
+ virtual void initTransform(physx::PxTransform t) {}
+ std::map<uint32_t, bool>& getVisibleChangedChunks() { return m_VisibleChangedChunks; }
+ void clearVisibleChangedChunks() { m_VisibleChangedChunks.clear(); }
+ virtual void getMaterial(RenderMaterial** ppRenderMaterial, bool externalSurface) {}
+ virtual void setMaterial(RenderMaterial* pRenderMaterial, bool externalSurface) {}
+// Add By Lixu End
+
+ enum DebugRenderMode
+ {
+ DEBUG_RENDER_DISABLED,
+ DEBUG_RENDER_HEALTH_GRAPH,
+ DEBUG_RENDER_CENTROIDS,
+ DEBUG_RENDER_HEALTH_GRAPH_CENTROIDS,
+ DEBUG_RENDER_JOINTS,
+ DEBUG_RENDER_STRESS_GRAPH,
+ DEBUG_RENDER_STRESS_GRAPH_NODES_IMPULSES,
+ DEBUG_RENDER_STRESS_GRAPH_BONDS_IMPULSES,
+
+ // count
+ DEBUG_RENDER_MODES_COUNT
+ };
+
+ void fillDebugRender(DebugRenderBuffer& debugRenderBuffer, DebugRenderMode mode, float renderScale);
+
+
+ //////// public getters ////////
+
+ const ExtPxFamily* getFamily() const
+ {
+ return m_pxFamily;
+ }
+
+ uint32_t getActorCount() const;
+
+ uint32_t getTotalVisibleChunkCount() const
+ {
+ return m_totalVisibleChunkCount;
+ }
+
+ size_t getFamilySize() const
+ {
+ return m_familySize;
+ }
+
+ const BlastAsset& getBlastAsset()
+ {
+ return m_blastAsset;
+ }
+
+ void resetStress();
+
+ void refreshStressSolverSettings();
+
+ void reloadStressSolver();
+
+
+ //////// consts ////////
+
+ static const float BOND_HEALTH_MAX;
+
+
+ //////// settings ////////
+
+ struct Settings
+ {
+ bool stressSolverEnabled;
+ ExtStressSolverSettings stressSolverSettings;
+ bool stressDamageEnabled;
+ NvBlastExtMaterial material;
+ };
+
+ void setSettings(const Settings& settings);
+
+ const Settings& getSettings() const
+ {
+ return m_settings;
+ }
+
+
+ //////// dtor ////////
+
+ virtual ~BlastFamily();
+
+protected:
+
+ //////// ctor ////////
+
+ BlastFamily(PhysXController& physXController, ExtPxManager& pxManager, const BlastAsset& blastAsset);
+
+ void initialize(const BlastAsset::ActorDesc& desc);
+
+
+ //////// internal virtual callbacks ////////
+
+ virtual void onActorCreated(const ExtPxActor& actor) = 0;
+ virtual void onActorUpdate(const ExtPxActor& actor) = 0;
+ virtual void onActorDestroyed(const ExtPxActor& actor) = 0;
+ virtual void onActorHealthUpdate(const ExtPxActor& pxActor) {};
+
+ virtual void onUpdate() {}
+
+
+ //////// protected data ////////
+
+ PhysXController& m_physXController;
+ ExtPxManager& m_pxManager;
+ const BlastAsset& m_blastAsset;
+ std::map<uint32_t, bool> m_VisibleChangedChunks;
+
+private:
+
+ //////// physics listener ////////
+
+ class PxManagerListener : public ExtPxListener
+ {
+ public:
+ PxManagerListener(BlastFamily* family) : m_family(family) {}
+
+ virtual void onActorCreated(ExtPxFamily& family, ExtPxActor& actor)
+ {
+ m_family->processActorCreated(family, actor);
+
+ }
+
+ virtual void onActorDestroyed(ExtPxFamily& family, ExtPxActor& actor)
+ {
+ m_family->processActorDestroyed(family, actor);
+ }
+ private:
+ BlastFamily* m_family;
+ };
+
+ friend class PxManagerListener;
+
+ //////// private methods ////////
+
+ void processActorCreated(ExtPxFamily&, ExtPxActor& actor);
+ void processActorDestroyed(ExtPxFamily&, ExtPxActor& actor);
+
+
+ //////// private data ////////
+
+ TkFamily* m_tkFamily;
+ ExtPxFamily* m_pxFamily;
+ PxManagerListener m_listener;
+ Settings m_settings;
+ size_t m_familySize;
+ uint32_t m_totalVisibleChunkCount;
+ ExtStressSolver* m_stressSolver;
+ double m_stressSolveTime;
+ std::set<ExtPxActor*> m_actors;
+ std::set<const ExtPxActor*> m_actorsToUpdateHealth;
+};
+
+
+#endif //BLAST_FAMILY_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyBoxes.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyBoxes.cpp
new file mode 100644
index 0000000..e8b7b27
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyBoxes.cpp
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+
+#include "BlastFamilyBoxes.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlastExtPxActor.h"
+#include "BlastAssetBoxes.h"
+#include "Renderer.h"
+#include "PhysXController.h"
+#include "RenderUtils.h"
+#include "PxRigidDynamic.h"
+
+using namespace physx;
+
+
+BlastFamilyBoxes::BlastFamilyBoxes(PhysXController& physXController, ExtPxManager& pxManager, Renderer& renderer, const BlastAssetBoxes& blastAsset, const BlastAsset::ActorDesc& desc)
+ : BlastFamily(physXController, pxManager, blastAsset), m_renderer(renderer)
+{
+ // prepare renderables
+ IRenderMesh* boxRenderMesh = renderer.getPrimitiveRenderMesh(PrimitiveRenderMeshType::Box);
+ RenderMaterial* primitiveRenderMaterial = physXController.getPrimitiveRenderMaterial();
+
+ const ExtPxAsset* pxAsset = m_blastAsset.getPxAsset();
+ const uint32_t chunkCount = pxAsset->getChunkCount();
+ const ExtPxChunk* chunks = pxAsset->getChunks();
+ const ExtPxSubchunk* subChunks = pxAsset->getSubchunks();
+ m_chunkRenderables.resize(chunkCount);
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ Renderable* renderable = renderer.createRenderable(*boxRenderMesh, *primitiveRenderMaterial);
+ renderable->setHidden(true);
+ renderable->setScale(subChunks[chunks[i].firstSubchunkIndex].geometry.scale.scale);
+ m_chunkRenderables[i] = renderable;
+ }
+
+ // initialize in position
+ initialize(desc);
+}
+
+BlastFamilyBoxes::~BlastFamilyBoxes()
+{
+ for (uint32_t i = 0; i < m_chunkRenderables.size(); i++)
+ {
+ m_renderer.removeRenderable(m_chunkRenderables[i]);
+ }
+}
+
+void BlastFamilyBoxes::onActorCreated(const ExtPxActor& actor)
+{
+ DirectX::XMFLOAT4 color = getRandomPastelColor();
+
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ const uint32_t chunkIndex = chunkIndices[i];
+ m_chunkRenderables[chunkIndex]->setHidden(false);
+ m_chunkRenderables[chunkIndex]->setColor(color);
+ }
+}
+
+void BlastFamilyBoxes::onActorUpdate(const ExtPxActor& actor)
+{
+ const ExtPxChunk* chunks = m_blastAsset.getPxAsset()->getChunks();
+ const ExtPxSubchunk* subChunks = m_blastAsset.getPxAsset()->getSubchunks();
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ const uint32_t chunkIndex = chunkIndices[i];
+ m_chunkRenderables[chunkIndex]->setTransform(actor.getPhysXActor().getGlobalPose() * subChunks[chunks[chunkIndex].firstSubchunkIndex].transform);
+ }
+}
+
+void BlastFamilyBoxes::onActorDestroyed(const ExtPxActor& actor)
+{
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ m_chunkRenderables[chunkIndices[i]]->setHidden(true);
+ }
+
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyBoxes.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyBoxes.h
new file mode 100644
index 0000000..1f70451
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyBoxes.h
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_FAMILY_BOXES
+#define BLAST_FAMILY_BOXES
+
+#include "BlastFamily.h"
+
+class BlastAssetBoxes;
+class Renderable;
+
+
+class BlastFamilyBoxes : public BlastFamily
+{
+public:
+ BlastFamilyBoxes(PhysXController& physXController, ExtPxManager& pxManager, Renderer& renderer, const BlastAssetBoxes& blastAsset, const BlastAsset::ActorDesc& desc);
+ virtual ~BlastFamilyBoxes();
+
+protected:
+ virtual void onActorCreated(const ExtPxActor& actor);
+ virtual void onActorUpdate(const ExtPxActor& actor);
+ virtual void onActorDestroyed(const ExtPxActor& actor);
+
+private:
+ Renderer& m_renderer;
+ std::vector<Renderable*> m_chunkRenderables;
+};
+
+
+#endif //BLAST_FAMILY_BOXES \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSimple.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSimple.cpp
new file mode 100644
index 0000000..54df3cd
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSimple.cpp
@@ -0,0 +1,638 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastFamilyModelSimple.h"
+#include "RenderUtils.h"
+#include "DeviceManager.h"
+#include "Renderer.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlastExtPxActor.h"
+#include "NvBlastTkActor.h"
+#include "NvBlastTkAsset.h"
+#include "PxRigidDynamic.h"
+
+using namespace physx;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SimpleRenderMesh
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SimpleRenderMesh : public IRenderMesh
+{
+public:
+ SimpleRenderMesh(const SimpleMesh* mesh) : m_mesh(mesh)
+ {
+ m_device = GetDeviceManager()->GetDevice();
+
+ m_inputDesc.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ m_inputDesc.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ m_inputDesc.push_back({ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ m_inputDesc.push_back({ "TEXCOORD", 1, DXGI_FORMAT_R32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+
+ m_numVertices = static_cast<uint32_t>(mesh->vertices.size());
+ m_numFaces = static_cast<uint32_t>(mesh->indices.size());
+
+ // VB
+ {
+ D3D11_SUBRESOURCE_DATA vertexBufferData;
+ ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
+ vertexBufferData.pSysMem = mesh->vertices.data();
+
+ D3D11_BUFFER_DESC bufferDesc;
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.ByteWidth = sizeof(SimpleMesh::Vertex) * m_numVertices;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+
+ V(m_device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_vertexBuffer));
+ }
+
+ // Health Buffer
+ {
+ // fill with 1.0f initially
+ std::vector<float> healths(mesh->vertices.size());
+ std::fill(healths.begin(), healths.end(), 1.0f);
+
+ D3D11_SUBRESOURCE_DATA vertexBufferData;
+ ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
+ vertexBufferData.pSysMem = healths.data();
+
+ D3D11_BUFFER_DESC bufferDesc;
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.ByteWidth = (uint32_t)(sizeof(float) * m_numVertices);
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+
+ V(m_device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_healthBuffer));
+ }
+
+ // IB
+ if (m_numFaces)
+ {
+ D3D11_SUBRESOURCE_DATA indexBufferData;
+
+ ZeroMemory(&indexBufferData, sizeof(indexBufferData));
+ indexBufferData.pSysMem = mesh->indices.data();
+
+ D3D11_BUFFER_DESC bufferDesc;
+
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ bufferDesc.ByteWidth = sizeof(uint16_t) * m_numFaces;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+
+ V(m_device->CreateBuffer(&bufferDesc, &indexBufferData, &m_indexBuffer));
+ }
+ }
+
+ ~SimpleRenderMesh()
+ {
+ SAFE_RELEASE(m_healthBuffer);
+ SAFE_RELEASE(m_vertexBuffer);
+ SAFE_RELEASE(m_indexBuffer);
+ }
+
+
+ void render(ID3D11DeviceContext& context) const
+ {
+ context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+
+ UINT strides[2] = { sizeof(SimpleMesh::Vertex), sizeof(uint32_t) };
+ UINT offsets[2] = { 0 };
+ ID3D11Buffer* buffers[2] = { m_vertexBuffer, m_healthBuffer };
+ context.IASetVertexBuffers(0, 2, buffers, strides, offsets);
+
+
+ context.IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0);
+
+ if (m_indexBuffer)
+ context.DrawIndexed(m_numFaces, 0, 0);
+ else
+ context.Draw(m_numVertices, 0);
+ }
+
+ const std::vector<D3D11_INPUT_ELEMENT_DESC>& getInputElementDesc() const { return m_inputDesc; }
+
+ const SimpleMesh* getMesh() { return m_mesh; }
+
+ void updateHealths(const std::vector<float>& healths)
+ {
+ ID3D11DeviceContext* context;
+ m_device->GetImmediateContext(&context);
+
+ // update buffer
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedRead;
+ V(context->Map(m_healthBuffer, 0, D3D11_MAP_WRITE_DISCARD, NULL, &mappedRead));
+ memcpy(mappedRead.pData, healths.data(), sizeof(float) * healths.size());
+ context->Unmap(m_healthBuffer, 0);
+ }
+
+ }
+
+// Add By Lixu Begin
+ void setScale(PxMat44 scale, bool replace)
+ {
+ std::vector<SimpleMesh::Vertex> newVertex(m_numVertices);
+ for (int v = 0; v < m_numVertices; v++)
+ {
+ newVertex[v] = m_mesh->vertices[v];
+ newVertex[v].position = scale.transform(newVertex[v].position);
+ }
+
+ D3D11_SUBRESOURCE_DATA vertexBufferData;
+ ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
+ vertexBufferData.pSysMem = newVertex.data();
+
+ D3D11_BUFFER_DESC bufferDesc;
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.ByteWidth = sizeof(SimpleMesh::Vertex) * m_numVertices;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+
+ ID3D11Buffer* pBuffer = m_vertexBuffer;
+ V(m_device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_vertexBuffer));
+ if (NULL != pBuffer)
+ {
+ pBuffer->Release();
+ pBuffer = NULL;
+ }
+
+ if (replace)
+ {
+ memcpy((void*)m_mesh->vertices.data(), newVertex.data(), bufferDesc.ByteWidth);
+ }
+ }
+// Add By Lixu End
+
+private:
+
+ ID3D11Device* m_device;
+
+ ID3D11Buffer* m_vertexBuffer;
+ ID3D11Buffer* m_healthBuffer;
+ ID3D11Buffer* m_indexBuffer;
+ uint32_t m_numFaces;
+ uint32_t m_numVertices;
+
+ std::vector<D3D11_INPUT_ELEMENT_DESC> m_inputDesc;
+
+ const SimpleMesh* m_mesh;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// BlastFamilyModelSimple
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+BlastFamilyModelSimple::BlastFamilyModelSimple(PhysXController& physXController, ExtPxManager& pxManager, Renderer& renderer, const BlastAssetModelSimple& blastAsset, const BlastAsset::ActorDesc& desc)
+ : BlastFamily(physXController, pxManager, blastAsset), m_renderer(renderer)
+{
+ // materials
+ auto materials = blastAsset.getRenderMaterials();
+
+ // model
+ const BlastModel& model = blastAsset.getModel();
+
+ // create render mesh for every BlastModel::Chunk::Mesh and renderable with it
+ const std::vector<BlastModel::Chunk>& modelChunks = model.chunks;
+ m_chunks.resize(modelChunks.size());
+ for (uint32_t chunkIndex = 0; chunkIndex < modelChunks.size(); chunkIndex++)
+ {
+ const std::vector<BlastModel::Chunk::Mesh>& meshes = modelChunks[chunkIndex].meshes;
+ std::vector<SimpleRenderMesh*>& renderMeshes = m_chunks[chunkIndex].renderMeshes;
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+// Add By Lixu Begin
+ std::vector<Renderable*>& ex_Renderables = m_chunks[chunkIndex].ex_Renderables;
+ ex_Renderables.clear();
+ std::vector<Renderable*>& in_Renderables = m_chunks[chunkIndex].in_Renderables;
+ in_Renderables.clear();
+// Add By Lixu End
+ renderMeshes.resize(meshes.size());
+ renderables.resize(meshes.size());
+ for (uint32_t i = 0; i < meshes.size(); i++)
+ {
+ renderMeshes[i] = new SimpleRenderMesh(&meshes[i].mesh);
+
+ uint32_t materialIndex = model.chunks[chunkIndex].meshes[i].materialIndex;
+ Renderable* renderable = renderer.createRenderable(*renderMeshes[i], *materials[materialIndex]);
+ renderable->setHidden(true);
+ renderables[i] = renderable;
+// Add By Lixu Begin
+ if (materialIndex == 0)
+ {
+ ex_Renderables.push_back(renderable);
+ }
+ else if (materialIndex == 1)
+ {
+ in_Renderables.push_back(renderable);
+ }
+// Add By Lixu End
+ }
+ }
+
+ // initialize in position
+ initialize(desc);
+}
+
+BlastFamilyModelSimple::~BlastFamilyModelSimple()
+{
+ // release all chunks
+ for (uint32_t chunkIndex = 0; chunkIndex < m_chunks.size(); chunkIndex++)
+ {
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (uint32_t i = 0; i < m_chunks[chunkIndex].renderables.size(); i++)
+ {
+ m_renderer.removeRenderable(m_chunks[chunkIndex].renderables[i]);
+ SAFE_DELETE(m_chunks[chunkIndex].renderMeshes[i]);
+ }
+ }
+}
+
+void BlastFamilyModelSimple::onActorCreated(const ExtPxActor& actor)
+{
+ // separate color for every material
+ std::vector<DirectX::XMFLOAT4> colors;
+
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (uint32_t r = 0; r < renderables.size(); r++)
+ {
+ if (colors.size() <= r)
+ colors.push_back(getRandomPastelColor());
+
+ renderables[r]->setHidden(false);
+ renderables[r]->setColor(colors[r]);
+
+ m_VisibleChangedChunks[chunkIndex] = true;
+ }
+ }
+}
+
+void BlastFamilyModelSimple::onActorUpdate(const ExtPxActor& actor)
+{
+// Add By Lixu Begin
+ uint32_t shapesCount = actor.getPhysXActor().getNbShapes();
+ PxTransform lp;
+ if (shapesCount > 0)
+ {
+ std::vector<PxShape*> shapes(shapesCount);
+ actor.getPhysXActor().getShapes(&shapes[0], shapesCount);
+ PxShape* shape = shapes[0];
+ lp = shape->getLocalPose();
+ }
+// Add By Lixu End
+
+ const ExtPxChunk* chunks = m_blastAsset.getPxAsset()->getChunks();
+ const ExtPxSubchunk* subChunks = m_blastAsset.getPxAsset()->getSubchunks();
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (Renderable* r : renderables)
+ {
+// Add By Lixu Begin
+ r->setTransform(actor.getPhysXActor().getGlobalPose() * lp * subChunks[chunks[chunkIndex].firstSubchunkIndex].transform);
+// Add By Lixu End
+ }
+ }
+}
+
+void BlastFamilyModelSimple::onActorDestroyed(const ExtPxActor& actor)
+{
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setHidden(true);
+
+ m_VisibleChangedChunks[chunkIndex] = false;
+ }
+ }
+}
+
+void BlastFamilyModelSimple::onActorHealthUpdate(const ExtPxActor& actor)
+{
+ TkActor& tkActor = actor.getTkActor();
+ const TkAsset* tkAsset = tkActor.getAsset();
+
+ const float* bondHealths = tkActor.getBondHealths();
+ uint32_t nodeCount = tkActor.getGraphNodeCount();
+ if (nodeCount == 0) // subsupport chunks don't have graph nodes
+ return;
+
+ std::vector<uint32_t> nodes(tkActor.getGraphNodeCount());
+ tkActor.getGraphNodeIndices(nodes.data(), static_cast<uint32_t>(nodes.size()));
+
+ const NvBlastChunk* chunks = tkAsset->getChunks();
+ const NvBlastBond* bonds = tkAsset->getBonds();
+
+ const NvBlastSupportGraph graph = tkAsset->getGraph();
+
+ std::vector<float> healthBuffer;
+
+ for (uint32_t node0 : nodes)
+ {
+ uint32_t chunkIndex = graph.chunkIndices[node0];
+
+ if (chunkIndex >= m_chunks.size())
+ continue;
+
+ std::vector<SimpleRenderMesh*>& meshes = m_chunks[chunkIndex].renderMeshes;
+ const auto& renderables = m_chunks[chunkIndex].renderables;
+ for (uint32_t i = 0; i < meshes.size(); ++i)
+ {
+ if(renderables[i]->isHidden())
+ continue;
+
+ SimpleRenderMesh* renderMesh = meshes[i];
+
+ const SimpleMesh* mesh = renderMesh->getMesh();
+ healthBuffer.resize(mesh->vertices.size());
+
+ for (uint32_t vertexIndex = 0; vertexIndex < mesh->vertices.size(); vertexIndex++)
+ {
+ PxVec3 position = mesh->vertices[vertexIndex].position;
+ float health = 0.0f;
+ float healthDenom = 0.0f;
+
+ for (uint32_t adjacencyIndex = graph.adjacencyPartition[node0]; adjacencyIndex < graph.adjacencyPartition[node0 + 1]; adjacencyIndex++)
+ {
+ uint32_t node1 = graph.adjacentNodeIndices[adjacencyIndex];
+ uint32_t bondIndex = graph.adjacentBondIndices[adjacencyIndex];
+ float bondHealth = PxClamp(bondHealths[bondIndex] / BOND_HEALTH_MAX, 0.0f, 1.0f);
+ const NvBlastBond& solverBond = bonds[bondIndex];
+ const PxVec3& centroid = reinterpret_cast<const PxVec3&>(solverBond.centroid);
+
+ float factor = 1.0f / (centroid - position).magnitudeSquared();
+
+ health += bondHealth * factor;
+ healthDenom += factor;
+ }
+
+ healthBuffer[vertexIndex] = healthDenom > 0.0f ? health / healthDenom : 1.0f;
+ }
+
+ renderMesh->updateHealths(healthBuffer);
+ }
+ }
+}
+
+// Add By Lixu Begin
+void BlastFamilyModelSimple::setActorSelected(const ExtPxActor& actor, bool selected)
+{
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setSelected(selected);
+ }
+ }
+}
+
+void BlastFamilyModelSimple::setChunkSelected(uint32_t chunk, bool selected)
+{
+ if (chunk > m_chunks.size())
+ return;
+
+ std::vector<Renderable*>& renderables = m_chunks[chunk].renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setSelected(select);
+ }
+}
+
+void BlastFamilyModelSimple::setChunkSelected(std::vector<uint32_t> depths, bool selected)
+{
+ for (size_t i = 0; i < depths.size(); ++i)
+ {
+ const std::vector<uint32_t> indexes = m_blastAsset.getChunkIndexesByDepth(depths[i]);
+ for (size_t j = 0; j < indexes.size(); ++j)
+ {
+ setChunkSelected(indexes[j], selected);
+ }
+ }
+}
+
+void BlastFamilyModelSimple::clearChunksSelected()
+{
+ size_t count = m_chunks.size();
+ for (size_t chunkIndex = 0; chunkIndex < count; ++chunkIndex)
+ {
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setSelected(false);
+ }
+ }
+}
+
+bool BlastFamilyModelSimple::getChunkSelected(uint32_t chunk)
+{
+ if (chunk > m_chunks.size())
+ return false;
+
+ std::vector<Renderable*>& renderables = m_chunks[chunk].renderables;
+ for (Renderable* r : renderables)
+ {
+ for (Renderable* r : renderables)
+ {
+ if (r->isSelected())
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+std::vector<uint32_t> BlastFamilyModelSimple::getSelectedChunks()
+{
+ std::vector<uint32_t> selectedChunks;
+ size_t count = m_chunks.size();
+ for (size_t chunkIndex = 0; chunkIndex < count; ++chunkIndex)
+ {
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (Renderable* r : renderables)
+ {
+ if (r->isSelected())
+ {
+ selectedChunks.push_back(chunkIndex);
+ break;
+ }
+ }
+ }
+ return selectedChunks;
+}
+
+void BlastFamilyModelSimple::setActorScale(const ExtPxActor& actor, PxMat44& scale, bool replace)
+{
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setMeshScale(scale, replace);
+ }
+ }
+}
+
+bool BlastFamilyModelSimple::isChunkVisible(uint32_t chunkIndex)
+{
+ if (chunkIndex < 0 || chunkIndex >= m_chunks.size())
+ {
+ return false;
+ }
+
+ bool bVisible = false;
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ if (renderables.size() > 0)
+ {
+ bVisible = !renderables[0]->isHidden();
+ }
+ return bVisible;
+}
+
+void BlastFamilyModelSimple::setChunkVisible(uint32_t chunkIndex, bool bVisible)
+{
+ if (chunkIndex < 0 || chunkIndex >= m_chunks.size())
+ {
+ return;
+ }
+
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setHidden(!bVisible);
+ }
+}
+
+void BlastFamilyModelSimple::setChunkVisible(std::vector<uint32_t> depths, bool bVisible)
+{
+ for (size_t i = 0; i < depths.size(); ++i)
+ {
+ const std::vector<uint32_t> indexes = m_blastAsset.getChunkIndexesByDepth(depths[i]);
+ for (size_t j = 0; j < indexes.size(); ++j)
+ {
+ setChunkVisible(indexes[j], bVisible);
+ }
+ }
+}
+
+void BlastFamilyModelSimple::initTransform(physx::PxTransform t)
+{
+ int chunkSize = m_chunks.size();
+ for (int i = 0; i < chunkSize; i++)
+ {
+ std::vector<Renderable*>& renderables = m_chunks[i].renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setTransform(t);
+ }
+ }
+}
+
+void BlastFamilyModelSimple::getMaterial(RenderMaterial** ppRenderMaterial, bool externalSurface)
+{
+ *ppRenderMaterial = nullptr;
+
+ int chunkSize = m_chunks.size();
+ if (chunkSize == 0)
+ {
+ return;
+ }
+
+ if (externalSurface)
+ {
+ for (int i = 0; i < chunkSize; i++)
+ {
+ std::vector<Renderable*>& renderables = m_chunks[i].ex_Renderables;
+ if (renderables.size() > 0)
+ {
+ RenderMaterial& m = renderables[0]->getMaterial();
+ *ppRenderMaterial = &m;
+ return;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < chunkSize; i++)
+ {
+ std::vector<Renderable*>& renderables = m_chunks[i].in_Renderables;
+ if (renderables.size() > 0)
+ {
+ RenderMaterial& m = renderables[0]->getMaterial();
+ *ppRenderMaterial = &m;
+ return;
+ }
+ }
+ }
+}
+
+void BlastFamilyModelSimple::setMaterial(RenderMaterial* pRenderMaterial, bool externalSurface)
+{
+ RenderMaterial* p = pRenderMaterial;
+ if (p == nullptr)
+ {
+ p = RenderMaterial::getDefaultRenderMaterial();
+ }
+
+ int chunkSize = m_chunks.size();
+ if (externalSurface)
+ {
+ for (int i = 0; i < chunkSize; i++)
+ {
+ std::vector<Renderable*>& renderables = m_chunks[i].ex_Renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setMaterial(*p);
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < chunkSize; i++)
+ {
+ std::vector<Renderable*>& renderables = m_chunks[i].in_Renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setMaterial(*p);
+ }
+ }
+ }
+}
+// Add By Lixu End \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSimple.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSimple.h
new file mode 100644
index 0000000..ed51133
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSimple.h
@@ -0,0 +1,72 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_FAMILY_MODEL_SIMPLE_H
+#define BLAST_FAMILY_MODEL_SIMPLE_H
+
+#include "BlastFamily.h"
+#include "BlastAssetModelSimple.h"
+
+class SimpleRenderMesh;
+class Renderable;
+class Renderer;
+
+class BlastFamilyModelSimple : public BlastFamily
+{
+public:
+ //////// ctor ////////
+
+ BlastFamilyModelSimple(PhysXController& physXController, ExtPxManager& pxManager, Renderer& renderer, const BlastAssetModelSimple& blastAsset, const BlastAsset::ActorDesc& desc);
+ virtual ~BlastFamilyModelSimple();
+
+// Add By Lixu Begin
+ virtual void setActorSelected(const ExtPxActor& actor, bool selected);
+ virtual void clearChunksSelected();
+ virtual void setChunkSelected(uint32_t chunk, bool selected);
+ virtual void setChunkSelected(std::vector<uint32_t> depths, bool selected);
+ virtual bool getChunkSelected(uint32_t chunk);
+ virtual std::vector<uint32_t> getSelectedChunks();
+ virtual void setActorScale(const ExtPxActor& actor, PxMat44& scale, bool replace);
+ virtual bool isChunkVisible(uint32_t chunkIndex);
+ virtual void setChunkVisible(uint32_t chunkIndex, bool bVisible);
+ virtual void setChunkVisible(std::vector<uint32_t> depths, bool bVisible);
+ virtual void initTransform(physx::PxTransform t);
+ virtual void getMaterial(RenderMaterial** ppRenderMaterial, bool externalSurface);
+ virtual void setMaterial(RenderMaterial* pRenderMaterial, bool externalSurface);
+// Add By Lixu End
+
+protected:
+ //////// abstract implementation ////////
+
+ virtual void onActorCreated(const ExtPxActor& actor);
+ virtual void onActorUpdate(const ExtPxActor& actor);
+ virtual void onActorDestroyed(const ExtPxActor& actor);
+ virtual void onActorHealthUpdate(const ExtPxActor& pxActor);
+
+private:
+ //////// internal data ////////
+
+ Renderer& m_renderer;
+
+ struct Chunk
+ {
+ std::vector<SimpleRenderMesh*> renderMeshes;
+ std::vector<Renderable*> renderables;
+// Add By Lixu Begin
+ std::vector<Renderable*> ex_Renderables;
+ std::vector<Renderable*> in_Renderables;
+// Add By Lixu End
+ };
+
+ std::vector<Chunk> m_chunks;
+};
+
+
+#endif //BLAST_FAMILY_MODEL_SIMPLE_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSkinned.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSkinned.cpp
new file mode 100644
index 0000000..c0731d5
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSkinned.cpp
@@ -0,0 +1,167 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastFamilyModelSkinned.h"
+#include "RenderUtils.h"
+#include "Renderer.h"
+#include "SkinnedRenderMesh.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlastExtPxActor.h"
+#include "NvBlastTkActor.h"
+#include "PxRigidDynamic.h"
+
+using namespace physx;
+
+BlastFamilyModelSkinned::BlastFamilyModelSkinned(PhysXController& physXController, ExtPxManager& pxManager, Renderer& renderer, const BlastAssetModelSkinned& blastAsset, const BlastAsset::ActorDesc& desc)
+ : BlastFamily(physXController, pxManager, blastAsset), m_renderer(renderer), m_visibleActorsDirty(true)
+{
+ // materials
+ auto materials = blastAsset.getRenderMaterials();
+
+ const BlastModel& model = blastAsset.getModel();
+
+ // finalize (create) sub model
+ auto finalizeSubModelFunction = [&](SubModel* subModel, std::vector<const SimpleMesh*>& subModelMeshes, RenderMaterial& renderMaterial)
+ {
+ subModel->skinnedRenderMesh = new SkinnedRenderMesh(subModelMeshes);
+ subModel->renderable = renderer.createRenderable(*subModel->skinnedRenderMesh, renderMaterial);
+ subModel->renderable->setColor(getRandomPastelColor());
+ };
+
+ // create at least one submodel per every material (if mesh count is too high, more then one sub model per material to be created)
+ SubModel* subModel = nullptr;
+ std::vector<const SimpleMesh*> subModelMeshes;
+ subModelMeshes.reserve(model.chunks.size());
+ for (uint32_t materialIndex = 0; materialIndex < model.materials.size(); materialIndex++)
+ {
+ for (uint32_t chunkIndex = 0; chunkIndex < model.chunks.size(); chunkIndex++)
+ {
+ const BlastModel::Chunk& chunk = model.chunks[chunkIndex];
+ for (const BlastModel::Chunk::Mesh& mesh : chunk.meshes)
+ {
+ if (mesh.materialIndex == materialIndex)
+ {
+ // init new submodel?
+ if (subModel == nullptr)
+ {
+ m_subModels.push_back(SubModel());
+ subModel = &m_subModels.back();
+ subModel->chunkIdToBoneMap.resize(model.chunks.size());
+ std::fill(subModel->chunkIdToBoneMap.begin(), subModel->chunkIdToBoneMap.end(), SubModel::INVALID_BONE_ID);
+ subModelMeshes.clear();
+ }
+
+ // add mesh to map and list
+ subModel->chunkIdToBoneMap[chunkIndex] = (uint32_t)subModelMeshes.size();
+ subModelMeshes.push_back(&(mesh.mesh));
+
+ // mesh reached limit?
+ if (subModelMeshes.size() == SkinnedRenderMesh::MeshesCountMax)
+ {
+ finalizeSubModelFunction(subModel, subModelMeshes, *materials[materialIndex]);
+ subModel = nullptr;
+ }
+ }
+ }
+ }
+
+ // finalize subModel for this material
+ if (subModel && subModelMeshes.size() > 0)
+ {
+ finalizeSubModelFunction(subModel, subModelMeshes, *materials[materialIndex]);
+ subModel = nullptr;
+ }
+ }
+
+ // reserve for scratch
+ m_visibleBones.reserve(model.chunks.size());
+ m_visibleBoneTransforms.reserve(model.chunks.size());
+
+ // initialize in position
+ initialize(desc);
+}
+
+BlastFamilyModelSkinned::~BlastFamilyModelSkinned()
+{
+ for (uint32_t subModelIndex = 0; subModelIndex < m_subModels.size(); subModelIndex++)
+ {
+ m_renderer.removeRenderable(m_subModels[subModelIndex].renderable);
+ SAFE_DELETE(m_subModels[subModelIndex].skinnedRenderMesh);
+ }
+}
+
+void BlastFamilyModelSkinned::onActorCreated(const ExtPxActor& actor)
+{
+ m_visibleActors.insert(&actor);
+ m_visibleActorsDirty = true;
+}
+
+void BlastFamilyModelSkinned::onActorUpdate(const ExtPxActor& actor)
+{
+}
+
+void BlastFamilyModelSkinned::onActorDestroyed(const ExtPxActor& actor)
+{
+ m_visibleActors.erase(&actor);
+ m_visibleActorsDirty = true;
+}
+
+void BlastFamilyModelSkinned::onUpdate()
+{
+ // visible actors changed this frame?
+ if (m_visibleActorsDirty)
+ {
+ for (const SubModel& model : m_subModels)
+ {
+ // pass visible chunks list to render mesh
+ m_visibleBones.clear();
+ for (const ExtPxActor* actor : m_visibleActors)
+ {
+ const uint32_t* chunkIndices = actor->getChunkIndices();
+ uint32_t chunkCount = actor->getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; ++i)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ uint32_t boneIndex = model.chunkIdToBoneMap[chunkIndex];
+ if (boneIndex != SubModel::INVALID_BONE_ID)
+ {
+ m_visibleBones.push_back(boneIndex);
+ }
+ }
+ }
+ model.skinnedRenderMesh->updateVisibleMeshes(m_visibleBones);
+ }
+
+ m_visibleActorsDirty = false;
+ }
+
+ // update and pass chunk transforms
+ const ExtPxChunk* chunks = m_blastAsset.getPxAsset()->getChunks();
+ const ExtPxSubchunk* subChunks = m_blastAsset.getPxAsset()->getSubchunks();
+ for (const SubModel& model : m_subModels)
+ {
+ m_visibleBoneTransforms.clear();
+ for (const ExtPxActor* actor : m_visibleActors)
+ {
+ const uint32_t* chunkIndices = actor->getChunkIndices();
+ uint32_t chunkCount = actor->getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; ++i)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ uint32_t boneIndex = model.chunkIdToBoneMap[chunkIndex];
+ if (boneIndex != SubModel::INVALID_BONE_ID)
+ {
+ m_visibleBoneTransforms.push_back(PxMat44(actor->getPhysXActor().getGlobalPose() * subChunks[chunks[chunkIndex].firstSubchunkIndex].transform));
+ }
+ }
+ }
+ model.skinnedRenderMesh->updateVisibleMeshTransforms(m_visibleBoneTransforms);
+ }
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSkinned.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSkinned.h
new file mode 100644
index 0000000..aeb9353
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFamilyModelSkinned.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_FAMILY_MODEL_SKINNED_H
+#define BLAST_FAMILY_MODEL_SKINNED_H
+
+#include "BlastFamily.h"
+#include "BlastAssetModelSkinned.h"
+
+class SkinnedRenderMesh;
+class Renderable;
+
+class BlastFamilyModelSkinned : public BlastFamily
+{
+public:
+ //////// ctor ////////
+
+ BlastFamilyModelSkinned(PhysXController& physXController, ExtPxManager& pxManager, Renderer& renderer, const BlastAssetModelSkinned& blastAsset, const BlastAsset::ActorDesc& desc);
+ virtual ~BlastFamilyModelSkinned();
+
+protected:
+ //////// abstract implementation ////////
+
+ virtual void onActorCreated(const ExtPxActor& actor);
+ virtual void onActorUpdate(const ExtPxActor& actor);
+ virtual void onActorDestroyed(const ExtPxActor& actor);
+
+ virtual void onUpdate();
+
+private:
+ //////// internal data ////////
+
+ Renderer& m_renderer;
+
+ struct SubModel
+ {
+ static const uint32_t INVALID_BONE_ID = ~(uint32_t)0;
+
+ Renderable* renderable = nullptr;
+ SkinnedRenderMesh* skinnedRenderMesh = nullptr;
+ std::vector<uint32_t> chunkIdToBoneMap;
+ };
+ std::vector<SubModel> m_subModels;
+
+ std::set<const ExtPxActor*> m_visibleActors;
+ bool m_visibleActorsDirty;
+
+ //////// scratch buffers ////////
+
+ std::vector<uint32_t> m_visibleBones;
+ std::vector<PxMat44> m_visibleBoneTransforms;
+
+};
+
+
+#endif //BLAST_FAMILY_MODEL_SKINNED_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFractureTool.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFractureTool.cpp
new file mode 100644
index 0000000..aa738b9
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFractureTool.cpp
@@ -0,0 +1,171 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastFractureTool.h"
+#include <BlastAssetModel.h>
+#include <BlastAsset.h>
+#include <NvBlastExtPxAsset.h>
+#include <NvBlastTkAsset.h>
+
+void BlastFractureTool::free()
+{
+ std::vector<Nv::Blast::Mesh*>::iterator it;
+ for (it = chunkMeshes.begin(); it != chunkMeshes.end(); it++)
+ {
+ delete (*it);
+ (*it) = nullptr;
+ }
+ chunkMeshes.clear();
+}
+
+void BlastFractureTool::setSourceAsset(const BlastAsset* pBlastAsset)
+{
+ free();
+
+ BlastAssetModel* pBlastAssetModel = (BlastAssetModel*)pBlastAsset;
+ const BlastModel& blastModel = pBlastAssetModel->getModel();
+ const std::vector<BlastModel::Chunk>& chunks = blastModel.chunks;
+ int chunkSize = chunks.size();
+ if (chunkSize == 0)
+ {
+ return;
+ }
+
+ chunkMeshes.resize(chunkSize, nullptr);
+ for (int cs = 0; cs < chunkSize; cs++)
+ {
+ const BlastModel::Chunk& chunk = chunks[cs];
+ const std::vector<BlastModel::Chunk::Mesh>& meshes = chunk.meshes;
+ int meshSize = meshes.size();
+
+ if (meshSize == 0)
+ {
+ continue;
+ }
+
+ std::vector<physx::PxVec3> positions;
+ std::vector<physx::PxVec3> normals;
+ std::vector<physx::PxVec2> uv;
+ std::vector<uint32_t> ind;
+ std::vector<int> faceBreakPoint;
+ std::vector<uint32_t> materialIndexes;
+ uint16_t curIndex = 0;
+ for (int ms = 0; ms < meshSize; ms++)
+ {
+ const BlastModel::Chunk::Mesh& mesh = meshes[ms];
+ materialIndexes.push_back(mesh.materialIndex);
+ const SimpleMesh& simpleMesh = mesh.mesh;
+ const std::vector<SimpleMesh::Vertex>& vertices = simpleMesh.vertices;
+ const std::vector<uint16_t>& indices = simpleMesh.indices;
+
+ int NumVertices = vertices.size();
+ for (uint32_t i = 0; i < NumVertices; ++i)
+ {
+ positions.push_back(physx::PxVec3(vertices[i].position.x, vertices[i].position.y, vertices[i].position.z));
+ normals.push_back(physx::PxVec3(vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z));
+ uv.push_back(physx::PxVec2(vertices[i].uv.x, vertices[i].uv.y));
+ }
+ int NumIndices = indices.size();
+ for (uint32_t i = 0; i < NumIndices; ++i)
+ {
+ ind.push_back(indices[i] + curIndex);
+ }
+ curIndex += NumIndices;
+ faceBreakPoint.push_back(NumIndices / 3);
+ }
+
+ PxVec3* nr = (!normals.empty()) ? normals.data() : 0;
+ PxVec2* uvp = (!uv.empty()) ? uv.data() : 0;
+ Nv::Blast::Mesh* pMesh = new Nv::Blast::Mesh(
+ positions.data(), nr, uvp, static_cast<uint32_t>(positions.size()),
+ ind.data(), static_cast<uint32_t>(ind.size()));
+
+ int curFaceIndex = 0;
+ int curFaceBreakPoint = faceBreakPoint[curFaceIndex];
+ uint32_t curMaterialIndex = materialIndexes[curFaceIndex];
+ for (int fc = 0; fc < pMesh->getFacetCount(); fc++)
+ {
+ if (fc >= curFaceBreakPoint)
+ {
+ curFaceIndex++;
+ curFaceBreakPoint += faceBreakPoint[curFaceIndex];
+ curMaterialIndex = materialIndexes[curFaceIndex];
+ }
+
+ pMesh->getFacet(fc)->userData = curMaterialIndex;
+ }
+
+ chunkMeshes[cs] = pMesh;
+ }
+
+ const ExtPxAsset* pExtPxAsset = pBlastAsset->getPxAsset();
+ const TkAsset& tkAsset = pExtPxAsset->getTkAsset();
+
+ std::vector<int32_t> parentIds;
+ parentIds.resize(chunkSize);
+ parentIds.assign(chunkSize, -1);
+ {
+ const NvBlastChunk* pNvBlastChunk = tkAsset.getChunks();
+ for (uint32_t i = 0; i < chunkSize; ++i)
+ {
+ parentIds[i] = pNvBlastChunk[i].parentChunkIndex;
+ }
+ }
+ std::vector<bool> isLeafs;
+ isLeafs.resize(chunkSize);
+ isLeafs.assign(chunkSize, false);
+ {
+ const NvBlastSupportGraph supportGraph = tkAsset.getGraph();
+ for (uint32_t i = 0; i < supportGraph.nodeCount; ++i)
+ {
+ const uint32_t chunkIndex = supportGraph.chunkIndices[i];
+ isLeafs[chunkIndex] = true;
+ }
+ }
+
+ setSourceMesh(chunkMeshes[0]);
+
+ mChunkData.resize(chunkSize);
+ mChunkData[0].parent = parentIds[0];
+ mChunkData[0].isLeaf = isLeafs[0];
+ mChunkData[0].chunkId = 0;
+ Nv::Blast::Mesh* mesh = nullptr;
+ for (int cs = 1; cs < chunkSize; cs++)
+ {
+ if (chunkMeshes[cs] == nullptr)
+ continue;
+ mChunkData[cs].meshData = new Nv::Blast::Mesh(*chunkMeshes[cs]);
+ mChunkData[cs].parent = parentIds[cs];
+ mChunkData[cs].chunkId = cs;
+ mChunkData[cs].isLeaf = isLeafs[cs];
+
+ mesh = mChunkData[cs].meshData;
+ Nv::Blast::Vertex* verticesBuffer = mesh->getVertices();
+ for (uint32_t i = 0; i < mesh->getVerticesCount(); ++i)
+ {
+ verticesBuffer[i].p = (verticesBuffer[i].p - mOffset) * (1.0f / mScaleFactor);
+ }
+ mesh->getBoundingBox().minimum = (mesh->getBoundingBox().minimum - mOffset) * (1.0f / mScaleFactor);
+ mesh->getBoundingBox().maximum = (mesh->getBoundingBox().maximum - mOffset) * (1.0f / mScaleFactor);
+ for (uint32_t i = 0; i < mesh->getFacetCount(); ++i)
+ {
+ mesh->getFacet(i)->userData = chunkMeshes[cs]->getFacet(i)->userData;
+ }
+ }
+}
+
+Nv::Blast::Mesh* BlastFractureTool::getSourceMesh(int32_t chunkId)
+{
+ if (chunkId < 0 || chunkId >= chunkMeshes.size())
+ {
+ return nullptr;
+ }
+ return chunkMeshes[chunkId];
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFractureTool.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFractureTool.h
new file mode 100644
index 0000000..b50ccf3
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastFractureTool.h
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_FRACTURETOOL_H
+#define BLAST_FRACTURETOOL_H
+
+#include "NvBlastExtAuthoringFractureTool.h"
+
+class BlastAsset;
+namespace Nv
+{
+ namespace Blast
+ {
+ class Mesh;
+ }
+}
+
+class BlastFractureTool : public Nv::Blast::FractureTool
+{
+public:
+ BlastFractureTool(NvBlastLog logCallback = nullptr) : FractureTool(logCallback) {}
+ ~BlastFractureTool() { free(); }
+
+ void setSourceAsset(const BlastAsset* pBlastAsset);
+
+ Nv::Blast::Mesh* getSourceMesh(int32_t chunkId);
+
+private:
+ void free();
+
+ std::vector<Nv::Blast::Mesh*> chunkMeshes;
+};
+
+#endif //BLAST_FRACTURETOOL_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastModel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastModel.cpp
new file mode 100644
index 0000000..d231a6c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastModel.cpp
@@ -0,0 +1,167 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastModel.h"
+
+// Add By Lixu Begin
+//#define TINYOBJLOADER_IMPLEMENTATION
+// Add By Lixu End
+#include "tiny_obj_loader.h"
+
+
+using namespace physx;
+
+BlastModelPtr BlastModel::loadFromFileTinyLoader(const char* path)
+{
+// Add By Lixu Begin
+ BlastModel* model = new BlastModel();
+// Add By Lixu End
+
+ std::vector<tinyobj::shape_t> shapes;
+ std::vector<tinyobj::material_t> mats;
+ std::string err;
+ std::string mtlPath;
+ for (size_t i = strnlen(path, 255) - 1; i >= 0; --i)
+ {
+ if (path[i] == '\\')
+ {
+ mtlPath.resize(i + 2, 0);
+ strncpy(&mtlPath[0], path, i + 1);
+ break;
+ }
+ }
+
+
+ bool ret = tinyobj::LoadObj(shapes, mats, err, path, mtlPath.data());
+
+ // can't load?
+ if (!ret)
+ return false;
+
+ // one submodel per material
+ uint32_t materialsCount = (uint32_t)mats.size();
+ model->materials.resize(materialsCount);
+
+ // fill submodel materials
+ for (uint32_t i = 0; i < materialsCount; i++)
+ {
+ tinyobj::material_t *pMaterial = &mats[i];
+
+ if (!pMaterial->diffuse_texname.empty())
+ {
+// Add By Lixu Begin
+ model->materials[i].name = pMaterial->name;
+// Add By Lixu End
+ model->materials[i].diffuseTexture = pMaterial->diffuse_texname;
+ }
+ }
+
+ // estimate
+ model->chunks.reserve(shapes.size() / materialsCount + 1);
+
+ if (shapes.size() > 0)
+ {
+ uint32_t meshIndex = 0;
+ for (uint32_t m = 0; m < shapes.size(); m++)
+ {
+ tinyobj::shape_t& pMesh = shapes[m];
+ uint32_t materialIndex;
+ uint32_t chunkIndex;
+ sscanf(pMesh.name.data(), "%d_%d", &chunkIndex, &materialIndex);
+ if (model->chunks.size() <= chunkIndex)
+ {
+ model->chunks.resize(chunkIndex + 1);
+ }
+ model->chunks[chunkIndex].meshes.push_back(Chunk::Mesh());
+ Chunk::Mesh& mesh = model->chunks[chunkIndex].meshes.back();
+
+ mesh.materialIndex = materialIndex;
+ SimpleMesh& chunkMesh = mesh.mesh;
+
+ PxVec3 emin(FLT_MAX, FLT_MAX, FLT_MAX);
+ PxVec3 emax(FLT_MIN, FLT_MIN, FLT_MIN);
+
+
+
+ // create an index buffer
+ chunkMesh.indices.resize(pMesh.mesh.indices.size());
+
+ // Check if all faces are triangles
+ bool allTriangles = true;
+ for (uint32_t i = 0; i < pMesh.mesh.num_vertices.size(); ++i)
+ {
+ if (pMesh.mesh.num_vertices[i] != 3)
+ {
+ allTriangles = false;
+ break;
+ }
+ }
+
+ if (pMesh.mesh.indices.size() > 0 && allTriangles)
+ {
+ for (uint32_t i = 0; i < pMesh.mesh.indices.size(); i += 3)
+ {
+ chunkMesh.indices[i] = (uint16_t)pMesh.mesh.indices[i + 2];
+ chunkMesh.indices[i + 1] = (uint16_t)pMesh.mesh.indices[i + 1];
+ chunkMesh.indices[i + 2] = (uint16_t)pMesh.mesh.indices[i];
+ }
+ }
+ // create vertex buffer
+ chunkMesh.vertices.resize(pMesh.mesh.positions.size() / 3);
+ // copy positions
+ uint32_t indexer = 0;
+ for (uint32_t i = 0; i < pMesh.mesh.positions.size() / 3; i++)
+ {
+ chunkMesh.vertices[i].position.x = pMesh.mesh.positions[indexer];
+ chunkMesh.vertices[i].position.y = pMesh.mesh.positions[indexer + 1];
+ chunkMesh.vertices[i].position.z = pMesh.mesh.positions[indexer + 2];
+ indexer += 3;
+ // calc min/max
+ emin = emin.minimum(chunkMesh.vertices[i].position);
+ emax = emax.maximum(chunkMesh.vertices[i].position);
+ }
+
+ // copy normals
+ if (pMesh.mesh.normals.size() > 0)
+ {
+ indexer = 0;
+ for (uint32_t i = 0; i < pMesh.mesh.normals.size() / 3; i++)
+ {
+ chunkMesh.vertices[i].normal.x = pMesh.mesh.normals[indexer];
+ chunkMesh.vertices[i].normal.y = pMesh.mesh.normals[indexer + 1];
+ chunkMesh.vertices[i].normal.z = pMesh.mesh.normals[indexer + 2];
+
+ indexer += 3;
+ }
+ }
+
+ // copy uv
+ if (pMesh.mesh.texcoords.size() > 0)
+ {
+ indexer = 0;
+ for (uint32_t i = 0; i < pMesh.mesh.texcoords.size() / 2; i++)
+ {
+ chunkMesh.vertices[i].uv.x = pMesh.mesh.texcoords[indexer];
+ chunkMesh.vertices[i].uv.y = pMesh.mesh.texcoords[indexer + 1];
+ indexer += 2;
+ }
+ }
+
+ // assign extents
+ chunkMesh.extents = (emax - emin) * 0.5f;
+
+ // get the center
+ chunkMesh.center = emin + chunkMesh.extents;
+
+ }
+ }
+
+ return model;
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastModel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastModel.h
new file mode 100644
index 0000000..683a343
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastModel.h
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_MODEL_H
+#define BLAST_MODEL_H
+
+#include "Mesh.h"
+#include <vector>
+#include <memory>
+
+
+class BlastModel;
+// Add By Lixu Begin
+typedef BlastModel* BlastModelPtr;
+// Add By Lixu End
+
+/**
+BlastModel struct represents graphic model.
+Now only loading from .obj file is supported.
+Can have >=0 materials
+Every chunk can have multiple meshes (1 for every material)
+*/
+class BlastModel
+{
+public:
+ struct Material
+ {
+// Add By Lixu Begin
+ std::string name;
+// Add By Lixu End
+ std::string diffuseTexture;
+ };
+
+ struct Chunk
+ {
+ struct Mesh
+ {
+ uint32_t materialIndex;
+ SimpleMesh mesh;
+ };
+
+ std::vector<Mesh> meshes;
+ };
+
+ std::vector<Material> materials;
+ std::vector<Chunk> chunks;
+
+ static BlastModelPtr loadFromFileTinyLoader(const char* path);
+private:
+ BlastModel() {}
+};
+
+#endif // ifndef BLAST_MODEL_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastReplay.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastReplay.cpp
new file mode 100644
index 0000000..13d2b33
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastReplay.cpp
@@ -0,0 +1,160 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "BlastReplay.h"
+#include "NvBlastTk.h"
+#include "NvBlastExtPxManager.h"
+#include "NvBlastExtPxFamily.h"
+#include "SampleProfiler.h"
+
+
+using namespace std::chrono;
+
+BlastReplay::BlastReplay() : m_sync(nullptr)
+{
+ m_sync = ExtSync::create();
+ reset();
+}
+
+BlastReplay::~BlastReplay()
+{
+ m_sync->release();
+ clearBuffer();
+}
+
+void BlastReplay::addFamily(TkFamily* family)
+{
+ family->addListener(*m_sync);
+}
+
+void BlastReplay::removeFamily(TkFamily* family)
+{
+ family->removeListener(*m_sync);
+}
+
+void BlastReplay::startRecording(ExtPxManager& manager, bool syncFamily, bool syncPhysics)
+{
+ if (isRecording())
+ return;
+
+ m_sync->releaseSyncBuffer();
+
+ if (syncFamily || syncPhysics)
+ {
+ std::vector<ExtPxFamily*> families(manager.getFamilyCount());
+ manager.getFamilies(families.data(), (uint32_t)families.size());
+ for (ExtPxFamily* family : families)
+ {
+ if (syncPhysics)
+ {
+ m_sync->syncFamily(*family);
+ }
+ else if (syncFamily)
+ {
+ m_sync->syncFamily(family->getTkFamily());
+ }
+ }
+ }
+
+ m_isRecording = true;
+}
+
+void BlastReplay::stopRecording()
+{
+ if (!isRecording())
+ return;
+
+ const ExtSyncEvent*const* buffer;
+ uint32_t size;
+ m_sync->acquireSyncBuffer(buffer, size);
+
+ clearBuffer();
+ m_buffer.resize(size);
+ for (uint32_t i = 0; i < size; ++i)
+ {
+ m_buffer[i] = buffer[i]->clone();
+ }
+
+ // TODO: sort by ts ? make sure?
+ //m_buffer.sort
+
+ m_sync->releaseSyncBuffer();
+
+ m_isRecording = false;
+}
+
+void BlastReplay::startPlayback(ExtPxManager& manager, TkGroup* group)
+{
+ if (isPlaying() || !hasRecord())
+ return;
+
+ m_isPlaying = true;
+ m_startTime = steady_clock::now();
+ m_nextEventIndex = 0;
+ m_firstEventTs = m_buffer[0]->timestamp;
+ m_pxManager = &manager;
+ m_group = group;
+}
+
+void BlastReplay::stopPlayback()
+{
+ if (!isPlaying())
+ return;
+
+ m_isPlaying = false;
+ m_pxManager = nullptr;
+ m_group = nullptr;
+}
+
+void BlastReplay::update()
+{
+ if (isPlaying())
+ {
+ PROFILER_SCOPED_FUNCTION();
+
+ auto now = steady_clock::now();
+ auto mil = duration_cast<milliseconds>((now - m_startTime));
+ bool stop = true;
+ while (m_nextEventIndex < m_buffer.size())
+ {
+ const ExtSyncEvent* e = m_buffer[m_nextEventIndex];
+ auto t = e->timestamp - m_firstEventTs;
+ if (t < (uint64_t)mil.count())
+ {
+ m_sync->applySyncBuffer(m_pxManager->getFramework(), &e, 1, m_group, m_pxManager);
+ m_nextEventIndex++;
+ }
+ else
+ {
+ stop = false;
+ break;
+ }
+ }
+
+ if (stop)
+ stopPlayback();
+ }
+}
+
+void BlastReplay::reset()
+{
+ m_isPlaying = false;
+ m_isRecording = false;
+ m_sync->releaseSyncBuffer();
+}
+
+void BlastReplay::clearBuffer()
+{
+ for (auto e : m_buffer)
+ {
+ e->release();
+ }
+ m_buffer.clear();
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastReplay.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastReplay.h
new file mode 100644
index 0000000..a85c996
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/blast/BlastReplay.h
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef BLAST_REPLAY_H
+#define BLAST_REPLAY_H
+
+#include "NvBlastExtSync.h"
+#include <chrono>
+
+using namespace Nv::Blast;
+
+class BlastReplay
+{
+public:
+ BlastReplay();
+ ~BlastReplay();
+
+ bool isRecording() const
+ {
+ return m_isRecording;
+ }
+
+ bool isPlaying() const
+ {
+ return m_isPlaying;
+ }
+
+ bool hasRecord() const
+ {
+ return m_buffer.size() > 0;
+ }
+
+ size_t getEventCount() const
+ {
+ return isRecording() ? m_sync->getSyncBufferSize() : m_buffer.size();
+ }
+
+ uint32_t getCurrentEventIndex() const
+ {
+ return m_nextEventIndex;
+ }
+
+ void addFamily(TkFamily* family);
+ void removeFamily(TkFamily* family);
+
+ void startRecording(ExtPxManager& manager, bool syncFamily, bool syncPhysics);
+ void stopRecording();
+ void startPlayback(ExtPxManager& manager, TkGroup* group);
+ void stopPlayback();
+ void update();
+ void reset();
+
+private:
+ void clearBuffer();
+
+ ExtPxManager* m_pxManager;
+ TkGroup* m_group;
+ std::chrono::steady_clock::time_point m_startTime;
+ uint64_t m_firstEventTs;
+ uint32_t m_nextEventIndex;
+ bool m_isRecording;
+ bool m_isPlaying;
+ ExtSync* m_sync;
+ std::vector<ExtSyncEvent*> m_buffer;
+};
+
+
+#endif // ifndef BLAST_REPLAY_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/Application.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/Application.cpp
new file mode 100644
index 0000000..955d841
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/Application.cpp
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "Application.h"
+#include <DirectXMath.h>
+#include "XInput.h"
+#include "DXUTMisc.h"
+
+
+Application::Application(DeviceManager* pDeviceManager)
+{
+ m_deviceManager = pDeviceManager;
+}
+
+void Application::addControllerToFront(IApplicationController* controller)
+{
+ m_controllers.push_back(controller);
+ m_deviceManager->AddControllerToFront(controller);
+}
+
+int Application::init()
+{
+ // FirstPersonCamera uses this timer, without it it will be FPS-dependent
+ DXUTGetGlobalTimer()->Start();
+
+ m_deviceManager->DeviceCreated();
+ m_deviceManager->BackBufferResized();
+
+ for (auto it = m_controllers.begin(); it != m_controllers.end(); it++)
+ (*it)->onInitialize();
+
+ for (auto it = m_controllers.begin(); it != m_controllers.end(); it++)
+ (*it)->onSampleStart();
+
+ m_deviceManager->SetVsyncEnabled(false);
+
+ return 0;
+}
+
+int Application::run()
+{
+ m_deviceManager->MessageLoop();
+
+ return 0;
+}
+
+int Application::free()
+{
+ for (auto it = m_controllers.rbegin(); it != m_controllers.rend(); it++)
+ (*it)->onSampleStop();
+
+ for (auto it = m_controllers.rbegin(); it != m_controllers.rend(); it++)
+ (*it)->onTerminate();
+
+ //m_deviceManager->Shutdown(); // destructor will call this function
+ delete m_deviceManager;
+
+ return 0;
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/Application.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/Application.h
new file mode 100644
index 0000000..f0e0601
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/Application.h
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef APPLICATION_H
+#define APPLICATION_H
+
+#include <DeviceManager.h>
+#include <vector>
+#include <string>
+
+/**
+ISampleController adds more onstart and onstop callbacks to IVisualController
+*/
+class IApplicationController : public IVisualController
+{
+ public:
+ virtual void onInitialize() {}
+ virtual void onSampleStart() {}
+ virtual void onSampleStop() {}
+ virtual void onTerminate() {}
+};
+
+
+/**
+Main manager which runs sample.
+You have to add controllers to it which will receive all the start, animate, render etc. callbacks.
+*/
+class Application
+{
+public:
+ Application(DeviceManager* pDeviceManager);
+ void addControllerToFront(IApplicationController* controller);
+
+ const std::vector<IApplicationController*>& getControllers() const
+ {
+ return m_controllers;
+ }
+
+ int init();
+ int run();
+ int free();
+
+private:
+ DeviceManager* m_deviceManager;
+ std::vector<IApplicationController*> m_controllers;
+// std::wstring m_sampleName;
+};
+
+
+#endif //APPLICATION_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/DeviceManager.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/DeviceManager.cpp
new file mode 100644
index 0000000..b29fb86
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/DeviceManager.cpp
@@ -0,0 +1,801 @@
+// TAGRELEASE: PUBLIC
+
+#include "DeviceManager.h"
+#include <WinUser.h>
+#include <Windows.h>
+#include <assert.h>
+#include <sstream>
+#include <algorithm>
+#include <vector>
+
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
+#endif
+
+#undef min
+#undef max
+
+namespace
+{
+ bool IsNvDeviceID(UINT id)
+ {
+ return id == 0x10DE;
+ }
+
+ // Find an adapter whose name contains the given string.
+ IDXGIAdapter* FindAdapter(const WCHAR* targetName, bool& isNv)
+ {
+ IDXGIAdapter* targetAdapter = NULL;
+ IDXGIFactory* IDXGIFactory_0001 = NULL;
+ HRESULT hres = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&IDXGIFactory_0001);
+ if (hres != S_OK)
+ {
+ printf("ERROR in CreateDXGIFactory, %s@%d.\nFor more info, get log from debug D3D runtime: (1) Install DX SDK, and enable Debug D3D from DX Control Panel Utility. (2) Install and start DbgView. (3) Try running the program again.\n",__FILE__,__LINE__);
+ return targetAdapter;
+ }
+
+ // changed by Junma Lixu
+ std::vector<IDXGIAdapter*> adapters;
+ // check current adapter first. EnumAdapters could fail on some device
+ IDXGIAdapter* pAdapter = nullptr;
+ ID3D11Device* pD3dDevice = nullptr;
+ ID3D11DeviceContext* pD3dDeviceContext = nullptr;
+ DWORD createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG;
+ D3D_FEATURE_LEVEL fl;
+ // This following code is the robust way to get all possible feature levels while handling DirectX 11.0 systems:
+ // please read https://blogs.msdn.microsoft.com/chuckw/2014/02/05/anatomy-of-direct3d-11-create-device/
+ D3D_FEATURE_LEVEL lvl[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0,
+ D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 };
+ HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
+ createDeviceFlags, lvl, _countof(lvl),
+ D3D11_SDK_VERSION, &pD3dDevice, &fl, &pD3dDeviceContext);
+ if (pD3dDevice)
+ {
+ IDXGIDevice* dxgiDevice = nullptr;
+ hr = pD3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
+ if (SUCCEEDED(hr))
+ {
+ hr = dxgiDevice->GetAdapter(&pAdapter);
+ if (pAdapter)
+ {
+ adapters.push_back(pAdapter);
+ }
+ SAFE_RELEASE(dxgiDevice);
+ }
+ SAFE_RELEASE(pD3dDeviceContext);
+ SAFE_RELEASE(pD3dDevice);
+ }
+
+ // Enum Adapters
+ unsigned int adapterNo = 0;
+ while (SUCCEEDED(hres = IDXGIFactory_0001->EnumAdapters(adapterNo, (IDXGIAdapter**)&pAdapter)))
+ {
+ adapters.push_back(pAdapter);
+ adapterNo++;
+ }
+ if (wcslen(targetName) != 0)
+ {
+ // find the adapter with specified name
+ for (int i = 0; i < adapters.size(); ++i)
+ {
+ IDXGIAdapter* pAdapter = adapters[i];
+ DXGI_ADAPTER_DESC aDesc;
+ pAdapter->GetDesc(&aDesc);
+ std::wstring aName = aDesc.Description;
+ if (aName.find(targetName) != std::string::npos)
+ {
+ targetAdapter = pAdapter;
+ isNv = IsNvDeviceID(aDesc.VendorId);
+ }
+ }
+ }
+ else
+ {
+ // no name specified, find one NV adapter
+ for (int i = 0; i < adapters.size(); ++i)
+ {
+ IDXGIAdapter* pAdapter = adapters[i];
+ DXGI_ADAPTER_DESC aDesc;
+ pAdapter->GetDesc(&aDesc);
+ std::wstring aName = aDesc.Description;
+ if (IsNvDeviceID(aDesc.VendorId))
+ {
+ targetAdapter = pAdapter;
+ isNv = true;
+ }
+ }
+ }
+ if (targetAdapter == nullptr)
+ targetAdapter = adapters[0];
+ for (int i = 0; i < adapters.size(); ++i)
+ {
+ IDXGIAdapter* pAdapter = adapters[i];
+ if (pAdapter != targetAdapter)
+ {
+ pAdapter->Release();
+ }
+ }
+
+ if (IDXGIFactory_0001)
+ IDXGIFactory_0001->Release();
+
+ return targetAdapter;
+ }
+
+ // Adjust window rect so that it is centred on the given adapter. Clamps to fit if it's too big.
+ RECT MoveWindowOntoAdapter(IDXGIAdapter* targetAdapter, const RECT& rect)
+ {
+ assert(targetAdapter != NULL);
+
+ RECT result = rect;
+ HRESULT hres = S_OK;
+ unsigned int outputNo = 0;
+ while (SUCCEEDED(hres))
+ {
+ IDXGIOutput* pOutput = NULL;
+ hres = targetAdapter->EnumOutputs(outputNo++, &pOutput);
+
+ if (SUCCEEDED(hres) && pOutput)
+ {
+ DXGI_OUTPUT_DESC OutputDesc;
+ pOutput->GetDesc( &OutputDesc );
+ const RECT desktop = OutputDesc.DesktopCoordinates;
+ const int centreX = (int) desktop.left + (int)(desktop.right - desktop.left) / 2;
+ const int centreY = (int) desktop.top + (int)(desktop.bottom - desktop.top) / 2;
+ const int winW = rect.right - rect.left;
+ const int winH = rect.bottom - rect.top;
+ int left = centreX - winW/2;
+ int right = left + winW;
+ int top = centreY - winH/2;
+ int bottom = top + winH;
+ result.left = std::max(left, (int) desktop.left);
+ result.right = std::min(right, (int) desktop.right);
+ result.bottom = std::min(bottom, (int) desktop.bottom);
+ result.top = std::max(top, (int) desktop.top);
+ pOutput->Release();
+
+ // If there is more than one output, go with the first found. Multi-monitor support could go here.
+ break;
+ }
+ }
+ return result;
+ }
+}
+
+HRESULT
+DeviceManager::CreateWindowDeviceAndSwapChain(const DeviceCreationParameters& params)
+{
+ IDXGIAdapter* targetAdapter = FindAdapter(params.adapterNameSubstring, m_IsNvidia);
+ if (targetAdapter)
+ {
+ RECT rect = { 0, 0, params.backBufferWidth, params.backBufferHeight };
+ rect = MoveWindowOntoAdapter(targetAdapter, rect);
+ }
+ else
+ {
+ return E_FAIL;
+ }
+
+ HRESULT hr = E_FAIL;
+
+ m_hWnd = params.hWnd;
+
+ RECT clientRect;
+ GetClientRect(m_hWnd, &clientRect);
+ UINT width = clientRect.right - clientRect.left;
+ UINT height = clientRect.bottom - clientRect.top;
+
+ ZeroMemory(&m_SwapChainDesc, sizeof(m_SwapChainDesc));
+ m_SwapChainDesc.BufferCount = params.swapChainBufferCount;
+ m_SwapChainDesc.BufferDesc.Width = width;
+ m_SwapChainDesc.BufferDesc.Height = height;
+ m_SwapChainDesc.BufferDesc.Format = params.swapChainFormat;
+ m_SwapChainDesc.BufferDesc.RefreshRate.Numerator = params.refreshRate;
+ m_SwapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
+ m_SwapChainDesc.BufferUsage = params.swapChainUsage;
+ m_SwapChainDesc.OutputWindow = m_hWnd;
+ m_SwapChainDesc.SampleDesc.Count = params.swapChainSampleCount;
+ m_SwapChainDesc.SampleDesc.Quality = params.swapChainSampleQuality;
+ m_SwapChainDesc.Windowed = !params.startFullscreen;
+ m_SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+
+ // The D3D documentation says that if adapter is non-null, driver type must be unknown. Why not put
+ // this logic in the CreateDevice fns then?!?
+ const D3D_DRIVER_TYPE dType = (targetAdapter)? D3D_DRIVER_TYPE_UNKNOWN: params.driverType;
+
+ hr = D3D11CreateDeviceAndSwapChain(
+ targetAdapter, // pAdapter
+ dType, // DriverType
+ NULL, // Software
+ params.createDeviceFlags, // Flags
+ &params.featureLevel, // pFeatureLevels
+ 1, // FeatureLevels
+ D3D11_SDK_VERSION, // SDKVersion
+ &m_SwapChainDesc, // pSwapChainDesc
+ &m_SwapChain, // ppSwapChain
+ &m_Device, // ppDevice
+ NULL, // pFeatureLevel
+ &m_ImmediateContext // ppImmediateContext
+ );
+
+ if (targetAdapter)
+ targetAdapter->Release();
+
+ if(FAILED(hr))
+ return hr;
+
+ m_DepthStencilDesc.ArraySize = 1;
+ m_DepthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+ m_DepthStencilDesc.CPUAccessFlags = 0;
+ m_DepthStencilDesc.Format = params.depthStencilFormat;
+ m_DepthStencilDesc.Width = width;
+ m_DepthStencilDesc.Height = height;
+ m_DepthStencilDesc.MipLevels = 1;
+ m_DepthStencilDesc.MiscFlags = 0;
+ m_DepthStencilDesc.SampleDesc.Count = params.swapChainSampleCount;
+ m_DepthStencilDesc.SampleDesc.Quality = 0;
+ m_DepthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
+
+ hr = CreateRenderTargetAndDepthStencil();
+
+ return hr;
+}
+
+void
+DeviceManager::Shutdown()
+{
+ if(m_SwapChain && GetWindowState() == kWindowFullscreen)
+ m_SwapChain->SetFullscreenState(false, NULL);
+
+ DeviceDestroyed();
+
+ // changed by Junma Lixu
+ //SAFE_RELEASE(m_BackBufferRTV);
+ //SAFE_RELEASE(m_DepthStencilDSV);
+ //SAFE_RELEASE(m_DepthStencilBuffer);
+
+// g_DeviceManagerInstance = NULL;
+
+ // changed by Junma Lixu
+ //SAFE_RELEASE(m_ImmediateContext);
+ //SAFE_RELEASE(m_SwapChain);
+
+#if defined(DEBUG) || defined(_DEBUG)
+ ID3D11Debug * d3dDebug = nullptr;
+ if (nullptr != m_Device)
+ {
+ ID3D11DeviceContext* pCtx;
+ m_Device->GetImmediateContext(&pCtx);
+ pCtx->ClearState();
+ pCtx->Flush();
+ pCtx->Release();
+ if (SUCCEEDED(m_Device->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<void**>(&d3dDebug))))
+ {
+ d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
+ d3dDebug->Release();
+ }
+ }
+#endif
+
+ // changed by Junma Lixu
+ //SAFE_RELEASE(m_Device);
+
+ if(m_hWnd)
+ {
+ DestroyWindow(m_hWnd);
+ m_hWnd = NULL;
+ }
+}
+
+HRESULT
+DeviceManager::CreateRenderTargetAndDepthStencil()
+{
+ HRESULT hr;
+
+ ID3D11Texture2D *backBuffer = NULL;
+ hr = m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBuffer);
+ if (FAILED(hr))
+ return hr;
+
+ hr = m_Device->CreateRenderTargetView(backBuffer, NULL, &m_BackBufferRTV);
+ backBuffer->Release();
+ if (FAILED(hr))
+ return hr;
+
+ if(m_DepthStencilDesc.Format != DXGI_FORMAT_UNKNOWN)
+ {
+ hr = m_Device->CreateTexture2D(&m_DepthStencilDesc, NULL, &m_DepthStencilBuffer);
+ if (FAILED(hr))
+ return hr;
+
+ hr = m_Device->CreateDepthStencilView(m_DepthStencilBuffer, NULL, &m_DepthStencilDSV);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ return S_OK;
+}
+
+#include "SimpleScene.h"
+#include "RenderInterface.h"
+
+void
+DeviceManager::MessageLoop()
+{
+ LARGE_INTEGER newTime;
+ QueryPerformanceCounter(&newTime);
+
+ double elapsedSeconds = (m_FixedFrameInterval >= 0)
+ ? m_FixedFrameInterval
+ : (double)(newTime.QuadPart - previousTime.QuadPart) / (double)perfFreq.QuadPart;
+
+ if (m_SwapChain && GetWindowState() != kWindowMinimized)
+ {
+ Animate(elapsedSeconds);
+ // changed by Junma Lixu
+ CoreLib* pCore = CoreLib::Inst();
+ RenderInterface::SwitchToDX11();
+ pCore->SimpleScene_Draw_DX11();
+ Render();
+ RenderInterface::FlushDX11();
+ RenderInterface::PresentRenderWindow();
+ //m_SwapChain->Present(m_SyncInterval, 0);
+ Sleep(0);
+ }
+ else
+ {
+ // Release CPU resources when idle
+ Sleep(1);
+ }
+
+ {
+ m_vFrameTimes.push_back(elapsedSeconds);
+ double timeSum = 0;
+ for (auto it = m_vFrameTimes.begin(); it != m_vFrameTimes.end(); it++)
+ timeSum += *it;
+
+ if (timeSum > m_AverageTimeUpdateInterval)
+ {
+ m_AverageFrameTime = timeSum / (double)m_vFrameTimes.size();
+ m_vFrameTimes.clear();
+ }
+ }
+
+ previousTime = newTime;
+}
+
+LRESULT
+DeviceManager::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_DESTROY:
+ case WM_CLOSE:
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_SYSKEYDOWN:
+ if(wParam == VK_F4)
+ {
+ PostQuitMessage(0);
+ return 0;
+ }
+ break;
+
+ case WM_ENTERSIZEMOVE:
+ m_InSizingModalLoop = true;
+ m_NewWindowSize.cx = m_SwapChainDesc.BufferDesc.Width;
+ m_NewWindowSize.cy = m_SwapChainDesc.BufferDesc.Height;
+ break;
+
+ case WM_EXITSIZEMOVE:
+ m_InSizingModalLoop = false;
+ ResizeSwapChain();
+ break;
+
+ case WM_SIZE:
+ // Ignore the WM_SIZE event if there is no device,
+ // or if the window has been minimized (size == 0),
+ // or if it has been restored to the previous size (this part is tested inside ResizeSwapChain)
+ if (m_Device && (lParam != 0))
+ {
+ m_NewWindowSize.cx = LOWORD(lParam);
+ m_NewWindowSize.cy = HIWORD(lParam);
+
+ if(!m_InSizingModalLoop)
+ ResizeSwapChain();
+ }
+ }
+
+ if( uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST )
+ {
+ // processing messages front-to-back
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ if((*it)->IsEnabled())
+ {
+ // for kb/mouse messages, 0 means the message has been handled
+ if(0 == (*it)->MsgProc(hWnd, uMsg, wParam, lParam))
+ return 0;
+ }
+ }
+ }
+
+ if (uMsg >= WM_KEYFIRST && uMsg <= WM_KEYLAST)
+ {
+ return 0;
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+void
+DeviceManager::ResizeSwapChain()
+{
+ // changed by Junma Lixu
+ RenderPlugin* pPlugin = RenderPlugin::Instance();
+ D3DHandles handles;
+ SetWindowDeviceAndSwapChain(pPlugin->GetDeviceHandles(handles));
+ BackBufferResized();
+ return;
+
+ if (m_NewWindowSize.cx == (LONG)m_SwapChainDesc.BufferDesc.Width &&
+ m_NewWindowSize.cy == (LONG)m_SwapChainDesc.BufferDesc.Height)
+ return;
+
+ m_SwapChainDesc.BufferDesc.Width = m_NewWindowSize.cx;
+ m_SwapChainDesc.BufferDesc.Height = m_NewWindowSize.cy;
+
+ ID3D11RenderTargetView *nullRTV = NULL;
+ m_ImmediateContext->OMSetRenderTargets(1, &nullRTV, NULL);
+ SAFE_RELEASE(m_BackBufferRTV);
+ SAFE_RELEASE(m_DepthStencilDSV);
+ SAFE_RELEASE(m_DepthStencilBuffer);
+
+ if (m_SwapChain)
+ {
+ // Resize the swap chain
+ m_SwapChain->ResizeBuffers(m_SwapChainDesc.BufferCount, m_SwapChainDesc.BufferDesc.Width,
+ m_SwapChainDesc.BufferDesc.Height, m_SwapChainDesc.BufferDesc.Format,
+ m_SwapChainDesc.Flags);
+
+ m_DepthStencilDesc.Width = m_NewWindowSize.cx;
+ m_DepthStencilDesc.Height = m_NewWindowSize.cy;
+
+ CreateRenderTargetAndDepthStencil();
+
+ BackBufferResized();
+ }
+}
+
+void
+DeviceManager::Render()
+{
+ D3D11_VIEWPORT viewport = { 0.0f, 0.0f, (float)m_SwapChainDesc.BufferDesc.Width, (float)m_SwapChainDesc.BufferDesc.Height, 0.0f, 1.0f };
+
+ // rendering back-to-front
+ for(auto it = m_vControllers.rbegin(); it != m_vControllers.rend(); it++)
+ {
+ if((*it)->IsEnabled())
+ {
+ m_ImmediateContext->OMSetRenderTargets(1, &m_BackBufferRTV, m_DepthStencilDSV);
+ m_ImmediateContext->RSSetViewports(1, &viewport);
+
+ (*it)->Render(m_Device, m_ImmediateContext, m_BackBufferRTV, m_DepthStencilDSV);
+ }
+ }
+
+ m_ImmediateContext->OMSetRenderTargets(0, NULL, NULL);
+}
+
+void
+DeviceManager::Animate(double fElapsedTimeSeconds)
+{
+ // front-to-back, but the order shouldn't matter
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ if((*it)->IsEnabled())
+ {
+ (*it)->Animate(fElapsedTimeSeconds);
+ }
+ }
+}
+
+void
+DeviceManager::DeviceCreated()
+{
+ // creating resources front-to-back
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ (*it)->DeviceCreated(m_Device);
+ }
+}
+
+void
+DeviceManager::DeviceDestroyed()
+{
+ // releasing resources back-to-front
+ for(auto it = m_vControllers.rbegin(); it != m_vControllers.rend(); it++)
+ {
+ (*it)->DeviceDestroyed();
+ }
+}
+
+void
+DeviceManager::BackBufferResized()
+{
+ if(m_SwapChain == NULL)
+ return;
+
+ DXGI_SURFACE_DESC backSD;
+ backSD.Format = m_SwapChainDesc.BufferDesc.Format;
+ backSD.Width = m_SwapChainDesc.BufferDesc.Width;
+ backSD.Height = m_SwapChainDesc.BufferDesc.Height;
+ backSD.SampleDesc = m_SwapChainDesc.SampleDesc;
+
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ (*it)->BackBufferResized(m_Device, &backSD);
+ }
+}
+
+HRESULT
+DeviceManager::ChangeBackBufferFormat(DXGI_FORMAT format, UINT sampleCount)
+{
+ HRESULT hr = E_FAIL;
+
+ if((format == DXGI_FORMAT_UNKNOWN || format == m_SwapChainDesc.BufferDesc.Format) &&
+ (sampleCount == 0 || sampleCount == m_SwapChainDesc.SampleDesc.Count))
+ return S_FALSE;
+
+ if(m_Device)
+ {
+ bool fullscreen = (GetWindowState() == kWindowFullscreen);
+ if(fullscreen)
+ m_SwapChain->SetFullscreenState(false, NULL);
+
+ IDXGISwapChain* newSwapChain = NULL;
+ DXGI_SWAP_CHAIN_DESC newSwapChainDesc = m_SwapChainDesc;
+
+ if(format != DXGI_FORMAT_UNKNOWN)
+ newSwapChainDesc.BufferDesc.Format = format;
+ if(sampleCount != 0)
+ newSwapChainDesc.SampleDesc.Count = sampleCount;
+
+ IDXGIAdapter* pDXGIAdapter = GetDXGIAdapter();
+
+ IDXGIFactory* pDXGIFactory = NULL;
+ pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&pDXGIFactory));
+
+ hr = pDXGIFactory->CreateSwapChain(m_Device, &newSwapChainDesc, &newSwapChain);
+
+ pDXGIFactory->Release();
+ pDXGIAdapter->Release();
+
+ if (FAILED(hr))
+ {
+ if(fullscreen)
+ m_SwapChain->SetFullscreenState(true, NULL);
+
+ return hr;
+ }
+
+ SAFE_RELEASE(m_BackBufferRTV);
+ SAFE_RELEASE(m_SwapChain);
+ SAFE_RELEASE(m_DepthStencilBuffer);
+ SAFE_RELEASE(m_DepthStencilDSV);
+
+ m_SwapChain = newSwapChain;
+ m_SwapChainDesc = newSwapChainDesc;
+
+ m_DepthStencilDesc.SampleDesc.Count = sampleCount;
+
+ if(fullscreen)
+ m_SwapChain->SetFullscreenState(true, NULL);
+
+ CreateRenderTargetAndDepthStencil();
+ BackBufferResized();
+ }
+
+ return S_OK;
+}
+
+void
+DeviceManager::AddControllerToFront(IVisualController* pController)
+{
+ m_vControllers.remove(pController);
+ m_vControllers.push_front(pController);
+}
+
+void
+DeviceManager::AddControllerToBack(IVisualController* pController)
+{
+ m_vControllers.remove(pController);
+ m_vControllers.push_back(pController);
+}
+
+void
+DeviceManager::RemoveController(IVisualController* pController)
+{
+ m_vControllers.remove(pController);
+}
+
+HRESULT
+DeviceManager::ResizeWindow(int width, int height)
+{
+ if(m_SwapChain == NULL)
+ return E_FAIL;
+
+ RECT rect;
+ GetWindowRect(m_hWnd, &rect);
+
+ ShowWindow(m_hWnd, SW_RESTORE);
+
+ if(!MoveWindow(m_hWnd, rect.left, rect.top, width, height, true))
+ return E_FAIL;
+
+ // No need to call m_SwapChain->ResizeBackBuffer because MoveWindow will send WM_SIZE, which calls that function.
+
+ return S_OK;
+}
+
+#define WINDOW_STYLE_NORMAL (WS_OVERLAPPEDWINDOW | WS_VISIBLE)
+#define WINDOW_STYLE_FULLSCREEN (WS_POPUP | WS_SYSMENU | WS_VISIBLE)
+
+HRESULT
+DeviceManager::EnterFullscreenMode(int width, int height)
+{
+ if(m_SwapChain == NULL)
+ return E_FAIL;
+
+ if(GetWindowState() == kWindowFullscreen)
+ return S_FALSE;
+
+ if(width <= 0 || height <= 0)
+ {
+ width = m_SwapChainDesc.BufferDesc.Width;
+ height = m_SwapChainDesc.BufferDesc.Height;
+ }
+
+ SetWindowLong(m_hWnd, GWL_STYLE, WINDOW_STYLE_FULLSCREEN);
+ MoveWindow(m_hWnd, 0, 0, width, height, true);
+
+ HRESULT hr = m_SwapChain->SetFullscreenState(true, NULL);
+
+ if(FAILED(hr))
+ {
+ SetWindowLong(m_hWnd, GWL_STYLE, WINDOW_STYLE_NORMAL);
+ return hr;
+ }
+
+ UpdateWindow(m_hWnd);
+ m_SwapChain->GetDesc(&m_SwapChainDesc);
+
+ return S_OK;
+}
+
+HRESULT
+DeviceManager::LeaveFullscreenMode(int windowWidth, int windowHeight)
+{
+ if(m_SwapChain == NULL)
+ return E_FAIL;
+
+ if(GetWindowState() != kWindowFullscreen)
+ return S_FALSE;
+
+ HRESULT hr = m_SwapChain->SetFullscreenState(false, NULL);
+ if(FAILED(hr)) return hr;
+
+ SetWindowLong(m_hWnd, GWL_STYLE, WINDOW_STYLE_NORMAL);
+
+ if(windowWidth <= 0 || windowHeight <= 0)
+ {
+ windowWidth = m_SwapChainDesc.BufferDesc.Width;
+ windowHeight = m_SwapChainDesc.BufferDesc.Height;
+ }
+
+ RECT rect = { 0, 0, windowWidth, windowHeight };
+ AdjustWindowRect(&rect, WINDOW_STYLE_NORMAL, FALSE);
+ MoveWindow(m_hWnd, 0, 0, rect.right - rect.left, rect.bottom - rect.top, true);
+ UpdateWindow(m_hWnd);
+
+ m_SwapChain->GetDesc(&m_SwapChainDesc);
+
+ return S_OK;
+}
+
+HRESULT
+DeviceManager::ToggleFullscreen()
+{
+ if(GetWindowState() == kWindowFullscreen)
+ return LeaveFullscreenMode();
+ else
+ return EnterFullscreenMode();
+}
+
+DeviceManager::WindowState
+DeviceManager::GetWindowState()
+{
+ if(m_SwapChain && !m_SwapChainDesc.Windowed)
+ return kWindowFullscreen;
+
+ if(m_hWnd == INVALID_HANDLE_VALUE)
+ return kWindowNone;
+
+ if(IsZoomed(m_hWnd))
+ return kWindowMaximized;
+
+ if(IsIconic(m_hWnd))
+ return kWindowMinimized;
+
+ return kWindowNormal;
+}
+
+HRESULT
+DeviceManager::GetDisplayResolution(int& width, int& height)
+{
+ if(m_hWnd != INVALID_HANDLE_VALUE)
+ {
+ HMONITOR monitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTOPRIMARY);
+ MONITORINFO info;
+ info.cbSize = sizeof(MONITORINFO);
+
+ if(GetMonitorInfo(monitor, &info))
+ {
+ width = info.rcMonitor.right - info.rcMonitor.left;
+ height = info.rcMonitor.bottom - info.rcMonitor.top;
+ return S_OK;
+ }
+ }
+
+ return E_FAIL;
+}
+
+IDXGIAdapter*
+DeviceManager::GetDXGIAdapter()
+{
+ if(!m_Device)
+ return NULL;
+
+ IDXGIDevice* pDXGIDevice = NULL;
+ m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDXGIDevice));
+
+ IDXGIAdapter* pDXGIAdapter = NULL;
+ pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pDXGIAdapter));
+
+ pDXGIDevice->Release();
+
+ return pDXGIAdapter;
+}
+
+// added by Junma Lixu
+void
+DeviceManager::SetWindowHandle(HWND hWnd)
+{
+ m_hWnd = hWnd;
+}
+
+HRESULT
+DeviceManager::SetWindowDeviceAndSwapChain(D3DHandles& deviceHandles)
+{
+ ID3D11Device* pDevice = (ID3D11Device*)(deviceHandles.pDevice);
+ ID3D11DeviceContext* pImmediateContext = (ID3D11DeviceContext*)(deviceHandles.pDeviceContext);
+ if (pDevice == nullptr || pImmediateContext == nullptr)
+ {
+ return E_FAIL;
+ }
+
+ m_Device = pDevice;
+ m_ImmediateContext = pImmediateContext;
+ m_SwapChain = deviceHandles.pDXGISwapChain;
+ HRESULT res0 = m_SwapChain->GetDesc(&m_SwapChainDesc);
+ assert(m_SwapChainDesc.OutputWindow == m_hWnd);
+
+ m_BackBufferRTV = (ID3D11RenderTargetView*)deviceHandles.pD3D11RenderTargetView;
+ m_DepthStencilBuffer = (ID3D11Texture2D*)deviceHandles.pD3D11DepthBuffer;
+ m_DepthStencilDSV = (ID3D11DepthStencilView*)deviceHandles.pD3D11DepthStencilView;
+ m_DepthStencilBuffer->GetDesc(&m_DepthStencilDesc);
+ //m_DepthStencilDSV->GetDesc(&);
+ return S_OK;
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/DeviceManager.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/DeviceManager.h
new file mode 100644
index 0000000..bd6f7e2
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/DeviceManager.h
@@ -0,0 +1,179 @@
+// TAGRELEASE: PUBLIC
+
+#pragma once
+#include <Windows.h>
+#include <DXGI.h>
+#include <D3D11.h>
+#include <list>
+// added by Junma Lixu
+#include "RenderPlugin.h"
+
+struct DeviceCreationParameters
+{
+ bool startMaximized;
+ bool startFullscreen;
+ int backBufferWidth;
+ int backBufferHeight;
+ int refreshRate;
+ int swapChainBufferCount;
+ DXGI_FORMAT swapChainFormat;
+ DXGI_FORMAT depthStencilFormat;
+ DXGI_USAGE swapChainUsage;
+ int swapChainSampleCount;
+ int swapChainSampleQuality;
+ UINT createDeviceFlags;
+ D3D_DRIVER_TYPE driverType;
+ D3D_FEATURE_LEVEL featureLevel;
+ HWND hWnd;
+
+ // For use in the case of multiple adapters. If this is non-null, device creation will try to match
+ // the given string against an adapter name. If the specified string exists as a sub-string of the
+ // adapter name, the device and window will be created on that adapter. Case sensitive.
+ const WCHAR* adapterNameSubstring;
+
+ DeviceCreationParameters()
+ : startMaximized(false)
+ , startFullscreen(false)
+ , backBufferWidth(1280)
+ , backBufferHeight(720)
+ , refreshRate(0)
+ , swapChainBufferCount(1)
+ , swapChainFormat(DXGI_FORMAT_R8G8B8A8_UNORM)
+ , depthStencilFormat(DXGI_FORMAT_D24_UNORM_S8_UINT)
+ , swapChainUsage(DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT)
+ , swapChainSampleCount(1)
+ , swapChainSampleQuality(0)
+ , createDeviceFlags(0)
+ , driverType(D3D_DRIVER_TYPE_HARDWARE)
+ , featureLevel(D3D_FEATURE_LEVEL_11_0)
+ , adapterNameSubstring(L"")
+ , hWnd(0)
+ { }
+};
+
+#pragma warning(push)
+#pragma warning(disable: 4100) // unreferenced formal parameter
+class IVisualController
+{
+private:
+ bool m_Enabled;
+public:
+ IVisualController() : m_Enabled(true) { }
+
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return 1; }
+ virtual void Render(ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext, ID3D11RenderTargetView* pRTV, ID3D11DepthStencilView* pDSV) { }
+ virtual void Animate(double fElapsedTimeSeconds) { }
+ virtual HRESULT DeviceCreated(ID3D11Device* pDevice) { return S_OK; }
+ virtual void DeviceDestroyed() { }
+ virtual void BackBufferResized(ID3D11Device* pDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc) { }
+
+ virtual void EnableController() { m_Enabled = true; }
+ virtual void DisableController() { m_Enabled = false; }
+ virtual bool IsEnabled() { return m_Enabled; }
+};
+#pragma warning(pop)
+
+struct D3DHandles;
+
+class DeviceManager
+{
+public:
+ enum WindowState
+ {
+ kWindowNone,
+ kWindowNormal,
+ kWindowMinimized,
+ kWindowMaximized,
+ kWindowFullscreen
+ };
+
+protected:
+ ID3D11Device* m_Device;
+ ID3D11DeviceContext* m_ImmediateContext;
+ IDXGISwapChain* m_SwapChain;
+ ID3D11RenderTargetView* m_BackBufferRTV;
+ ID3D11Texture2D* m_DepthStencilBuffer;
+ ID3D11DepthStencilView* m_DepthStencilDSV;
+ DXGI_SWAP_CHAIN_DESC m_SwapChainDesc;
+ D3D11_TEXTURE2D_DESC m_DepthStencilDesc;
+ bool m_IsNvidia;
+ HWND m_hWnd;
+ std::list<IVisualController*> m_vControllers;
+ std::wstring m_WindowTitle;
+ double m_FixedFrameInterval;
+ UINT m_SyncInterval;
+ std::list<double> m_vFrameTimes;
+ double m_AverageFrameTime;
+ double m_AverageTimeUpdateInterval;
+ bool m_InSizingModalLoop;
+ SIZE m_NewWindowSize;
+ LARGE_INTEGER perfFreq, previousTime;
+private:
+ HRESULT CreateRenderTargetAndDepthStencil();
+ void ResizeSwapChain();
+public:
+
+ DeviceManager()
+ : m_Device(NULL)
+ , m_ImmediateContext(NULL)
+ , m_SwapChain(NULL)
+ , m_BackBufferRTV(NULL)
+ , m_DepthStencilBuffer(NULL)
+ , m_DepthStencilDSV(NULL)
+ , m_IsNvidia(false)
+ , m_hWnd(NULL)
+ , m_WindowTitle(L"")
+ , m_FixedFrameInterval(-1)
+ , m_SyncInterval(0)
+ , m_AverageFrameTime(0)
+ , m_AverageTimeUpdateInterval(0.5)
+ , m_InSizingModalLoop(false)
+ {
+ QueryPerformanceFrequency(&perfFreq);
+ QueryPerformanceCounter(&previousTime);
+ }
+
+ virtual ~DeviceManager()
+ { Shutdown(); }
+
+ virtual HRESULT CreateWindowDeviceAndSwapChain(const DeviceCreationParameters& params);
+ virtual HRESULT ChangeBackBufferFormat(DXGI_FORMAT format, UINT sampleCount);
+ virtual HRESULT ResizeWindow(int width, int height);
+ virtual HRESULT EnterFullscreenMode(int width = 0, int height = 0);
+ virtual HRESULT LeaveFullscreenMode(int windowWidth = 0, int windowHeight = 0);
+ virtual HRESULT ToggleFullscreen();
+
+ virtual void Shutdown();
+ virtual void MessageLoop();
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Render();
+ virtual void Animate(double fElapsedTimeSeconds);
+ virtual void DeviceCreated();
+ virtual void DeviceDestroyed();
+ virtual void BackBufferResized();
+
+ void AddControllerToFront(IVisualController* pController);
+ void AddControllerToBack(IVisualController* pController);
+ void RemoveController(IVisualController* pController);
+
+ void SetFixedFrameInterval(double seconds) { m_FixedFrameInterval = seconds; }
+ void DisableFixedFrameInterval() { m_FixedFrameInterval = -1; }
+
+ bool IsNvidia() const { return m_IsNvidia; }
+ HWND GetHWND() { return m_hWnd; }
+ ID3D11Device* GetDevice() { return m_Device; }
+ WindowState GetWindowState();
+ bool GetVsyncEnabled() { return m_SyncInterval > 0; }
+ void SetVsyncEnabled(bool enabled) { m_SyncInterval = enabled ? 1 : 0; }
+ HRESULT GetDisplayResolution(int& width, int& height);
+ IDXGIAdapter* GetDXGIAdapter();
+ double GetAverageFrameTime() { return m_AverageFrameTime; }
+ void SetAverageTimeUpdateInterval(double value) { m_AverageTimeUpdateInterval = value; }
+
+ // added by Junma Lixu
+ void SetWindowHandle(HWND hWnd);
+ virtual HRESULT SetWindowDeviceAndSwapChain(D3DHandles& pDeviceHandles);
+};
+
+
+DeviceManager* GetDeviceManager();
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleController.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleController.cpp
new file mode 100644
index 0000000..163b3b4
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleController.cpp
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "SampleController.h"
+#include "SceneController.h"
+#include "CommonUIController.h"
+#include "BlastController.h"
+#include "PhysXController.h"
+
+#include "imgui.h"
+
+SampleController::SampleController()
+{
+}
+
+SampleController::~SampleController()
+{
+}
+
+void SampleController::onSampleStart()
+{
+ // start with GPU physics by default
+ setUseGPUPhysics(true);
+}
+
+
+void SampleController::setUseGPUPhysics(bool useGPUPhysics)
+{
+ if (!getPhysXController().getGPUPhysicsAvailable())
+ {
+ useGPUPhysics = false;
+ }
+
+ if (getPhysXController().getUseGPUPhysics() == useGPUPhysics)
+ {
+ return;
+ }
+
+ int assetNum = getSceneController().releaseAll();
+
+ getPhysXController().setUseGPUPhysics(useGPUPhysics);
+ getBlastController().reinitialize();
+
+ getSceneController().spawnAsset(assetNum);
+}
+
+
+void SampleController::drawPhysXGpuUI()
+{
+ // GPU Physics
+ bool useGPU = getPhysXController().getUseGPUPhysics();
+ if (ImGui::Checkbox("Use GPU Physics", &useGPU))
+ {
+ getCommonUIController().addDelayedCall([=]() { setUseGPUPhysics(useGPU); }, "Loading...");
+ }
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleController.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleController.h
new file mode 100644
index 0000000..a52c2fe
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleController.h
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SAMPLE_CONTROLLER_H
+#define SAMPLE_CONTROLLER_H
+
+#include "SampleManager.h"
+
+class SampleController : public ISampleController
+{
+public:
+ SampleController();
+ virtual ~SampleController();
+
+ virtual void onSampleStart();
+ void drawPhysXGpuUI();
+
+private:
+ SampleController& operator= (SampleController&);
+
+
+ //////// used controllers ////////
+
+ PhysXController& getPhysXController() const
+ {
+ return getManager()->getPhysXController();
+ }
+
+ BlastController& getBlastController() const
+ {
+ return getManager()->getBlastController();
+ }
+
+ SceneController& getSceneController() const
+ {
+ return getManager()->getSceneController();
+ }
+
+ CommonUIController& getCommonUIController() const
+ {
+ return getManager()->getCommonUIController();
+ }
+
+
+ //////// private methods ////////
+
+ void setUseGPUPhysics(bool useGPUPhysics);
+};
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleManager.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleManager.cpp
new file mode 100644
index 0000000..2e13687
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleManager.cpp
@@ -0,0 +1,1267 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+#include "NvBlastExtAuthoringTypes.h"
+#include "NvBlastExtAuthoringFractureTool.h"
+#include "NvBlastExtAuthoringBondGenerator.h"
+#include "NvBlastIndexFns.h"
+
+#include "SampleManager.h"
+
+#include "Utils.h"
+
+#include "Renderer.h"
+#include "PhysXController.h"
+#include "BlastController.h"
+#include "CommonUIController.h"
+#include "DamageToolController.h"
+#include "SelectionToolController.h"
+#include "GizmoToolController.h"
+#include "EditionToolController.h"
+#include "SceneController.h"
+#include "SampleController.h"
+
+#include "tclap/CmdLine.h"
+#include "PxPhysics.h"
+#include "PsFileBuffer.h"
+#include "NvBlast.h"
+#include "NvBlastExtAuthoringCollisionBuilder.h"
+#include "NvBlastExtPxAsset.h"
+#include "BlastFractureTool.h"
+#include <set>
+#include "MaterialLibraryPanel.h"
+#include "MaterialAssignmentsPanel.h"
+
+using namespace physx;
+
+physx::PxFoundation* foundation = nullptr;
+physx::PxPhysics* physics = nullptr;
+physx::PxCooking* cooking = nullptr;
+Nv::Blast::ExtPxManager* physicsManager = nullptr;
+SampleManager* sSampleManager = nullptr;
+
+class SimpleRandomGenerator : public RandomGeneratorBase
+{
+public:
+ SimpleRandomGenerator() {
+ remember = false;
+ };
+
+ virtual float getRandomValue()
+ {
+ float r = (float)rand();
+ r = r / RAND_MAX;
+ return r;
+ }
+
+ virtual float getExponential(float lambda)
+ {
+ return -1.0f / lambda * log(1 - getRandomValue());
+ }
+
+ virtual void seed(int32_t seed)
+ {
+ srand(seed);
+ }
+
+ virtual ~SimpleRandomGenerator() {};
+
+private:
+ bool remember;
+};
+static SimpleRandomGenerator sRandomGenerator;
+
+void loggingCallback(int type, const char* msg, const char* file, int line)
+{
+ (void)type;
+
+ std::cout << msg << " FILE:" << file << " Line: " << line << "\n";
+}
+
+void buildPxChunks(const std::vector<std::vector<Triangle>>& chunkGeometry, std::vector<ExtPxAssetDesc::ChunkDesc>& pxChunks,
+ std::vector<ExtPxAssetDesc::SubchunkDesc>& pxSubchunks)
+{
+ ConvexMeshBuilder collisionBuilder(cooking, &physics->getPhysicsInsertionCallback());
+
+ pxChunks.resize(chunkGeometry.size());
+ pxSubchunks.resize(chunkGeometry.size());
+
+ for (uint32_t i = 0; i < chunkGeometry.size(); ++i)
+ {
+ std::vector<physx::PxVec3> vertices;
+ for (uint32_t p = 0; p < chunkGeometry[i].size(); ++p)
+ {
+ vertices.push_back(chunkGeometry[i][p].a.p);
+ vertices.push_back(chunkGeometry[i][p].b.p);
+ vertices.push_back(chunkGeometry[i][p].c.p);
+ }
+ pxSubchunks[i].transform = physx::PxTransform(physx::PxIdentity);
+ pxSubchunks[i].geometry = physx::PxConvexMeshGeometry(collisionBuilder.buildConvexMesh(vertices));
+ pxChunks[i].isStatic = false;
+ pxChunks[i].subchunkCount = 1;
+ pxChunks[i].subchunks = &pxSubchunks[i];
+ }
+
+ // only effect when chunk is support
+ pxChunks[0].isStatic = true;
+}
+
+void saveFractureToObj(std::vector<std::vector<Triangle> > chunksGeometry, std::string name, std::string path)
+{
+ MaterialAssignmentsPanel* pMaterialAssignmentsPanel = MaterialAssignmentsPanel::ins();
+ std::vector<std::string> materialNames;
+ std::vector<std::string> materialPaths;
+ pMaterialAssignmentsPanel->getMaterialNameAndPaths(materialNames, materialPaths);
+
+ uint32_t submeshCount = 2;
+ // export materials (mtl file)
+ {
+ std::ostringstream mtlFilePath;
+ mtlFilePath << path << name << ".mtl";
+ FILE* f = fopen(mtlFilePath.str().c_str(), "w");
+ if (!f)
+ return;
+
+ for (uint32_t submeshIndex = 0; submeshIndex < submeshCount; ++submeshIndex)
+ {
+ fprintf(f, "newmtl %s\n", materialNames[submeshIndex].c_str());
+ fprintf(f, "\tmap_Kd %s\n", materialPaths[submeshIndex].c_str());
+ fprintf(f, "\n");
+ }
+
+ fclose(f);
+ }
+
+ {
+ std::ostringstream objFilePath;
+ objFilePath << path << name << ".obj";
+ FILE* outStream = fopen(objFilePath.str().c_str(), "w");
+
+ fprintf(outStream, "mtllib %s.mtl\n", name.c_str());
+ fprintf(outStream, "o frac \n");
+
+
+ for (uint32_t vc = 0; vc < chunksGeometry.size(); ++vc)
+ {
+ std::vector<Triangle>& chunk = chunksGeometry[vc];
+ for (uint32_t i = 0; i < chunk.size(); ++i)
+ {
+ fprintf(outStream, "v %lf %lf %lf\n", chunk[i].a.p.x, chunk[i].a.p.y, chunk[i].a.p.z);
+ fprintf(outStream, "v %lf %lf %lf\n", chunk[i].b.p.x, chunk[i].b.p.y, chunk[i].b.p.z);
+ fprintf(outStream, "v %lf %lf %lf\n", chunk[i].c.p.x, chunk[i].c.p.y, chunk[i].c.p.z);
+ }
+
+ for (uint32_t i = 0; i < chunk.size(); ++i)
+ {
+ fprintf(outStream, "vt %lf %lf \n", chunk[i].a.uv[0].x, chunk[i].a.uv[0].y);
+ fprintf(outStream, "vt %lf %lf \n", chunk[i].b.uv[0].x, chunk[i].b.uv[0].y);
+ fprintf(outStream, "vt %lf %lf \n", chunk[i].c.uv[0].x, chunk[i].c.uv[0].y);
+ }
+
+ for (uint32_t i = 0; i < chunk.size(); ++i)
+ {
+ fprintf(outStream, "vn %lf %lf %lf\n", chunk[i].a.n.x, chunk[i].a.n.y, chunk[i].a.n.z);
+ fprintf(outStream, "vn %lf %lf %lf\n", chunk[i].b.n.x, chunk[i].b.n.y, chunk[i].b.n.z);
+ fprintf(outStream, "vn %lf %lf %lf\n", chunk[i].c.n.x, chunk[i].c.n.y, chunk[i].c.n.z);
+ }
+ }
+ int indx = 1;
+ for (uint32_t vc = 0; vc < chunksGeometry.size(); ++vc)
+ {
+ fprintf(outStream, "g %d_%d \n", vc, 0);
+ fprintf(outStream, "usemtl %s\n", materialNames[0].c_str());
+ int totalSize = chunksGeometry[vc].size();
+ std::vector<int> internalSurfaces;
+ for (uint32_t i = 0; i < totalSize; ++i)
+ {
+ if (chunksGeometry[vc][i].userInfo != 0)
+ {
+ internalSurfaces.push_back(indx++);
+ internalSurfaces.push_back(indx++);
+ internalSurfaces.push_back(indx++);
+ continue;
+ }
+ fprintf(outStream, "f %d/%d/%d ", indx, indx, indx);
+ indx++;
+ fprintf(outStream, "%d/%d/%d ", indx, indx, indx);
+ indx++;
+ fprintf(outStream, "%d/%d/%d \n", indx, indx, indx);
+ indx++;
+ }
+ int internalSize = internalSurfaces.size();
+ if (internalSize > 0)
+ {
+ fprintf(outStream, "g %d_%d \n", vc, 1);
+ fprintf(outStream, "usemtl %s\n", materialNames[1].c_str());
+ int isIndex;
+ for (uint32_t is = 0; is < internalSize;)
+ {
+ isIndex = internalSurfaces[is++];
+ fprintf(outStream, "f %d/%d/%d ", isIndex, isIndex, isIndex);
+ isIndex = internalSurfaces[is++];
+ fprintf(outStream, "%d/%d/%d ", isIndex, isIndex, isIndex);
+ isIndex = internalSurfaces[is++];
+ fprintf(outStream, "%d/%d/%d \n", isIndex, isIndex, isIndex);
+ }
+ }
+ }
+ fclose(outStream);
+ }
+}
+
+void FractureExecutor::setSourceMesh(Nv::Blast::Mesh* mesh)
+{
+ assert(m_fractureTool);
+ m_sourMesh = mesh;
+ m_fractureTool->setSourceMesh(mesh);
+}
+
+void FractureExecutor::setSourceAsset(const BlastAsset* blastAsset)
+{
+ assert(m_fractureTool);
+ m_fractureTool->setSourceAsset(blastAsset);
+ m_sourMesh = nullptr;
+}
+
+VoronoiFractureExecutor::VoronoiFractureExecutor()
+: m_cellsCount(5)
+{
+ if (sSampleManager)
+ m_fractureTool = sSampleManager->m_fTool;
+}
+
+void VoronoiFractureExecutor::setCellsCount(uint32_t cellsCount)
+{
+ m_cellsCount = cellsCount;
+}
+
+bool VoronoiFractureExecutor::execute()
+{
+ Nv::Blast::Mesh* mesh = nullptr;
+ if (m_sourMesh)
+ {
+ mesh = m_sourMesh;
+ }
+ else
+ {
+ mesh = m_fractureTool->getSourceMesh(m_chunkId);
+ }
+ // Prevent crash Junma Added By Lixu
+ if (mesh == nullptr)
+ return false;
+
+ VoronoiSitesGenerator stGenerator(mesh, (m_randomGenerator == nullptr ? &sRandomGenerator : m_randomGenerator));
+ stGenerator.uniformlyGenerateSitesInMesh(m_cellsCount);
+ m_fractureTool->voronoiFracturing(m_chunkId, stGenerator.getVoronoiSites(), false);
+ m_fractureTool->finalizeFracturing();
+
+ return sSampleManager->postProcessCurrentAsset();
+}
+
+SliceFractureExecutor::SliceFractureExecutor()
+: m_config(new Nv::Blast::SlicingConfiguration())
+{
+ if (sSampleManager)
+ m_fractureTool = sSampleManager->m_fTool;
+}
+
+void SliceFractureExecutor::applyNoise(float amplitude, float frequency, int32_t octaves, float falloff, int32_t relaxIterations, float relaxFactor, int32_t seed)
+{
+ m_fractureTool->applyNoise(amplitude, frequency, octaves, falloff, relaxIterations, relaxFactor, seed);
+}
+
+void SliceFractureExecutor::applyConfig(int32_t xSlices, int32_t ySlices, int32_t zSlices, float offsetVariations, float angleVariations)
+{
+ m_config->x_slices = xSlices;
+ m_config->y_slices = ySlices;
+ m_config->z_slices = zSlices;
+ m_config->offset_variations = offsetVariations;
+ m_config->angle_variations = angleVariations;
+}
+
+bool SliceFractureExecutor::execute()
+{
+ m_fractureTool->slicing(m_chunkId, *m_config, false, (m_randomGenerator == nullptr ? &sRandomGenerator : m_randomGenerator));
+ m_fractureTool->finalizeFracturing();
+ return sSampleManager->postProcessCurrentAsset();
+}
+
+static VoronoiFractureExecutor sVoronoiFracture;
+
+SampleManager* SampleManager::ins()
+{
+ return sSampleManager;
+}
+
+SampleManager::SampleManager(DeviceManager* pDeviceManager)
+{
+ sSampleManager = this;
+ m_bNeedConfig = false;
+ m_bNeedRefreshTree = false;
+
+ m_renderer = new Renderer();
+ m_physXController = new PhysXController(ExtImpactDamageManager::FilterShader);
+ m_blastController = new BlastController();
+ m_sceneController = new SceneController();
+ m_damageToolController = new DamageToolController();
+ m_selectionToolController = new SelectionToolController();
+ m_gizmoToolController = new GizmoToolController();
+ m_editionToolController = new EditionToolController();
+ m_sampleController = new SampleController();
+// m_commonUIController = new CommonUIController();
+
+ m_pApplication = new Application(pDeviceManager);
+
+ Application& app = *m_pApplication;
+
+ app.addControllerToFront(m_renderer);
+ app.addControllerToFront(m_physXController);
+ app.addControllerToFront(m_blastController);
+ app.addControllerToFront(m_sceneController);
+ app.addControllerToFront(m_damageToolController);
+ app.addControllerToFront(m_selectionToolController);
+ app.addControllerToFront(m_gizmoToolController);
+ app.addControllerToFront(m_editionToolController);
+ app.addControllerToFront(m_sampleController);
+// app.addControllerToFront(m_commonUIController);
+
+ for (IApplicationController* c : app.getControllers())
+ {
+ (static_cast<ISampleController*>(c))->setManager(this);
+ }
+
+ m_config.sampleName = L"";
+ m_config.assetsFile = "";
+
+ m_config.additionalResourcesDir.clear();
+ m_config.additionalResourcesDir.push_back("../resources");
+ m_config.additionalResourcesDir.push_back("../../../../bin/resources");
+
+ m_config.additionalAssetList.models.clear();
+ m_config.additionalAssetList.boxes.clear();
+ m_config.additionalAssetList.composites.clear();
+
+ m_fTool = new BlastFractureTool(loggingCallback);
+ m_fractureExecutor = nullptr;
+
+ setFractureExecutor(&sVoronoiFracture);
+
+ m_pCurBlastAsset = nullptr;
+ m_nCurFamilyIndex = -1;
+}
+
+SampleManager::~SampleManager()
+{
+ delete m_renderer;
+ delete m_physXController;
+ delete m_blastController;
+ delete m_sceneController;
+ delete m_damageToolController;
+ delete m_selectionToolController;
+ delete m_gizmoToolController;
+ delete m_editionToolController;
+ delete m_sampleController;
+ delete m_fTool;
+// delete m_commonUIController;
+}
+
+int SampleManager::init()
+{
+ Application& app = *m_pApplication;
+ app.init();
+
+ m_ToolType = BTT_Num;
+ setBlastToolType(BTT_Edit);
+
+ return 0;
+}
+
+int SampleManager::run()
+{
+ if (m_bNeedConfig)
+ {
+ getSceneController().onSampleStop();
+ getSceneController().onSampleStart();
+
+ _setSourceAsset();
+
+ m_bNeedConfig = false;
+ m_bNeedRefreshTree = true;
+ }
+
+ Application& app = *m_pApplication;
+ app.run();
+
+ std::vector<std::string>::iterator itStr;
+ std::vector<Renderable*>::iterator itRenderable;
+ for (itStr = m_NeedDeleteRenderMaterials.begin(); itStr != m_NeedDeleteRenderMaterials.end(); itStr++)
+ {
+ std::string materialName = *itStr;
+ RenderMaterial* pRenderMaterial = m_RenderMaterialMap[materialName];
+ std::vector<Renderable*>& renderables = pRenderMaterial->getRelatedRenderables();
+ for (itRenderable = renderables.begin(); itRenderable != renderables.end(); itRenderable++)
+ {
+ Renderable* pRenderable = *itRenderable;
+ pRenderable->setMaterial(*RenderMaterial::getDefaultRenderMaterial());
+ }
+
+ removeRenderMaterial(materialName);
+ }
+ m_NeedDeleteRenderMaterials.clear();
+
+ MaterialLibraryPanel::ins()->deleteMaterials();
+
+ return 0;
+}
+
+int SampleManager::free()
+{
+ std::map<BlastAsset*, std::vector<BlastFamily*>>::iterator it;
+ for (it = m_AssetFamiliesMap.begin(); it != m_AssetFamiliesMap.end(); it++)
+ {
+ std::vector<BlastFamily*>& fs = it->second;
+ fs.clear();
+ }
+ m_AssetFamiliesMap.clear();
+ m_AssetDescMap.clear();
+
+ Application& app = *m_pApplication;
+ app.free();
+
+ /*
+ std::vector<AssetList::ModelAsset>& modelAssets = m_config.additionalAssetList.models;
+ std::vector<AssetList::ModelAsset>::iterator it;
+ char filename[50];
+ for (it = modelAssets.begin(); it != modelAssets.end(); it++)
+ {
+ AssetList::ModelAsset& m = *it;
+
+ sprintf(filename, "../../../../bin/resources/models/%s.bpxa", m.id.c_str());
+ DeleteFileA(filename);
+
+ sprintf(filename, "../../../../bin/resources/models/%s.mtl", m.id.c_str());
+ DeleteFileA(filename);
+
+ sprintf(filename, "../../../../bin/resources/models/%s.obj", m.id.c_str());
+ DeleteFileA(filename);
+ }
+ */
+
+ return 0;
+}
+
+void SampleManager::addModelAsset(std::string file, bool isSkinned, physx::PxTransform transform, bool clear)
+{
+ if (clear)
+ {
+ m_config.additionalAssetList.models.clear();
+ }
+ else
+ {
+ std::vector<AssetList::ModelAsset>& modelAssets = m_config.additionalAssetList.models;
+ std::vector<AssetList::ModelAsset>::iterator it = modelAssets.begin();
+ for (; it != modelAssets.end(); it++)
+ {
+ AssetList::ModelAsset& m = *it;
+ if (m.id == file)
+ {
+ modelAssets.erase(it);
+ break;
+ }
+ }
+ }
+
+ AssetList::ModelAsset modelAsset;
+ modelAsset.name = file;
+ modelAsset.id = file;
+ modelAsset.file = file;
+ modelAsset.isSkinned = isSkinned;
+ modelAsset.transform = transform;
+
+ m_config.additionalAssetList.models.push_back(modelAsset);
+
+ m_bNeedConfig = true;
+}
+
+bool SampleManager::createAsset(
+ std::string assetName,
+ std::vector<physx::PxVec3>& positions,
+ std::vector<physx::PxVec3>& normals,
+ std::vector<physx::PxVec2>& uv,
+ std::vector<unsigned int>& indices,
+ bool fracture)
+{
+ PhysXController& pc = getPhysXController();
+ BlastController& bc = getBlastController();
+
+ physics = &pc.getPhysics();
+ foundation = &physics->getFoundation();
+ cooking = &pc.getCooking();
+ physicsManager = &bc.getExtPxManager();
+
+ std::vector<Nv::Blast::Mesh* > meshes;
+ PxVec3* nr = (!normals.empty()) ? normals.data() : 0;
+ PxVec2* uvp = (!uv.empty()) ? uv.data() : 0;
+ Nv::Blast::Mesh* sourceMesh = new Nv::Blast::Mesh(positions.data(), nr, uvp, static_cast<uint32_t>(positions.size()),
+ indices.data(), static_cast<uint32_t>(indices.size()));
+ meshes.push_back(sourceMesh);
+
+ m_fractureExecutor->setSourceMesh(sourceMesh);
+ if (fracture)
+ {
+ m_fractureExecutor->execute();
+ m_fractureExecutor = &sVoronoiFracture;
+ }
+ else
+ {
+ m_fTool->finalizeFracturing();
+ }
+
+ std::string outDir = "../../../../bin/resources/models/";
+ _createAsset(assetName, outDir, meshes);
+
+ delete sourceMesh;
+ sourceMesh = 0;
+
+ m_bNeedConfig = true;
+
+ return true;
+}
+
+bool SampleManager::createAsset(
+ const std::string& assetName,
+ const std::vector<Nv::Blast::Mesh* >& meshes,
+ bool fracture)
+{
+ PhysXController& pc = getPhysXController();
+ BlastController& bc = getBlastController();
+
+ physics = &pc.getPhysics();
+ foundation = &physics->getFoundation();
+ cooking = &pc.getCooking();
+ physicsManager = &bc.getExtPxManager();
+
+ if (meshes.size() == 1)
+ {
+ Nv::Blast::Mesh* sourceMesh = meshes[0];
+ m_fractureExecutor->setSourceMesh(sourceMesh);
+ if (fracture)
+ {
+ m_fractureExecutor->execute();
+ m_fractureExecutor = &sVoronoiFracture;
+ }
+ else
+ {
+ m_fTool->finalizeFracturing();
+ }
+ }
+
+ std::string outDir = "../../../../bin/resources/models/";
+ _createAsset(assetName, outDir, meshes);
+
+ m_bNeedConfig = true;
+
+ return true;
+}
+
+bool SampleManager::saveAsset()
+{
+ if (m_pCurBlastAsset == nullptr)
+ {
+ return false;
+ }
+
+ AssetList::ModelAsset& desc = m_AssetDescMap[m_pCurBlastAsset];
+
+ PhysXController& pc = getPhysXController();
+ BlastController& bc = getBlastController();
+ physics = &pc.getPhysics();
+ foundation = &physics->getFoundation();
+ cooking = &pc.getCooking();
+ physicsManager = &bc.getExtPxManager();
+
+ std::string outDir = "../../../../bin/resources/models/";
+
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << desc.name << ".bpxa";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+ const ExtPxAsset* asset = m_pCurBlastAsset->getPxAsset();
+ if (asset == nullptr)
+ {
+ return false;
+ }
+ physx::PsFileBuffer fileBuf(outBlastFilePath.c_str(), physx::PxFileBuf::OPEN_WRITE_ONLY);
+ if (!asset->serialize(fileBuf, *cooking))
+ {
+ return false;
+ }
+ fileBuf.close();
+
+ m_fTool->setSourceAsset(m_pCurBlastAsset);
+ m_fTool->finalizeFracturing();
+
+ size_t nChunkListSize = m_fTool->getChunkList().size();
+ std::vector<std::vector<Triangle> > chunkMeshes(nChunkListSize);
+ std::vector<bool> isSupport(nChunkListSize);
+ for (uint32_t i = 0; i < nChunkListSize; ++i)
+ {
+ m_fTool->getBaseMesh(i, chunkMeshes[i]);
+ isSupport[i] = m_fTool->getChunkList()[i].isLeaf;
+ }
+
+ BlastBondGenerator bondGenerator(cooking, &physics->getPhysicsInsertionCallback());
+ BondGenerationConfig cnf;
+ cnf.bondMode = BondGenerationConfig::AVERAGE;
+ std::vector<NvBlastChunkDesc> chunkDesc;
+ std::vector<NvBlastBondDesc> bondDescs;
+ bondGenerator.buildDescFromInternalFracture(m_fTool, isSupport, bondDescs, chunkDesc);
+ const uint32_t chunkCount = static_cast<uint32_t>(chunkDesc.size());
+ const uint32_t bondCount = static_cast<uint32_t>(bondDescs.size());
+ if (bondCount == 0)
+ {
+ std::cout << "Can't create bonds descriptors..." << std::endl;
+ }
+
+ std::vector<uint32_t> chunkReorderInvMap;
+ {
+ std::vector<uint32_t> chunkReorderMap(chunkCount);
+ std::vector<char> scratch(chunkCount * sizeof(NvBlastChunkDesc));
+ NvBlastEnsureAssetExactSupportCoverage(chunkDesc.data(), chunkCount, scratch.data(), loggingCallback);
+ NvBlastBuildAssetDescChunkReorderMap(chunkReorderMap.data(), chunkDesc.data(), chunkCount, scratch.data(), loggingCallback);
+ NvBlastApplyAssetDescChunkReorderMapInplace(chunkDesc.data(), chunkCount, bondDescs.data(), bondCount, chunkReorderMap.data(), scratch.data(), loggingCallback);
+ chunkReorderInvMap.resize(chunkReorderMap.size());
+ Nv::Blast::invertMap(chunkReorderInvMap.data(), chunkReorderMap.data(), static_cast<unsigned int>(chunkReorderMap.size()));
+ }
+
+ std::vector<std::vector<Triangle>> resultGeometry(chunkMeshes.size());
+ for (uint32_t i = 0; i < chunkMeshes.size(); ++i)
+ {
+ uint32_t chunkIndex = chunkReorderInvMap[i];
+ resultGeometry[chunkIndex] = chunkMeshes[i];
+ }
+
+ saveFractureToObj(resultGeometry, desc.name, outDir);
+
+ std::string saveInfo = outBlastFilePath + " saved successfully\n";
+ output(saveInfo.c_str());
+
+ return true;
+}
+
+bool SampleManager::fractureAsset(std::string& assetName, const BlastAsset* pBlastAsset, int32_t chunkId)
+{
+ PhysXController& pc = getPhysXController();
+ BlastController& bc = getBlastController();
+
+ physics = &pc.getPhysics();
+ foundation = &physics->getFoundation();
+ cooking = &pc.getCooking();
+ physicsManager = &bc.getExtPxManager();
+
+ m_fractureExecutor->setSourceAsset(pBlastAsset);
+ m_fractureExecutor->setTargetChunk(chunkId);
+ m_fractureExecutor->execute();
+ m_fractureExecutor = &sVoronoiFracture;
+
+ std::string outDir = "../../../../bin/resources/models/";
+
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << assetName << ".bpxa";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+
+ std::vector<NvBlastChunkDesc> chunkDesc;
+ std::vector<NvBlastBondDesc> bondDescs;
+ std::vector<std::vector<Triangle> > chunkMeshes;
+ std::vector<bool> isSupport;
+
+ size_t nChunkListSize = m_fTool->getChunkList().size();
+ chunkMeshes.resize(nChunkListSize);
+ isSupport.resize(nChunkListSize);
+ for (uint32_t i = 0; i < nChunkListSize; ++i)
+ {
+ m_fTool->getBaseMesh(i, chunkMeshes[i]);
+ isSupport[i] = m_fTool->getChunkList()[i].isLeaf;
+ }
+
+ BlastBondGenerator bondGenerator(cooking, &physics->getPhysicsInsertionCallback());
+
+ BondGenerationConfig cnf;
+ cnf.bondMode = BondGenerationConfig::AVERAGE;
+ bondGenerator.buildDescFromInternalFracture(m_fTool, isSupport, bondDescs, chunkDesc);
+
+ const uint32_t chunkCount = static_cast<uint32_t>(chunkDesc.size());
+ const uint32_t bondCount = static_cast<uint32_t>(bondDescs.size());
+ if (bondCount == 0)
+ {
+ std::cout << "Can't create bonds descriptors..." << std::endl;
+ }
+
+ // order chunks, build map
+ std::vector<uint32_t> chunkReorderInvMap;
+ {
+ std::vector<uint32_t> chunkReorderMap(chunkCount);
+ std::vector<char> scratch(chunkCount * sizeof(NvBlastChunkDesc));
+ NvBlastEnsureAssetExactSupportCoverage(chunkDesc.data(), chunkCount, scratch.data(), loggingCallback);
+ NvBlastBuildAssetDescChunkReorderMap(chunkReorderMap.data(), chunkDesc.data(), chunkCount, scratch.data(), loggingCallback);
+ NvBlastApplyAssetDescChunkReorderMapInplace(chunkDesc.data(), chunkCount, bondDescs.data(), bondCount, chunkReorderMap.data(), scratch.data(), loggingCallback);
+ chunkReorderInvMap.resize(chunkReorderMap.size());
+ Nv::Blast::invertMap(chunkReorderInvMap.data(), chunkReorderMap.data(), static_cast<unsigned int>(chunkReorderMap.size()));
+ }
+
+ // get result geometry
+ std::vector<std::vector<Triangle>> resultGeometry(chunkMeshes.size());
+ for (uint32_t i = 0; i < chunkMeshes.size(); ++i)
+ {
+ uint32_t chunkIndex = chunkReorderInvMap[i];
+ resultGeometry[chunkIndex] = chunkMeshes[i];
+ }
+
+ // prepare physics data (convexes)
+ std::vector<ExtPxAssetDesc::ChunkDesc> pxChunks(chunkCount);
+ std::vector<ExtPxAssetDesc::SubchunkDesc> pxSubchunks;
+ buildPxChunks(resultGeometry, pxChunks, pxSubchunks);
+
+ // build and serialize ExtPhysicsAsset
+ ExtPxAssetDesc descriptor;
+ descriptor.bondCount = bondCount;
+ descriptor.bondDescs = bondDescs.data();
+ descriptor.chunkCount = chunkCount;
+ descriptor.chunkDescs = chunkDesc.data();
+ descriptor.bondFlags = nullptr;
+ descriptor.pxChunks = pxChunks.data();
+ ExtPxAsset* asset = ExtPxAsset::create(descriptor, bc.getTkFramework());
+ if (asset == nullptr)
+ {
+ return false;
+ }
+
+ physx::PsFileBuffer fileBuf(outBlastFilePath.c_str(), physx::PxFileBuf::OPEN_WRITE_ONLY);
+ if (!asset->serialize(fileBuf, *cooking))
+ {
+ return false;
+ }
+ fileBuf.close();
+ asset->release();
+
+ saveFractureToObj(resultGeometry, assetName, outDir);
+
+ m_bNeedConfig = true;
+
+ return true;
+}
+
+bool SampleManager::postProcessCurrentAsset()
+{
+ std::vector<AssetList::ModelAsset>& models = m_config.additionalAssetList.models;
+ if (models.size() < 0)
+ {
+ return true;
+ }
+
+ std::string assetName = models.at(models.size() - 1).file;
+ std::string outDir = "../../../../bin/resources/models/";
+ std::vector<Nv::Blast::Mesh* > meshes;
+ _createAsset(assetName, outDir, meshes);
+
+ m_bNeedConfig = true;
+
+ return true;
+}
+
+std::vector<uint32_t> SampleManager::getCurrentSelectedChunks()
+{
+ std::vector<uint32_t> selectedChunks;
+ std::vector<BlastFamilyPtr>& spFamilies = m_blastController->getFamilies();
+ if (spFamilies.size() > 0)
+ {
+ return spFamilies.back()->getSelectedChunks();
+ }
+ return selectedChunks;
+}
+
+std::map<BlastAsset*, std::vector<uint32_t>> SampleManager::getSelectedChunks()
+{
+ std::map<BlastAsset*, std::vector<uint32_t>> selectedChunks;
+ std::map<BlastAsset*, std::vector<BlastFamily*>>::iterator itrBlast = m_AssetFamiliesMap.begin();
+ for (; itrBlast != m_AssetFamiliesMap.end(); ++itrBlast)
+ {
+ std::set<uint32_t> assetChunks;
+ std::vector<BlastFamily*>& families = itrBlast->second;
+ std::vector<BlastFamily*>::iterator itrFamily = families.begin();
+ for (; itrFamily != families.end(); ++itrFamily)
+ {
+ std::vector<uint32_t> familyChunks = (*itrFamily)->getSelectedChunks();
+ for (std::vector<uint32_t>::iterator itrChunk = familyChunks.begin(); itrChunk != familyChunks.end(); ++itrChunk)
+ {
+ assetChunks.insert(*itrChunk);
+ }
+ }
+
+ if (assetChunks.size() == 0)
+ continue;
+
+ std::vector<uint32_t> vecAssetChunks;
+ for (std::set<uint32_t>::iterator itrChunk = assetChunks.begin(); itrChunk != assetChunks.end(); ++itrChunk)
+ {
+ vecAssetChunks.push_back(*itrChunk);
+ }
+
+ selectedChunks.insert(std::make_pair(itrBlast->first, vecAssetChunks));
+ }
+
+ return selectedChunks;
+}
+
+void SampleManager::clearChunksSelected()
+{
+ std::map<BlastAsset*, std::vector<BlastFamily*>>::iterator itr = m_AssetFamiliesMap.begin();
+ for (; itr != m_AssetFamiliesMap.end(); ++itr)
+ {
+ BlastAsset* pBlastAsset = itr->first;
+ std::vector<BlastFamily*>& fs = itr->second;
+
+ for (BlastFamily* f : fs)
+ {
+ f->clearChunksSelected();
+ }
+ }
+}
+
+void SampleManager::setChunkSelected(std::vector<uint32_t> depths, bool selected)
+{
+ std::map<BlastAsset*, std::vector<BlastFamily*>>::iterator itrBlast = m_AssetFamiliesMap.begin();
+ for (; itrBlast != m_AssetFamiliesMap.end(); ++itrBlast)
+ {
+ std::vector<BlastFamily*>& families = itrBlast->second;
+ std::vector<BlastFamily*>::iterator itrFamily = families.begin();
+ for (; itrFamily != families.end(); ++itrFamily)
+ {
+ (*itrFamily)->setChunkSelected(depths, selected);
+ }
+ }
+}
+
+void SampleManager::setChunkVisible(std::vector<uint32_t> depths, bool bVisible)
+{
+ std::map<BlastAsset*, std::vector<BlastFamily*>>::iterator itrBlast = m_AssetFamiliesMap.begin();
+ for (; itrBlast != m_AssetFamiliesMap.end(); ++itrBlast)
+ {
+ std::vector<BlastFamily*>& families = itrBlast->second;
+ std::vector<BlastFamily*>::iterator itrFamily = families.begin();
+ for (; itrFamily != families.end(); ++itrFamily)
+ {
+ (*itrFamily)->setChunkVisible(depths, bVisible);
+ }
+ }
+}
+
+void SampleManager::setFractureExecutor(FractureExecutor* executor)
+{
+ m_fractureExecutor = executor;
+ if (executor)
+ {
+ executor->m_fractureTool = m_fTool;
+ if (executor->m_randomGenerator == nullptr)
+ executor->m_randomGenerator = &sRandomGenerator;
+ }
+}
+
+void SampleManager::setBlastToolType(BlastToolType type)
+{
+ if (m_ToolType == type)
+ {
+ getPhysXController().setPaused(type != BTT_Damage);
+ return;
+ }
+
+ // refresh selection
+ bool needClear = true;
+ bool currentGizmo = (m_ToolType >= BTT_Translate && m_ToolType <= BTT_Rotation);
+ bool switchToGizmo = (type >= BTT_Translate && type <= BTT_Rotation);
+ if (currentGizmo && switchToGizmo)
+ {
+ needClear = false;
+ }
+ if (needClear)
+ {
+ getSelectionToolController().clearSelect();
+ getGizmoToolController().resetPos();
+ }
+
+ getDamageToolController().getPickPointer()->setHidden(type != BTT_Damage);
+ getGizmoToolController().showAxisRenderables(switchToGizmo);
+ getPhysXController().setPaused(type != BTT_Damage);
+
+ getDamageToolController().DisableController();
+ getSelectionToolController().DisableController();
+ getGizmoToolController().DisableController();
+ getEditionToolController().DisableController();
+
+ switch (type)
+ {
+ case BTT_Damage:
+ {
+ getDamageToolController().EnableController();
+ }
+ break;
+ case BTT_Drag:
+ {
+ getDamageToolController().EnableController();
+ }
+ break;
+ case BTT_Select:
+ {
+ getSelectionToolController().EnableController();
+ }
+ break;
+ case BTT_Translate:
+ {
+ getGizmoToolController().EnableController();
+ getGizmoToolController().setGizmoToolMode(GTM_Translate);
+ }
+ break;
+ case BTT_Scale:
+ {
+ getGizmoToolController().EnableController();
+ getGizmoToolController().setGizmoToolMode(GTM_Scale);
+ }
+ break;
+ case BTT_Rotation:
+ {
+ getGizmoToolController().EnableController();
+ getGizmoToolController().setGizmoToolMode(GTM_Rotation);
+ }
+ break;
+ case BTT_Edit:
+ {
+ getEditionToolController().EnableController();
+ }
+ break;
+ default:
+ break;
+ }
+
+ m_ToolType = type;
+}
+
+#include <ViewerOutput.h>
+void SampleManager::output(const char* str)
+{
+ viewer_msg("%s", str);
+}
+
+void SampleManager::output(float value)
+{
+ viewer_msg("%f", value);
+}
+
+void SampleManager::output(physx::PxVec3& vec)
+{
+ viewer_msg("%f,%f,%f", vec.x, vec.y, vec.z);
+}
+
+void SampleManager::clearScene()
+{
+ getSceneController().ClearScene();
+ m_config.sampleName.clear();
+ m_config.assetsFile.clear();
+ //m_config.additionalResourcesDir.clear();
+ m_config.additionalAssetList.models.clear();
+ m_config.additionalAssetList.composites.clear();
+ m_config.additionalAssetList.boxes.clear();
+
+ std::map<BlastAsset*, std::vector<BlastFamily*>>::iterator it;
+ for (it = m_AssetFamiliesMap.begin(); it != m_AssetFamiliesMap.end(); it++)
+ {
+ std::vector<BlastFamily*>& fs = it->second;
+ fs.clear();
+ }
+ m_AssetFamiliesMap.clear();
+ m_AssetDescMap.clear();
+}
+
+bool SampleManager::_createAsset(
+ const std::string& assetName,
+ const std::string& outDir,
+ const std::vector<Nv::Blast::Mesh* >& meshes)
+{
+ PhysXController& pc = getPhysXController();
+ BlastController& bc = getBlastController();
+
+ physics = &pc.getPhysics();
+ foundation = &physics->getFoundation();
+ cooking = &pc.getCooking();
+ physicsManager = &bc.getExtPxManager();
+ TkFramework& tk = bc.getTkFramework();
+
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << assetName << ".bpxa";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+
+ std::vector<NvBlastChunkDesc> chunkDesc;
+ std::vector<NvBlastBondDesc> bondDescs;
+ std::vector<std::vector<Triangle> > chunkMeshes;
+ std::vector<bool> isSupport;
+
+ if (meshes.size() <= 1)
+ {
+ size_t nChunkListSize = m_fTool->getChunkList().size();
+ chunkMeshes.resize(nChunkListSize);
+ isSupport.resize(nChunkListSize);
+ for (uint32_t i = 0; i < nChunkListSize; ++i)
+ {
+ m_fTool->getBaseMesh(i, chunkMeshes[i]);
+ isSupport[i] = m_fTool->getChunkList()[i].isLeaf;
+ }
+ }
+ // If there are more than one mesh, then it seems that it prefractured, lets consider first mesh in meshes as depth 0, other meshes as depth 1 chunks
+ // we should just build Blast descriptors for such input.
+ else
+ {
+ chunkMeshes.resize(meshes.size());
+ std::vector<PxVec3> chunkCentroids(meshes.size(), PxVec3(0, 0, 0));
+
+ for (uint32_t i = 0; i < meshes.size(); ++i)
+ {
+ std::vector<Triangle>& chunk = chunkMeshes[i];
+
+ Vertex* vbf = meshes[i]->getVertices();
+ Edge* ebf = meshes[i]->getEdges();
+
+ for (uint32_t fc = 0; fc < meshes[i]->getFacetCount(); ++fc)
+ {
+ Facet* f = meshes[i]->getFacet(fc);
+ Triangle tr;
+ tr.a = vbf[ebf[f->firstEdgeNumber].s];
+ tr.b = vbf[ebf[f->firstEdgeNumber + 1].s];
+ tr.c = vbf[ebf[f->firstEdgeNumber + 2].s];
+ chunk.push_back(tr);
+
+ chunkCentroids[i] += tr.a.p + tr.b.p + tr.c.p;
+ }
+
+ chunkCentroids[i] *= 1.0f / (3 * meshes[i]->getFacetCount());
+ }
+
+ isSupport.resize(chunkMeshes.size());
+ chunkDesc.resize(chunkMeshes.size());
+ isSupport[0] = false;
+
+ chunkDesc[0].centroid[0] = chunkCentroids[0].x;
+ chunkDesc[0].centroid[1] = chunkCentroids[0].y;
+ chunkDesc[0].centroid[2] = chunkCentroids[0].z;
+ chunkDesc[0].parentChunkIndex = UINT32_MAX;
+
+ for (uint32_t i = 1; i < chunkDesc.size(); ++i)
+ {
+ chunkDesc[i].parentChunkIndex = 0;
+ chunkDesc[i].flags = NvBlastChunkDesc::SupportFlag;
+ chunkDesc[i].centroid[0] = chunkCentroids[i].x;
+ chunkDesc[i].centroid[1] = chunkCentroids[i].y;
+ chunkDesc[i].centroid[2] = chunkCentroids[i].z;
+ isSupport[i] = true;
+ }
+ }
+
+ BlastBondGenerator bondGenerator(cooking, &physics->getPhysicsInsertionCallback());
+
+ BondGenerationConfig cnf;
+ cnf.bondMode = BondGenerationConfig::AVERAGE;
+
+ if (meshes.size() > 1)
+ {
+ bondGenerator.bondsFromPrefractured(chunkMeshes, isSupport, bondDescs, cnf);
+ }
+ else
+ {
+ bondGenerator.buildDescFromInternalFracture(m_fTool, isSupport, bondDescs, chunkDesc);
+ }
+
+ const uint32_t chunkCount = static_cast<uint32_t>(chunkDesc.size());
+ const uint32_t bondCount = static_cast<uint32_t>(bondDescs.size());
+ if (bondCount == 0)
+ {
+ std::cout << "Can't create bonds descriptors..." << std::endl;
+ }
+
+ // order chunks, build map
+ std::vector<uint32_t> chunkReorderInvMap;
+ {
+ std::vector<uint32_t> chunkReorderMap(chunkCount);
+ std::vector<char> scratch(chunkCount * sizeof(NvBlastChunkDesc));
+ NvBlastEnsureAssetExactSupportCoverage(chunkDesc.data(), chunkCount, scratch.data(), loggingCallback);
+ NvBlastBuildAssetDescChunkReorderMap(chunkReorderMap.data(), chunkDesc.data(), chunkCount, scratch.data(), loggingCallback);
+ NvBlastApplyAssetDescChunkReorderMapInplace(chunkDesc.data(), chunkCount, bondDescs.data(), bondCount, chunkReorderMap.data(), scratch.data(), loggingCallback);
+ chunkReorderInvMap.resize(chunkReorderMap.size());
+ Nv::Blast::invertMap(chunkReorderInvMap.data(), chunkReorderMap.data(), static_cast<unsigned int>(chunkReorderMap.size()));
+ }
+
+ // get result geometry
+ std::vector<std::vector<Triangle>> resultGeometry(chunkMeshes.size());
+ for (uint32_t i = 0; i < chunkMeshes.size(); ++i)
+ {
+ uint32_t chunkIndex = chunkReorderInvMap[i];
+ resultGeometry[chunkIndex] = chunkMeshes[i];
+ }
+
+ // prepare physics data (convexes)
+ std::vector<ExtPxAssetDesc::ChunkDesc> pxChunks(chunkCount);
+ std::vector<ExtPxAssetDesc::SubchunkDesc> pxSubchunks;
+ buildPxChunks(resultGeometry, pxChunks, pxSubchunks);
+
+ // build and serialize ExtPhysicsAsset
+ ExtPxAssetDesc descriptor;
+ descriptor.bondCount = bondCount;
+ descriptor.bondDescs = bondDescs.data();
+ descriptor.chunkCount = chunkCount;
+ descriptor.chunkDescs = chunkDesc.data();
+ descriptor.bondFlags = nullptr;
+ descriptor.pxChunks = pxChunks.data();
+ ExtPxAsset* asset = ExtPxAsset::create(descriptor, tk);
+ if (asset == nullptr)
+ {
+ return false;
+ }
+
+ physx::PsFileBuffer fileBuf(outBlastFilePath.c_str(), physx::PxFileBuf::OPEN_WRITE_ONLY);
+ if (!asset->serialize(fileBuf, *cooking))
+ {
+ return false;
+ }
+ fileBuf.close();
+ asset->release();
+
+ saveFractureToObj(resultGeometry, assetName, outDir);
+
+ m_bNeedConfig = true;
+
+ return true;
+}
+
+void SampleManager::_setSourceAsset()
+{
+ std::vector<BlastFamilyPtr>& families = m_blastController->getFamilies();
+ if (families.size() > 0)
+ {
+ BlastFamilyPtr spLastFamily = families.back();
+
+ m_fTool->setSourceAsset(&(spLastFamily->getBlastAsset()));
+ }
+}
+
+void SampleManager::addRenderMaterial(RenderMaterial* pRenderMaterial)
+{
+ if (pRenderMaterial == nullptr)
+ {
+ return;
+ }
+
+ std::string materialName = pRenderMaterial->getMaterialName();
+ if (materialName.empty())
+ {
+ return;
+ }
+
+ m_RenderMaterialMap[materialName] = pRenderMaterial;
+
+ std::string textureFileName = pRenderMaterial->getTextureFileName();
+ MaterialLibraryPanel::ins()->addMaterial(materialName, textureFileName);
+}
+
+void SampleManager::removeRenderMaterial(std::string name)
+{
+ if (name.empty())
+ {
+ return;
+ }
+
+ std::map<std::string, RenderMaterial*>::iterator it = m_RenderMaterialMap.find(name);
+ if (it != m_RenderMaterialMap.end())
+ {
+ m_RenderMaterialMap.erase(it);
+ MaterialLibraryPanel::ins()->removeMaterial(name);
+ }
+}
+
+void SampleManager::deleteRenderMaterial(std::string name)
+{
+ if (name.empty())
+ {
+ return;
+ }
+
+ m_NeedDeleteRenderMaterials.push_back(name);
+}
+
+void SampleManager::renameRenderMaterial(std::string oldName, std::string newName)
+{
+ if (oldName.empty() || newName.empty())
+ {
+ return;
+ }
+
+ std::map<std::string, RenderMaterial*>::iterator it = m_RenderMaterialMap.find(oldName);
+ if (it != m_RenderMaterialMap.end())
+ {
+ RenderMaterial* pRenderMaterial = it->second;
+ m_RenderMaterialMap.erase(it);
+ pRenderMaterial->setMaterialName(newName);
+ m_RenderMaterialMap[newName] = pRenderMaterial;
+ }
+}
+
+void SampleManager::getCurrentSelectedInstance(BlastAsset** ppBlastAsset, int& index)
+{
+ *ppBlastAsset = m_pCurBlastAsset;
+ index = m_nCurFamilyIndex;
+}
+
+void SampleManager::setCurrentSelectedInstance(BlastAsset* pBlastAsset, int index)
+{
+ m_pCurBlastAsset = pBlastAsset;
+ m_nCurFamilyIndex = index;
+
+ MaterialAssignmentsPanel::ins()->updateValues();
+}
+
+void SampleManager::getMaterialForCurrentFamily(RenderMaterial** ppRenderMaterial, bool externalSurface)
+{
+ if (m_pCurBlastAsset == nullptr || m_nCurFamilyIndex < 0)
+ {
+ return;
+ }
+
+ std::vector<BlastFamily*>& fs = m_AssetFamiliesMap[m_pCurBlastAsset];
+ int fsSize = fs.size();
+ if (fsSize == 0 || fsSize < m_nCurFamilyIndex)
+ {
+ return;
+ }
+
+ BlastFamily* pBlastFamily = fs[m_nCurFamilyIndex];
+ pBlastFamily->getMaterial(ppRenderMaterial, externalSurface);
+}
+
+void SampleManager::setMaterialForCurrentFamily(RenderMaterial* pRenderMaterial, bool externalSurface)
+{
+ if (m_pCurBlastAsset == nullptr || m_nCurFamilyIndex < 0)
+ {
+ return;
+ }
+
+ std::vector<BlastFamily*>& fs = m_AssetFamiliesMap[m_pCurBlastAsset];
+ int fsSize = fs.size();
+ if (fsSize == 0 || fsSize < m_nCurFamilyIndex)
+ {
+ return;
+ }
+
+ BlastFamily* pBlastFamily = fs[m_nCurFamilyIndex];
+ pBlastFamily->setMaterial(pRenderMaterial, externalSurface);
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleManager.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleManager.h
new file mode 100644
index 0000000..e0b0ac9
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/core/SampleManager.h
@@ -0,0 +1,302 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SAMPLE_MANAGER_H
+#define SAMPLE_MANAGER_H
+
+#include "Application.h"
+#include "Sample.h"
+#include <map>
+
+class SampleManager;
+class BlastFractureTool;
+class BlastAsset;
+class BlastFamily;
+class RenderMaterial;
+namespace Nv
+{
+namespace Blast
+{
+ class Mesh;
+ class RandomGeneratorBase;
+ class VoronoiSitesGenerator;
+ struct SlicingConfiguration;
+}
+}
+
+class ISampleController : public IApplicationController
+{
+public:
+
+ void setManager(SampleManager* manager)
+ {
+ m_manager = manager;
+ }
+protected:
+
+ SampleManager* getManager() const
+ {
+ return m_manager;
+ }
+
+private:
+ SampleManager* m_manager;
+};
+
+class FractureExecutor
+{
+ friend class SampleManager;
+public:
+ FractureExecutor()
+ : m_fractureTool(0)
+ , m_chunkId(-1)
+ , m_randomGenerator(nullptr)
+ , m_sourMesh(nullptr)
+ {
+ }
+
+ virtual bool execute() = 0;
+ void setSourceMesh(Nv::Blast::Mesh* mesh);
+ void setSourceAsset(const BlastAsset* blastAsset);
+ void setTargetChunk(uint32_t chunkId) { m_chunkId = chunkId; }
+ void setRandomGenerator(Nv::Blast::RandomGeneratorBase* randomGenerator) { m_randomGenerator = randomGenerator; }
+protected:
+ BlastFractureTool* m_fractureTool;
+ uint32_t m_chunkId;
+ Nv::Blast::RandomGeneratorBase* m_randomGenerator;
+ Nv::Blast::Mesh* m_sourMesh;
+};
+
+class VoronoiFractureExecutor : public FractureExecutor
+{
+public:
+ VoronoiFractureExecutor();
+ void setCellsCount(uint32_t cellsCount);
+
+ virtual bool execute();
+
+private:
+ uint32_t m_cellsCount;
+};
+
+class SliceFractureExecutor : public FractureExecutor
+{
+public:
+ SliceFractureExecutor();
+ void applyNoise(float amplitude, float frequency, int32_t octaves, float falloff, int32_t relaxIterations, float relaxFactor, int32_t seed = 0);
+ void applyConfig(int32_t xSlices, int32_t ySlices, int32_t zSlices, float offsetVariations, float angleVariations);
+
+ virtual bool execute();
+
+private:
+ Nv::Blast::SlicingConfiguration* m_config;
+};
+
+enum BlastToolType
+{
+ BTT_Damage = 0,
+ BTT_Drag,
+ BTT_Select,
+ BTT_Translate,
+ BTT_Scale,
+ BTT_Rotation,
+ BTT_Edit,
+ BTT_Num
+};
+
+enum SelectMode
+{
+ SM_RESET = 0,
+ SM_ADD,
+ SM_SUB,
+ SM_REMAIN,
+};
+
+class Renderer;
+class PhysXController;
+class BlastController;
+class SceneController;
+class DamageToolController;
+class SelectionToolController;
+class GizmoToolController;
+class EditionToolController;
+class SampleController;
+class CommonUIController;
+class SimpleRandomGenerator;
+
+/**
+*/
+class SampleManager
+{
+ friend class VoronoiFractureExecutor;
+ friend class SliceFractureExecutor;
+ public:
+ static SampleManager* ins();
+ SampleManager(DeviceManager* pDeviceManager);
+ ~SampleManager();
+
+ int init();
+ int run();
+ int free();
+
+ void addModelAsset(std::string file, bool isSkinned, physx::PxTransform transform, bool clear = true);
+
+ bool createAsset(
+ std::string assetName,
+ std::vector<physx::PxVec3>& positions,
+ std::vector<physx::PxVec3>& normals,
+ std::vector<physx::PxVec2>& uv,
+ std::vector<unsigned int>& indices,
+ bool fracture = false);
+
+ bool createAsset(
+ const std::string& assetName,
+ const std::vector<Nv::Blast::Mesh* >& meshes,
+ bool fracture = false);
+
+ bool saveAsset();
+ bool fractureAsset(std::string& assetName, const BlastAsset* blastAsset, int32_t chunkId);
+
+ bool postProcessCurrentAsset();
+
+ Renderer& getRenderer()
+ {
+ return *m_renderer;
+ }
+
+ PhysXController& getPhysXController() const
+ {
+ return *m_physXController;
+ }
+
+ BlastController& getBlastController() const
+ {
+ return *m_blastController;
+ }
+
+ SceneController& getSceneController() const
+ {
+ return *m_sceneController;
+ }
+
+ DamageToolController& getDamageToolController() const
+ {
+ return *m_damageToolController;
+ }
+
+ SelectionToolController& getSelectionToolController() const
+ {
+ return *m_selectionToolController;
+ }
+
+ GizmoToolController& getGizmoToolController() const
+ {
+ return *m_gizmoToolController;
+ }
+
+ EditionToolController& getEditionToolController() const
+ {
+ return *m_editionToolController;
+ }
+
+ SampleController& getSampleController() const
+ {
+ return *m_sampleController;
+ }
+
+ CommonUIController& getCommonUIController() const
+ {
+ return *m_commonUIController;
+ }
+
+ const SampleConfig& getConfig() const
+ {
+ return m_config;
+ }
+
+ std::vector<uint32_t> getCurrentSelectedChunks();
+ std::map<BlastAsset*, std::vector<uint32_t>> getSelectedChunks();
+ void clearChunksSelected();
+ void setChunkSelected(std::vector<uint32_t> depths, bool selected);
+ void setChunkVisible(std::vector<uint32_t> depths, bool bVisible);
+
+ void setFractureExecutor(FractureExecutor* executor);
+
+ void setBlastToolType(BlastToolType type);
+
+ void output(const char* str);
+ void output(float value);
+ void output(physx::PxVec3& vec);
+
+ void clearScene();
+
+ std::map<BlastAsset*, std::vector<BlastFamily*>>& getAssetFamiliesMap()
+ {
+ return m_AssetFamiliesMap;
+ }
+ std::map<BlastAsset*, AssetList::ModelAsset>& getAssetDescMap()
+ {
+ return m_AssetDescMap;
+ }
+
+ std::map<std::string, RenderMaterial*>& getRenderMaterials(){ return m_RenderMaterialMap; }
+ void addRenderMaterial(RenderMaterial* pRenderMaterial);
+ void removeRenderMaterial(std::string name);
+ void deleteRenderMaterial(std::string name);
+ void renameRenderMaterial(std::string oldName, std::string newName);
+
+ bool m_bNeedRefreshTree;
+
+ void getCurrentSelectedInstance(BlastAsset** ppBlastAsset, int& index);
+ void setCurrentSelectedInstance(BlastAsset* pBlastAsset, int index);
+ void getMaterialForCurrentFamily(RenderMaterial** ppRenderMaterial, bool externalSurface);
+ void setMaterialForCurrentFamily(RenderMaterial* pRenderMaterial, bool externalSurface);
+
+private:
+ bool _createAsset(
+ const std::string& assetName,
+ const std::string& outDir,
+ const std::vector<Nv::Blast::Mesh* >& meshes);
+
+ void _setSourceAsset();
+
+private:
+ Renderer* m_renderer;
+ PhysXController* m_physXController;
+ BlastController* m_blastController;
+ SceneController* m_sceneController;
+ DamageToolController* m_damageToolController;
+ SelectionToolController* m_selectionToolController;
+ GizmoToolController* m_gizmoToolController;
+ EditionToolController* m_editionToolController;
+ SampleController* m_sampleController;
+ CommonUIController* m_commonUIController;
+
+ SampleConfig m_config;
+
+ Application* m_pApplication;
+ BlastToolType m_ToolType;
+
+ BlastFractureTool* m_fTool;
+ FractureExecutor* m_fractureExecutor;
+
+ std::map<BlastAsset*, std::vector<BlastFamily*>> m_AssetFamiliesMap;
+ std::map<BlastAsset*, AssetList::ModelAsset> m_AssetDescMap;
+ std::map<std::string, RenderMaterial*> m_RenderMaterialMap;
+ std::vector<std::string> m_NeedDeleteRenderMaterials;
+
+ BlastAsset* m_pCurBlastAsset;
+ int m_nCurFamilyIndex;
+
+ bool m_bNeedConfig;
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/physx/PhysXController.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/physx/PhysXController.cpp
new file mode 100644
index 0000000..5146914
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/physx/PhysXController.cpp
@@ -0,0 +1,825 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, related documentation
+ * and any modifications thereto. Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
+ */
+
+#include "PhysXController.h"
+#include "RenderMaterial.h"
+#include "ResourceManager.h"
+#include "Renderer.h"
+
+#include "XInput.h"
+#include "DXUTMisc.h"
+#include "DXUTCamera.h"
+#include "ConvexRenderMesh.h"
+#include "RenderUtils.h"
+#include "SampleProfiler.h"
+#include "NvBlastProfiler.h"
+
+#include "PxPhysicsVersion.h"
+#include "PxPvdTransport.h"
+#include "PxDefaultCpuDispatcher.h"
+#include "PxPhysics.h"
+#include "PxScene.h"
+#include "PxCooking.h"
+#include "PxGpu.h"
+#include "PxSimpleFactory.h"
+#include "PxRigidBodyExt.h"
+#include "PxRigidDynamic.h"
+#include "PxRigidStatic.h"
+#include "PxMaterial.h"
+#include "PxFoundationVersion.h"
+#include "PxMath.h"
+
+#include <imgui.h>
+#include <chrono>
+
+using namespace std::chrono;
+
+#define PVD_TO_FILE 0
+
+const DirectX::XMFLOAT4 PLANE_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
+const DirectX::XMFLOAT4 HOOK_LINE_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
+const float DEFAULT_FIXED_TIMESTEP = 1.0f / 60.0f;
+
+PhysXController::PhysXController(PxSimulationFilterShader filterShader)
+: m_filterShader(filterShader)
+, m_gpuPhysicsAvailable(true)
+, m_useGPUPhysics(true)
+, m_lastSimulationTime(0)
+, m_paused(false)
+, m_draggingActor(nullptr)
+, m_draggingEnabled(true)
+, m_draggingTryReconnect(false)
+, m_perfWriter(NULL)
+, m_fixedTimeStep(DEFAULT_FIXED_TIMESTEP)
+, m_timeAccumulator(0)
+, m_useFixedTimeStep(true)
+, m_maxSubstepCount(1)
+{
+ QueryPerformanceFrequency(&m_performanceFreq);
+
+// Add By Lixu Begin
+ m_bForce = true;
+// Add By Lixu End
+}
+
+PhysXController::~PhysXController()
+{
+}
+
+void PhysXController::onInitialize()
+{
+ initPhysX();
+ initPhysXPrimitives();
+}
+
+void PhysXController::onTerminate()
+{
+ releasePhysXPrimitives();
+ releasePhysX();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PhysX init/release
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void PhysXController::initPhysX()
+{
+ m_foundation = PxCreateFoundation(PX_FOUNDATION_VERSION, m_allocator, m_errorCallback);
+
+ m_pvd = PxCreatePvd(*m_foundation);
+
+ NvBlastProfilerSetCallback(m_pvd);
+ NvBlastProfilerEnablePlatform(false);
+ NvBlastProfilerSetDetail(NvBlastProfilerDetail::LOW);
+
+ PxTolerancesScale scale;
+
+ m_physics = PxCreatePhysics(PX_PHYSICS_VERSION, *m_foundation, scale, true, m_pvd);
+
+ PxCookingParams cookingParams(scale);
+ cookingParams.buildGPUData = true;
+ m_cooking = PxCreateCooking(PX_PHYSICS_VERSION, m_physics->getFoundation(), cookingParams);
+
+ PxCudaContextManagerDesc ctxMgrDesc;
+ m_cudaContext = PxCreateCudaContextManager(m_physics->getFoundation(), ctxMgrDesc);
+ if (m_cudaContext && !m_cudaContext->contextIsValid())
+ {
+ m_cudaContext->release();
+ m_cudaContext = NULL;
+ }
+
+ PxSceneDesc sceneDesc(m_physics->getTolerancesScale());
+ sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
+ m_dispatcher = PxDefaultCpuDispatcherCreate(4);
+ sceneDesc.cpuDispatcher = m_dispatcher;
+ sceneDesc.gpuDispatcher = m_cudaContext != NULL ? m_cudaContext->getGpuDispatcher() : NULL;
+ sceneDesc.filterShader = m_filterShader;
+ sceneDesc.flags |= PxSceneFlag::eENABLE_STABILIZATION;
+ sceneDesc.flags |= PxSceneFlag::eENABLE_PCM;
+ if (sceneDesc.gpuDispatcher == nullptr)
+ {
+ m_gpuPhysicsAvailable = false;
+ m_useGPUPhysics = false;
+ }
+ if (m_useGPUPhysics)
+ {
+ sceneDesc.flags |= PxSceneFlag::eENABLE_GPU_DYNAMICS;
+ sceneDesc.broadPhaseType = PxBroadPhaseType::eGPU;
+
+ sceneDesc.gpuDynamicsConfig.constraintBufferCapacity *= 4;
+ sceneDesc.gpuDynamicsConfig.contactBufferCapacity *= 4;
+ sceneDesc.gpuDynamicsConfig.contactStreamSize *= 4;
+ sceneDesc.gpuDynamicsConfig.forceStreamCapacity *= 4;
+ sceneDesc.gpuDynamicsConfig.foundLostPairsCapacity *= 4;
+ sceneDesc.gpuDynamicsConfig.patchStreamSize *= 4;
+ sceneDesc.gpuDynamicsConfig.tempBufferCapacity *= 4;
+
+ }
+ m_physicsScene = m_physics->createScene(sceneDesc);
+
+ m_defaultMaterial = m_physics->createMaterial(0.8f, 0.7f, 0.1f);
+
+ PxPvdSceneClient* pvdClient = m_physicsScene->getScenePvdClient();
+ if(pvdClient)
+ {
+ pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
+ pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
+ pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
+ }
+
+ m_physicsScene->setVisualizationParameter(PxVisualizationParameter::eSCALE, 0);
+
+#if NV_DEBUG || NV_CHECKED || NV_PROFILE
+ PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate("localhost", 5425, 10);
+ if (transport)
+ {
+ m_pvd->connect(*transport,
+#if NV_DEBUG || NV_CHECKED
+ PxPvdInstrumentationFlag::eALL
+#else
+ PxPvdInstrumentationFlag::ePROFILE
+#endif
+ );
+ }
+#endif
+}
+
+void PhysXController::releasePhysX()
+{
+ m_defaultMaterial->release();
+ m_physicsScene->release();
+ if (m_cudaContext)
+ m_cudaContext->release();
+ m_dispatcher->release();
+ m_physics->release();
+ if (m_pvd)
+ {
+ PxPvdTransport* transport = m_pvd->getTransport();
+ m_pvd->release();
+ if (transport)
+ transport->release();
+ }
+ m_cooking->release();
+ m_foundation->release();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// GPU toggle
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void PhysXController::setUseGPUPhysics(bool useGPUPhysics)
+{
+ if (!m_gpuPhysicsAvailable)
+ {
+ useGPUPhysics = false;
+ }
+
+ if (m_useGPUPhysics == useGPUPhysics)
+ {
+ return;
+ }
+
+ onTerminate();
+
+ m_useGPUPhysics = useGPUPhysics;
+
+ onInitialize();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PhysX wrappers
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+PxRigidDynamic* PhysXController::createRigidDynamic(const PxTransform& transform)
+{
+ return m_physics->createRigidDynamic(transform);
+}
+
+void PhysXController::releaseRigidDynamic(PxRigidDynamic* rigidDynamic)
+{
+ notifyRigidDynamicDestroyed(rigidDynamic);
+
+ m_physXActorsToRemove.push_back(rigidDynamic);
+}
+
+void PhysXController::notifyRigidDynamicDestroyed(PxRigidDynamic* rigidDynamic)
+{
+ if (m_draggingActor == rigidDynamic)
+ {
+ m_draggingActor = nullptr;
+ m_draggingTryReconnect = true;
+ }
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Controller events
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void PhysXController::Animate(double dt)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+// Add By Lixu Begin
+ if (m_paused && !m_bForce)
+ return;
+ if (m_bForce)
+ {
+ m_paused = true;
+ m_bForce = false;
+ }
+// Add By Lixu End
+
+ // slower physics if fps is too low
+ dt = PxClamp(dt, 0.0, 0.033333);
+
+ updateDragging(dt);
+
+ {
+ PROFILER_SCOPED("PhysX simulate");
+ steady_clock::time_point start = steady_clock::now();
+ if (m_useFixedTimeStep)
+ {
+ m_timeAccumulator += dt;
+ m_substepCount = (uint32_t)std::floor(m_timeAccumulator / m_fixedTimeStep);
+ m_timeAccumulator -= m_fixedTimeStep * m_substepCount;
+ m_substepCount = m_maxSubstepCount > 0 ? physx::PxClamp<uint32_t>(m_substepCount, 0, m_maxSubstepCount) : m_substepCount;
+ for (uint32_t i = 0; i < m_substepCount; ++i)
+ {
+ PROFILER_SCOPED("PhysX simulate (substep)");
+ m_physicsScene->simulate(m_fixedTimeStep);
+ m_physicsScene->fetchResults(true);
+ }
+ }
+ else
+ {
+ m_substepCount = 1;
+ m_physicsScene->simulate(dt);
+ m_physicsScene->fetchResults(true);
+ }
+ m_lastSimulationTime = duration_cast<microseconds>(steady_clock::now() - start).count() * 0.000001;
+ }
+
+ PROFILER_BEGIN("Debug Render Buffer");
+ getRenderer().queueRenderBuffer(&m_physicsScene->getRenderBuffer());
+ PROFILER_END();
+
+ updateActorTransforms();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Dragging
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void PhysXController::setDraggingEnabled(bool enabled)
+{
+ m_draggingEnabled = enabled;
+
+ if (!m_draggingEnabled)
+ {
+ m_draggingActor = nullptr;
+ }
+}
+
+void PhysXController::updateDragging(double dt)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ // If dragging actor was recently removed we try to reconnect to new one once, using previous hook world point.
+ // Often it is removed because it was split into smaller chunks (actors), so we wont to stay connected for nicer user experience.
+ if (m_draggingActor == nullptr && m_draggingTryReconnect)
+ {
+ class OverlapCallback : public PxOverlapBufferN<32>
+ {
+ public:
+ OverlapCallback() : hitActor(nullptr) {}
+
+ PxAgain processTouches(const PxOverlapHit* buffer, PxU32 nbHits)
+ {
+ for (PxU32 i = 0; i < nbHits; ++i)
+ {
+ PxRigidDynamic* rigidDynamic = buffer[i].actor->is<PxRigidDynamic>();
+ if (rigidDynamic)
+ {
+ hitActor = rigidDynamic;
+ break;
+ }
+ }
+ return true;
+ }
+
+ PxRigidDynamic* hitActor;
+ };
+
+ OverlapCallback overlapCallback;
+ PxSphereGeometry sphere(0.15f);
+ bool isHit = getPhysXScene().overlap(sphere, PxTransform(m_draggingActorLastHookWorldPoint), overlapCallback, PxQueryFilterData(PxQueryFlag::eDYNAMIC));
+ if (isHit && overlapCallback.hitActor)
+ {
+ m_draggingActor = overlapCallback.hitActor;
+ }
+
+ m_draggingTryReconnect = false;
+ }
+
+ // Update dragging force and debug render (line)
+ if (m_draggingEnabled && m_draggingActor != NULL)
+ {
+ const float DRAGGING_FORCE_FACTOR = 10.0f;
+ const float DRAGGING_VELOCITY_FACTOR = 2.0f;
+ PxVec3 attractionPoint = m_dragAttractionPoint;
+ PxVec3 hookPoint = m_draggingActor->getGlobalPose().transform(m_draggingActorHookLocalPoint);
+ m_draggingActorLastHookWorldPoint = hookPoint;
+ m_dragVector = (m_dragAttractionPoint - hookPoint);
+ PxVec3 dragVeloctiy = (m_dragVector * DRAGGING_FORCE_FACTOR - DRAGGING_VELOCITY_FACTOR * m_draggingActor->getLinearVelocity()) * dt;
+ PxRigidBodyExt::addForceAtLocalPos(*m_draggingActor, dragVeloctiy * m_draggingActor->getMass(), m_draggingActorHookLocalPoint, PxForceMode::eIMPULSE, true);
+
+ // debug render line
+ m_dragDebugRenderBuffer.clear();
+ m_dragDebugRenderBuffer.m_lines.push_back(PxDebugLine(attractionPoint, hookPoint, XMFLOAT4ToU32Color(HOOK_LINE_COLOR)));
+ getRenderer().queueRenderBuffer(&m_dragDebugRenderBuffer);
+ }
+}
+
+void PhysXController::resetDragging()
+{
+ m_draggingActor = nullptr;
+}
+
+
+LRESULT PhysXController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ if (m_draggingEnabled && (uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP))
+ {
+ float mouseX = (short)LOWORD(lParam) / getRenderer().getScreenWidth();
+ float mouseY = (short)HIWORD(lParam) / getRenderer().getScreenHeight();
+
+ PxVec3 eyePos, pickDir;
+ getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ if (uMsg == WM_LBUTTONDOWN)
+ {
+ if (pickDir.magnitude() > 0)
+ {
+ PxRaycastHit hit;
+ PxRaycastBuffer rcBuffer(&hit, 1);
+ bool isHit = getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, rcBuffer, PxHitFlag::ePOSITION, PxQueryFilterData(PxQueryFlag::eDYNAMIC));
+ if (isHit)
+ {
+ m_dragDistance = (eyePos - hit.position).magnitude();
+ m_draggingActor = hit.actor->is<PxRigidDynamic>();
+ m_draggingActorHookLocalPoint = m_draggingActor->getGlobalPose().getInverse().transform(hit.position);
+ m_draggingActor->setLinearVelocity(PxVec3(0, 0, 0));
+ m_draggingActor->setAngularVelocity(PxVec3(0, 0, 0));
+ m_dragAttractionPoint = hit.position;
+ }
+ }
+ }
+ else if (uMsg == WM_MOUSEMOVE)
+ {
+ PxRaycastHit hit;
+ PxRaycastBuffer rcBuffer(&hit, 1);
+ bool isHit = getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, rcBuffer, PxHitFlag::ePOSITION, PxQueryFilterData(PxQueryFlag::eSTATIC));
+ if (isHit)
+ {
+ m_dragDistance = PxMin(m_dragDistance, (eyePos - hit.position).magnitude());
+ }
+
+ m_dragAttractionPoint = eyePos + pickDir * m_dragDistance;
+ }
+ else if (uMsg == WM_LBUTTONUP)
+ {
+ m_draggingActor = NULL;
+ }
+ }
+
+ return 1;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// UI
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void PhysXController::drawUI()
+{
+ ImGui::Checkbox("Use Fixed Timestep", &m_useFixedTimeStep);
+ if (m_useFixedTimeStep)
+ {
+ ImGui::InputFloat("Fixed Timestep", &m_fixedTimeStep);
+ ImGui::InputInt("Max Substep Count", &m_maxSubstepCount);
+ }
+
+ ImGui::Text("Substep Count: %d", m_substepCount);
+ ImGui::Text("Simulation Time (total): %4.2f ms", getLastSimulationTime() * 1000);
+ ImGui::Text("Simulation Time (substep): %4.2f ms", m_substepCount > 0 ? (getLastSimulationTime() / m_substepCount) * 1000 : 0.0);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PhysX Primitive
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void PhysXController::initPhysXPrimitives()
+{
+ // physx primitive render materials
+ {
+// Add By Lixu Begin
+ m_physXPrimitiveRenderMaterial = new RenderMaterial("", getRenderer().getResourceManager(), "physx_primitive", "");
+ m_physXPlaneRenderMaterial = new RenderMaterial("", getRenderer().getResourceManager(), "physx_primitive_plane", "");
+ m_physXPrimitiveTransparentRenderMaterial = new RenderMaterial("", getRenderer().getResourceManager(), "physx_primitive_transparent", "", RenderMaterial::BLEND_ALPHA_BLENDING);
+// Add By Lixu End
+ }
+
+ // create plane
+ Actor* plane = spawnPhysXPrimitivePlane(PxPlane(PxVec3(0, 1, 0).getNormalized(), 0));
+ plane->setColor(PLANE_COLOR);
+}
+
+void PhysXController::releasePhysXPrimitives()
+{
+ // remove all actors
+ for (std::set<Actor*>::iterator it = m_actors.begin(); it != m_actors.end(); it++)
+ {
+ delete (*it);
+ }
+ m_actors.clear();
+
+ // remove all materials
+ SAFE_DELETE(m_physXPrimitiveRenderMaterial);
+ SAFE_DELETE(m_physXPlaneRenderMaterial);
+ SAFE_DELETE(m_physXPrimitiveTransparentRenderMaterial);
+
+ // remove all convex render meshes
+ for (auto it = m_convexRenderMeshes.begin(); it != m_convexRenderMeshes.end(); it++)
+ {
+ SAFE_DELETE((*it).second);
+ }
+ m_convexRenderMeshes.clear();
+}
+
+void PhysXController::updateActorTransforms()
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ for (std::set<Actor*>::iterator it = m_actors.begin(); it != m_actors.end(); it++)
+ {
+ (*it)->update();
+ }
+}
+
+PhysXController::Actor* PhysXController::spawnPhysXPrimitiveBox(const PxTransform& position, PxVec3 extents, float density)
+{
+ PxBoxGeometry geom = PxBoxGeometry(extents);
+ PxRigidDynamic* actor = PxCreateDynamic(*m_physics, position, geom, *m_defaultMaterial, density);
+
+ return spawnPhysXPrimitive(actor);
+}
+
+PhysXController::Actor* PhysXController::spawnPhysXPrimitivePlane(const PxPlane& plane)
+{
+ PxRigidStatic* actor = PxCreatePlane(*m_physics, plane, *m_defaultMaterial);
+ PhysXController::Actor* p = spawnPhysXPrimitive(actor, true, true);
+ return p;
+}
+
+PhysXController::Actor* PhysXController::spawnPhysXPrimitive(PxRigidActor* actor, bool addToScene, bool ownPxActor)
+{
+ if (addToScene)
+ {
+ m_physicsScene->addActor(*actor);
+ }
+
+ Actor* a = new Actor(this, actor, ownPxActor);
+
+ m_actors.emplace(a);
+
+ return a;
+}
+
+void PhysXController::removePhysXPrimitive(Actor* actor)
+{
+ if (m_actors.find(actor) == m_actors.end())
+ return;
+
+ m_actors.erase(actor);
+
+ if (!actor->ownsPxActor())
+ {
+ m_physXActorsToRemove.push_back(actor->getActor());
+ }
+
+ if (m_draggingActor == actor->getActor())
+ {
+ m_draggingActor = nullptr;
+ }
+
+ delete actor;
+}
+
+void PhysXController::removeUnownedPhysXActors()
+{
+ if (m_physXActorsToRemove.size())
+ {
+ m_physicsScene->removeActors(&m_physXActorsToRemove[0], (PxU32)m_physXActorsToRemove.size());
+ for (size_t i = 0; i < m_physXActorsToRemove.size(); ++i)
+ {
+ m_physXActorsToRemove[i]->release();
+ }
+ m_physXActorsToRemove.resize(0);
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Actor
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+PhysXController::Actor::Actor(PhysXController* controller, PxRigidActor* actor, bool ownPxActor) :
+ m_controller(controller),
+ m_ownPxActor(ownPxActor),
+ m_hidden(false)
+{
+ m_actor = actor;
+
+ uint32_t shapesCount = actor->getNbShapes();
+ m_shapes.resize(shapesCount);
+ actor->getShapes(&m_shapes[0], shapesCount);
+
+ m_renderables.resize(m_shapes.size());
+ for (uint32_t i = 0; i < m_shapes.size(); i++)
+ {
+ PxShape* shape = m_shapes[i];
+ IRenderMesh* mesh = m_controller->getRenderMeshForShape(shape);
+ RenderMaterial* material = shape->getGeometryType() == PxGeometryType::ePLANE ? m_controller->m_physXPlaneRenderMaterial : m_controller->m_physXPrimitiveRenderMaterial;
+ m_renderables[i] = m_controller->getRenderer().createRenderable(*mesh, *material);
+ m_renderables[i]->setScale(m_controller->getMeshScaleForShape(shape));
+ }
+}
+
+PhysXController::Actor::~Actor()
+{
+ for (uint32_t i = 0; i < m_renderables.size(); i++)
+ {
+ m_controller->getRenderer().removeRenderable(m_renderables[i]);
+ }
+ if (m_ownPxActor)
+ {
+ m_actor->release();
+ }
+}
+
+void PhysXController::Actor::setColor(DirectX::XMFLOAT4 color)
+{
+ m_color = color;
+
+ for (uint32_t i = 0; i < m_renderables.size(); i++)
+ {
+ m_renderables[i]->setColor(color);
+ }
+}
+
+void PhysXController::Actor::setHidden(bool hidden)
+{
+ m_hidden = hidden;
+
+ for (uint32_t i = 0; i < m_renderables.size(); i++)
+ {
+ m_renderables[i]->setHidden(hidden);
+ }
+}
+
+void PhysXController::Actor::update()
+{
+ for (uint32_t i = 0; i < m_renderables.size(); i++)
+ {
+ m_renderables[i]->setTransform(m_actor->getGlobalPose() * m_shapes[i]->getLocalPose());
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PhysX Shapes Renderer
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+IRenderMesh* PhysXController::getConvexRenderMesh(const PxConvexMesh* mesh)
+{
+ auto it = m_convexRenderMeshes.find(mesh);
+ if (it != m_convexRenderMeshes.end())
+ {
+ return (*it).second;
+ }
+ else
+ {
+ ConvexRenderMesh* renderMesh = new ConvexRenderMesh(mesh);
+ m_convexRenderMeshes[mesh] = renderMesh;
+ return renderMesh;
+ }
+}
+
+IRenderMesh* PhysXController::getRenderMeshForShape(const PxShape* shape)
+{
+ switch (shape->getGeometryType())
+ {
+ case PxGeometryType::eBOX:
+ return getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Box);
+ case PxGeometryType::ePLANE:
+ return getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Plane);
+ case PxGeometryType::eSPHERE:
+ return getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Sphere);
+ case PxGeometryType::eCONVEXMESH:
+ {
+ PxConvexMeshGeometry geom;
+ shape->getConvexMeshGeometry(geom);
+ return getConvexRenderMesh(geom.convexMesh);
+ }
+ default:
+ PX_ALWAYS_ASSERT_MESSAGE("Unsupported PxGeometryType");
+ return NULL;
+ }
+}
+
+PxVec3 PhysXController::getMeshScaleForShape(const PxShape* shape)
+{
+ switch (shape->getGeometryType())
+ {
+ case PxGeometryType::eBOX:
+ {
+ PxBoxGeometry boxGeom;
+ shape->getBoxGeometry(boxGeom);
+ return boxGeom.halfExtents;
+ }
+ case PxGeometryType::ePLANE:
+ {
+ return PxVec3(1, 2000, 2000);
+ }
+ case PxGeometryType::eSPHERE:
+ {
+ PxSphereGeometry sphereGeom;
+ shape->getSphereGeometry(sphereGeom);
+ return PxVec3(sphereGeom.radius, sphereGeom.radius, sphereGeom.radius);
+ }
+ case PxGeometryType::eCONVEXMESH:
+ {
+ PxConvexMeshGeometry convexGeom;
+ shape->getConvexMeshGeometry(convexGeom);
+ return convexGeom.scale.scale; // maybe incorrect because of rotation not used
+ }
+ default:
+ return PxVec3(1, 1, 1);
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Utils
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+PxVec3 unproject(PxMat44& proj, PxMat44& view, float x, float y)
+{
+ PxVec4 screenPoint(x, y, 0, 1);
+ PxVec4 viewPoint = PxVec4(x / proj[0][0], y / proj[1][1], 1, 1);
+ PxVec4 nearPoint = view.inverseRT().transform(viewPoint);
+ if (nearPoint.w)
+ nearPoint *= 1.0f / nearPoint.w;
+ return PxVec3(nearPoint.x, nearPoint.y, nearPoint.z);
+}
+
+
+void PhysXController::getEyePoseAndPickDir(float mouseX, float mouseY, PxVec3& eyePos, PxVec3& pickDir)
+{
+ PxMat44 view = XMMATRIXToPxMat44(getRenderer().getCamera().GetViewMatrix());
+ PxMat44 proj = XMMATRIXToPxMat44(getRenderer().getCamera().GetProjMatrix());
+
+ PxMat44 eyeTransform = view.inverseRT();
+ eyePos = eyeTransform.getPosition();
+ PxVec3 nearPos = unproject(proj, view, mouseX * 2 - 1, 1 - mouseY * 2);
+ pickDir = nearPos - eyePos;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Add By Lixu Begin
+#include "PxExtensionsAPI.h"
+#include "PxDefaultStreams.h"
+#include "PxCollectionExt.h"
+// export collision as RepX. In exported file, it includes collisions as convexMesh. But for Rigidbodies, it will only export those exists.
+// if export as file A before damaging, it exports all of the chunks as convexMeshes. And Chunk 0 as Dynamic rigid body.
+// if export as file B after damaging and fracturing in the middle of simulation, it exports all of the chunks as convexMeshes. And the existing chunks as dynamic rigid bodies.
+bool PhysXController::ExportCollisionRepX(const char* fname, physx::PxPhysics* pSDK, physx::PxScene* pScene, bool asBinary)
+{
+ if ((pSDK == NULL) || (pScene == NULL) || (fname == NULL))
+ return false;
+
+ int count = pSDK->getNbScenes();
+ assert(count == 1);
+
+ physx::PxSerializationRegistry* psr = physx::PxSerialization::createSerializationRegistry(*pSDK);
+
+ physx::PxCollection* collectionSdk = physx::PxCollectionExt::createCollection(*pSDK);
+ PX_ASSERT(collectionSdk);
+
+ physx::PxCollection* collectionScene = physx::PxCollectionExt::createCollection(*pScene);
+ PX_ASSERT(collectionScene);
+
+ collectionSdk->add(*collectionScene);
+ physx::PxSerialization::complete(*collectionSdk, *psr, NULL, true);
+
+ physx::PxDefaultFileOutputStream theStream(fname);
+ bool exportNames = true;
+ bool bExportOk = false;
+ if (asBinary)
+ bExportOk = physx::PxSerialization::serializeCollectionToBinary(theStream, *collectionSdk, *psr, NULL, exportNames);
+ else
+ bExportOk = physx::PxSerialization::serializeCollectionToXml(theStream, *collectionSdk, *psr);
+
+ if (!bExportOk)
+ {
+ std::string warning = "Fail to save scene: ";
+ warning += fname;
+ warning += "!";
+ MessageBoxA(NULL, warning.c_str(), "", MB_OK | MB_ICONWARNING);
+ bExportOk = false;
+ }
+
+ collectionScene->release();
+ collectionSdk->release();
+
+ psr->release();
+
+ return bExportOk;
+}
+
+// we have to clear those convexMeshes when init scene. if not, they increase.
+void PhysXController::ClearOldCOllisions()
+{
+ physx::PxU32 size = m_physics->getNbShapes();
+ if (size > 0)
+ {
+ physx::PxShape** pShapes = new physx::PxShape*[size];
+ memset(pShapes, 0, size); // clear
+ physx::PxU32 count = m_physics->getShapes(pShapes, size);
+ for (physx::PxU32 i = 0; i < count; i++)
+ {
+ physx::PxShape& shape = *pShapes[i];
+ PxGeometryType::Enum type = shape.getGeometryType();
+ if (type == PxGeometryType::eCONVEXMESH)
+ shape.release();
+ }
+ delete[] pShapes;
+ size = m_physics->getNbShapes();
+ }
+ // release convexMesh
+ size = m_physics->getNbConvexMeshes();
+ if (size > 0)
+ {
+ physx::PxConvexMesh** pConvex = new physx::PxConvexMesh*[size];
+ memset(pConvex, 0, size); // clear
+ physx::PxU32 count = m_physics->getConvexMeshes(pConvex, size);
+ for (physx::PxU32 i = 0; i < count; i++)
+ {
+ pConvex[i]->release();
+ }
+ delete[] pConvex;
+ size = m_physics->getNbConvexMeshes();
+ }
+}
+// Add By Lixu Begin
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/physx/PhysXController.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/physx/PhysXController.h
new file mode 100644
index 0000000..2473526
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/physx/PhysXController.h
@@ -0,0 +1,296 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef PHYSX_CONTROLLER_H
+#define PHYSX_CONTROLLER_H
+
+#include "SampleManager.h"
+#include <DirectXMath.h>
+#include "DebugRenderBuffer.h"
+#include "PxFiltering.h"
+#include "PxDefaultAllocator.h"
+#include "PxDefaultErrorCallback.h"
+#include <set>
+#include <map>
+
+
+using namespace physx;
+
+class PerformanceDataWriter;
+class RenderMaterial;
+class Renderable;
+class IRenderMesh;
+
+namespace physx
+{
+class PxCpuDispatcher;
+class PxFoundation;
+class PxDefaultAllocator;
+class PxDefaultErrorCallback;
+class PxPhysics;
+class PxCooking;
+class PxPvd;
+class PxCudaContextManager;
+class PxDefaultCpuDispatcher;
+}
+
+
+/**
+SampleController which manages all the PhysX related work:
+1. initialization, scene updates, release.
+2. it can create update and render physx primitives. They are represented by PhysXController::Actor, see public API.
+3. provides ability to drag actors by mouse or other similar input
+
+NOTE: this class does too much, probably should be split in a few smaller ones.
+*/
+class PhysXController : public ISampleController
+{
+ public:
+
+ //////// Actor ////////
+
+ class Actor
+ {
+ public:
+
+ Actor(PhysXController* controller, PxRigidActor* actor, bool ownPxActor = true);
+ ~Actor();
+
+ void setColor(DirectX::XMFLOAT4 color);
+ DirectX::XMFLOAT4 getColor() const { return m_color; }
+
+ bool isHidden() { return m_hidden; }
+ void setHidden(bool hidden);
+
+ void update();
+ PxRigidActor* getActor() const { return m_actor; }
+
+ bool ownsPxActor() const { return m_ownPxActor; }
+
+ private:
+ PhysXController* m_controller;
+ PxRigidActor* m_actor;
+ std::vector<PxShape*> m_shapes;
+
+ std::vector<Renderable*> m_renderables;
+ DirectX::XMFLOAT4 m_color;
+
+ bool m_hidden;
+ bool m_ownPxActor;
+ };
+
+
+ //////// ctor ////////
+
+ PhysXController(PxSimulationFilterShader filterShader);
+ virtual ~PhysXController();
+
+
+ //////// virtual callbacks ////////
+
+ virtual void onInitialize();
+ virtual void onTerminate();
+
+ virtual void Animate(double dt);
+
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+
+ //////// public API ////////
+
+ void getEyePoseAndPickDir(float mouseX, float mouseY, PxVec3& eyePos, PxVec3& pickDir);
+
+ // wrappers to physx calls
+ PxRigidDynamic* createRigidDynamic(const PxTransform& transform);
+ void releaseRigidDynamic(PxRigidDynamic*);
+
+ Actor* spawnPhysXPrimitiveBox(const PxTransform& position, PxVec3 extents = PxVec3(1, 1, 1), float density = 2000.0f);
+ Actor* spawnPhysXPrimitivePlane(const PxPlane& plane);
+ Actor* spawnPhysXPrimitive(PxRigidActor* actor, bool addToScene = true, bool ownPxActor = true);
+ void removePhysXPrimitive(Actor*);
+
+ IRenderMesh* getConvexRenderMesh(const PxConvexMesh* mesh);
+ IRenderMesh* getRenderMeshForShape(const PxShape* shape);
+ PxVec3 getMeshScaleForShape(const PxShape* shape);
+
+ void removeUnownedPhysXActors();
+
+ bool isPaused() const
+ {
+ return m_paused;
+ }
+
+ void setPaused(bool paused)
+ {
+ m_paused = paused;
+ }
+
+ void setDraggingEnabled(bool enabled);
+ bool getDraggingEnabled() const { return m_draggingEnabled; }
+ void resetDragging();
+
+ void notifyRigidDynamicDestroyed(PxRigidDynamic*);
+
+ void drawUI();
+
+ //////// public getters ////////
+
+ double getLastSimulationTime() const
+ {
+ return m_lastSimulationTime;
+ }
+
+ RenderMaterial* getPrimitiveRenderMaterial()
+ {
+ return m_physXPrimitiveRenderMaterial;
+ }
+
+// Add By Lixu Begin
+ bool ExportCollisionRepX(const char* fname, physx::PxPhysics* pSDK, physx::PxScene* pScene, bool asBinary);
+ void ClearOldCOllisions();
+ RenderMaterial* getFBXRenderMaterial()
+ {
+ return m_physXPlaneRenderMaterial;
+ }
+ bool m_bForce;
+// Add By Lixu End
+
+ PxPhysics& getPhysics() const
+ {
+ return *m_physics;
+ }
+
+ PxScene& getPhysXScene() const
+ {
+ return *m_physicsScene;
+ }
+
+ PxMaterial* getDefaultMaterial() const
+ {
+ return m_defaultMaterial;
+ }
+
+ PxCooking& getCooking() const
+ {
+ return *m_cooking;
+ }
+
+ PxDefaultCpuDispatcher* getCPUDispatcher() const
+ {
+ return m_dispatcher;
+ }
+
+ void setPerformanceWriter(PerformanceDataWriter* perfWriter)
+ {
+ m_perfWriter = perfWriter;
+ }
+
+ bool getGPUPhysicsAvailable() const
+ {
+ return m_gpuPhysicsAvailable;
+ }
+
+ void setUseGPUPhysics(bool useGPUPhysics);
+
+ bool getUseGPUPhysics() const
+ {
+ return m_useGPUPhysics;
+ }
+
+ const PxVec3& getDragActorHookLocalPoint() const
+ {
+ return m_draggingActorHookLocalPoint;
+ }
+
+ const PxVec3& getDragVector() const
+ {
+ return m_dragVector;
+ }
+
+ PxRigidDynamic* getDraggingActor() const
+ {
+ return m_draggingActor;
+ }
+
+ private:
+ //////// internal methods ////////
+
+ void initPhysX();
+ void releasePhysX();
+
+ void initPhysXPrimitives();
+ void releasePhysXPrimitives();
+ void updateActorTransforms();
+ void updateDragging(double dt);
+
+
+ //////// used controllers ////////
+
+ Renderer& getRenderer() const
+ {
+ return getManager()->getRenderer();
+ }
+
+
+ //////// internal data ////////
+
+ // PhysX
+ PxFoundation* m_foundation;
+ PxDefaultAllocator m_allocator;
+ PxDefaultErrorCallback m_errorCallback;
+ PxPhysics* m_physics;
+ PxCooking* m_cooking;
+ PxPvd* m_pvd;
+ PxCudaContextManager* m_cudaContext;
+ PxDefaultCpuDispatcher* m_dispatcher;
+ PxMaterial* m_defaultMaterial;
+ PxSimulationFilterShader m_filterShader;
+ PxScene* m_physicsScene;
+
+ // PhysX API related
+ std::vector<PxActor*> m_physXActorsToRemove;
+
+ // primitives/actors
+ std::set<Actor*> m_actors;
+ std::map<const PxConvexMesh*, IRenderMesh*> m_convexRenderMeshes;
+ RenderMaterial* m_physXPrimitiveRenderMaterial;
+ RenderMaterial* m_physXPlaneRenderMaterial;
+ RenderMaterial* m_physXPrimitiveTransparentRenderMaterial;
+
+ // simulation
+ bool m_gpuPhysicsAvailable;
+ bool m_useGPUPhysics;
+ double m_lastSimulationTime;
+ LARGE_INTEGER m_performanceFreq;
+ bool m_paused;
+ bool m_useFixedTimeStep;
+ float m_fixedTimeStep;
+ float m_timeAccumulator;
+ uint32_t m_substepCount;
+ int32_t m_maxSubstepCount;
+
+ // dragging
+ bool m_draggingEnabled;
+ PxRigidDynamic* m_draggingActor;
+ PxVec3 m_draggingActorHookLocalPoint;
+ PxVec3 m_dragAttractionPoint;
+ PxVec3 m_dragVector;
+ float m_dragDistance;
+ DebugRenderBuffer m_dragDebugRenderBuffer;
+ PxVec3 m_draggingActorLastHookWorldPoint;
+ bool m_draggingTryReconnect;
+
+ // Performance writer
+ PerformanceDataWriter* m_perfWriter;
+
+
+};
+
+#endif
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ConvexRenderMesh.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ConvexRenderMesh.cpp
new file mode 100644
index 0000000..074cc2d
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ConvexRenderMesh.cpp
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "ConvexRenderMesh.h"
+#include "Renderer.h"
+#include "PxConvexMesh.h"
+
+
+struct Vertex
+{
+ PxVec3 position;
+ PxVec3 normal;
+};
+
+ConvexRenderMesh::ConvexRenderMesh(const PxConvexMesh* mesh)
+{
+ const uint32_t nbPolygons = mesh->getNbPolygons();
+ const uint8_t* indexBuffer = mesh->getIndexBuffer();
+ const PxVec3* meshVertices = mesh->getVertices();
+
+ uint32_t nbVerts = 0;
+ uint32_t nbFaces = 0;
+
+ for (uint32_t i = 0; i < nbPolygons; i++)
+ {
+ PxHullPolygon data;
+ mesh->getPolygonData(i, data);
+ uint32_t nbPolyVerts = data.mNbVerts;
+ nbVerts += nbPolyVerts;
+ nbFaces += (nbPolyVerts - 2) * 3;
+ }
+
+ std::vector<Vertex> vertices;
+ std::vector<uint16_t> faces;
+
+ vertices.resize(nbVerts);
+ faces.resize(nbFaces);
+
+ uint32_t vertCounter = 0;
+ uint32_t facesCounter = 0;
+ for (uint32_t i = 0; i < nbPolygons; i++)
+ {
+ PxHullPolygon data;
+ mesh->getPolygonData(i, data);
+
+ PxVec3 normal(data.mPlane[0], data.mPlane[1], data.mPlane[2]);
+
+ uint32_t vI0 = vertCounter;
+ for (uint32_t vI = 0; vI < data.mNbVerts; vI++)
+ {
+ vertices[vertCounter].position = meshVertices[indexBuffer[data.mIndexBase + vI]];
+ vertices[vertCounter].normal = normal;
+ vertCounter++;
+ }
+
+ for (uint32_t vI = 1; vI < uint32_t(data.mNbVerts) - 1; vI++)
+ {
+ faces[facesCounter++] = uint16_t(vI0);
+ faces[facesCounter++] = uint16_t(vI0 + vI + 1);
+ faces[facesCounter++] = uint16_t(vI0 + vI);
+ }
+ }
+
+ std::vector<D3D11_INPUT_ELEMENT_DESC> layout;
+ layout.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ layout.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+
+ initialize(vertices.data(), (uint32_t)vertices.size(), sizeof(Vertex), layout, faces.data(), nbFaces);
+}
+
+
+ConvexRenderMesh::~ConvexRenderMesh()
+{
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ConvexRenderMesh.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ConvexRenderMesh.h
new file mode 100644
index 0000000..dfe8d8f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ConvexRenderMesh.h
@@ -0,0 +1,34 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef CONVEX_RENDER_MESH_H
+#define CONVEX_RENDER_MESH_H
+
+#include "CustomRenderMesh.h"
+
+namespace physx
+{
+class PxConvexMesh;
+}
+
+
+/**
+PxConvexMesh render mesh
+(this class relates to PhysX more then to Renderer)
+*/
+class ConvexRenderMesh : public CustomRenderMesh
+{
+public:
+ ConvexRenderMesh(const PxConvexMesh* mesh);
+ virtual ~ConvexRenderMesh();
+};
+
+
+#endif //CONVEX_RENDER_MESH_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/CustomRenderMesh.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/CustomRenderMesh.cpp
new file mode 100644
index 0000000..61ae9e0
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/CustomRenderMesh.cpp
@@ -0,0 +1,96 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "CustomRenderMesh.h"
+
+
+CustomRenderMesh::CustomRenderMesh()
+ : m_indexBuffer(nullptr)
+{
+}
+
+CustomRenderMesh::CustomRenderMesh(const void* vertices, uint32_t numVertices, uint32_t vertexSize, std::vector<D3D11_INPUT_ELEMENT_DESC>& inputDesc, const uint16_t* faces, uint32_t numFaces)
+ : m_indexBuffer(nullptr)
+{
+ initialize(vertices, numVertices, vertexSize, inputDesc, faces, numFaces);
+}
+
+void CustomRenderMesh::initialize(const void* vertices, uint32_t numVertices, uint32_t vertexSize, std::vector<D3D11_INPUT_ELEMENT_DESC>& inputDesc, const uint16_t* faces, uint32_t numFaces)
+{
+ ID3D11Device* device = GetDeviceManager()->GetDevice();
+
+ m_inputDesc = inputDesc;
+ m_numVertices = numVertices;
+ m_vertexSize = vertexSize;
+ m_numFaces = numFaces;
+
+ // VB
+ {
+ D3D11_SUBRESOURCE_DATA vertexBufferData;
+
+ ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
+ vertexBufferData.pSysMem = vertices;
+
+ D3D11_BUFFER_DESC bufferDesc;
+
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.ByteWidth = vertexSize * numVertices;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+
+ V(device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_vertexBuffer));
+ }
+
+ // IB
+ if (faces != nullptr)
+ {
+ D3D11_SUBRESOURCE_DATA indexBufferData;
+
+ ZeroMemory(&indexBufferData, sizeof(indexBufferData));
+ indexBufferData.pSysMem = faces;
+
+ D3D11_BUFFER_DESC bufferDesc;
+
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ bufferDesc.ByteWidth = sizeof(uint16_t) * numFaces;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+
+ V(device->CreateBuffer(&bufferDesc, &indexBufferData, &m_indexBuffer));
+ }
+}
+
+CustomRenderMesh::~CustomRenderMesh()
+{
+ SAFE_RELEASE(m_vertexBuffer);
+ SAFE_RELEASE(m_indexBuffer);
+}
+
+
+void CustomRenderMesh::render(ID3D11DeviceContext& context) const
+{
+ context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+
+ UINT strides[1] = { m_vertexSize };
+ UINT offsets[1] = { 0 };
+ context.IASetVertexBuffers(0, 1, &m_vertexBuffer, strides, offsets);
+
+ context.IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0);
+
+ if (m_indexBuffer)
+ context.DrawIndexed(m_numFaces, 0, 0);
+ else
+ context.Draw(m_numVertices, 0);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/CustomRenderMesh.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/CustomRenderMesh.h
new file mode 100644
index 0000000..b0ddea1
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/CustomRenderMesh.h
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef CUSTOM_RENDER_MESH_H
+#define CUSTOM_RENDER_MESH_H
+
+#include "Renderable.h"
+
+
+class CustomRenderMesh : public IRenderMesh
+{
+public:
+ const std::vector<D3D11_INPUT_ELEMENT_DESC>& getInputElementDesc() const { return m_inputDesc; }
+ void render(ID3D11DeviceContext& context) const;
+
+ CustomRenderMesh(const void* vertices, uint32_t numVertices, uint32_t vertexSize, std::vector<D3D11_INPUT_ELEMENT_DESC>& inputDesc, const uint16_t* faces = nullptr, uint32_t numFaces = 0);
+ virtual ~CustomRenderMesh();
+
+protected:
+ CustomRenderMesh();
+ void initialize(const void* vertices, uint32_t numVertices, uint32_t vertexSize, std::vector<D3D11_INPUT_ELEMENT_DESC>& inputDesc, const uint16_t* faces, uint32_t numFaces);
+
+private:
+ ID3D11Buffer* m_vertexBuffer;
+ ID3D11Buffer* m_indexBuffer;
+ uint32_t m_numFaces;
+ uint32_t m_numVertices;
+ uint32_t m_vertexSize;
+
+ std::vector<D3D11_INPUT_ELEMENT_DESC> m_inputDesc;
+};
+
+
+#endif //CUSTOM_RENDER_MESH_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/DebugRenderBuffer.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/DebugRenderBuffer.h
new file mode 100644
index 0000000..7810733
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/DebugRenderBuffer.h
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef DEBUGRENDERBUFFER_H
+#define DEBUGRENDERBUFFER_H
+
+#include "PxRenderBuffer.h"
+#include <vector>
+
+using namespace physx;
+
+
+/**
+Simple PxRenderBuffer implementation for easy debug primitives adding
+*/
+class DebugRenderBuffer : public PxRenderBuffer
+{
+public:
+ ~DebugRenderBuffer() {}
+
+ virtual PxU32 getNbPoints() const { return 0; }
+ virtual const PxDebugPoint* getPoints() const { return nullptr; }
+
+ virtual PxU32 getNbLines() const { return static_cast<PxU32>(m_lines.size()); }
+ virtual const PxDebugLine* getLines() const { return m_lines.data(); }
+
+ virtual PxU32 getNbTriangles() const { return 0; }
+ virtual const PxDebugTriangle* getTriangles() const { return nullptr; }
+
+ virtual PxU32 getNbTexts() const { return 0; }
+ virtual const PxDebugText* getTexts() const { return nullptr; }
+
+ virtual void append(const PxRenderBuffer& other) {}
+ virtual void clear()
+ {
+ m_lines.clear();
+ }
+
+ std::vector<PxDebugLine> m_lines;
+};
+
+
+#endif //DEBUGRENDERBUFFER_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Mesh.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Mesh.cpp
new file mode 100644
index 0000000..cdf63f2
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Mesh.cpp
@@ -0,0 +1,13 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+
+#include "Mesh.h"
+
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Mesh.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Mesh.h
new file mode 100644
index 0000000..b10f0d6
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Mesh.h
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef MESH_H
+#define MESH_H
+
+#include <vector>
+#include "PxVec2.h"
+#include "PxVec3.h"
+
+// Add By Lixu Begin
+class MeshBase
+// Add By Lixu End
+{
+ virtual uint32_t getVertexStride() = 0;
+ // ... TBD
+};
+
+/**
+SimpleMesh: position + normal + uv
+We use only this type everywhere, once other versions will be required we should generalize Mesh and refactor code.
+*/
+// Add By Lixu Begin
+class SimpleMesh : public MeshBase
+// Add By Lixu End
+{
+public:
+
+ class Vertex
+ {
+ public:
+ physx::PxVec3 position;
+ physx::PxVec3 normal;
+ physx::PxVec2 uv;
+ };
+
+ virtual uint32_t getVertexStride() { return sizeof(Vertex); }
+
+ std::vector<Vertex> vertices;
+ std::vector<uint16_t> indices;
+
+ physx::PxVec3 extents;
+ physx::PxVec3 center;
+};
+
+
+#endif //MESH_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/PrimitiveRenderMesh.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/PrimitiveRenderMesh.cpp
new file mode 100644
index 0000000..06c7616
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/PrimitiveRenderMesh.cpp
@@ -0,0 +1,284 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+
+#include "PrimitiveRenderMesh.h"
+#include "Renderer.h"
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Base Mesh internal class
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+PrimitiveRenderMesh::PrimitiveRenderMesh(const float v[], UINT numVertices)
+{
+ std::vector<D3D11_INPUT_ELEMENT_DESC> layout;
+ layout.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ layout.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+
+ initialize(v, numVertices, sizeof(float) * 6, layout, nullptr, 0);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Box Mesh
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const float boxVertices[] =
+{
+ -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f,
+ 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f,
+ 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f,
+ 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f,
+ -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f,
+ -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f,
+
+ -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+
+ -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
+ -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f,
+ -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f,
+ -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f,
+ -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
+ -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
+
+ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
+ 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f,
+ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f,
+ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f,
+ 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
+
+ -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f,
+ 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f,
+ 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f,
+ 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f,
+ -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f,
+ -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f,
+
+ -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
+ 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
+ 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+ 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+ -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+ -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f
+};
+
+BoxRenderMesh::BoxRenderMesh() : PrimitiveRenderMesh(boxVertices, sizeof(boxVertices) / (6 * sizeof(boxVertices[0]))) {}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Plane Mesh
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const float planeSize = 1.0f; // we use scaling instead
+const float planeTilesCount = 1000.0f;
+
+const float planeVertices[] =
+{
+ 0, planeSize, planeSize, 1.0f, 0.0f, 0.0f, planeTilesCount, planeTilesCount,
+ 0, planeSize, -planeSize, 1.0f, 0.0f, 0.0f, planeTilesCount, -planeTilesCount,
+ 0, -planeSize, -planeSize, 1.0f, 0.0f, 0.0f, -planeTilesCount, -planeTilesCount,
+ 0, -planeSize, -planeSize, 1.0f, 0.0f, 0.0f, -planeTilesCount, -planeTilesCount,
+ 0, -planeSize, planeSize, 1.0f, 0.0f, 0.0f, -planeTilesCount, planeTilesCount,
+ 0, planeSize, planeSize, 1.0f, 0.0f, 0.0f, planeTilesCount, planeTilesCount
+};
+
+PlaneRenderMesh::PlaneRenderMesh()
+{
+ std::vector<D3D11_INPUT_ELEMENT_DESC> layout;
+ layout.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ layout.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ layout.push_back({ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+
+ initialize(planeVertices, sizeof(planeVertices) / (8 * sizeof(planeVertices[0])), sizeof(float) * 8, layout, nullptr, 0);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Sphere Mesh
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+const uint32_t g_numSlices = 8; // along lines of longitude
+const uint32_t g_numStacks = 16; // along lines of latitude
+
+const uint32_t g_numSphereVertices = (g_numSlices * 2 + 1)*(g_numStacks + 1);
+const uint32_t g_numSphereIndices = g_numSlices * 2 * g_numStacks * 6;
+
+const uint32_t g_numConeVertices = (g_numSlices * 2 + 1) * 2;
+const uint32_t g_numConeIndices = g_numSlices * 2 * 6;
+
+PxVec3 g_spherePositions[g_numSphereVertices];
+uint16_t g_sphereIndices[g_numSphereIndices];
+
+void generateSphereMesh(uint16_t slices, uint16_t stacks, PxVec3* positions, uint16_t* indices)
+{
+ const PxF32 thetaStep = PxPi / stacks;
+ const PxF32 phiStep = PxTwoPi / (slices * 2);
+
+ PxF32 theta = 0.0f;
+
+ // generate vertices
+ for (uint16_t y = 0; y <= stacks; ++y)
+ {
+ PxF32 phi = 0.0f;
+
+ PxF32 cosTheta = PxCos(theta);
+ PxF32 sinTheta = PxSin(theta);
+
+ for (uint16_t x = 0; x <= slices * 2; ++x)
+ {
+ PxF32 cosPhi = PxCos(phi);
+ PxF32 sinPhi = PxSin(phi);
+
+ PxVec3 p(cosPhi*sinTheta, cosTheta, sinPhi*sinTheta);
+
+ // write vertex
+ *(positions++) = p;
+
+ phi += phiStep;
+ }
+
+ theta += thetaStep;
+ }
+
+ const uint16_t numRingQuads = 2 * slices;
+ const uint16_t numRingVerts = 2 * slices + 1;
+
+ // add faces
+ for (uint16_t y = 0; y < stacks; ++y)
+ {
+ for (uint16_t i = 0; i < numRingQuads; ++i)
+ {
+ // add a quad
+ *(indices++) = (y + 0)*numRingVerts + i;
+ *(indices++) = (y + 1)*numRingVerts + i;
+ *(indices++) = (y + 1)*numRingVerts + i + 1;
+
+ *(indices++) = (y + 1)*numRingVerts + i + 1;
+ *(indices++) = (y + 0)*numRingVerts + i + 1;
+ *(indices++) = (y + 0)*numRingVerts + i;
+ }
+ }
+}
+
+
+struct SphereVertex
+{
+ PxVec3 position;
+ PxVec3 normal;
+};
+
+SphereRenderMesh::SphereRenderMesh()
+{
+ generateSphereMesh(g_numSlices, g_numStacks, g_spherePositions, g_sphereIndices);
+
+ std::vector<SphereVertex> vertices;
+ for (uint32_t i = 0; i < g_numSphereVertices; i++)
+ {
+ vertices.push_back({ g_spherePositions[i], g_spherePositions[i] });
+ }
+
+ std::vector<D3D11_INPUT_ELEMENT_DESC> layout;
+ layout.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ layout.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+
+ initialize(vertices.data(), (uint32_t)vertices.size(), sizeof(SphereVertex), layout, g_sphereIndices, g_numSphereIndices);
+}
+
+
+SphereRenderMesh::~SphereRenderMesh()
+{
+}
+
+// Add By Lixu Begin
+const float coneVertices[] =
+{
+ 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f,//top
+ -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f,//left bottom
+ -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f,//left top
+
+ 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,//top
+ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f,//right top
+ 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f,//right bottom
+
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f,//top
+ -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f,//left top
+ 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f,//right top
+
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,//top
+ 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,//right bottom
+ -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,//left bottom
+
+ -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f,//left top
+ 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f,//right bottom
+ 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f,//right top
+
+ 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f,//right bottom
+ -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f,//left top
+ -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f,//left bottom
+};
+
+ConeRenderMesh::ConeRenderMesh() : PrimitiveRenderMesh(coneVertices, sizeof(coneVertices) / (6 * sizeof(coneVertices[0]))) {}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// FBX Mesh class
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#include <AnimUtil.h>
+#include <PxVec2.h>
+#include <vector>
+
+struct FBXVertex
+{
+ PxVec3 position;
+ PxVec3 normal;
+ PxVec2 uv;
+};
+
+FBXRenderMesh::FBXRenderMesh(MeshDesc* pMeshData)
+{
+ std::vector<D3D11_INPUT_ELEMENT_DESC> layout;
+ layout.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ layout.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ layout.push_back({ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+
+ std::vector<FBXVertex> vertices;
+ std::vector<uint16_t> indices;
+
+ for (uint32_t i = 0; i < pMeshData->m_NumVertices; ++i)
+ {
+ atcore_float3 pos = pMeshData->m_pVertices[i];
+ atcore_float3 vertexNormal = pMeshData->m_pVertexNormals[i];
+ atcore_float2 texcoord = pMeshData->m_pTexCoords[i];
+
+ FBXVertex newVertex;
+ newVertex.position = physx::PxVec3(pos.x, pos.y, pos.z);
+ newVertex.normal = physx::PxVec3(vertexNormal.x, vertexNormal.y, vertexNormal.z);
+ newVertex.uv = physx::PxVec2(texcoord.x, texcoord.y);
+
+ vertices.push_back(newVertex);
+ }
+
+ for (uint32_t i = 0; i < pMeshData->m_NumTriangles; ++i)
+ {
+ indices.push_back(pMeshData->m_pIndices[i * 3 + 0]);
+ indices.push_back(pMeshData->m_pIndices[i * 3 + 1]);
+ indices.push_back(pMeshData->m_pIndices[i * 3 + 2]);
+ }
+
+ initialize(vertices.data(), (uint32_t)vertices.size(), sizeof(FBXVertex), layout, indices.data(), (uint32_t)indices.size());
+}
+// Add By Lixu End \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/PrimitiveRenderMesh.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/PrimitiveRenderMesh.h
new file mode 100644
index 0000000..0f3f345
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/PrimitiveRenderMesh.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef PRIMITIVE_RENDER_MESH_H
+#define PRIMITIVE_RENDER_MESH_H
+
+#include "Utils.h"
+#include <DirectXMath.h>
+
+#include <vector>
+#include "Renderable.h"
+#include "CustomRenderMesh.h"
+
+
+class PrimitiveRenderMesh : public CustomRenderMesh
+{
+protected:
+ PrimitiveRenderMesh(const float v[], UINT numVertices);
+};
+
+class BoxRenderMesh : public PrimitiveRenderMesh
+{
+public:
+ BoxRenderMesh();
+};
+
+
+class PlaneRenderMesh : public CustomRenderMesh
+{
+public:
+ PlaneRenderMesh();
+};
+
+
+class SphereRenderMesh : public CustomRenderMesh
+{
+public:
+ SphereRenderMesh();
+ virtual ~SphereRenderMesh();
+};
+
+
+// Add By Lixu Begin
+class ConeRenderMesh : public PrimitiveRenderMesh
+{
+public:
+ ConeRenderMesh();
+};
+
+class MeshDesc;
+
+class FBXRenderMesh : public CustomRenderMesh
+{
+public:
+ FBXRenderMesh(MeshDesc* pMeshData);
+};
+// Add By Lixu End
+
+
+struct PrimitiveRenderMeshType
+{
+ enum Enum
+ {
+ Box,
+ Plane,
+ Sphere,
+// Add By Lixu Begin
+ Cone,
+// Add By Lixu End
+ Count
+ };
+};
+
+#endif //PRIMITIVE_RENDER_MESH_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderMaterial.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderMaterial.cpp
new file mode 100644
index 0000000..1b90f8f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderMaterial.cpp
@@ -0,0 +1,277 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "RenderMaterial.h"
+#include <DirectXMath.h>
+#include "ShaderUtils.h"
+#include "Renderer.h"
+#include "SampleManager.h"
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// RenderMaterial
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+RenderMaterial::RenderMaterial(const char* materialName, ResourceManager& resourceCallback, const char* shaderFileName,
+ const char* textureFileName, BlendMode blendMode)
+{
+// Add By Lixu Begin
+ mMaterialName = materialName;
+ mTextureFileName = textureFileName;
+ SampleManager::ins()->addRenderMaterial(this);
+// Add By Lixu End
+
+ this->initialize(resourceCallback, shaderFileName, textureFileName, blendMode);
+}
+
+void RenderMaterial::initialize(ResourceManager& resourceCallback, const char* shaderFileName, const char* textureFileName, BlendMode blendMode)
+{
+ std::vector<std::string> v;
+ v.push_back(shaderFileName);
+ initialize(resourceCallback, v, textureFileName, blendMode);
+}
+
+void RenderMaterial::initialize(ResourceManager& resourceCallback, std::vector<std::string> shaderFileNames, const char* textureFileName, BlendMode blendMode)
+{
+ mTextureSRV = nullptr;
+ mTexture = nullptr;
+ mBlendState = nullptr;
+
+ for (uint32_t i = 0; i < shaderFileNames.size(); i++)
+ {
+ const ShaderFileResource* resource = resourceCallback.requestShaderFile(shaderFileNames[i].c_str());
+ if (resource)
+ {
+ std::string shaderFilePath = resource->path;
+ mShaderFilePathes.push_back(shaderFilePath);
+ }
+ }
+ mShaderGroups.reserve(mShaderFilePathes.size());
+
+ if (!mTextureFileName.empty())
+ {
+ mTexture = resourceCallback.requestTexture(mTextureFileName.c_str());
+ }
+
+ setBlending(blendMode);
+
+ reload();
+}
+
+void RenderMaterial::releaseReloadableResources()
+{
+ for (std::vector<ShaderGroup*>::iterator it = mShaderGroups.begin(); it != mShaderGroups.end(); it++)
+ {
+ delete *it;
+ }
+ mShaderGroups.clear();
+
+// Add By Lixu Begin
+ for (std::map<const IRenderMesh*, Instance*>::iterator it = mRenderMeshToInstanceMap.begin();
+ it != mRenderMeshToInstanceMap.end(); it++)
+ {
+ delete it->second;
+ }
+ mRenderMeshToInstanceMap.clear();
+// Add By Lixu End
+
+ SAFE_RELEASE(mTextureSRV);
+}
+
+RenderMaterial::~RenderMaterial()
+{
+// Add By Lixu Begin
+ SampleManager::ins()->removeRenderMaterial(mMaterialName);
+// Add By Lixu End
+
+ releaseReloadableResources();
+ SAFE_RELEASE(mBlendState);
+}
+
+void RenderMaterial::setBlending(BlendMode blendMode)
+{
+ mBlendMode = blendMode;
+
+ SAFE_RELEASE(mBlendState);
+
+ D3D11_BLEND_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+
+ switch (blendMode)
+ {
+ case BLEND_NONE:
+ desc.RenderTarget[0].BlendEnable = FALSE;
+ desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
+ break;
+ case BLEND_ALPHA_BLENDING:
+ desc.AlphaToCoverageEnable = FALSE;
+ desc.IndependentBlendEnable = TRUE;
+ desc.RenderTarget[0].BlendEnable = TRUE;
+ desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
+ desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
+ desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
+ desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
+ desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
+ break;
+ case BLEND_ADDITIVE: // actually, is's additive by alpha
+ desc.AlphaToCoverageEnable = FALSE;
+ desc.IndependentBlendEnable = TRUE;
+ desc.RenderTarget[0].BlendEnable = TRUE;
+ desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
+ desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
+ desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
+ desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
+ desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
+ break;
+ default:
+ PX_ALWAYS_ASSERT_MESSAGE("Unknown blend mode");
+ }
+
+ ID3D11Device* device = GetDeviceManager()->GetDevice();
+ V(device->CreateBlendState(&desc, &mBlendState));
+}
+
+void RenderMaterial::reload()
+{
+ releaseReloadableResources();
+
+ // load shaders
+ ID3D11Device* device = GetDeviceManager()->GetDevice();
+
+ for (std::vector<std::string>::iterator it = mShaderFilePathes.begin(); it != mShaderFilePathes.end(); it++)
+ {
+ const char* shaderFilePath = (*it).c_str();
+ ShaderGroup* shaderGroup = new ShaderGroup();
+ V(createShaderFromFile(device, shaderFilePath, "VS", &(shaderGroup->vs), shaderGroup->buffer));
+ createShaderFromFile(device, shaderFilePath, "PS", &shaderGroup->ps);
+ createShaderFromFile(device, shaderFilePath, "GS", &shaderGroup->gs);
+ mShaderGroups.push_back(shaderGroup);
+ }
+
+ // load texture
+ if (mTexture)
+ {
+ V(DirectX::CreateShaderResourceView(device, mTexture->image.GetImages(), mTexture->image.GetImageCount(),
+ mTexture->metaData, &mTextureSRV));
+ }
+}
+
+
+
+RenderMaterial::InstancePtr RenderMaterial::getMaterialInstance(const IRenderMesh* mesh)
+{
+ // look in cache
+ auto it = mRenderMeshToInstanceMap.find(mesh);
+ if (it != mRenderMeshToInstanceMap.end())
+ {
+// Add By Lixu Begin
+ /*
+ if (!(*it).second.expired())
+ {
+ return (*it).second.lock();
+ }
+ */
+ return it->second;
+// Add By Lixu End
+ }
+
+ // create new
+ const std::vector<D3D11_INPUT_ELEMENT_DESC>& descs = mesh->getInputElementDesc();
+ RenderMaterial::InstancePtr instance = getMaterialInstance(&descs[0], (uint32_t)descs.size());
+ mRenderMeshToInstanceMap[mesh] = instance;
+ return instance;
+}
+
+RenderMaterial::InstancePtr RenderMaterial::getMaterialInstance(const D3D11_INPUT_ELEMENT_DESC* elementDescs, uint32_t numElements)
+{
+ ID3D11Device* device = GetDeviceManager()->GetDevice();
+
+ for (uint32_t i = 0; i < mShaderGroups.size(); i++)
+ {
+ if (mShaderGroups[i]->buffer == NULL)
+ continue;
+
+ ID3D11InputLayout* inputLayout = NULL;
+ device->CreateInputLayout(elementDescs, numElements, mShaderGroups[i]->buffer->GetBufferPointer(), mShaderGroups[i]->buffer->GetBufferSize(), &inputLayout);
+
+ if (inputLayout)
+ {
+ RenderMaterial::InstancePtr materialInstance(new Instance(*this, inputLayout, i));
+ return materialInstance;
+ }
+ }
+ PX_ALWAYS_ASSERT();
+ return NULL;
+}
+
+void RenderMaterial::Instance::bind(ID3D11DeviceContext& context, uint32_t slot, bool depthStencilOnly)
+{
+ mMaterial.mShaderGroups[mShaderNum]->Set(&context, !depthStencilOnly);
+
+ context.OMSetBlendState(mMaterial.mBlendState, nullptr, 0xFFFFFFFF);
+ context.PSSetShaderResources(slot, 1, &(mMaterial.mTextureSRV));
+ context.IASetInputLayout(mInputLayout);
+}
+
+bool RenderMaterial::Instance::isValid()
+{
+ return mMaterial.mShaderGroups.size() > 0 && mMaterial.mShaderGroups[mShaderNum]->IsValid();
+}
+
+// Add By Lixu Begin
+void RenderMaterial::setTextureFileName(std::string textureFileName)
+{
+ if (mTextureFileName == textureFileName)
+ {
+ return;
+ }
+
+ mTextureFileName = textureFileName;
+ mTexture = nullptr;
+ SAFE_RELEASE(mTextureSRV);
+
+ if (mTextureFileName.empty())
+ {
+ return;
+ }
+
+ std::string searchDir = mTextureFileName;
+ size_t ind = searchDir.find_last_of('/');
+ if (ind > 0)
+ searchDir = searchDir.substr(0, ind);
+
+ ResourceManager* pResourceManager = ResourceManager::ins();
+ pResourceManager->addSearchDir(searchDir.c_str());
+ mTexture = pResourceManager->requestTexture(mTextureFileName.c_str());
+ if (mTexture == nullptr)
+ {
+ return;
+ }
+
+ ID3D11Device* device = GetDeviceManager()->GetDevice();
+ DirectX::CreateShaderResourceView(device, mTexture->image.GetImages(), mTexture->image.GetImageCount(),
+ mTexture->metaData, &mTextureSRV);
+}
+
+RenderMaterial* g_DefaultRenderMaterial = nullptr;
+RenderMaterial* RenderMaterial::getDefaultRenderMaterial()
+{
+ if (g_DefaultRenderMaterial == nullptr)
+ {
+ ResourceManager* pResourceManager = ResourceManager::ins();
+ g_DefaultRenderMaterial = new RenderMaterial("", *pResourceManager, "model_simple_ex");
+ }
+ return g_DefaultRenderMaterial;
+}
+// Add By Lixu End \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderMaterial.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderMaterial.h
new file mode 100644
index 0000000..912a81a
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderMaterial.h
@@ -0,0 +1,132 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef RENDER_MATERIAL_H
+#define RENDER_MATERIAL_H
+
+#include "Utils.h"
+#include "DirectXTex.h"
+
+#include <string>
+#include <vector>
+#include <list>
+#include <map>
+#include <memory>
+
+
+class IRenderMesh;
+class ResourceManager;
+struct TextureResource;
+class Renderable;
+
+
+class RenderMaterial
+{
+ public:
+
+ enum BlendMode
+ {
+ BLEND_NONE,
+ BLEND_ALPHA_BLENDING,
+ BLEND_ADDITIVE
+ };
+
+ RenderMaterial(const char* materialName, ResourceManager& resourceProvider, const char* shaderFileName, const char* textureFileName = "", BlendMode blendMode = BLEND_NONE);
+ ~RenderMaterial();
+
+ void setBlending(BlendMode blendMode);
+ BlendMode getBlending() const { return mBlendMode; }
+
+ void reload();
+
+ class Instance
+ {
+ public:
+ Instance(RenderMaterial& material, ID3D11InputLayout* inputLayout, uint32_t shaderNum = 0) : mMaterial(material), mInputLayout(inputLayout), mShaderNum(shaderNum) {}
+ ~Instance() { SAFE_RELEASE(mInputLayout); }
+
+ bool isValid();
+ void bind(ID3D11DeviceContext& context, uint32_t slot, bool depthStencilOnly = false);
+ RenderMaterial& getMaterial() const { return mMaterial; }
+ private:
+ RenderMaterial& mMaterial;
+ ID3D11InputLayout* mInputLayout;
+ uint32_t mShaderNum;
+ };
+
+// Add By Lixu Begin
+ typedef Instance* InstancePtr;
+ std::string getMaterialName(){ return mMaterialName; }
+ void setMaterialName(std::string materialName){ mMaterialName = materialName; }
+ std::string getTextureFileName(){ return mTextureFileName; }
+ void setTextureFileName(std::string textureFileName);
+ void addRelatedRenderable(Renderable* pRenderable){ mRelatedRenderables.push_back(pRenderable); }
+ std::vector<Renderable*>& getRelatedRenderables(){ return mRelatedRenderables; }
+ static RenderMaterial* getDefaultRenderMaterial();
+// Add By Lixu End
+
+ InstancePtr getMaterialInstance(const IRenderMesh* mesh);
+ InstancePtr getMaterialInstance(const D3D11_INPUT_ELEMENT_DESC* elementDescs, uint32_t numElements);
+
+ private:
+ void initialize(ResourceManager& resourceCallback, const char* shaderFileName, const char* textureFileName, BlendMode blendMode);
+ void initialize(ResourceManager&resourceProvider, std::vector<std::string> shaderFileNames, const char* textureFileName, BlendMode blendMode);
+
+ void releaseReloadableResources();
+
+ std::string mMaterialName;
+ std::string mShaderFileName;
+ std::string mTextureFileName;
+
+ struct ShaderGroup
+ {
+ ShaderGroup() : vs(nullptr), gs(nullptr), ps(nullptr), buffer(nullptr)
+ {
+ }
+ ~ShaderGroup()
+ {
+ Release();
+ }
+ void Release()
+ {
+ SAFE_RELEASE(vs);
+ SAFE_RELEASE(gs);
+ SAFE_RELEASE(ps);
+ SAFE_RELEASE(buffer);
+ }
+ void Set(ID3D11DeviceContext* c, bool setPixelShader = true)
+ {
+ c->VSSetShader(vs, nullptr, 0);
+ c->GSSetShader(gs, nullptr, 0);
+ c->PSSetShader(setPixelShader ? ps : nullptr, nullptr, 0);
+ }
+ bool IsValid()
+ {
+ return vs != nullptr;
+ }
+ ID3D11VertexShader* vs;
+ ID3D11GeometryShader* gs;
+ ID3D11PixelShader* ps;
+ ID3DBlob* buffer;
+ };
+
+// Add By Lixu Begin
+ std::map<const IRenderMesh*, Instance*> mRenderMeshToInstanceMap;
+ std::vector<Renderable*> mRelatedRenderables;
+// Add By Lixu End
+ const TextureResource* mTexture;
+ ID3D11ShaderResourceView* mTextureSRV;
+ std::vector<std::string> mShaderFilePathes;
+ std::vector<ShaderGroup*> mShaderGroups;
+ ID3D11BlendState* mBlendState;
+ BlendMode mBlendMode;
+};
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderUtils.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderUtils.h
new file mode 100644
index 0000000..12df9f2
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RenderUtils.h
@@ -0,0 +1,78 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef RENDER_UTILS_H
+#define RENDER_UTILS_H
+
+#include "DirectXTex.h"
+#include <DirectXMath.h>
+#include "PxMat44.h"
+#include "PxVec3.h"
+#include "PxVec4.h"
+
+static DirectX::XMFLOAT4 getRandomPastelColor()
+{
+ float r = ((double)rand() / (RAND_MAX)) * 0.5f + 0.5f;
+ float g = ((double)rand() / (RAND_MAX)) * 0.5f + 0.5f;
+ float b = ((double)rand() / (RAND_MAX)) * 0.5f + 0.5f;
+ return DirectX::XMFLOAT4(r, g, b, 1.0f);
+}
+
+static physx::PxMat44 XMMATRIXToPxMat44(const DirectX::XMMATRIX& mat)
+{
+ physx::PxMat44 m;
+ memcpy(const_cast<float*>(m.front()), &mat.r[0], 4 * 4 * sizeof(float));
+ return m;
+}
+
+static DirectX::XMMATRIX PxMat44ToXMMATRIX(const physx::PxMat44& mat)
+{
+ return DirectX::XMMATRIX(mat.front());
+}
+
+static physx::PxVec4 XMVECTORToPxVec4(const DirectX::XMVECTOR& vec)
+{
+ DirectX::XMFLOAT4 f;
+ DirectX::XMStoreFloat4(&f, vec);
+ return physx::PxVec4(f.x, f.y, f.z, f.w);
+}
+
+static physx::PxVec3 XMFLOAT3ToPxVec3(const DirectX::XMFLOAT3& vec)
+{
+ return physx::PxVec3(vec.x, vec.y, vec.z);
+}
+
+static physx::PxVec4 XMFLOAT4ToPxVec4(const DirectX::XMFLOAT4& vec)
+{
+ return physx::PxVec4(vec.x, vec.y, vec.z, vec.w);
+}
+
+static uint32_t XMFLOAT4ToU32Color(const DirectX::XMFLOAT4& color)
+{
+ uint32_t c = 0;
+ c |= (int)(color.w * 255); c <<= 8;
+ c |= (int)(color.z * 255); c <<= 8;
+ c |= (int)(color.y * 255); c <<= 8;
+ c |= (int)(color.x * 255);
+ return c;
+}
+
+static DirectX::XMFLOAT4 XMFLOAT4Lerp(const DirectX::XMFLOAT4 v0, const DirectX::XMFLOAT4 v1, float val)
+{
+ DirectX::XMFLOAT4 v(
+ v0.x * (1 - val) + v1.x * val,
+ v0.y * (1 - val) + v1.y * val,
+ v0.z * (1 - val) + v1.z * val,
+ v0.w * (1 - val) + v1.w * val
+ );
+ return v;
+}
+
+#endif //RENDER_UTILS_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderable.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderable.cpp
new file mode 100644
index 0000000..51569b7
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderable.cpp
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "Renderable.h"
+#include "Renderer.h"
+#include "RenderUtils.h"
+
+const DirectX::XMFLOAT4 DEFAULT_COLOR(0.5f, 0.5f, 0.5f, 1.0f);
+
+Renderable::Renderable(IRenderMesh& mesh, RenderMaterial& material) : m_mesh(mesh), m_scale(1, 1, 1), m_color(DEFAULT_COLOR), m_hidden(false), m_transform(PxIdentity)
+// Add By Lixu Begin
+, m_selected(false)
+// Add By Lixu End
+{
+ setMaterial(material);
+}
+
+void Renderable::setMaterial(RenderMaterial& material)
+{
+ material.addRelatedRenderable(this);
+ m_materialInstance = material.getMaterialInstance(&m_mesh);
+}
+
+void Renderable::render(Renderer& renderer, bool depthStencilOnly) const
+{
+ if (!m_materialInstance->isValid())
+ {
+ PX_ALWAYS_ASSERT();
+ return;
+ }
+
+ m_materialInstance->bind(*renderer.m_context, 0, depthStencilOnly);
+
+ // setup object CB
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ renderer.m_context->Map(renderer.m_objectCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ Renderer::CBObject* objectBuffer = (Renderer::CBObject*)mappedResource.pData;
+ objectBuffer->world = PxMat44ToXMMATRIX(getModelMatrix());
+ objectBuffer->color = getColor();
+// Add By Lixu Begin
+ objectBuffer->selected = m_selected ? 1.0 : -1.0;
+// Add By Lixu End
+ renderer.m_context->Unmap(renderer.m_objectCB, 0);
+ }
+
+ m_mesh.render(*renderer.m_context);
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderable.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderable.h
new file mode 100644
index 0000000..9e38e4f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderable.h
@@ -0,0 +1,151 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef RENDERABLE_H
+#define RENDERABLE_H
+
+#include "RenderMaterial.h"
+#include <DirectXMath.h>
+#include "PxMat44.h"
+#include "PxVec3.h"
+#include "PxVec4.h"
+
+using namespace physx;
+
+class Renderer;
+
+/**
+RenderMesh interface, used by Renderable
+*/
+class IRenderMesh
+{
+public:
+ virtual ~IRenderMesh() {}
+ virtual const std::vector<D3D11_INPUT_ELEMENT_DESC>& getInputElementDesc() const = 0;
+ virtual void render(ID3D11DeviceContext& context) const = 0;
+// Add By Lixu Begin
+ virtual void setScale(PxMat44 scale, bool replace) {};
+// Add By Lixu End
+};
+
+/**
+Renderable, represents single object renderer by Renderer.
+Basically Renderable = RenderMaterial + RenderMesh
+*/
+class Renderable
+{
+public:
+ //////// public API ////////
+
+ void setMaterial(RenderMaterial& material);
+
+ PxMat44 getModelMatrix() const
+ {
+ return PxMat44(m_transform) * PxMat44(PxVec4(m_scale, 1));
+ }
+
+ void setTransform(PxTransform& transform)
+ {
+ m_transform = transform;
+ }
+
+ const PxTransform& getTransform() const
+ {
+ return m_transform;
+ }
+
+ void setScale(PxVec3 scale)
+ {
+ m_scale = scale;
+ }
+
+ const PxVec3& getScale() const
+ {
+ return m_scale;
+ }
+
+ void setColor(DirectX::XMFLOAT4 color)
+ {
+ m_color = color;
+ }
+ DirectX::XMFLOAT4 getColor() const
+ {
+ return m_color;
+ }
+
+ void setHidden(bool hidden)
+ {
+ m_hidden = hidden;
+ }
+
+ bool isHidden() const
+ {
+ return m_hidden;
+ }
+
+// Add By Lixu Begin
+ void setSelected(bool selected)
+ {
+ m_selected = selected;
+ }
+
+ bool isSelected() const
+ {
+ return m_selected;
+ }
+
+ void setMeshScale(PxMat44 scale, bool replace)
+ {
+ m_mesh.setScale(scale, replace);
+ }
+// Add By Lixu End
+
+ bool isTransparent() const
+ {
+ return !(m_materialInstance->getMaterial().getBlending() == RenderMaterial::BLEND_NONE);
+ }
+
+ RenderMaterial& getMaterial() const { return m_materialInstance->getMaterial(); }
+
+private:
+ //////// methods used by Renderer ////////
+
+ friend class Renderer;
+
+ void render(Renderer& renderer) const
+ {
+ render(renderer, false);
+ }
+
+ void renderDepthStencilOnly(Renderer& renderer) const
+ {
+ render(renderer, true);
+ }
+
+ Renderable(IRenderMesh& mesh, RenderMaterial& material);
+
+ void render(Renderer& renderer, bool depthStencilOnly) const;
+
+
+ //////// internal data ////////
+
+ DirectX::XMFLOAT4 m_color;
+ PxTransform m_transform;
+ PxVec3 m_scale;
+
+ RenderMaterial::InstancePtr m_materialInstance;
+ IRenderMesh& m_mesh;
+ bool m_hidden;
+// Add By Lixu Begin
+ bool m_selected;
+// Add By Lixu End
+};
+
+#endif //RENDERABLE_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderer.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderer.cpp
new file mode 100644
index 0000000..49b1669
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderer.cpp
@@ -0,0 +1,736 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "Renderer.h"
+#include "RenderUtils.h"
+#include "UIHelpers.h"
+#include "SampleProfiler.h"
+
+#include "PxRenderBuffer.h"
+
+#include <set>
+
+
+const float CAMERA_CLIP_NEAR = 1.0f;
+const float CAMERA_CLIP_FAR = 1000.00f;
+
+const float CLEAR_SCENE_COLOR[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Renderer
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+Renderer::Renderer()
+: m_cameraCB(nullptr)
+, m_worldCB(nullptr)
+, m_objectCB(nullptr)
+, m_RSState(nullptr)
+, m_opaqueRenderDSState(nullptr)
+, m_transparencyRenderDSState(nullptr)
+, m_DSTexture(nullptr)
+, m_DSView(nullptr)
+, m_DSTextureSRV(nullptr)
+, m_pointSampler(nullptr)
+, m_linearSampler(nullptr)
+, m_wireframeMode(false)
+, m_debugPrimitiveVB(nullptr)
+, m_debugPrimitiveVBVerticesCount(0)
+, m_shadowEnabled(true)
+, m_HBAOEnabled(true)
+, m_visibleOpaqueRenderablesCount(0)
+, m_visibleTransparentRenderablesCount(0)
+{
+ m_worldCBData.ambientColor = DirectX::XMFLOAT3(0.21f, 0.21f, 0.22f);
+ m_worldCBData.pointLightColor = DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f);
+ m_worldCBData.pointLightPos = DirectX::XMFLOAT3(0.0f, 30.0f, 12.0f);
+ m_worldCBData.dirLightColor = DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f);
+ m_worldCBData.dirLightDir = DirectX::XMFLOAT3(-0.08f, -0.34f, -0.91f);
+ m_worldCBData.specularPower = 140.0f;
+ m_worldCBData.specularIntensity = 0.4f;
+
+ toggleCameraSpeed(false);
+}
+
+Renderer::~Renderer()
+{
+}
+
+void Renderer::initializeDefaultRSState()
+{
+ SAFE_RELEASE(m_RSState);
+ D3D11_RASTERIZER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+// Add By Lixu Begin
+ desc.CullMode = D3D11_CULL_NONE;
+// Add By Lixu End
+ desc.FillMode = m_wireframeMode ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID;
+ desc.AntialiasedLineEnable = FALSE;
+ desc.DepthBias = 0;
+ desc.DepthBiasClamp = 0;
+ desc.DepthClipEnable = TRUE;
+ desc.FrontCounterClockwise = FALSE;
+ desc.MultisampleEnable = TRUE;
+ desc.ScissorEnable = FALSE;
+ desc.SlopeScaledDepthBias = 0;
+
+ V(m_device->CreateRasterizerState(&desc, &m_RSState));
+}
+
+HRESULT Renderer::DeviceCreated(ID3D11Device* device)
+{
+ m_device = device;
+
+ // Camera constant buffer
+ {
+ D3D11_BUFFER_DESC buffer_desc;
+ ZeroMemory(&buffer_desc, sizeof(buffer_desc));
+ buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
+ buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ buffer_desc.ByteWidth = sizeof(CBCamera);
+ _ASSERT((buffer_desc.ByteWidth % 16) == 0);
+
+ V(device->CreateBuffer(&buffer_desc, nullptr, &m_cameraCB));
+ }
+
+ // World constant buffer
+ {
+ D3D11_BUFFER_DESC buffer_desc;
+ ZeroMemory(&buffer_desc, sizeof(buffer_desc));
+ buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
+ buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ buffer_desc.ByteWidth = sizeof(CBWorld);
+ _ASSERT((buffer_desc.ByteWidth % 16) == 0);
+
+ V(device->CreateBuffer(&buffer_desc, nullptr, &m_worldCB));
+ }
+
+ // Object constant buffer
+ {
+ D3D11_BUFFER_DESC buffer_desc;
+ ZeroMemory(&buffer_desc, sizeof(buffer_desc));
+ buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
+ buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ buffer_desc.ByteWidth = sizeof(CBObject);
+ _ASSERT((buffer_desc.ByteWidth % 16) == 0);
+
+ V(device->CreateBuffer(&buffer_desc, nullptr, &m_objectCB));
+ }
+
+ // Opaque Render Depth-Stencil state
+ {
+ D3D11_DEPTH_STENCIL_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.StencilEnable = FALSE;
+ desc.DepthEnable = TRUE;
+ desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
+
+ V(device->CreateDepthStencilState(&desc, &m_opaqueRenderDSState));
+ }
+
+ // Transparency Render Depth-Stencil state
+ {
+ D3D11_DEPTH_STENCIL_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.StencilEnable = FALSE;
+ desc.DepthEnable = TRUE;
+ desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
+ desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
+
+ V(device->CreateDepthStencilState(&desc, &m_transparencyRenderDSState));
+ }
+
+ // Linear sampler
+ {
+ D3D11_SAMPLER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ desc.MaxAnisotropy = 1;
+ desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
+ desc.MinLOD = 0;
+ desc.MaxLOD = D3D11_FLOAT32_MAX;
+ V(device->CreateSamplerState(&desc, &m_linearSampler));
+ }
+
+ // Point sampler
+ {
+ D3D11_SAMPLER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
+ desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ desc.MaxAnisotropy = 1;
+ desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
+ desc.MinLOD = 0;
+ desc.MaxLOD = D3D11_FLOAT32_MAX;
+ V(device->CreateSamplerState(&desc, &m_pointSampler));
+ }
+
+ // Rasterizer state
+ initializeDefaultRSState();
+
+ // init primitive render meshes
+ for (uint32_t i = 0; i < PrimitiveRenderMeshType::Count; i++)
+ {
+ m_primitiveRenderMeshes[i] = nullptr;
+ }
+
+ // init shadows
+ ID3D11DeviceContext* pd3dDeviceContext;
+ m_device->GetImmediateContext(&pd3dDeviceContext);
+ m_shadow.createResources(m_device, pd3dDeviceContext, &m_camera);
+
+ // init hbao
+ m_HBAO.createResources(m_device);
+
+ return S_OK;
+}
+
+void Renderer::DeviceDestroyed()
+{
+ SAFE_RELEASE(m_cameraCB);
+ SAFE_RELEASE(m_worldCB);
+ SAFE_RELEASE(m_objectCB);
+ SAFE_RELEASE(m_RSState);
+ SAFE_RELEASE(m_opaqueRenderDSState);
+ SAFE_RELEASE(m_transparencyRenderDSState);
+ SAFE_RELEASE(m_pointSampler);
+ SAFE_RELEASE(m_linearSampler);
+ SAFE_RELEASE(m_debugPrimitiveVB);
+ SAFE_RELEASE(m_DSTexture);
+ SAFE_RELEASE(m_DSView);
+ SAFE_RELEASE(m_DSTextureSRV);
+
+ for (uint32_t i = 0; i < PrimitiveRenderMeshType::Count; i++)
+ {
+ SAFE_DELETE(m_primitiveRenderMeshes[i]);
+ }
+}
+
+void Renderer::onInitialize()
+{
+ // search paths
+ m_resourceManager.addSearchDir("..\\..\\samples\\resources");
+ m_resourceManager.addSearchDir("..\\..\\..\\samples\\resources");
+ for (const std::string& d : getManager()->getConfig().additionalResourcesDir)
+ {
+ m_resourceManager.addSearchDir(d.c_str());
+ }
+
+ // debug primitive render material and input layout
+ {
+ m_debugPrimitiveRenderMaterial = new RenderMaterial("", m_resourceManager, "debug_primitive", "");
+
+ D3D11_INPUT_ELEMENT_DESC layout[] = {
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
+ };
+
+ m_debugPrimitiveRenderMaterialInstance = m_debugPrimitiveRenderMaterial->getMaterialInstance(layout, ARRAYSIZE(layout));
+ }
+}
+
+void Renderer::onTerminate()
+{
+ SAFE_DELETE(m_debugPrimitiveRenderMaterial);
+}
+
+void Renderer::BackBufferResized(ID3D11Device* /*device*/, const DXGI_SURFACE_DESC* sd)
+{
+ // Setup the camera's projection parameters
+ m_screenWidth = sd->Width;
+ m_screenHeight = sd->Height;
+ float fAspectRatio = m_screenWidth / m_screenHeight;
+ m_camera.SetProjParams(DirectX::XM_PIDIV4, fAspectRatio, CAMERA_CLIP_NEAR, CAMERA_CLIP_FAR);
+
+ SAFE_RELEASE(m_DSTexture);
+ SAFE_RELEASE(m_DSView);
+ SAFE_RELEASE(m_DSTextureSRV);
+
+ // create a new Depth-Stencil texture
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Width = sd->Width;
+ desc.Height = sd->Height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = DXGI_FORMAT_R32_TYPELESS; // Use a typeless type here so that it can be both depth-stencil and shader resource.
+ desc.SampleDesc.Count = sd->SampleDesc.Count;
+ desc.SampleDesc.Quality = sd->SampleDesc.Quality;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+ V(m_device->CreateTexture2D(&desc, NULL, &m_DSTexture));
+ }
+
+ // create Depth-Stencil view
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.ViewDimension = sd->SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
+ desc.Format = DXGI_FORMAT_D32_FLOAT; // Make the view see this as D32_FLOAT instead of typeless
+ desc.Texture2D.MipSlice = 0;
+ V(m_device->CreateDepthStencilView(m_DSTexture, &desc, &m_DSView));
+ }
+
+ // create Depth-Stencil shader resource view
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Format = DXGI_FORMAT_R32_FLOAT; // Make the shaders see this as R32_FLOAT instead of typeless
+ desc.ViewDimension = sd->SampleDesc.Count > 1 ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
+ desc.Texture2D.MipLevels = 1;
+ desc.Texture2D.MostDetailedMip = 0;
+ V(m_device->CreateShaderResourceView(m_DSTexture, &desc, &m_DSTextureSRV));
+ }
+
+ // setup viewport
+ m_viewport.Width = (FLOAT)sd->Width;
+ m_viewport.Height = (FLOAT)sd->Height;
+ m_viewport.MinDepth = 0;
+ m_viewport.MaxDepth = 1;
+ m_viewport.TopLeftX = 0;
+ m_viewport.TopLeftY = 0;
+
+ // setup shadows
+ m_shadow.setScreenResolution(0, sd->Width, sd->Height, sd->SampleDesc.Count, nullptr);
+}
+
+void Renderer::setAllConstantBuffers(ID3D11DeviceContext* ctx)
+{
+ ID3D11Buffer* cbs[3] = { m_cameraCB, m_worldCB, m_objectCB };
+ ctx->VSSetConstantBuffers(0, 3, cbs);
+ ctx->GSSetConstantBuffers(0, 3, cbs);
+ ctx->PSSetConstantBuffers(0, 3, cbs);
+}
+
+void Renderer::Render(ID3D11Device* /*device*/, ID3D11DeviceContext* ctx, ID3D11RenderTargetView* pRTV,
+ ID3D11DepthStencilView*)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ m_context = ctx;
+
+ ctx->ClearRenderTargetView(pRTV, CLEAR_SCENE_COLOR);
+ ctx->ClearDepthStencilView(m_DSView, D3D11_CLEAR_DEPTH, 1.0, 0);
+ ctx->RSSetViewports(1, &m_viewport);
+
+ // needed matrices
+ DirectX::XMMATRIX viewMatrix = m_camera.GetViewMatrix();
+ DirectX::XMMATRIX projMatrix = m_camera.GetProjMatrix();
+ DirectX::XMMATRIX projMatrixInv = DirectX::XMMatrixInverse(NULL, projMatrix);
+ DirectX::XMMATRIX viewProjMatrix = viewMatrix * projMatrix;
+
+ // Fill Camera constant buffer
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ctx->Map(m_cameraCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ CBCamera* cameraBuffer = (CBCamera*)mappedResource.pData;
+ cameraBuffer->viewProjection = viewProjMatrix;
+ cameraBuffer->projectionInv = projMatrixInv;
+ DirectX::XMStoreFloat3(&(cameraBuffer->viewPos), m_camera.GetEyePt());
+ ctx->Unmap(m_cameraCB, 0);
+ }
+
+ // Fill World constant buffer
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ctx->Map(m_worldCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ CBWorld* worldBuffer = (CBWorld*)mappedResource.pData;
+ memcpy(worldBuffer, &m_worldCBData, sizeof(m_worldCBData));
+ //worldBuffer->ambientColor = m_CBWorldData.ambientColor;
+ //worldBuffer->pointLightPos = m_CBWorldData.pointLightPos;
+ //worldBuffer->pointLightColor = m_CBWorldData.pointLightColor;
+ //worldBuffer->dirLightDir = m_CBWorldData.dirLightDir;
+ //worldBuffer->specularPower = m_CBWorldData.specularPower;
+ //worldBuffer->dirLightColor = m_CBWorldData.dirLightColor;
+ //worldBuffer->specularIntensity = m_CBWorldData.specularIntensity;
+ ctx->Unmap(m_worldCB, 0);
+ }
+
+ ctx->RSSetState(m_RSState);
+ ctx->PSSetSamplers(0, 1, &m_linearSampler);
+ ctx->PSSetSamplers(1, 1, &m_pointSampler);
+
+
+ if (m_shadowEnabled)
+ {
+ // render depth only
+ {
+ ctx->OMSetRenderTargets(0, nullptr, m_DSView);
+ ctx->OMSetDepthStencilState(m_opaqueRenderDSState, 0xFF);
+
+ // set constants buffers
+ setAllConstantBuffers(ctx);
+
+ for (auto it = m_renderables.begin(); it != m_renderables.end(); it++)
+ {
+ if (!(*it)->isTransparent() && !(*it)->isHidden())
+ (*it)->renderDepthStencilOnly(*this);
+ }
+ }
+
+ // render shadow map
+ m_shadow.renderShadowMaps(this);
+
+ // render shadow buffer
+ ctx->OMSetRenderTargets(0, nullptr, nullptr);
+ m_shadow.renderShadowBuffer(m_DSTextureSRV, nullptr);
+ }
+
+ // Opaque render
+ {
+ ctx->RSSetViewports(1, &m_viewport);
+ ctx->RSSetState(m_RSState);
+ ctx->OMSetRenderTargets(1, &pRTV, m_DSView);
+ ctx->OMSetDepthStencilState(m_opaqueRenderDSState, 0xFF);
+
+ // set constants buffers
+ setAllConstantBuffers(ctx);
+
+ // Fill Camera constant buffer
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ctx->Map(m_cameraCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ CBCamera* cameraBuffer = (CBCamera*)mappedResource.pData;
+ cameraBuffer->viewProjection = viewProjMatrix;
+ cameraBuffer->projectionInv = projMatrixInv;
+ DirectX::XMStoreFloat3(&(cameraBuffer->viewPos), m_camera.GetEyePt());
+ ctx->Unmap(m_cameraCB, 0);
+ }
+
+ // Render opaque renderables
+ m_visibleOpaqueRenderablesCount = 0;
+ for (auto it = m_renderables.begin(); it != m_renderables.end(); it++)
+ {
+ if (!(*it)->isTransparent() && !(*it)->isHidden())
+ {
+ (*it)->render(*this);
+ m_visibleOpaqueRenderablesCount++;
+ }
+ }
+ }
+
+ // modulate shadows
+ if (m_shadowEnabled)
+ {
+ m_shadow.modulateShadowBuffer(pRTV);
+ }
+
+ // render AO
+ if (m_HBAOEnabled)
+ {
+ m_HBAO.renderAO(m_context, pRTV, m_DSTextureSRV, projMatrix);
+ }
+
+ ctx->RSSetViewports(1, &m_viewport);
+
+ // render debug render buffers
+ while (m_queuedRenderBuffers.size() > 0)
+ {
+ render(m_queuedRenderBuffers.back());
+ m_queuedRenderBuffers.pop_back();
+ }
+
+ // Transparency render
+ ctx->OMSetRenderTargets(1, &pRTV, m_DSView);
+ ctx->OMSetDepthStencilState(m_transparencyRenderDSState, 0xFF);
+
+ // depth as SRV isn't used now (uncommenting will produce a warning, probably need readonly depth?)
+ //ctx->PSSetShaderResources(1, 1, &mDSTextureSRV);
+
+ // Render transparent renderables
+ m_visibleTransparentRenderablesCount = 0;
+ for (auto it = m_renderables.begin(); it != m_renderables.end(); it++)
+ {
+ if ((*it)->isTransparent() && !(*it)->isHidden())
+ {
+ (*it)->render(*this);
+ m_visibleTransparentRenderablesCount++;
+ }
+ }
+
+ // shadows debug render
+ if (0)
+ {
+ m_shadow.displayMapFrustums(pRTV, m_DSView);
+ }
+
+ // Reset RT and SRV state
+ ID3D11ShaderResourceView* nullAttach[16] = { nullptr };
+ ctx->PSSetShaderResources(0, 16, nullAttach);
+ ctx->OMSetRenderTargets(0, nullptr, nullptr);
+}
+
+LRESULT Renderer::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ PX_UNUSED(hWnd);
+ PX_UNUSED(wParam);
+ PX_UNUSED(lParam);
+
+ if (uMsg == WM_KEYDOWN || uMsg == WM_KEYUP)
+ {
+ // Camera overspeed event
+ int iKeyPressed = static_cast<int>(wParam);
+ if (iKeyPressed == VK_SHIFT)
+ {
+ toggleCameraSpeed(uMsg == WM_KEYDOWN);
+ }
+ }
+
+ // Camera events
+ return m_camera.HandleMessages(hWnd, uMsg, wParam, lParam);
+}
+
+void Renderer::Animate(double fElapsedTimeSeconds)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ m_camera.FrameMove((float)fElapsedTimeSeconds);
+}
+
+void Renderer::renderDepthOnly(DirectX::XMMATRIX* viewProjectionSubstitute)
+{
+ // Fill Camera constant buffer
+ if (viewProjectionSubstitute)
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ m_context->Map(m_cameraCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ CBCamera* cameraBuffer = (CBCamera*)mappedResource.pData;
+ cameraBuffer->viewProjection = *viewProjectionSubstitute;
+ m_context->Unmap(m_cameraCB, 0);
+ }
+
+ // set constants buffers
+ setAllConstantBuffers(m_context);
+
+ // render
+ for (auto it = m_renderables.begin(); it != m_renderables.end(); it++)
+ {
+ if (!(*it)->isTransparent() && !(*it)->isHidden())
+ (*it)->renderDepthStencilOnly(*this);
+ }
+}
+
+void Renderer::render(const PxRenderBuffer* renderBuffer)
+{
+ // points
+ uint32_t pointsCount = renderBuffer->getNbPoints();
+ if (pointsCount > 0)
+ {
+ RenderDebugVertex* verts = new RenderDebugVertex[pointsCount];
+ const PxDebugPoint* points = renderBuffer->getPoints();
+ for (uint32_t i = 0; i < pointsCount; i++)
+ {
+ verts[i].mPos = points[i].pos;
+ verts[i].mColor = points[i].color;
+ }
+
+ renderDebugPrimitive(verts, pointsCount, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
+ delete[] verts;
+ }
+
+ // lines
+ uint32_t linesCount = renderBuffer->getNbLines();
+ if (linesCount > 0)
+ {
+ RenderDebugVertex* verts = new RenderDebugVertex[linesCount * 2];
+ const PxDebugLine* lines = renderBuffer->getLines();
+ for (uint32_t i = 0; i < linesCount; i++)
+ {
+ verts[i * 2].mPos = lines[i].pos0;
+ verts[i * 2].mColor = lines[i].color0;
+ verts[i * 2 + 1].mPos = lines[i].pos1;
+ verts[i * 2 + 1].mColor = lines[i].color1;
+ }
+
+ renderDebugPrimitive(verts, linesCount * 2, D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
+ delete[] verts;
+ }
+
+ // triangles
+ uint32_t trianglesCount = renderBuffer->getNbTriangles();
+ if (trianglesCount > 0)
+ {
+ RenderDebugVertex* verts = new RenderDebugVertex[trianglesCount * 3];
+ const PxDebugTriangle* triangles = renderBuffer->getTriangles();
+ for (uint32_t i = 0; i < trianglesCount; i++)
+ {
+ verts[i * 3].mPos = triangles[i].pos0;
+ verts[i * 3].mColor = triangles[i].color0;
+ verts[i * 3 + 1].mPos = triangles[i].pos1;
+ verts[i * 3 + 1].mColor = triangles[i].color1;
+ verts[i * 3 + 2].mPos = triangles[i].pos2;
+ verts[i * 3 + 2].mColor = triangles[i].color2;
+ }
+
+ renderDebugPrimitive(verts, trianglesCount * 3, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ delete[] verts;
+ }
+
+ // texts?
+ // ....
+}
+
+void Renderer::renderDebugPrimitive(const Renderer::RenderDebugVertex *vertices, uint32_t verticesCount, D3D11_PRIMITIVE_TOPOLOGY topology)
+{
+ m_context->IASetPrimitiveTopology(topology);
+
+ m_debugPrimitiveRenderMaterialInstance->bind(*m_context, 0);
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ m_context->Map(m_objectCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ CBObject* objectBuffer = (CBObject*)mappedResource.pData;
+
+ objectBuffer->world = PxMat44ToXMMATRIX(PxMat44(PxIdentity));
+
+ m_context->Unmap(m_objectCB, 0);
+
+ if (m_debugPrimitiveVBVerticesCount < verticesCount)
+ {
+ m_debugPrimitiveVBVerticesCount = verticesCount;
+ SAFE_RELEASE(m_debugPrimitiveVB);
+
+ D3D11_BUFFER_DESC bufferDesc;
+
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.ByteWidth = sizeof(Renderer::RenderDebugVertex) * m_debugPrimitiveVBVerticesCount;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_DEFAULT;
+
+ V(m_device->CreateBuffer(&bufferDesc, NULL, &m_debugPrimitiveVB));
+ }
+
+ CD3D11_BOX box(0, 0, 0, (LONG)(sizeof(Renderer::RenderDebugVertex) * verticesCount), 1, 1);
+ m_context->UpdateSubresource(m_debugPrimitiveVB, 0, &box, vertices, 0, 0);
+
+ ID3D11Buffer* pBuffers[1] = { m_debugPrimitiveVB };
+ UINT strides[1] = { sizeof(RenderDebugVertex) };
+ UINT offsets[1] = { 0 };
+ m_context->IASetVertexBuffers(0, 1, pBuffers, strides, offsets);
+
+ m_context->Draw(verticesCount, 0);
+}
+
+IRenderMesh* Renderer::getPrimitiveRenderMesh(PrimitiveRenderMeshType::Enum type)
+{
+ if (m_primitiveRenderMeshes[type] == NULL)
+ {
+ switch (type)
+ {
+ case PrimitiveRenderMeshType::Box:
+ m_primitiveRenderMeshes[type] = new BoxRenderMesh();
+ break;
+ case PrimitiveRenderMeshType::Plane:
+ m_primitiveRenderMeshes[type] = new PlaneRenderMesh();
+ break;
+ case PrimitiveRenderMeshType::Sphere:
+ m_primitiveRenderMeshes[type] = new SphereRenderMesh();
+ break;
+// Add By Lixu Begin
+ case PrimitiveRenderMeshType::Cone:
+ m_primitiveRenderMeshes[type] = new ConeRenderMesh();
+ break;
+// Add By Lixu End
+ default:
+ PX_ALWAYS_ASSERT_MESSAGE("Unsupported PxGeometryType");
+ return NULL;
+ }
+ }
+
+ return m_primitiveRenderMeshes[type];
+}
+
+
+Renderable* Renderer::createRenderable(IRenderMesh& mesh, RenderMaterial& material)
+{
+ Renderable* renderable = new Renderable(mesh, material);
+ m_renderables.emplace(renderable);
+ return renderable;
+}
+
+void Renderer::removeRenderable(Renderable* r)
+{
+ m_renderables.erase(m_renderables.find(r));
+ delete r;
+}
+
+void Renderer::toggleCameraSpeed(bool overspeed)
+{
+ m_camera.SetScalers(0.002f, overspeed ? 150.f : 25.f);
+}
+
+void Renderer::reloadShaders()
+{
+ // iterate Renderables materials and call reload()
+ std::set<RenderMaterial*> materials;
+ for (auto it = m_renderables.begin(); it != m_renderables.end(); it++)
+ {
+ materials.emplace(&((*it)->getMaterial()));
+ }
+ for (std::set<RenderMaterial*>::iterator it = materials.begin(); it != materials.end(); it++)
+ {
+ (*it)->reload();
+ }
+}
+
+void Renderer::drawUI()
+{
+ // Lighting
+ if (ImGui::TreeNode("Lighting"))
+ {
+ ImGui::ColorEdit3("Ambient Color", &(m_worldCBData.ambientColor.x));
+ ImGui::ColorEdit3("Point Light Color", &(m_worldCBData.pointLightColor.x));
+ ImGui::DragFloat3("Point Light Pos", &(m_worldCBData.pointLightPos.x));
+ ImGui::ColorEdit3("Dir Light Color", &(m_worldCBData.dirLightColor.x));
+ ImGui_DragFloat3Dir("Dir Light Dir", &(m_worldCBData.dirLightDir.x));
+ ImGui::DragFloat("Specular Power", &(m_worldCBData.specularPower), 1.0f, 1.0f, 500.0f);
+ ImGui::DragFloat("Specular Intensity", &(m_worldCBData.specularIntensity), 0.01f, 0.0f, 2.0f);
+
+ ImGui::TreePop();
+ }
+
+ // Shadow
+ if (ImGui::TreeNode("Shadow"))
+ {
+ ImGui::Checkbox("Shadows Enabled", &m_shadowEnabled);
+ if (m_shadowEnabled)
+ {
+ m_shadow.drawUI();
+ }
+
+ ImGui::TreePop();
+ }
+
+ // HBAO+
+ if (ImGui::TreeNode("HBAO+"))
+ {
+ ImGui::Checkbox("HBAO Enabled", &(m_HBAOEnabled));
+ if (m_HBAOEnabled)
+ {
+ m_HBAO.drawUI();
+ }
+
+ ImGui::TreePop();
+ }
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderer.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderer.h
new file mode 100644
index 0000000..58662a6
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/Renderer.h
@@ -0,0 +1,251 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef RENDERER_H
+#define RENDERER_H
+
+#include "RenderMaterial.h"
+#include <DirectXMath.h>
+#include "XInput.h"
+#include "DXUTMisc.h"
+#include "DXUTCamera.h"
+#include "SampleManager.h"
+#include "Utils.h"
+#include "ResourceManager.h"
+#include "PrimitiveRenderMesh.h"
+#include "RendererShadow.h"
+#include "RendererHBAO.h"
+#include <unordered_set>
+
+class CFirstPersonCamera;
+class PhysXPrimitive;
+class RenderDebugImpl;
+
+namespace physx
+{
+class PxRenderBuffer;
+}
+
+
+/**
+3D World Renderer
+- use createRenderable() to add objects to render.
+- use queueRenderBuffer() every frame to render debug primitives.
+- contains ResourceManager to search for file and load resources.
+- contains RendererShadow and RendererHBAO, use them through getters to control shadows.
+*/
+class Renderer : public ISampleController
+{
+ friend class Renderable;
+
+ public:
+ //////// ctor ////////
+
+ Renderer();
+ ~Renderer();
+
+
+ //////// public API ////////
+
+ void reloadShaders();
+
+ bool getWireframeMode()
+ {
+ return m_wireframeMode;
+ }
+
+ void setWireframeMode(bool enabled)
+ {
+ if(m_wireframeMode != enabled)
+ {
+ m_wireframeMode = enabled;
+ initializeDefaultRSState();
+ }
+ }
+
+ IRenderMesh* getPrimitiveRenderMesh(PrimitiveRenderMeshType::Enum type);
+
+ Renderable* createRenderable(IRenderMesh& mesh, RenderMaterial& material);
+ void removeRenderable(Renderable* r);
+
+ void drawUI();
+
+
+ //////// public getters ////////
+
+ float getScreenWidth() const
+ {
+ return m_screenWidth;
+ }
+
+ float getScreenHeight() const
+ {
+ return m_screenHeight;
+ }
+
+ void queueRenderBuffer(const PxRenderBuffer* buffer)
+ {
+ m_queuedRenderBuffers.push_back(buffer);
+ }
+
+ ResourceManager& getResourceManager()
+ {
+ return m_resourceManager;
+ }
+
+ uint32_t getVisibleOpaqueRenderablesCount()
+ {
+ return m_visibleOpaqueRenderablesCount;
+ }
+
+ uint32_t getVisibleTransparentRenderablesCount()
+ {
+ return m_visibleTransparentRenderablesCount;
+ }
+
+ CFirstPersonCamera& getCamera()
+ {
+ return m_camera;
+ }
+
+
+ //////// public 'internal' methods ////////
+
+ // for internal usage (used by RenderShadows)
+ void renderDepthOnly(DirectX::XMMATRIX* viewProjectionSubstitute);
+
+ protected:
+
+ //////// controller callbacks ////////
+
+ virtual HRESULT DeviceCreated(ID3D11Device* pDevice);
+ virtual void DeviceDestroyed();
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Animate(double fElapsedTimeSeconds);
+ virtual void onInitialize();
+ virtual void onTerminate();
+ virtual void BackBufferResized(ID3D11Device* pDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc);
+ virtual void Render(ID3D11Device* /*device*/, ID3D11DeviceContext* ctx, ID3D11RenderTargetView* pRTV,
+ ID3D11DepthStencilView* pDSV);
+
+ private:
+
+ //////// internal methods ////////
+
+ struct RenderDebugVertex
+ {
+ PxVec3 mPos;
+ uint32_t mColor;
+ };
+
+ void render(const PxRenderBuffer* renderBuffer);
+ void render(Renderable* renderable);
+ void renderDebugPrimitive(const RenderDebugVertex *vertices, uint32_t verticesCount, D3D11_PRIMITIVE_TOPOLOGY topology);
+ void initializeDefaultRSState();
+ void setAllConstantBuffers(ID3D11DeviceContext* ctx);
+ void toggleCameraSpeed(bool overspeed);
+
+
+ //////// constant buffers ////////
+
+ struct CBCamera
+ {
+ DirectX::XMMATRIX viewProjection;
+ DirectX::XMMATRIX projectionInv;
+ DirectX::XMFLOAT3 viewPos;
+ float unusedPad;
+ };
+ struct CBWorld
+ {
+ DirectX::XMFLOAT3 ambientColor;
+ float unusedPad1;
+ DirectX::XMFLOAT3 pointLightPos;
+ float unusedPad2;
+ DirectX::XMFLOAT3 pointLightColor;
+ float unusedPad3;
+ DirectX::XMFLOAT3 dirLightDir;
+ float specularPower;
+ DirectX::XMFLOAT3 dirLightColor;
+ float specularIntensity; // TODO: actually it's per object property
+ };
+ struct CBObject
+ {
+ DirectX::XMMATRIX world;
+ DirectX::XMFLOAT4 color;
+// Add By Lixu Begin
+ float selected;
+// Add By Lixu End
+ };
+
+
+ //////// internal data ////////
+
+ // camera
+ CFirstPersonCamera m_camera;
+ float m_screenWidth;
+ float m_screenHeight;
+
+ // resources
+ ResourceManager m_resourceManager;
+
+ // additional render modules(libs)
+ RendererShadow m_shadow;
+ bool m_shadowEnabled;
+ RendererHBAO m_HBAO;
+ bool m_HBAOEnabled;
+
+ // DX11 common
+ ID3D11Device* m_device;
+ ID3D11DeviceContext* m_context;
+ D3D11_VIEWPORT m_viewport;
+
+ // DX11 states
+ ID3D11RasterizerState* m_RSState;
+ ID3D11DepthStencilState* m_opaqueRenderDSState;
+ ID3D11DepthStencilState* m_transparencyRenderDSState;
+
+ // DX11 samplers
+ ID3D11SamplerState* m_pointSampler;
+ ID3D11SamplerState* m_linearSampler;
+
+ // Depth Buffer
+ ID3D11Texture2D* m_DSTexture;
+ ID3D11DepthStencilView* m_DSView;
+ ID3D11ShaderResourceView* m_DSTextureSRV;
+
+ // Constant Buffers
+ ID3D11Buffer* m_cameraCB;
+ ID3D11Buffer* m_worldCB;
+ CBWorld m_worldCBData;
+ ID3D11Buffer* m_objectCB;
+
+ // toggles (options)
+ bool m_wireframeMode;
+
+ // renderables
+ std::unordered_set<Renderable*> m_renderables;
+
+ // primitive meshes cache
+ IRenderMesh* m_primitiveRenderMeshes[PrimitiveRenderMeshType::Count];
+
+ // stats
+ uint32_t m_visibleOpaqueRenderablesCount;
+ uint32_t m_visibleTransparentRenderablesCount;
+
+ // Debug Render
+ RenderMaterial* m_debugPrimitiveRenderMaterial;
+ RenderMaterial::InstancePtr m_debugPrimitiveRenderMaterialInstance;
+ ID3D11Buffer* m_debugPrimitiveVB;
+ uint32_t m_debugPrimitiveVBVerticesCount;
+ std::vector<const PxRenderBuffer*> m_queuedRenderBuffers;
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererHBAO.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererHBAO.cpp
new file mode 100644
index 0000000..5e20a49
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererHBAO.cpp
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+
+#include "RendererHBAO.h"
+#include "Renderer.h"
+#include "imgui.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Renderer HBAO (wrapper for hbao+)
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+RendererHBAO::RendererHBAO()
+{
+ m_SSAOContext = NULL;
+
+ // default parameters
+ m_SSAOParameters.Radius = 2.0f;
+}
+
+
+RendererHBAO::~RendererHBAO()
+{
+ releaseResources();
+}
+
+
+void RendererHBAO::createResources(ID3D11Device *pd3dDevice)
+{
+ GFSDK_SSAO_Status status;
+ status = GFSDK_SSAO_CreateContext_D3D11(pd3dDevice, &m_SSAOContext, nullptr);
+ assert(status == GFSDK_SSAO_OK);
+}
+
+
+void RendererHBAO::releaseResources()
+{
+ if (m_SSAOContext != NULL)
+ {
+ m_SSAOContext->Release();
+ }
+}
+
+
+void RendererHBAO::renderAO(ID3D11DeviceContext *pd3dDeviceContext, ID3D11RenderTargetView* pRTV, ID3D11ShaderResourceView* pDepthSRV, DirectX::XMMATRIX& projMatrix)
+{
+ GFSDK_SSAO_InputData_D3D11 InputData;
+ InputData.DepthData.pFullResDepthTextureSRV = pDepthSRV;
+ InputData.DepthData.DepthTextureType = GFSDK_SSAO_HARDWARE_DEPTHS;
+ InputData.DepthData.MetersToViewSpaceUnits = 1.0f;
+ InputData.DepthData.ProjectionMatrix.Data = GFSDK_SSAO_Float4x4(reinterpret_cast<const GFSDK_SSAO_FLOAT*>(&(projMatrix.r[0])));
+ InputData.DepthData.ProjectionMatrix.Layout = GFSDK_SSAO_ROW_MAJOR_ORDER;
+
+ GFSDK_SSAO_Output_D3D11 Output;
+ Output.pRenderTargetView = pRTV;// m_pSceneRTs->ColorRTV;
+ Output.Blend.Mode = GFSDK_SSAO_MULTIPLY_RGB;
+
+ m_SSAOContext->RenderAO(pd3dDeviceContext, InputData, m_SSAOParameters, Output);
+}
+
+
+void RendererHBAO::drawUI()
+{
+ ImGui::DragFloat("Radius", &(m_SSAOParameters.Radius), 0.05f, 0.0f, 100.0f);
+ ImGui::DragFloat("Bias", &(m_SSAOParameters.Bias), 0.01f, 0.0f, 0.5f);
+ ImGui::DragFloat("NearAO", &(m_SSAOParameters.NearAO), 0.01f, 1.0f, 4.0f);
+ ImGui::DragFloat("FarAO", &(m_SSAOParameters.FarAO), 0.01, 1.0f, 4.0f);
+ ImGui::DragFloat("PowerExponent", &(m_SSAOParameters.PowerExponent), 0.01f, 1.0f, 8.0f);
+ ImGui::Checkbox("ForegroundAO Enabled", (bool*)&(m_SSAOParameters.ForegroundAO.Enable));
+ ImGui::DragFloat("ForegroundAO ViewDepth", &(m_SSAOParameters.ForegroundAO.ForegroundViewDepth), 0.01f, 0.0f, 100.0f);
+ ImGui::Checkbox("BackgroundAO Enabled", (bool*)&(m_SSAOParameters.BackgroundAO.Enable));
+ ImGui::DragFloat("BackgroundAO ViewDepth", &(m_SSAOParameters.BackgroundAO.BackgroundViewDepth), 0.01f, 0.0f, 100.0f);
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererHBAO.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererHBAO.h
new file mode 100644
index 0000000..2478628
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererHBAO.h
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef RENDERER_HBAO_H
+#define RENDERER_HBAO_H
+
+#include <DirectXMath.h>
+#include "GFSDK_SSAO.h"
+
+
+class Renderer;
+
+class RendererHBAO
+{
+public:
+ RendererHBAO();
+ ~RendererHBAO();
+
+ void createResources(ID3D11Device *pd3dDevice);
+ void renderAO(ID3D11DeviceContext *pd3dDeviceContext, ID3D11RenderTargetView* pRTV, ID3D11ShaderResourceView* pDepthSRV, DirectX::XMMATRIX& projMatrix);
+
+ void drawUI();
+
+private:
+ void releaseResources();
+
+ GFSDK_SSAO_Parameters m_SSAOParameters;
+
+ GFSDK_SSAO_Context_D3D11* m_SSAOContext;
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererShadow.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererShadow.cpp
new file mode 100644
index 0000000..28a79e5
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererShadow.cpp
@@ -0,0 +1,417 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+
+#include "RendererShadow.h"
+
+#include "XInput.h"
+#include "DXUTMisc.h"
+#include "DXUTCamera.h"
+#include "Renderer.h"
+#include "UIHelpers.h"
+
+#define CASCADES 1
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Renderer Shadows (wrapper for shadow_lib)
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const float DEFAULT_LIGHT_SIZE = 3.0f;
+const DirectX::XMFLOAT3 DEFAULT_LIGHT_POS(-25, 25, 25);
+const DirectX::XMFLOAT3 DEFAULT_LIGHT_LOOK_AT(0, 0, 0);
+const DirectX::XMFLOAT3 DEFAULT_SHADOW_COLOR(0.25f, 0.25f, 0.25f);
+
+RendererShadow::RendererShadow()
+{
+ m_shadowLibContext = NULL;
+
+ m_PCSSEnabled = false;
+ m_lightSize = DEFAULT_LIGHT_SIZE;
+ m_lightPos = DEFAULT_LIGHT_POS;
+ m_lightLookAt = DEFAULT_LIGHT_LOOK_AT;
+ m_shadowColor = DEFAULT_SHADOW_COLOR;
+
+ m_worldSpaceBBox0.x = m_worldSpaceBBox0.y = m_worldSpaceBBox0.z = -100;
+ m_worldSpaceBBox1.x = m_worldSpaceBBox1.y = m_worldSpaceBBox1.z = 100;
+
+ // Penumbra params
+ m_PCSSParams.fMaxThreshold = 80.0f;
+ m_PCSSParams.fMaxClamp = 40.0f;
+ m_PCSSParams.fMinSizePercent = 3.0f;
+ m_PCSSParams.fMinWeightExponent = 5.0f;
+ m_PCSSParams.fMinWeightThresholdPercent = 20.0f;
+
+ m_softShadowTestScale = 0.002f;
+
+ memset(&m_shadowBufferSRV, 0, sizeof(m_shadowBufferSRV));
+
+ m_shadowMapHandle = NULL;
+ m_shadowBufferHandle = NULL;
+}
+
+
+RendererShadow::~RendererShadow()
+{
+ ReleaseResources();
+}
+
+
+void RendererShadow::createResources(ID3D11Device *pd3dDevice, ID3D11DeviceContext* context, CFirstPersonCamera* camera)
+{
+ m_camera = camera;
+
+#if !CASCADES
+ uint32_t shadowMapScale = 5;
+ uint32_t shadowMapWidth = 1024;
+ uint32_t shadowMapHeight = 1024;
+
+ // SM Desc
+ m_SMDesc.eViewType = GFSDK_ShadowLib_ViewType_Single;
+ m_SMDesc.eMapType = GFSDK_ShadowLib_MapType_Texture;
+#else
+
+ uint32_t shadowMapScale = 5;
+ uint32_t shadowMapWidth = 1024;
+ uint32_t shadowMapHeight = 1024;
+
+ // SM Desc
+ m_SMDesc.eViewType = GFSDK_ShadowLib_ViewType_Cascades_2;
+ m_SMDesc.eMapType = GFSDK_ShadowLib_MapType_TextureArray;
+#endif
+
+ m_SMDesc.uResolutionWidth = shadowMapWidth * shadowMapScale;
+ m_SMDesc.uResolutionHeight = shadowMapHeight * shadowMapScale;
+ m_SMDesc.uArraySize = m_SMDesc.eViewType;
+
+ for (int j = 0; j < GFSDK_ShadowLib_ViewType_Cascades_4; j++)
+ {
+ m_SMDesc.ViewLocation[j].uMapID = j;
+ m_SMDesc.ViewLocation[j].v2Origin.x = 0;
+ m_SMDesc.ViewLocation[j].v2Origin.y = 0;
+ m_SMDesc.ViewLocation[j].v2Dimension.x = shadowMapWidth * shadowMapScale;
+ m_SMDesc.ViewLocation[j].v2Dimension.y = shadowMapHeight * shadowMapScale;
+ }
+
+
+ // SM Render Params
+ m_SMRenderParams.iDepthBias = 1000;
+ m_SMRenderParams.fSlopeScaledDepthBias = 8;
+
+ // SB Render Params
+ m_SBRenderParams.eTechniqueType = GFSDK_ShadowLib_TechniqueType_PCSS;
+ m_SBRenderParams.eQualityType = GFSDK_ShadowLib_QualityType_High;
+
+ // DLL version
+ GFSDK_ShadowLib_Version DLLVersion;
+ GFSDK_ShadowLib_Status retCode = GFSDK_ShadowLib_GetDLLVersion(&DLLVersion);
+
+ // Header version
+ GFSDK_ShadowLib_Version headerVersion;
+ headerVersion.uMajor = GFSDK_SHADOWLIB_MAJOR_VERSION;
+ headerVersion.uMinor = GFSDK_SHADOWLIB_MINOR_VERSION;
+
+ // Do they match?
+ if (DLLVersion.uMajor == headerVersion.uMajor && DLLVersion.uMinor == headerVersion.uMinor)
+ {
+ GFSDK_ShadowLib_DeviceContext deviceAndContext;
+ deviceAndContext.pD3DDevice = pd3dDevice;
+ deviceAndContext.pDeviceContext = context;
+
+ retCode = GFSDK_ShadowLib_Create(&headerVersion, &m_shadowLibContext, &deviceAndContext, NULL);
+
+ if (retCode != GFSDK_ShadowLib_Status_Ok) assert(false);
+ }
+ else
+ {
+ assert(false);
+ }
+}
+
+
+void RendererShadow::ReleaseResources()
+{
+ SAFE_RELEASE(m_downsampledShadowMap.pTexture);
+ SAFE_RELEASE(m_downsampledShadowMap.pSRV);
+ SAFE_RELEASE(m_downsampledShadowMap.pRTV);
+
+ if (m_shadowLibContext != NULL)
+ {
+ m_shadowLibContext->Destroy();
+ m_shadowLibContext = NULL;
+ }
+}
+
+
+void RendererShadow::setScreenResolution(float FovyRad, UINT Width, UINT Height, UINT uSampleCount, ID3D11DepthStencilView* pReadOnlyDSV)
+{
+ changeShadowSettings(Width, Height, uSampleCount, pReadOnlyDSV);
+}
+
+
+void RendererShadow::changeShadowSettings(UINT Width, UINT Height, UINT uSampleCount, ID3D11DepthStencilView* pReadOnlyDSV)
+{
+ m_SBDesc.uResolutionWidth = Width;
+ m_SBDesc.uResolutionHeight = Height;
+ m_SBDesc.uSampleCount = uSampleCount;
+ m_SBDesc.ReadOnlyDSV.pDSV = pReadOnlyDSV;
+
+ reloadBuffers();
+}
+
+void RendererShadow::reloadBuffers()
+{
+ {
+ m_shadowLibContext->RemoveMap(&m_shadowMapHandle);
+
+ if (m_SMDesc.eMapType == GFSDK_ShadowLib_MapType_Texture &&
+ m_SMDesc.eViewType == GFSDK_ShadowLib_ViewType_Single &&
+ m_SBRenderParams.eTechniqueType == GFSDK_ShadowLib_TechniqueType_PCSS)
+ {
+ m_SMDesc.bDownsample = true;
+ }
+
+ m_shadowLibContext->AddMap(&m_SMDesc, &m_shadowMapHandle);
+ }
+
+ if (m_SMDesc.eMapType == GFSDK_ShadowLib_MapType_Texture && m_SMDesc.eViewType == GFSDK_ShadowLib_ViewType_Single)
+ {
+ m_downsampledShadowMap.uWidth = m_SMDesc.uResolutionWidth >> 1;
+ m_downsampledShadowMap.uHeight = m_SMDesc.uResolutionHeight >> 1;
+ m_downsampledShadowMap.uSampleCount = 1;
+ m_downsampledShadowMap.Format = DXGI_FORMAT_R32_FLOAT;
+ SAFE_RELEASE(m_downsampledShadowMap.pTexture);
+ SAFE_RELEASE(m_downsampledShadowMap.pSRV);
+ SAFE_RELEASE(m_downsampledShadowMap.pRTV);
+ m_shadowLibContext->DevModeCreateTexture2D(&m_downsampledShadowMap);
+ }
+
+ m_shadowLibContext->RemoveBuffer(&m_shadowBufferHandle);
+ m_shadowLibContext->AddBuffer(&m_SBDesc, &m_shadowBufferHandle);
+}
+
+
+
+//--------------------------------------------------------------------------------------
+// Data passed to the shadow map render function
+//--------------------------------------------------------------------------------------
+struct ShadowMapRenderFunctionParams
+{
+ Renderer* renderer;
+};
+static ShadowMapRenderFunctionParams s_RenderParams;
+
+//--------------------------------------------------------------------------------------
+// Shadow map render function
+//--------------------------------------------------------------------------------------
+static void ShadowMapRenderFunction(void* pParams, gfsdk_float4x4* pViewProj)
+{
+ ShadowMapRenderFunctionParams* pRP = (ShadowMapRenderFunctionParams*)pParams;
+
+ DirectX::XMMATRIX viewProjection;
+ memcpy(&viewProjection, &pViewProj->_11, sizeof(gfsdk_float4x4));
+
+ pRP->renderer->renderDepthOnly(&viewProjection);
+}
+
+void RendererShadow::renderShadowMaps(Renderer* renderer)
+{
+ // select technique
+ GFSDK_ShadowLib_TechniqueType technique = m_SBRenderParams.eTechniqueType;
+ m_SBRenderParams.eTechniqueType = m_PCSSEnabled ? GFSDK_ShadowLib_TechniqueType_PCSS : GFSDK_ShadowLib_TechniqueType_PCF;
+ if (technique != m_SBRenderParams.eTechniqueType)
+ reloadBuffers();
+
+
+ DirectX::XMMATRIX viewMatrix = m_camera->GetViewMatrix();
+ DirectX::XMMATRIX projMatrix = m_camera->GetProjMatrix();
+
+ memcpy(&m_SMRenderParams.m4x4EyeViewMatrix, &viewMatrix.r[0], sizeof(gfsdk_float4x4));
+ memcpy(&m_SMRenderParams.m4x4EyeProjectionMatrix, &projMatrix.r[0], sizeof(gfsdk_float4x4));
+
+ // TODO: (better world space bbox needed)
+ m_SMRenderParams.v3WorldSpaceBBox[0] = m_worldSpaceBBox0;
+ m_SMRenderParams.v3WorldSpaceBBox[1] = m_worldSpaceBBox1;
+
+ m_SMRenderParams.LightDesc.eLightType = GFSDK_ShadowLib_LightType_Directional;
+ memcpy(&m_SMRenderParams.LightDesc.v3LightPos, &m_lightPos.x, sizeof(gfsdk_float3));
+ memcpy(&m_SMRenderParams.LightDesc.v3LightLookAt, &m_lightLookAt.x, sizeof(gfsdk_float3));
+ m_SMRenderParams.LightDesc.fLightSize = m_lightSize;
+ m_SMRenderParams.LightDesc.bLightFalloff = false;
+
+ // Scene specific setup for the shadow map phase that follows
+ s_RenderParams.renderer = renderer;
+ m_SMRenderParams.fnpDrawFunction = GFSDK_ShadowLib_FunctionPointer(ShadowMapRenderFunction);
+ m_SMRenderParams.pDrawFunctionParams = &s_RenderParams;
+
+ // render shadow map
+ m_shadowLibContext->RenderMap(m_shadowMapHandle, &m_SMRenderParams);
+}
+
+
+void RendererShadow::renderShadowBuffer(ID3D11ShaderResourceView* pDepthStencilSRV, ID3D11ShaderResourceView* pResolvedDepthStencilSRV)
+{
+ if (m_SBRenderParams.eTechniqueType == GFSDK_ShadowLib_TechniqueType_PCSS &&
+ m_SMDesc.eMapType == GFSDK_ShadowLib_MapType_Texture &&
+ m_SMDesc.eViewType == GFSDK_ShadowLib_ViewType_Single)
+ {
+ m_tempResources.pDownsampledShadowMap = &m_downsampledShadowMap;
+ m_shadowLibContext->SetTempResources(&m_tempResources);
+ }
+
+ m_SBRenderParams.PCSSPenumbraParams = m_PCSSParams;
+ m_SBRenderParams.fSoftShadowTestScale = m_softShadowTestScale;
+
+ m_shadowLibContext->ClearBuffer(m_shadowBufferHandle);
+
+ m_SBRenderParams.DepthBufferDesc.DepthStencilSRV.pSRV = pDepthStencilSRV;
+
+ m_shadowLibContext->RenderBuffer(m_shadowMapHandle, m_shadowBufferHandle, &m_SBRenderParams);
+
+ m_shadowLibContext->FinalizeBuffer(m_shadowBufferHandle, &m_shadowBufferSRV);
+}
+
+
+void RendererShadow::modulateShadowBuffer(ID3D11RenderTargetView* pOutputRTV)
+{
+ GFSDK_ShadowLib_RenderTargetView ColorRTV;
+ ColorRTV.pRTV = pOutputRTV;
+
+ gfsdk_float3 v3ShadowColor = { m_shadowColor.x, m_shadowColor.y, m_shadowColor.z };
+ m_shadowLibContext->ModulateBuffer(m_shadowBufferHandle, &ColorRTV, v3ShadowColor, GFSDK_ShadowLib_ModulateBufferMask_RGB);
+}
+
+
+void RendererShadow::displayShadowMaps(ID3D11RenderTargetView* pOutputRTV, UINT Width, UINT Height)
+{
+ GFSDK_ShadowLib_RenderTargetView ColorRTV;
+ ColorRTV.pRTV = pOutputRTV;
+
+ float fMapResW = (float)m_SMDesc.uResolutionWidth;
+ float fMapResH = (float)m_SMDesc.uResolutionHeight;
+
+ float fWidthScale = Width / ((float)m_SMDesc.uArraySize * fMapResW);
+ fWidthScale = (fWidthScale > 1.0f) ? (1.0f) : (fWidthScale);
+
+ float fOneFifth = (float)Height / (5.0f);
+ float fHeightScale = fOneFifth / fMapResH;
+ fHeightScale = (fHeightScale > 1.0f) ? (1.0f) : (fHeightScale);
+
+ float fScale = (fHeightScale < fWidthScale) ? (fHeightScale) : (fWidthScale);
+
+ fMapResW = floorf(fMapResW * fScale);
+ fMapResH = floorf(fMapResH * fScale);
+
+ for (unsigned int j = 0; j < (unsigned int)m_SMDesc.uArraySize; j++)
+ {
+ m_shadowLibContext->DevModeDisplayMap(m_shadowBufferHandle,
+ &ColorRTV,
+ m_shadowMapHandle,
+ j,
+ j * (unsigned int)fMapResW + j,
+ Height - (unsigned int)fMapResH,
+ fScale);
+ }
+}
+
+
+void RendererShadow::displayMapFrustums(ID3D11RenderTargetView* pOutputRTV, ID3D11DepthStencilView* pDSV)
+{
+ gfsdk_float3 v3Color;
+ v3Color.x = 1.0f;
+ v3Color.y = 0.0f;
+ v3Color.z = 0.0f;
+
+ GFSDK_ShadowLib_RenderTargetView ColorRTV;
+ ColorRTV.pRTV = pOutputRTV;
+
+ GFSDK_ShadowLib_DepthStencilView DSV;
+ DSV.pDSV = pDSV;
+
+ unsigned int NumViews;
+ NumViews = m_SMDesc.eViewType;
+
+ for (unsigned int j = 0; j < NumViews; j++)
+ {
+ switch (j)
+ {
+ case 0:
+ v3Color.x = 1.0f;
+ v3Color.y = 0.0f;
+ v3Color.z = 0.0f;
+ break;
+ case 1:
+ v3Color.x = 0.0f;
+ v3Color.y = 1.0f;
+ v3Color.z = 0.0f;
+ break;
+ case 2:
+ v3Color.x = 0.0f;
+ v3Color.y = 0.0f;
+ v3Color.z = 1.0f;
+ break;
+ case 3:
+ v3Color.x = 1.0f;
+ v3Color.y = 1.0f;
+ v3Color.z = 0.0f;
+ break;
+ }
+
+ m_shadowLibContext->DevModeDisplayMapFrustum(m_shadowBufferHandle,
+ &ColorRTV,
+ &DSV,
+ m_shadowMapHandle,
+ j,
+ v3Color);
+ }
+}
+
+
+void RendererShadow::displayShadowBuffer(ID3D11RenderTargetView* pOutputRTV)
+{
+ gfsdk_float2 v2Scale;
+ v2Scale.x = 1.0f;
+ v2Scale.y = 1.0f;
+
+ GFSDK_ShadowLib_RenderTargetView ColorRTV;
+ ColorRTV.pRTV = pOutputRTV;
+
+ m_shadowLibContext->DevModeDisplayBuffer(m_shadowBufferHandle,
+ &ColorRTV,
+ v2Scale,
+ NULL);
+}
+
+
+void RendererShadow::toggleDisplayCascades(bool bToggle)
+{
+ m_shadowLibContext->DevModeToggleDebugCascadeShader(m_shadowBufferHandle,
+ bToggle);
+}
+
+
+void RendererShadow::drawUI()
+{
+ ImGui::Checkbox("PCSS", &m_PCSSEnabled);
+ ImGui::ColorEdit3("Shadow Color", &(m_shadowColor.x));
+ ImGui::DragFloat("Light Size", &m_lightSize, 0.05f, 0.0f, 100.0f);
+ ImGui::DragFloat3("Light Position", &(m_lightPos.x));
+ ImGui_DragFloat3Dir("Light LookAt", &(m_lightLookAt.x));
+ ImGui::DragFloat("SoftShadowTestScale", &(m_softShadowTestScale), 0.0001f, 0.0f, 10.0f);
+ if (m_PCSSEnabled)
+ {
+ ImGui::DragFloat("PCSS: fMaxClamp", &(m_PCSSParams.fMaxClamp), 0.001f, 0.0f, 100.0f);
+ ImGui::DragFloat("PCSS: fMaxThreshold", &(m_PCSSParams.fMaxThreshold), 0.001f, 0.0f, 100.0f);
+ ImGui::DragFloat("PCSS: fMinSizePercent", &(m_PCSSParams.fMinSizePercent), 0.001f, 0.0f, 100.0f);
+ ImGui::DragFloat("PCSS: fMinWeightExponent", &(m_PCSSParams.fMinWeightExponent), 0.001f, 0.0f, 100.0f);
+ ImGui::DragFloat("PCSS: fMinWeightThresholdPercent", &(m_PCSSParams.fMinWeightThresholdPercent), 0.001f, 0.0f, 100.0f);
+ ImGui::DragFloat("PCSS: fBlockerSearchDitherPercent", &(m_PCSSParams.fBlockerSearchDitherPercent), 0.001f, 0.0f, 100.0f);
+ ImGui::DragFloat("PCSS: fFilterDitherPercent", &(m_PCSSParams.fFilterDitherPercent), 0.001f, 0.0f, 100.0f);
+ }
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererShadow.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererShadow.h
new file mode 100644
index 0000000..cc81c67
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/RendererShadow.h
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef RENDERER_SHADOW_H
+#define RENDERER_SHADOW_H
+
+#include <DirectXMath.h>
+#include "Utils.h"
+#include "gfsdk_shadowlib.h"
+
+#include <string>
+
+
+class CFirstPersonCamera;
+class Renderer;
+
+class RendererShadow
+{
+public:
+ RendererShadow();
+ ~RendererShadow();
+
+ void createResources(ID3D11Device *pd3dDevice, ID3D11DeviceContext* context, CFirstPersonCamera* camera);
+
+ void setScreenResolution(float FovyRad, UINT Width, UINT Height, UINT uSampleCount, ID3D11DepthStencilView* pReadOnlyDSV);
+ void changeShadowSettings(UINT Width, UINT Height, UINT uSampleCount, ID3D11DepthStencilView* pReadOnlyDSV);
+ void renderShadowMaps(Renderer* renderer);
+ void renderShadowBuffer(ID3D11ShaderResourceView* pDepthStencilSRV, ID3D11ShaderResourceView* pResolvedDepthStencilSRV);
+ void modulateShadowBuffer(ID3D11RenderTargetView* pOutputRTV);
+ void displayShadowMaps(ID3D11RenderTargetView* pOutputRTV, UINT Width, UINT Height);
+ void displayMapFrustums(ID3D11RenderTargetView* pOutputRTV, ID3D11DepthStencilView* pDSV);
+ void displayShadowBuffer(ID3D11RenderTargetView* pOutputRTV);
+ void toggleDisplayCascades(bool bToggle);
+
+
+ void drawUI();
+
+private:
+ void reloadBuffers();
+ void ReleaseResources();
+
+
+ GFSDK_ShadowLib_Context* m_shadowLibContext;
+
+ GFSDK_ShadowLib_ShaderResourceView m_shadowBufferSRV;
+
+ GFSDK_ShadowLib_Map* m_shadowMapHandle;
+ GFSDK_ShadowLib_MapDesc m_SMDesc;
+ GFSDK_ShadowLib_BufferDesc m_SBDesc;
+ GFSDK_ShadowLib_MapRenderParams m_SMRenderParams;
+
+ GFSDK_ShadowLib_Buffer* m_shadowBufferHandle;
+ GFSDK_ShadowLib_BufferRenderParams m_SBRenderParams;
+
+ GFSDK_ShadowLib_TempResources m_tempResources;
+ GFSDK_ShadowLib_Texture2D m_downsampledShadowMap;
+
+ CFirstPersonCamera* m_camera;
+
+ // params
+ bool m_PCSSEnabled;
+ float m_lightSize;
+ DirectX::XMFLOAT3 m_lightPos;
+ DirectX::XMFLOAT3 m_lightLookAt;
+ DirectX::XMFLOAT3 m_shadowColor;
+ GFSDK_ShadowLib_PCSSPenumbraParams m_PCSSParams;
+ float m_softShadowTestScale;
+
+ gfsdk_float3 m_worldSpaceBBox0;
+ gfsdk_float3 m_worldSpaceBBox1;
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ResourceManager.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ResourceManager.cpp
new file mode 100644
index 0000000..a051f96
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ResourceManager.cpp
@@ -0,0 +1,246 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "ResourceManager.h"
+#include "PxAssert.h"
+#include "PsString.h"
+#include "Utils.h"
+
+#include <windows.h>
+
+
+using namespace physx;
+
+#define PATH_MAX_LEN 512
+
+// Add By Lixu Begin
+ResourceManager* pResourceManager = nullptr;
+ResourceManager* ResourceManager::ins()
+{
+ return pResourceManager;
+}
+// Add By Lixu End
+
+ResourceManager::ResourceManager()
+{
+ // search for root folder by default
+ addSearchDir(".");
+
+// Add By Lixu Begin
+ pResourceManager = this;
+// Add By Lixu End
+}
+
+const ShaderFileResource* ResourceManager::requestShaderFile(const char* name)
+{
+ const Resource* resource = requestResource(eSHADER_FILE, name);
+ return resource != nullptr ? static_cast<const ShaderFileResource*>(resource) : nullptr;
+}
+
+const TextureResource* ResourceManager::requestTexture(const char* name)
+{
+ const Resource* resource = requestResource(eTEXTURE, name);
+ return resource != nullptr ? static_cast<const TextureResource*>(resource) : nullptr;
+}
+
+const Resource* ResourceManager::requestResource(ResourceType type, const char* name)
+{
+ // search in loaded
+ std::pair<ResourceType, std::string> key(type, name);
+ auto val = m_loadedResources.find(key);
+ if (val != m_loadedResources.end())
+ {
+ return val->second.get();
+ }
+
+ std::shared_ptr<Resource> resource;
+ if (type == eSHADER_FILE)
+ {
+ char path[PATH_MAX_LEN];
+ const char* exts[] = { "hlsl" };
+ if (findFile(name, std::vector<const char*>(exts, exts + sizeof(exts) / sizeof(exts[0])), path))
+ {
+ resource = std::shared_ptr<Resource>(new ShaderFileResource(path));
+ }
+ else
+ {
+ PX_ALWAYS_ASSERT_MESSAGE(name);
+ }
+ }
+ else if (type == eTEXTURE)
+ {
+ char path[PATH_MAX_LEN];
+// Add By Lixu Begin
+ const char* exts[] = { "dds", "tga", "jpg", "png" };
+// Add By Lixu End
+ if (findFile(name, std::vector<const char*>(exts, exts + sizeof(exts) / sizeof(exts[0])), path))
+ {
+ std::shared_ptr<TextureResource> textureResource(new TextureResource());
+ WCHAR wPath[MAX_PATH];
+ MultiByteToWideChar(CP_ACP, 0, path, -1, wPath, MAX_PATH);
+ wPath[MAX_PATH - 1] = 0;
+
+ const char* ext = strext(path);
+ if (::strcmp(ext, "dds") == 0)
+ {
+ V(DirectX::LoadFromDDSFile(wPath, DirectX::DDS_FLAGS_NONE, &textureResource->metaData,
+ textureResource->image));
+ }
+ else if (::strcmp(ext, "tga") == 0)
+ {
+ V(DirectX::LoadFromTGAFile(wPath, &textureResource->metaData,
+ textureResource->image));
+ }
+// Add By Lixu Begin
+ else if (::strcmp(ext, "jpg") == 0)
+ {
+ V(DirectX::LoadFromWICFile(wPath, DirectX::TEX_FILTER_DEFAULT | DirectX::WIC_FLAGS_ALL_FRAMES, &textureResource->metaData,
+ textureResource->image));
+ }
+ else if (::strcmp(ext, "png") == 0)
+ {
+ V(DirectX::LoadFromWICFile(wPath, DirectX::TEX_FILTER_DEFAULT | DirectX::WIC_FLAGS_ALL_FRAMES, &textureResource->metaData,
+ textureResource->image));
+ }
+// Add By Lixu End
+ else
+ {
+ PX_ALWAYS_ASSERT_MESSAGE("Unsupported texture extension");
+ }
+ resource = textureResource;
+ }
+ }
+
+ if (resource.get())
+ {
+ m_loadedResources.emplace(key, resource);
+ return resource.get();
+ }
+ else
+ {
+ PX_ALWAYS_ASSERT_MESSAGE(name);
+ return nullptr;
+ }
+}
+
+bool dirExists(const char* dir)
+{
+ DWORD ftyp = GetFileAttributesA(dir);
+ if (ftyp == INVALID_FILE_ATTRIBUTES)
+ return false; // something is wrong with path!
+
+ if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
+ return true; // this is a directory!
+
+ return false; // this is not a directory!
+}
+
+bool ResourceManager::addSearchDir(const char* dir, bool recursive)
+{
+ if (dirExists(dir))
+ {
+ m_searchDirs.push_back(SearchDir(dir, recursive));
+ return true;
+ }
+ return false;
+}
+
+
+ResourceManager::~ResourceManager()
+{
+}
+
+
+bool ResourceManager::findFileInDir(std::string fileNameFull, const char* path, bool recursive, char* foundPath)
+{
+ WIN32_FIND_DATAA ffd;
+ char tmp[PATH_MAX_LEN];
+ shdfnd::snprintf(tmp, sizeof(tmp), "%s\\*", path);
+ HANDLE hFind = FindFirstFileA(tmp, &ffd);
+
+ if(INVALID_HANDLE_VALUE == hFind)
+ {
+ return NULL;
+ }
+
+ do
+ {
+ if (0 == shdfnd::strcmp(".", ffd.cFileName) || 0 == shdfnd::strcmp("..", ffd.cFileName))
+ continue;
+
+ if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ shdfnd::snprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName);
+ if(findFileInDir(fileNameFull, tmp, recursive, foundPath))
+ return true;
+ }
+ else if (shdfnd::stricmp(ffd.cFileName, fileNameFull.c_str()) == 0)
+ {
+ shdfnd::snprintf(foundPath, PATH_MAX_LEN, "%s\\%s", path, ffd.cFileName);
+ return true;
+ }
+ } while(FindNextFileA(hFind, &ffd) != 0);
+ // release handle
+ FindClose(hFind);
+ return false;
+}
+
+bool ResourceManager::findFile(std::string fileName, const std::vector<const char*>& exts, char* foundPath)
+{
+ std::string fileNameOnly = fileName;
+ size_t ind = fileNameOnly.find_last_of('/');
+ if (ind > 0)
+ fileNameOnly = fileNameOnly.substr(ind + 1);
+
+// Add By Lixu Begin
+ std::string fileDir = ".";
+ size_t fl = fileName.length();
+ if (ind >= 0 && ind < fl)
+ fileDir = fileName.substr(0, ind);
+ if (findFileInDir(fileNameOnly.c_str(), fileDir.c_str(), true, foundPath))
+ return true;
+// Add By Lixu End
+
+ for(size_t i = 0; i < m_searchDirs.size(); i++)
+ {
+ const SearchDir& searchDir = m_searchDirs[i];
+
+ for(size_t j = 0; j < exts.size(); j++)
+ {
+ const char* ext = exts[j];
+ const uint32_t fileMaxLen = 128;
+ char fileNameFull[fileMaxLen] = { 0 };
+
+ physx::shdfnd::snprintf(fileNameFull, fileMaxLen, "%s.%s", fileNameOnly.c_str(), ext);
+ if(findFileInDir(fileNameFull, searchDir.path.c_str(), searchDir.recursive, foundPath))
+ return true;
+ }
+
+ if (findFileInDir(fileNameOnly.c_str(), searchDir.path.c_str(), searchDir.recursive, foundPath))
+ return true;
+ }
+ return false;
+}
+
+bool ResourceManager::findFile(std::string fileName, std::string& foundPath)
+{
+ std::vector<const char*> exts;
+ char path[PATH_MAX_LEN];
+ if (findFile(fileName, exts, path))
+ {
+ foundPath = path;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ResourceManager.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ResourceManager.h
new file mode 100644
index 0000000..0378438
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ResourceManager.h
@@ -0,0 +1,97 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef RESOURCE_MANAGER_H
+#define RESOURCE_MANAGER_H
+
+#include <vector>
+#include <string>
+#include <map>
+#include <memory>
+#include "DirectXTex.h"
+
+
+struct Resource
+{
+private:
+ Resource& operator = (const Resource&);
+};
+
+
+struct ShaderFileResource : public Resource
+{
+ ShaderFileResource(const std::string& p) : path(p) {}
+ std::string path;
+};
+
+
+struct TextureResource : public Resource
+{
+ DirectX::TexMetadata metaData;
+ DirectX::ScratchImage image;
+};
+
+
+/**
+ResourceManager used to look for files in provided dirs (see addSearchDir). Also it loads resources and caches them.
+*/
+class ResourceManager
+{
+public:
+ //////// ctor ////////
+
+ ResourceManager();
+ ~ResourceManager();
+
+// Add By Lixu Begin
+ static ResourceManager* ins();
+// Add By Lixu End
+
+ //////// public API ////////
+
+ bool addSearchDir(const char* dir, bool recursive = true);
+
+ const ShaderFileResource* requestShaderFile(const char* name);
+
+ const TextureResource* requestTexture(const char* name);
+
+ bool findFile(std::string fileName, std::string& foundPath);
+
+ bool findFile(std::string fileName, const std::vector<const char*>& exts, char* foundPath);
+
+
+private:
+ //////// internal methods ////////
+
+ enum ResourceType
+ {
+ eSHADER_FILE,
+ eTEXTURE
+ };
+
+ const Resource* requestResource(ResourceType type, const char* name);
+
+ bool findFileInDir(std::string fileNameFull, const char* path, bool recursive, char* foundPath);
+
+ struct SearchDir
+ {
+ SearchDir(std::string path_, bool recursive_) : path(path_), recursive(recursive_) {}
+
+ std::string path;
+ bool recursive;
+ };
+
+
+ //////// internal data ////////
+
+ std::vector<SearchDir> m_searchDirs;
+ std::map<std::pair<ResourceType, std::string>, std::shared_ptr<Resource>> m_loadedResources;
+};
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ShaderUtils.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ShaderUtils.h
new file mode 100644
index 0000000..778c811
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/ShaderUtils.h
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SHADER_UTILS_H
+#define SHADER_UTILS_H
+
+#include "Utils.h"
+#include <d3dcompiler.h>
+
+
+static HRESULT CompileShaderFromFile(const char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel,
+ ID3DBlob** ppBlobOut)
+{
+ HRESULT hr = S_OK;
+ ID3DBlob* pErrorBlob = NULL;
+
+ WCHAR wFileName[MAX_PATH];
+ MultiByteToWideChar(CP_ACP, 0, szFileName, -1, wFileName, MAX_PATH);
+ wFileName[MAX_PATH - 1] = 0;
+ hr = D3DCompileFromFile(wFileName, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE, szEntryPoint, szShaderModel, D3D10_SHADER_ENABLE_STRICTNESS, 0,
+ ppBlobOut, &pErrorBlob);
+ if(FAILED(hr))
+ {
+ OutputDebugStringA((char*)pErrorBlob->GetBufferPointer());
+ SAFE_RELEASE(pErrorBlob);
+ return hr;
+ }
+ SAFE_RELEASE(pErrorBlob);
+
+ return S_OK;
+}
+
+static HRESULT createShader(ID3D11Device* pDev, const void* pData, size_t len, ID3D11VertexShader** ppShd, bool)
+{
+ return pDev->CreateVertexShader(pData, len, nullptr, ppShd);
+}
+
+static HRESULT createShader(ID3D11Device* pDev, const void* pData, size_t len, ID3D11GeometryShader** ppShd,
+ bool forceFast)
+{
+ PX_UNUSED(forceFast);
+ return pDev->CreateGeometryShader(pData, len, nullptr, ppShd);
+}
+
+static HRESULT createShader(ID3D11Device* pDev, const void* pData, size_t len, ID3D11PixelShader** ppShd, bool)
+{
+ return pDev->CreatePixelShader(pData, len, nullptr, ppShd);
+}
+
+static const char* shaderModel(ID3D11VertexShader**)
+{
+ return "vs_5_0";
+}
+
+static const char* shaderModel(ID3D11GeometryShader**)
+{
+ return "gs_5_0";
+}
+
+static const char* shaderModel(ID3D11PixelShader**)
+{
+ return "ps_5_0";
+}
+
+// Give back the shader buffer blob for use in CreateVertexLayout. Caller must release the blob.
+template <class S>
+static HRESULT createShaderFromFile(ID3D11Device* pDev, const char* szFileName, LPCSTR szEntryPoint, S** ppShd,
+ ID3DBlob*& pShaderBuffer, bool forceFast = false)
+{
+ HRESULT hr = CompileShaderFromFile(szFileName, szEntryPoint, shaderModel(ppShd), &pShaderBuffer);
+ if(SUCCEEDED(hr) && pShaderBuffer)
+ {
+ const void* shaderBufferData = pShaderBuffer->GetBufferPointer();
+ const UINT shaderBufferSize = pShaderBuffer->GetBufferSize();
+ createShader(pDev, shaderBufferData, shaderBufferSize, ppShd, forceFast);
+ }
+ return hr;
+}
+
+// Overloaded, same as above but don't give back the shader buffer blob.
+template <class S>
+static HRESULT createShaderFromFile(ID3D11Device* pDev, const char* szFileName, LPCSTR szEntryPoint, S** ppShd,
+ bool forceFast = false)
+{
+ ID3DBlob* pShaderBuffer = NULL;
+ HRESULT hr = createShaderFromFile(pDev, szFileName, szEntryPoint, ppShd, pShaderBuffer, forceFast);
+ SAFE_RELEASE(pShaderBuffer);
+ return hr;
+}
+
+
+#endif //SHADER_UTILS_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/SkinnedRenderMesh.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/SkinnedRenderMesh.cpp
new file mode 100644
index 0000000..c575d6c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/SkinnedRenderMesh.cpp
@@ -0,0 +1,217 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+
+#include "SkinnedRenderMesh.h"
+#include "Renderer.h"
+
+SkinnedRenderMesh::SkinnedRenderMesh(const std::vector<const SimpleMesh*>& meshes)
+{
+ PX_ASSERT_WITH_MESSAGE(meshes.size() <= MeshesCountMax, "meshes.size() have to be <= SkinnedRenderMesh::MeshesCountMax");
+
+ m_device = GetDeviceManager()->GetDevice();
+
+ // input element desc setup
+ m_inputDesc.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ m_inputDesc.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ m_inputDesc.push_back({ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ m_inputDesc.push_back({ "TEXCOORD", 1, DXGI_FORMAT_R32_UINT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+
+ // reserve VB
+ uint32_t verticesTotal = 0;
+ std::for_each(meshes.begin(), meshes.end(), [&](const SimpleMesh* c) { verticesTotal += (uint32_t)c->vertices.size(); });
+ std::vector<SimpleMesh::Vertex> vertexBuffer;
+ vertexBuffer.reserve(verticesTotal);
+
+ // reserve IB
+ uint32_t indicesTotal = 0;
+ std::for_each(meshes.begin(), meshes.end(), [&](const SimpleMesh* c) { indicesTotal += (uint32_t)c->indices.size(); });
+ m_indices.reserve(indicesTotal);
+
+ // fill VB, IB, MeshInfo
+ m_meshesInfo.resize(meshes.size());
+ for (uint32_t meshIndex = 0; meshIndex < meshes.size(); ++meshIndex)
+ {
+ const SimpleMesh* mesh = meshes[meshIndex];
+ MeshInfo& meshInfo = m_meshesInfo[meshIndex];
+
+ meshInfo.firstVertex = (uint32_t)vertexBuffer.size();
+ vertexBuffer.insert(vertexBuffer.end(), mesh->vertices.begin(), mesh->vertices.end());
+ meshInfo.verticesCount = (uint32_t)mesh->vertices.size();
+
+ meshInfo.firstIndex = (uint32_t)m_indices.size();
+ uint32_t indexOffset = meshInfo.firstVertex;
+ for (uint32_t index : mesh->indices)
+ {
+ m_indices.push_back((uint32_t)index + indexOffset);
+ }
+ meshInfo.indicesCount = (uint32_t)mesh->indices.size();
+ }
+
+ // vertex buffer
+ {
+ D3D11_SUBRESOURCE_DATA vertexBufferData;
+
+ ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
+ vertexBufferData.pSysMem = vertexBuffer.data();
+
+ D3D11_BUFFER_DESC bufferDesc;
+
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.ByteWidth = (uint32_t)(sizeof(SimpleMesh::Vertex) * vertexBuffer.size());
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+
+ V(m_device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_vertexBuffer));
+ }
+
+ // bone index buffer
+ {
+ D3D11_BUFFER_DESC bufferDesc;
+
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.ByteWidth = (uint32_t)(sizeof(uint32_t) * vertexBuffer.size());
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+
+ V(m_device->CreateBuffer(&bufferDesc, nullptr, &m_boneIndexBuffer));
+ }
+
+ // index buffer
+ {
+ D3D11_BUFFER_DESC bufferDesc;
+
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ bufferDesc.ByteWidth = (uint32_t)(sizeof(uint32_t) * m_indices.size());
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+
+ V(m_device->CreateBuffer(&bufferDesc, nullptr, &m_indexBuffer));
+ }
+
+ // bone texture
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Width = 4;
+ desc.Height = (uint32_t)meshes.size();
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+
+ V(m_device->CreateTexture2D(&desc, nullptr, &m_boneTexture));
+ }
+
+ // bone texture SRV
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
+ desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ desc.Texture2D.MipLevels = 1;
+ desc.Texture2D.MostDetailedMip = 0;
+ V(m_device->CreateShaderResourceView(m_boneTexture, &desc, &m_boneTextureSRV));
+ }
+}
+
+SkinnedRenderMesh::~SkinnedRenderMesh()
+{
+ SAFE_RELEASE(m_vertexBuffer);
+ SAFE_RELEASE(m_boneIndexBuffer);
+ SAFE_RELEASE(m_indexBuffer);
+ SAFE_RELEASE(m_boneTexture);
+ SAFE_RELEASE(m_boneTextureSRV);
+}
+
+void SkinnedRenderMesh::updateVisibleMeshes(const std::vector<uint32_t>& visibleMeshes)
+{
+ ID3D11DeviceContext* context;
+ m_device->GetImmediateContext(&context);
+
+ // update bone index buffer
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedRead;
+ V(context->Map(m_boneIndexBuffer, 0, D3D11_MAP_WRITE_DISCARD, NULL, &mappedRead));
+
+ uint32_t* boneIndexBuffer = (uint32_t*)mappedRead.pData;
+ for (uint32_t i = 0; i < visibleMeshes.size(); ++i)
+ {
+ const MeshInfo& info = m_meshesInfo[visibleMeshes[i]];
+ for (uint32_t v = info.firstVertex; v < info.firstVertex + info.verticesCount; ++v)
+ {
+ boneIndexBuffer[v] = i;
+ }
+ }
+
+ context->Unmap(m_boneIndexBuffer, 0);
+ }
+
+ // update index buffer
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedRead;
+ V(context->Map(m_indexBuffer, 0, D3D11_MAP_WRITE_DISCARD, NULL, &mappedRead));
+
+ uint32_t* indexBuffer = (uint32_t*)mappedRead.pData;
+ uint32_t indexCount = 0;
+ for (uint32_t meshIndex : visibleMeshes)
+ {
+ const MeshInfo& info = m_meshesInfo[meshIndex];
+ memcpy(indexBuffer + indexCount, &m_indices[info.firstIndex], info.indicesCount * sizeof(uint32_t));
+ indexCount += info.indicesCount;
+ }
+ context->Unmap(m_indexBuffer, 0);
+ m_indexCount = indexCount;
+ PX_ASSERT(m_indexCount % 3 == 0);
+ }
+}
+
+void SkinnedRenderMesh::updateVisibleMeshTransforms(std::vector<PxMat44>& transforms)
+{
+ ID3D11DeviceContext* context;
+ m_device->GetImmediateContext(&context);
+
+ // update bone transform texture
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedRead;
+ V(context->Map(m_boneTexture, 0, D3D11_MAP_WRITE_DISCARD, NULL, &mappedRead));
+ for (uint32_t i = 0; i < transforms.size(); ++i)
+ {
+ std::memcpy((uint8_t*)mappedRead.pData + i * mappedRead.RowPitch, &transforms[i], sizeof(PxMat44));
+ }
+ context->Unmap(m_boneTexture, 0);
+ }
+}
+
+void SkinnedRenderMesh::render(ID3D11DeviceContext& context) const
+{
+ context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+
+ UINT strides[2] = { sizeof(SimpleMesh::Vertex), sizeof(uint32_t) };
+ UINT offsets[2] = { 0 };
+ ID3D11Buffer* buffers[2] = { m_vertexBuffer, m_boneIndexBuffer };
+ context.IASetVertexBuffers(0, 2, buffers, strides, offsets);
+
+ context.IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
+
+ context.VSSetShaderResources(1, 1, &m_boneTextureSRV);
+
+ context.DrawIndexed(m_indexCount, 0, 0);
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/SkinnedRenderMesh.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/SkinnedRenderMesh.h
new file mode 100644
index 0000000..2f690d8
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/renderer/SkinnedRenderMesh.h
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SKINNED_RENDER_MESH_H
+#define SKINNED_RENDER_MESH_H
+
+#include "Utils.h"
+#include <DirectXMath.h>
+
+#include <vector>
+#include "Renderable.h"
+#include "Mesh.h"
+
+/**
+SkinnedRenderMesh:
+ bonde indices are passed as vertex input,
+ bone transforms are stored in texture
+ max bone meshes count: SkinnedRenderMesh::MeshesCountMax
+*/
+class SkinnedRenderMesh : public IRenderMesh
+{
+public:
+ //////// ctor ////////
+
+ SkinnedRenderMesh(const std::vector<const SimpleMesh*>& meshes);
+ ~SkinnedRenderMesh();
+
+
+ //////// const ////////
+
+ static const uint32_t MeshesCountMax = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+
+ //////// public API ////////
+
+ void updateVisibleMeshes(const std::vector<uint32_t>& visibleMeshes);
+ void updateVisibleMeshTransforms(std::vector<PxMat44>& transforms);
+
+
+ //////// IRenderMesh implementation ////////
+
+ virtual const std::vector<D3D11_INPUT_ELEMENT_DESC>& getInputElementDesc() const { return m_inputDesc; }
+ virtual void render(ID3D11DeviceContext& context) const;
+
+private:
+ //////// internal data ////////
+
+ struct MeshInfo
+ {
+ uint32_t firstIndex;
+ uint32_t indicesCount;
+
+ uint32_t firstVertex;
+ uint32_t verticesCount;
+ };
+
+ std::vector<D3D11_INPUT_ELEMENT_DESC> m_inputDesc;
+
+ ID3D11Device* m_device;
+
+ ID3D11Buffer* m_vertexBuffer;
+ ID3D11Buffer* m_boneIndexBuffer;
+ ID3D11Buffer* m_indexBuffer;
+ ID3D11Texture2D* m_boneTexture;
+ ID3D11ShaderResourceView* m_boneTextureSRV;
+
+ uint32_t m_indexCount;
+
+ std::vector<MeshInfo> m_meshesInfo;
+ std::vector<uint32_t> m_indices;
+};
+
+
+
+#endif //SKINNED_RENDER_MESH_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SampleAssetListParser.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SampleAssetListParser.cpp
new file mode 100644
index 0000000..00cf4df
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SampleAssetListParser.cpp
@@ -0,0 +1,272 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "SampleAssetListParser.h"
+#include <PsFastXml.h>
+#include "Sample.h"
+#include "PxVec4.h"
+#include "PxInputDataFromPxFileBuf.h"
+
+
+using namespace physx;
+
+
+const float DEGREE_TO_RAD = acos(-1.0) / 180.0;
+
+class AssetListParser : public physx::shdfnd::FastXml::Callback
+{
+public:
+ AssetListParser(AssetList& assetList): m_assetList(assetList){}
+protected:
+
+ // encountered a comment in the XML
+ virtual bool processComment(const char* /*comment*/)
+ {
+ return true;
+ }
+
+ virtual bool processClose(const char* elementName, unsigned int /*depth*/, bool& /*isError*/)
+ {
+ if (::strcmp(elementName, "Box") == 0)
+ {
+ m_assetList.boxes.push_back(m_boxTemp);
+ m_boxTemp = AssetList::BoxAsset();
+ }
+ else if (::strcmp(elementName, "Composite") == 0)
+ {
+ m_assetList.composites.push_back(m_compositeTemp);
+ m_compositeTemp = AssetList::CompositeAsset();
+ }
+ return true;
+ }
+
+ // return true to continue processing the XML document, false to skip.
+ virtual bool processElement(const char* elementName, // name of the element
+ const char* elementData, // element data, null if none
+ const physx::shdfnd::FastXml::AttributePairs& attr,
+ int /*lineno*/) // line number in the source XML file
+ {
+ if (::strcmp(elementName, "Model") == 0)
+ {
+ m_assetList.models.resize(m_assetList.models.size() + 1);
+ auto& model = m_assetList.models.back();
+ for (int i = 0; i < attr.getNbAttr(); ++i)
+ {
+ if (::strcmp(attr.getKey(i), "id") == 0)
+ {
+ model.id = std::string(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "file") == 0)
+ {
+ model.file = std::string(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "name") == 0)
+ {
+ model.name = std::string(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "isSkinned") == 0)
+ {
+ std::string str = attr.getValue(i);
+ if (::strcmp(&str[0], "true") == 0)
+ {
+ model.isSkinned = true;
+ }
+ }
+ }
+
+ model.transform = parseTransform(attr);
+
+ if (model.name.empty())
+ {
+ model.name = model.file;
+ }
+ if (model.id.empty())
+ {
+ model.id = model.name;
+ }
+ }
+ else if (::strcmp(elementName, "Box") == 0)
+ {
+ for (int i = 0; i < attr.getNbAttr(); ++i)
+ {
+ if (::strcmp(attr.getKey(i), "id") == 0)
+ {
+ m_boxTemp.id = std::string(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "name") == 0)
+ {
+ m_boxTemp.name = std::string(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "staticHeight") == 0)
+ {
+ std::string str = attr.getValue(i);
+ sscanf(&str[0], "%f", &m_boxTemp.staticHeight);
+ }
+ else if (::strcmp(attr.getKey(i), "jointAllBonds") == 0)
+ {
+ std::string str = attr.getValue(i);
+ if (::strcmp(&str[0], "true") == 0)
+ {
+ m_boxTemp.jointAllBonds = true;
+ }
+ }
+ else if (::strcmp(attr.getKey(i), "extents") == 0)
+ {
+ std::string str = attr.getValue(i);
+ sscanf(&str[0], "%f %f %f", &m_boxTemp.extents.x, &m_boxTemp.extents.y, &m_boxTemp.extents.z);
+ }
+ }
+
+ if (m_boxTemp.id.empty())
+ {
+ m_boxTemp.id = m_boxTemp.name;
+ }
+ }
+ else if (::strcmp(elementName, "Level") == 0)
+ {
+ m_boxTemp.levels.push_back(AssetList::BoxAsset::Level());
+ auto& level = m_boxTemp.levels.back();
+ for (int i = 0; i < attr.getNbAttr(); ++i)
+ {
+ if (::strcmp(attr.getKey(i), "slices") == 0)
+ {
+ std::string str = attr.getValue(i);
+ sscanf(&str[0], "%d %d %d", &level.x, &level.y, &level.z);
+ }
+ if (::strcmp(attr.getKey(i), "isSupport") == 0)
+ {
+ std::string str = attr.getValue(i);
+ if (::strcmp(&str[0], "true") == 0)
+ {
+ level.isSupport = true;
+ }
+ }
+ }
+ }
+ else if (::strcmp(elementName, "Composite") == 0)
+ {
+ for (int i = 0; i < attr.getNbAttr(); ++i)
+ {
+ if (::strcmp(attr.getKey(i), "id") == 0)
+ {
+ m_compositeTemp.id = std::string(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "name") == 0)
+ {
+ m_compositeTemp.name = std::string(attr.getValue(i));
+ }
+ }
+ m_compositeTemp.transform = parseTransform(attr);
+
+ if (m_compositeTemp.id.empty())
+ {
+ m_compositeTemp.id = m_compositeTemp.name;
+ }
+ }
+ else if (::strcmp(elementName, "AssetRef") == 0)
+ {
+ m_compositeTemp.assetRefs.push_back(AssetList::CompositeAsset::AssetRef());
+ AssetList::CompositeAsset::AssetRef& assetRef = m_compositeTemp.assetRefs.back();
+ for (int i = 0; i < attr.getNbAttr(); ++i)
+ {
+ if (::strcmp(attr.getKey(i), "id") == 0)
+ {
+ assetRef.id = attr.getValue(i);
+ }
+ }
+ assetRef.transform = parseTransform(attr);
+ }
+ else if (::strcmp(elementName, "Joint") == 0)
+ {
+ m_compositeTemp.joints.push_back(AssetList::CompositeAsset::Joint());
+ AssetList::CompositeAsset::Joint& joint = m_compositeTemp.joints.back();
+ for (int i = 0; i < attr.getNbAttr(); ++i)
+ {
+ if (::strcmp(attr.getKey(i), "asset0") == 0)
+ {
+ joint.assetIndices[0] = std::stoi(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "asset1") == 0)
+ {
+ joint.assetIndices[1] = std::stoi(attr.getValue(i));
+ }
+ if (::strcmp(attr.getKey(i), "chunk0") == 0)
+ {
+ joint.chunkIndices[0] = std::stoi(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "chunk1") == 0)
+ {
+ joint.chunkIndices[1] = std::stoi(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "position0") == 0)
+ {
+ joint.attachPositions[0] = parsePosition(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "position1") == 0)
+ {
+ joint.attachPositions[1] = parsePosition(attr.getValue(i));
+ }
+ }
+ }
+ return true;
+ }
+
+private:
+ PxTransform parseTransform(const physx::shdfnd::FastXml::AttributePairs& attr)
+ {
+ PxTransform transform(PxIdentity);
+ for (int i = 0; i < attr.getNbAttr(); ++i)
+ {
+ if (::strcmp(attr.getKey(i), "position") == 0)
+ {
+ transform.p = parsePosition(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "rotation") == 0)
+ {
+ transform.q = parseRotation(attr.getValue(i));
+ }
+ }
+ return transform;
+ }
+
+ PxVec3 parsePosition(const char* value)
+ {
+ PxVec3 ps;
+ sscanf(value, "%f %f %f", &ps.x, &ps.y, &ps.z);
+ return ps;
+ }
+
+ PxQuat parseRotation(const char* value)
+ {
+ PxVec4 ps;
+ sscanf(value, "%f %f %f %f", &ps.x, &ps.y, &ps.z, &ps.w);
+ ps.w = ps.w * DEGREE_TO_RAD;
+ return PxQuat(ps.w, PxVec3(ps.x, ps.y, ps.z).getNormalized());;
+ }
+
+ AssetList::BoxAsset m_boxTemp;
+ AssetList::CompositeAsset m_compositeTemp;
+ AssetList& m_assetList;
+};
+
+
+void parseAssetList(AssetList& assetList, std::string filepath)
+{
+ physx::PsFileBuffer fileBuffer(filepath.c_str(), physx::general_PxIOStream2::PxFileBuf::OPEN_READ_ONLY);
+ if (!fileBuffer.isOpen())
+ {
+ return;
+ }
+ PxInputDataFromPxFileBuf inputData(fileBuffer);
+ AssetListParser parser(assetList);
+ physx::shdfnd::FastXml* xml = physx::shdfnd::createFastXml(&parser);
+ xml->processXml(inputData, false);
+ xml->release();
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SampleAssetListParser.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SampleAssetListParser.h
new file mode 100644
index 0000000..b6303ec
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SampleAssetListParser.h
@@ -0,0 +1,20 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SAMPLEASSETLISTPARSER_H
+#define SAMPLEASSETLISTPARSER_H
+
+#include <string>
+
+struct AssetList;
+
+void parseAssetList(AssetList& assetList, std::string filepath);
+
+#endif // SAMPLEASSETLISTPARSER_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp
new file mode 100644
index 0000000..2466304
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp
@@ -0,0 +1,1510 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "SceneController.h"
+#include "RenderUtils.h"
+#include "Utils.h"
+
+#include "BlastAssetBoxes.h"
+#include "BlastAssetModelSimple.h"
+#include "BlastAssetModelSkinned.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlastExtPxFamily.h"
+#include "NvBlastExtPxManager.h"
+
+#include "SampleAssetListParser.h"
+#include "BlastReplay.h"
+#include "Renderer.h"
+
+#include "BlastController.h"
+#include "CommonUIController.h"
+#include "PhysXController.h"
+
+#include "PxRigidDynamic.h"
+#include <PsFastXml.h>
+#include "PxInputDataFromPxFileBuf.h"
+
+#include <algorithm>
+#include <imgui.h>
+#include <sstream>
+#include <tuple>
+
+
+
+//////// Simple hash function ////////
+static NvBlastID generateIDFromString(const char* str)
+{
+ uint32_t h[4] = { 5381, 5381, 5381, 5381 };
+ int i = 0;
+ for (const char* ptr = str; *ptr; i = ((i + 1) & 3), ++ptr)
+ {
+ h[i] = ((h[i] << 5) + h[i]) ^ static_cast<uint32_t>(*ptr);
+ }
+ return *reinterpret_cast<NvBlastID*>(h);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Scenes Setup
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const DirectX::XMFLOAT4 PICK_POINTER_ACTIVE_COLOR(1.0f, 0.f, 0.f, 0.6f);
+const float RIGIDBODY_DENSITY = 2000.0f;
+
+
+class SingleSceneAsset;
+
+class SceneAsset
+{
+public:
+ SceneAsset() : spawnCount(0) {}
+ virtual ~SceneAsset() {}
+
+ void initialize(Scene* scene)
+ {
+ m_scene = scene;
+ }
+
+ virtual const char* getID() const = 0;
+ virtual const char* getName() const = 0;
+
+ virtual void load() = 0;
+ virtual void unload() = 0;
+ virtual bool isLoaded() const = 0;
+ virtual void spawn(PxVec3 shift) = 0;
+
+ virtual ImVec4 getUIColor() const
+ {
+ return ImGui::GetStyle().Colors[ImGuiCol_Text];
+ }
+
+ uint32_t spawnCount;
+protected:
+ Scene* m_scene;
+};
+
+
+class SceneActor
+{
+public:
+ virtual ~SceneActor() {}
+ virtual const char* getName() const = 0;
+ virtual const char* getSubname(int subindex) const { return nullptr; }
+ virtual ImVec4 getUIColor() const = 0;
+ virtual void drawUI(int subindex) {}
+ virtual void drawStatsUI(int subindex) {}
+ virtual uint32_t getSubactorCount() const { return 0; }
+ virtual PxVec3 getSpawnShift() const { return PxVec3(PxZero); }
+ virtual void reload() {}
+ virtual void removeSubactor(int subindex) {}
+};
+
+
+class Scene
+{
+public:
+ struct ActorIndex
+ {
+ int index;
+ int subindex;
+
+ ActorIndex() { reset(); }
+ ActorIndex(int i, int s) : index(i), subindex(s) {}
+
+ bool operator==(const ActorIndex& other) const
+ {
+ return index == other.index && subindex == other.subindex;
+ }
+
+ void reset()
+ {
+ index = -1;
+ subindex = -1;
+ }
+ };
+
+ Scene(Renderer& renderer, PhysXController& physXController, BlastController& blastController, CommonUIController& commonUIController) :
+ m_renderer(renderer), m_physXController(physXController), m_blastController(blastController), m_commonUIController(commonUIController)
+ {
+ }
+
+ ~Scene()
+ {
+ removeAllSceneActors();
+
+ for (uint32_t i = 0; i < m_assets.size(); i++)
+ {
+ SAFE_DELETE(m_assets[i]);
+ }
+ m_assets.clear();
+ m_assetsByID.clear();
+ m_tkAssetMap.clear();
+ }
+
+ void addAsset(SceneAsset* asset)
+ {
+ m_assets.push_back(asset);
+ asset->initialize(this);
+ m_assetsByID[asset->getID()] = asset;
+ }
+
+// Add By Lixu Begin
+ std::vector<SceneAsset*>& getAssets()
+ {
+ return m_assets;
+ }
+
+ std::vector<SceneActor*>& getActors()
+ {
+ return m_sceneActors;
+ }
+// Add By Lixu End
+
+ void drawUI()
+ {
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Assets Selection
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ static int mode = 0;
+ ImGui::RadioButton("Replace", &mode, 0); ImGui::SameLine();
+ ImGui::RadioButton("Append", &mode, 1);
+
+ ImGui::ListBoxHeader("Assets", (int)m_assets.size());
+ for (uint32_t i = 0; i < m_assets.size(); ++i)
+ {
+ ImVec4 color = m_assets[i]->getUIColor();
+ color.w = color.w * (m_assets[i]->isLoaded() ? 1.0f : 0.5f);
+ ImGui::PushStyleColor(ImGuiCol_Text, color);
+ if (ImGui::Selectable(m_assets[i]->getName(), m_lastSpawnedAsset == i))
+ {
+ m_lastSpawnedAsset = i;
+ if (mode == 0)
+ {
+ removeAllSceneActors();
+ }
+ m_commonUIController.addDelayedCall([=]() { spawnAsset(m_lastSpawnedAsset); }, "Loading Asset");
+ }
+ ImGui::PopStyleColor();
+ }
+ ImGui::ListBoxFooter();
+ }
+
+ ImGui::Spacing();
+ ImGui::Separator();
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Actors Selection
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ // actor's list
+ {
+ int itemCount = 0;
+ for (size_t i = 0; i < m_sceneActors.size(); ++i)
+ {
+ itemCount += 1 + m_sceneActors[i]->getSubactorCount();
+ }
+
+ ImGui::ListBoxHeader("Scene Actors", itemCount);
+ for (int i = 0; i < (int)m_sceneActors.size(); ++i)
+ {
+ ImVec4 color = m_sceneActors[i]->getUIColor();
+ ImGui::PushStyleColor(ImGuiCol_Text, color);
+
+ const bool isSelected = (m_selectedActor.index == i);
+
+ ImGui::PushID(i);
+ if (ImGui::Selectable(m_sceneActors[i]->getName(), isSelected && m_selectedActor.subindex == -1))
+ {
+ setSelectedActor(i);
+ }
+
+ for (int s = 0; s < (int)m_sceneActors[i]->getSubactorCount(); ++s)
+ {
+ ImGui::PushID(s);
+ if (ImGui::Selectable(m_sceneActors[i]->getSubname(s), isSelected && m_selectedActor.subindex == s))
+ {
+ setSelectedActor(i, s);
+ }
+ ImGui::PopID();
+ }
+
+ ImGui::PopID();
+ ImGui::PopStyleColor();
+ }
+ ImGui::ListBoxFooter();
+ }
+
+ SceneActor* selectedActor = getSelectedActor();
+ if (selectedActor)
+ {
+ if (ImGui::Button("Remove"))
+ {
+ removeSceneActor(m_selectedActor);
+ }
+
+ ImGui::SameLine();
+
+ if (ImGui::Button("Reload"))
+ {
+ selectedActor->reload();
+ }
+
+ ImGui::SameLine();
+ }
+
+ if (ImGui::Button("Remove All"))
+ {
+ removeAllSceneActors();
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("Reload All (R)"))
+ {
+ reloadAllActors();
+ }
+ }
+
+ ImGui::Spacing();
+ ImGui::Spacing();
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Selected Actor
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ SceneActor* selectedActor = getSelectedActor();
+ if (selectedActor)
+ {
+ ImGui::Text("Selected Actor: ");
+ ImGui::SameLine();
+ ImGui::PushStyleColor(ImGuiCol_Text, ImColor(40, 200, 80, 255));
+ ImGui::Text(m_selectedActor.subindex >= 0 ? selectedActor->getSubname(m_selectedActor.subindex) : selectedActor->getName());
+ ImGui::PopStyleColor();
+
+ ImGui::Spacing();
+
+ selectedActor->drawUI(m_selectedActor.subindex);
+ }
+ else
+ {
+ ImGui::Text("No Selected Actor");
+ }
+ }
+ }
+
+ void drawStatsUI()
+ {
+ SceneActor* selectedActor = getSelectedActor();
+ if (selectedActor)
+ {
+ selectedActor->drawStatsUI(m_selectedActor.subindex);
+ }
+ }
+
+ void spawnAsset(int32_t num)
+ {
+ m_lastSpawnedAsset = physx::PxClamp<int32_t>(num, -1, (uint32_t)m_assets.size() - 1);
+
+ if (m_lastSpawnedAsset < 0)
+ {
+ return;
+ }
+
+ PxVec3 shift(PxZero);
+// Add By Lixu Begin
+ /*
+ for (SceneActor* a : m_sceneActors)
+ {
+ shift += a->getSpawnShift();
+ }
+ */
+// Add By Lixu End
+
+ SceneAsset* asset = m_assets[m_lastSpawnedAsset];
+ asset->spawn(shift);
+ }
+
+ void addSceneActor(SceneActor* actor)
+ {
+ m_sceneActors.push_back(actor);
+ if (!getSelectedActor())
+ {
+ setSelectedActor((uint32_t)m_sceneActors.size() - 1);
+ }
+ }
+
+ void removeSceneActor(ActorIndex actorIndex)
+ {
+ SceneActor* actor = getActorByIndex(actorIndex.index);
+ if (actorIndex.subindex < 0)
+ {
+ delete actor;
+ m_sceneActors.erase(std::remove(m_sceneActors.begin(), m_sceneActors.end(), actor));
+ }
+ else
+ {
+ actor->removeSubactor(actorIndex.subindex);
+
+ if (actor->getSubactorCount() == 0)
+ {
+ removeSceneActor(ActorIndex(actorIndex.index, -1));
+ return;
+ }
+ }
+
+ SceneActor* selectedActor = getActorByIndex(m_selectedActor.index);
+ if (selectedActor == nullptr)
+ {
+ if (!m_sceneActors.empty())
+ {
+ setSelectedActor((uint32_t)m_sceneActors.size() - 1);
+ }
+ }
+ else
+ {
+ int subactorCount = selectedActor->getSubactorCount();
+ if (m_selectedActor.subindex >= subactorCount || (m_selectedActor.subindex < 0 && subactorCount > 0))
+ {
+ setSelectedActor(m_selectedActor.index, subactorCount - 1);
+ }
+ }
+ }
+
+ void removeAllSceneActors()
+ {
+ for (SceneActor* a : m_sceneActors)
+ {
+ delete a;
+ }
+ m_sceneActors.clear();
+ setSelectedActor(-1);
+ }
+
+ void setSelectedActor(int index, int subindex = -1)
+ {
+ m_selectedActor.index = physx::PxClamp<int32_t>(index, -1, (uint32_t)m_sceneActors.size() - 1);
+ m_selectedActor.subindex = subindex;
+ }
+
+ SceneActor* getSelectedActor() const
+ {
+ return getActorByIndex(m_selectedActor.index);
+ }
+
+ SceneActor* getActorByIndex(int index) const
+ {
+ return (index >= 0 && index < (int)m_sceneActors.size()) ? m_sceneActors[index] : nullptr;
+ }
+
+ int releaseAll()
+ {
+ removeAllSceneActors();
+
+ for (size_t i = 0; i < m_assets.size(); ++i)
+ {
+ m_assets[i]->unload();
+ }
+
+ const int currentAsset = m_lastSpawnedAsset;
+ m_lastSpawnedAsset = -1;
+ return currentAsset;
+ }
+
+ void reloadAllActors()
+ {
+ for (SceneActor* a : m_sceneActors)
+ {
+ a->reload();
+ }
+ }
+
+ void registerTkAsset(const TkAsset& tkAsset, SingleSceneAsset* asset)
+ {
+ m_tkAssetMap[&tkAsset] = asset;
+ }
+
+ void unregisterTkAsset(const TkAsset& tkAsset)
+ {
+ m_tkAssetMap.erase(&tkAsset);
+ }
+
+ SingleSceneAsset* findSingleSceneAsset(const TkAsset& tkAsset)
+ {
+ auto entry = m_tkAssetMap.find(&tkAsset);
+ return entry != m_tkAssetMap.end() ? entry->second : nullptr;
+ }
+
+ SceneAsset* findSceneAsset(const std::string& id)
+ {
+ auto entry = m_assetsByID.find(id);
+ return entry != m_assetsByID.end() ? entry->second : nullptr;
+ }
+
+
+ //////// used controllers ////////
+
+ Renderer& getRenderer() const
+ {
+ return m_renderer;
+ }
+
+ PhysXController& getPhysXController() const
+ {
+ return m_physXController;
+ }
+
+ BlastController& getBlastController() const
+ {
+ return m_blastController;
+ }
+
+ CommonUIController& getCommonUIController() const
+ {
+ return m_commonUIController;
+ }
+
+private:
+
+ Renderer& m_renderer;
+ PhysXController& m_physXController;
+ BlastController& m_blastController;
+ CommonUIController& m_commonUIController;
+
+ std::vector<SceneAsset*> m_assets;
+ std::vector<SceneActor*> m_sceneActors;
+ std::map<const TkAsset*, SingleSceneAsset*> m_tkAssetMap;
+ std::map<std::string, SceneAsset*> m_assetsByID;
+
+ int m_lastSpawnedAsset;
+
+ ActorIndex m_selectedActor;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Assets
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SingleSceneActor;
+
+class SingleSceneAsset : public SceneAsset
+{
+public:
+ SingleSceneAsset() : m_asset(nullptr) {}
+ virtual ~SingleSceneAsset() { unload(); }
+
+ virtual void spawn(PxVec3 shift) override;
+
+ virtual void load() override
+ {
+ if (!m_asset)
+ {
+ m_asset = createAsset();
+ m_scene->registerTkAsset(m_asset->getPxAsset()->getTkAsset(), this);
+ }
+ }
+
+ virtual void unload() override
+ {
+ if (m_asset)
+ {
+ m_scene->unregisterTkAsset(m_asset->getPxAsset()->getTkAsset());
+ delete m_asset;
+ m_asset = nullptr;
+ }
+ }
+
+ virtual bool isLoaded() const override
+ {
+ return m_asset != nullptr;
+ }
+
+ BlastAsset* getAsset() const
+ {
+ return m_asset;
+ }
+
+ virtual PxTransform getInitialTransform() = 0;
+
+protected:
+ virtual BlastAsset* createAsset() = 0;
+
+private:
+ BlastAsset* m_asset;
+};
+
+
+class ModelSceneAsset : public SingleSceneAsset
+{
+public:
+ ModelSceneAsset() {}
+
+ virtual const char* getID() const override{ return desc.id.c_str(); }
+ virtual const char* getName() const override { return desc.name.c_str(); }
+
+ AssetList::ModelAsset desc;
+
+ virtual PxTransform getInitialTransform() { return desc.transform; }
+};
+
+
+class SimpleModelSceneAsset : public ModelSceneAsset
+{
+public:
+ virtual BlastAsset* createAsset()
+ {
+ return new BlastAssetModelSimple(m_scene->getBlastController().getTkFramework(), m_scene->getPhysXController().getPhysics(),
+ m_scene->getPhysXController().getCooking(), m_scene->getRenderer(), desc.file.c_str());
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return ImColor(255, 255, 200, 255);
+ }
+};
+
+
+class SkinnedModelSceneAsset : public ModelSceneAsset
+{
+public:
+ virtual BlastAsset* createAsset()
+ {
+ return new BlastAssetModelSkinned(m_scene->getBlastController().getTkFramework(), m_scene->getPhysXController().getPhysics(),
+ m_scene->getPhysXController().getCooking(), m_scene->getRenderer(), desc.file.c_str());
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return ImColor(255, 200, 255, 255);
+ }
+};
+
+
+class BoxesSceneAsset : public SingleSceneAsset
+{
+public:
+ BoxesSceneAsset(const AssetList::BoxAsset& d) : desc(d)
+ {
+ for (uint32_t lv = 0; lv < desc.levels.size(); ++lv)
+ {
+ const AssetList::BoxAsset::Level& level = desc.levels[lv];
+ NvBlastChunkDesc::Flags fl = (level.isSupport) ? NvBlastChunkDesc::Flags::SupportFlag : NvBlastChunkDesc::Flags::NoFlags;
+ assetDesc.generatorSettings.depths.push_back({ GeneratorAsset::Vec3(level.x, level.y, level.z), fl });
+ }
+ assetDesc.generatorSettings.extents = GeneratorAsset::Vec3(desc.extents.x, desc.extents.y, desc.extents.z);
+ assetDesc.staticHeight = desc.staticHeight;
+ assetDesc.jointAllBonds = desc.jointAllBonds;
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return ImColor(255, 200, 200, 255);
+ }
+
+ virtual const char* getID() const override { return desc.id.c_str(); }
+ virtual const char* getName() const override { return desc.name.c_str(); }
+
+
+ AssetList::BoxAsset desc;
+ BlastAssetBoxes::Desc assetDesc;
+
+ virtual BlastAsset* createAsset()
+ {
+ return new BlastAssetBoxes(m_scene->getBlastController().getTkFramework(), m_scene->getPhysXController().getPhysics(),
+ m_scene->getPhysXController().getCooking(), m_scene->getRenderer(), assetDesc);
+ }
+
+ virtual PxTransform getInitialTransform() { return PxTransform(PxVec3(0, assetDesc.generatorSettings.extents.y / 2, 0)); }
+};
+
+
+class CompositeSceneAsset : public SceneAsset
+{
+public:
+ CompositeSceneAsset(const AssetList::CompositeAsset& desc)
+ : m_desc(desc)
+ {
+ }
+
+ virtual ~CompositeSceneAsset() { unload(); }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return ImColor(200, 255, 255, 255);
+ }
+
+ virtual const char* getID() const override { return m_desc.id.c_str(); }
+ virtual const char* getName() const override { return m_desc.name.c_str(); }
+
+ virtual void spawn(PxVec3 shift) override;
+
+ virtual void load() override
+ {
+ if (!isLoaded())
+ {
+ // load dependent assets
+ for (const auto& assetRef : m_desc.assetRefs)
+ {
+ SceneAsset* asset = m_scene->findSceneAsset(assetRef.id);
+ if (asset)
+ {
+ asset->load();
+ m_sceneAssets.push_back(static_cast<SingleSceneAsset*>(asset));
+ }
+ else
+ {
+ m_scene->getCommonUIController().addPopupMessage("Error", "Wrong asset dependency on composite");
+ m_sceneAssets.clear();
+ return;
+ }
+ }
+
+ // check joints
+ for (const auto& joint : m_desc.joints)
+ {
+ bool ok = (joint.assetIndices[0] >= 0 || joint.assetIndices[1] >= 0);
+ for (char k = 0; k < 2 && ok; ++k)
+ {
+ if (joint.assetIndices[k] < 0)
+ continue;
+ ok &= (joint.assetIndices[k] < (int32_t)m_sceneAssets.size());
+ if (!ok)
+ break;
+ ok &= joint.chunkIndices[k] < m_sceneAssets[joint.assetIndices[k]]->getAsset()->getPxAsset()->getTkAsset().getChunkCount();
+ }
+ if (!ok)
+ {
+ m_scene->getCommonUIController().addPopupMessage("Error", "Wrong joint on composite");
+ m_sceneAssets.clear();
+ return;
+ }
+ }
+ }
+ }
+
+ virtual void unload() override
+ {
+ m_sceneAssets.clear();
+ }
+
+ virtual bool isLoaded() const override
+ {
+ return !m_sceneAssets.empty();
+ }
+
+ virtual PxTransform getInitialTransform()
+ {
+ return m_desc.transform;
+ }
+
+ const AssetList::CompositeAsset& getDesc() const
+ {
+ return m_desc;
+ }
+
+ const std::vector<SingleSceneAsset*>& getSceneAssets() const
+ {
+ return m_sceneAssets;
+ }
+
+private:
+ AssetList::CompositeAsset m_desc;
+ std::vector<SingleSceneAsset*> m_sceneAssets;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Scene Actors
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SingleSceneActor : public SceneActor
+{
+public:
+ SingleSceneActor(Scene& scene, SingleSceneAsset* asset, PxVec3 shift)
+ : m_scene(scene)
+ , m_asset(asset)
+ , m_shift(shift)
+ {
+ m_index = m_asset->spawnCount++;
+ spawn();
+ }
+
+ SingleSceneActor::~SingleSceneActor()
+ {
+ remove();
+ }
+
+ virtual const char* getName() const override
+ {
+ return m_name.c_str();
+ }
+
+ virtual const char* getSubname(int) const override
+ {
+ return nullptr;
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return m_asset->getUIColor();
+ }
+
+ virtual void drawUI(int) override
+ {
+ m_actor->drawUI();
+ }
+
+ virtual void drawStatsUI(int) override
+ {
+ m_actor->drawStatsUI();
+ }
+
+ virtual PxVec3 getSpawnShift() const override
+ {
+ return PxVec3(-20, 0, 0);
+ }
+
+ virtual void reload() override
+ {
+ auto settings = m_actor->getSettings();
+ remove();
+ spawn();
+ m_actor->setSettings(settings);
+ }
+
+private:
+ void remove()
+ {
+ m_scene.getBlastController().removeFamily(m_actor);
+ m_actor = nullptr;
+ }
+
+ void spawn()
+ {
+ std::ostringstream str;
+ str << m_asset->getName();
+ if (m_index)
+ str << " (" << m_index << ")";
+ m_name = str.str();
+
+ PxTransform pose = m_asset->getInitialTransform();
+ pose.p += m_shift;
+
+ BlastAsset::ActorDesc actorDesc = {
+ actorDesc.id = generateIDFromString(m_name.c_str()),
+ pose,
+ m_scene.getBlastController().getTkGroup()
+ };
+
+ m_actor = m_scene.getBlastController().spawnFamily(m_asset->getAsset(), actorDesc);
+ }
+
+ Scene& m_scene;
+ BlastFamilyPtr m_actor;
+ SingleSceneAsset* m_asset;
+ PxVec3 m_shift;
+ uint32_t m_index;
+ std::string m_name;
+};
+
+class CompositeSceneActor : public SceneActor
+{
+public:
+ CompositeSceneActor(Scene& scene, CompositeSceneAsset* asset, PxVec3 shift)
+ : m_scene(scene)
+ , m_asset(asset)
+ , m_shift(shift)
+ {
+ m_index = m_asset->spawnCount++;
+ spawn();
+ }
+
+ CompositeSceneActor::~CompositeSceneActor()
+ {
+ remove();
+ }
+
+ virtual uint32_t getSubactorCount() const
+ {
+ return (uint32_t)m_actors.size();
+ }
+
+ virtual const char* getName() const override
+ {
+ return m_name.c_str();
+ }
+
+ virtual const char* getSubname(int subindex) const override
+ {
+ return m_actors[subindex].name.c_str();
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return m_asset->getUIColor();
+ }
+
+ virtual void drawUI(int subindex) override
+ {
+ if (subindex >= 0)
+ {
+ m_actors[subindex].actor->drawUI();
+ }
+ else
+ {
+ ImGui::Text("Select subactor to edit settings.");
+ }
+ }
+
+ virtual void drawStatsUI(int subindex) override
+ {
+ if (subindex >= 0)
+ {
+ m_actors[subindex].actor->drawStatsUI();
+ }
+ }
+
+ virtual PxVec3 getSpawnShift() const override
+ {
+ return PxVec3(-20, 0, 0);
+ }
+
+ virtual void reload() override
+ {
+ std::map<uint32_t, BlastFamily::Settings> settings;
+ for (uint32_t i = 0; i < m_actors.size(); ++i)
+ {
+ settings[m_actors[i].initialIndex] = m_actors[i].actor->getSettings();
+ }
+ remove();
+ spawn();
+ for (uint32_t i = 0; i < m_actors.size(); ++i)
+ {
+ if (settings.find(i) != settings.end())
+ {
+ m_actors[i].actor->setSettings(settings[i]);
+ }
+ }
+ }
+
+ virtual void removeSubactor(int subindex)
+ {
+ if (subindex >= 0 && subindex < (int)m_actors.size())
+ {
+ m_scene.getBlastController().removeFamily(m_actors[subindex].actor);
+ m_actors[subindex] = m_actors.back();
+ m_actors.resize(m_actors.size() - 1);
+ }
+ }
+
+private:
+ void remove()
+ {
+ for (uint32_t i = 0; i < m_actors.size(); ++i)
+ {
+ m_scene.getBlastController().removeFamily(m_actors[i].actor);
+ }
+ m_actors.clear();
+ }
+
+ void spawn()
+ {
+ std::ostringstream str;
+ str << m_asset->getName();
+ if (m_index)
+ str << " (" << m_index << ")";
+ m_name = str.str();
+
+ const AssetList::CompositeAsset& assetDesc = m_asset->getDesc();
+ const std::vector<SingleSceneAsset*>& sceneAssets = m_asset->getSceneAssets();
+
+ const uint32_t actorCount = (uint32_t)sceneAssets.size();
+ m_actors.resize(actorCount);
+
+ for (uint32_t i = 0; i < actorCount; ++i)
+ {
+ std::ostringstream str;
+ str << " -> " << i << "." << sceneAssets[i]->getName();
+ m_actors[i].name = str.str();
+ }
+
+ ExtPxManager& pxManager = m_scene.getBlastController().getExtPxManager();
+ for (uint32_t i = 0; i < actorCount; ++i)
+ {
+ PxTransform pose = m_asset->getInitialTransform();
+ pose.p += m_shift;
+ pose = assetDesc.assetRefs[i].transform.transform(pose);
+
+ BlastAsset::ActorDesc actorDesc = {
+ generateIDFromString(m_actors[i].name.c_str()),
+ pose,
+ m_scene.getBlastController().getTkGroup()
+ };
+ m_actors[i].actor = m_scene.getBlastController().spawnFamily(sceneAssets[i]->getAsset(), actorDesc);
+ m_actors[i].initialIndex = i;
+ }
+
+ for (const auto& joint : assetDesc.joints)
+ {
+ TkJointDesc jointDesc;
+ for (char k = 0; k < 2; ++k)
+ {
+ jointDesc.attachPositions[k] = joint.attachPositions[k];
+ jointDesc.chunkIndices[k] = joint.chunkIndices[k];
+ jointDesc.families[k] = (joint.assetIndices[k] < 0) ? nullptr : &m_actors[joint.assetIndices[k]].actor->getFamily()->getTkFamily();
+ }
+ TkJoint* joint = pxManager.getFramework().createJoint(jointDesc);
+ if (joint)
+ {
+ pxManager.createJoint(*joint);
+ }
+ else
+ {
+ m_scene.getCommonUIController().addPopupMessage("Error", "Some joints can't be created");
+ }
+ }
+ }
+
+ struct Subactor
+ {
+ BlastFamilyPtr actor;
+ uint32_t initialIndex;
+ std::string name;
+ };
+
+ Scene& m_scene;
+ std::vector<Subactor> m_actors;
+ CompositeSceneAsset* m_asset;
+ PxVec3 m_shift;
+ uint32_t m_index;
+ std::string m_name;
+};
+
+class PhysXSceneActor : public SceneActor
+{
+public:
+ PhysXSceneActor(PhysXController& physXController, PhysXController::Actor* actor, const char* name)
+ : m_physXController(physXController)
+ , m_actor(actor)
+ , m_name(name)
+ {
+ }
+
+ PhysXSceneActor::~PhysXSceneActor()
+ {
+ m_physXController.removePhysXPrimitive(m_actor);
+ }
+
+ virtual const char* getName() const override
+ {
+ return m_name;
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return ImColor(255, 100, 100, 255);
+ }
+
+
+private:
+ PhysXController& m_physXController;
+ PhysXController::Actor* m_actor;
+ const char* m_name;
+
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Assets Implementation
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void SingleSceneAsset::spawn(PxVec3 shift)
+{
+ load();
+ SingleSceneActor* actor = new SingleSceneActor(*m_scene, this, shift);
+ m_scene->addSceneActor(actor);
+}
+
+void CompositeSceneAsset::spawn(PxVec3 shift)
+{
+ load();
+ if (isLoaded())
+ {
+ CompositeSceneActor* actor = new CompositeSceneActor(*m_scene, this, shift);
+ m_scene->addSceneActor(actor);
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PackmanConfigParser
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class PackmanConfigParser : public physx::shdfnd::FastXml::Callback
+{
+public:
+ std::vector<std::pair<std::string, std::string>> dependencies;
+
+protected:
+
+ // encountered a comment in the XML
+ virtual bool processComment(const char* /*comment*/)
+ {
+ return true;
+ }
+
+ virtual bool processClose(const char* elementName, unsigned int /*depth*/, bool& /*isError*/)
+ {
+ return true;
+ }
+
+ // return true to continue processing the XML document, false to skip.
+ virtual bool processElement(const char* elementName, // name of the element
+ const char* elementData, // element data, null if none
+ const physx::shdfnd::FastXml::AttributePairs& attr,
+ int /*lineno*/) // line number in the source XML file
+ {
+ if (::strcmp(elementName, "dependency") == 0)
+ {
+ dependencies.resize(dependencies.size() + 1);
+ for (int i = 0; i < attr.getNbAttr(); ++i)
+ {
+ if (::strcmp(attr.getKey(i), "name") == 0)
+ {
+ dependencies.back().first = std::string(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "version") == 0)
+ {
+ dependencies.back().second = std::string(attr.getValue(i));
+ }
+ }
+ }
+ return true;
+ }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Controller
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+SceneController::SceneController() : m_cubeScale(1.0f)
+{
+ m_scene = NULL;
+}
+
+SceneController::~SceneController()
+{
+}
+
+void SceneController::onSampleStart()
+{
+ // setup camera
+ CFirstPersonCamera* camera = &getRenderer().getCamera();
+ DirectX::XMVECTORF32 lookAtPt = { 0, 10, 0, 0 };
+ DirectX::XMVECTORF32 eyePt = { 0, 20, 60, 0 };
+ camera->SetViewParams(eyePt, lookAtPt);
+ camera->SetRotateButtons(false, false, true, false);
+ camera->SetEnablePositionMovement(true);
+
+ // setup scene
+ m_scene = new Scene(getRenderer(), getPhysXController(), getBlastController(), getCommonUIController());
+
+ const SampleConfig& config = getManager()->getConfig();
+
+ // add packman repo to search dirs
+ bool packmanResourcesAdded = false;
+ if (const char* packmanPath = std::getenv("PM_PACKAGES_ROOT"))
+ {
+ const char* RESOURCES_CONFIG_FILE = "resources.xml";
+
+ std::string path;
+ if (getRenderer().getResourceManager().findFile(RESOURCES_CONFIG_FILE, path))
+ {
+ physx::PsFileBuffer fileBuffer(path.c_str(), physx::general_PxIOStream2::PxFileBuf::OPEN_READ_ONLY);
+ if (fileBuffer.isOpen())
+ {
+ PxInputDataFromPxFileBuf inputData(fileBuffer);
+ PackmanConfigParser parser;
+ physx::shdfnd::FastXml* xml = physx::shdfnd::createFastXml(&parser);
+ xml->processXml(inputData, false);
+ xml->release();
+ for (auto& dep : parser.dependencies)
+ {
+ std::stringstream ss;
+ ss << packmanPath << "\\" << dep.first << "\\" << dep.second;
+ if (getRenderer().getResourceManager().addSearchDir(ss.str().c_str()))
+ {
+ packmanResourcesAdded = true;
+ }
+ }
+ }
+ }
+ }
+ if (!packmanResourcesAdded)
+ {
+ getManager()->getCommonUIController().addPopupMessage("Error", "BlastSampleResources package wasn't found. Consider running download_sample_resources.bat in root folder.", 5.0f);
+ }
+
+ // parse asset file
+ AssetList assetList;
+ if (!config.assetsFile.empty())
+ {
+ std::string path;
+ if (getRenderer().getResourceManager().findFile(config.assetsFile, path))
+ {
+ parseAssetList(assetList, path);
+ }
+ }
+
+ // add both asset file and asset list from config
+ addAssets(config.additionalAssetList, packmanResourcesAdded);
+ addAssets(assetList, packmanResourcesAdded);
+
+// Add By Lixu Begin
+ int size = m_scene->getAssets().size();
+ for (int i = 0; i < size; i++)
+ {
+ spawnAsset(i);
+ }
+// Add By Lixu End
+}
+
+void SceneController::addAssets(const AssetList& assetList, bool loadModels)
+{
+ if (loadModels)
+ {
+ for (const auto& model : assetList.models)
+ {
+ ModelSceneAsset* asset;
+ if (!model.isSkinned)
+ {
+ asset = new SimpleModelSceneAsset();
+ }
+ else
+ {
+ asset = new SkinnedModelSceneAsset();
+ }
+ asset->desc = model;
+ m_scene->addAsset(asset);
+ }
+
+ for (const auto& composite : assetList.composites)
+ {
+ m_scene->addAsset(new CompositeSceneAsset(composite));
+ }
+ }
+
+ for (const auto& box : assetList.boxes)
+ {
+ BoxesSceneAsset* asset = new BoxesSceneAsset(box);
+ m_scene->addAsset(asset);
+ }
+}
+
+void SceneController::onInitialize()
+{
+
+}
+
+void SceneController::onSampleStop()
+{
+ if (NULL != m_scene)
+ {
+ delete m_scene;
+ m_scene = nullptr;
+ }
+}
+
+void SceneController::onTerminate()
+{
+}
+
+void SceneController::Animate(double dt)
+{
+}
+
+LRESULT SceneController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (uMsg == WM_KEYDOWN)
+ {
+ int iKeyPressed = static_cast<int>(wParam);
+ switch (iKeyPressed)
+ {
+ case 'R':
+ m_scene->reloadAllActors();
+ return 0;
+ case 'F':
+ throwCube();
+ return 0;
+ default:
+ break;
+ }
+ }
+
+ return 1;
+}
+
+void SceneController::drawUI()
+{
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Scene UI
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ m_scene->drawUI();
+
+
+ ImGui::Spacing();
+ ImGui::Spacing();
+ ImGui::Separator();
+ ImGui::Spacing();
+ ImGui::Spacing();
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Replay
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ ImGui::Text("Replay Control:");
+
+ BlastReplay* replay = getBlastController().getReplay();
+ if (replay->isRecording())
+ {
+ auto getAnimStr = []()
+ {
+ const uint32_t count = 5;
+ const uint64_t periodMS = 150;
+ static char str[count + 1] = "";
+ for (uint32_t i = 0; i < count; i++)
+ {
+ uint64_t ts = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
+ str[i] = (i == (ts % (periodMS * count)) / periodMS) ? '*' : ' ';
+ }
+ return str;
+ };
+ ImGui::Text("State: Recording [%s] | Events: %d", getAnimStr(), replay->getEventCount());
+
+ if (ImGui::Button("Stop Recording"))
+ {
+ replay->stopRecording();
+ }
+ }
+ else if (replay->isPlaying())
+ {
+ ImGui::Text("State: Playing | Events: %d / %d", replay->getCurrentEventIndex(), replay->getEventCount());
+
+ if (ImGui::Button("Stop Playing"))
+ {
+ replay->stopPlayback();
+ }
+ }
+ else
+ {
+ ImGui::Text("State: Idle | Events: %d", replay->getEventCount());
+
+ static bool syncFamilies = true;
+ static bool syncPhysics = true;
+
+ ImGui::Checkbox("Sync Initial Actors", &syncFamilies);
+ if (ImGui::Checkbox("Sync Initial Transforms", &syncPhysics))
+ {
+ syncFamilies = syncPhysics;
+ }
+
+ if (ImGui::Button("Start Recording"))
+ {
+ replay->startRecording(getBlastController().getExtPxManager(), syncFamilies, syncPhysics);
+ }
+
+ if (replay->hasRecord())
+ {
+ static bool reload = false;
+ if (ImGui::Button("Start Playback"))
+ {
+ if (reload)
+ m_scene->reloadAllActors();
+ replay->startPlayback(getBlastController().getExtPxManager(), getBlastController().getTkGroup());
+ }
+ ImGui::SameLine();
+ ImGui::Checkbox("Reload Scene On Playback", &reload);
+ }
+ }
+ }
+
+ ImGui::Spacing();
+ ImGui::Spacing();
+ ImGui::Separator();
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Cube
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ ImGui::Text("Thrown Cube Params (F)");
+ ImGui::DragFloat("Cube Size", &m_cubeScale, 1.0f, 0.0f, 100.0f);
+ }
+
+}
+
+void SceneController::drawStatsUI()
+{
+ m_scene->drawStatsUI();
+}
+
+void SceneController::throwCube()
+{
+ const float CUBE_VELOCITY = 100;
+ const float CUBE_DENSITY = 20000.0f;
+
+ CFirstPersonCamera* camera = &getRenderer().getCamera();
+ PxVec3 eyePos = XMVECTORToPxVec4(camera->GetEyePt()).getXYZ();
+ PxVec3 lookAtPos = XMVECTORToPxVec4(camera->GetLookAtPt()).getXYZ();
+ PhysXController::Actor* cube = getPhysXController().spawnPhysXPrimitiveBox(PxTransform(eyePos), PxVec3(m_cubeScale, m_cubeScale, m_cubeScale), CUBE_DENSITY);
+ PxRigidDynamic* rigidDynamic = cube->getActor()->is<PxRigidDynamic>();
+ cube->setColor(DirectX::XMFLOAT4(1, 0, 0, 1));
+
+ PxVec3 dir = (lookAtPos - eyePos).getNormalized();
+ rigidDynamic->setLinearVelocity(dir * CUBE_VELOCITY);
+
+// Add By Lixu Begin
+ std::string validname = "";
+ if (m_ReusedNames.size() > 0)
+ {
+ validname = m_ReusedNames.back();
+ m_ReusedNames.pop_back();
+ }
+ else
+ {
+ int projectilesSize = m_Projectiles.size();
+ char cubename[10];
+ sprintf(cubename, "Cube_%d", projectilesSize);
+ validname = cubename;
+ }
+ cube->setColor(DirectX::XMFLOAT4(1, 1, 1, 1));
+ PhysXSceneActor* p = new PhysXSceneActor(getPhysXController(), cube, validname.c_str());
+ m_UsedNames.push_back(validname);
+ m_Projectiles.push_back(p);
+ m_scene->addSceneActor(p);
+
+ getManager()->m_bNeedRefreshTree = true;
+// Add By Lixu End
+}
+
+void SceneController::spawnAsset(int32_t num)
+{
+ m_scene->spawnAsset(num);
+}
+
+int SceneController::releaseAll()
+{
+ return m_scene->releaseAll();
+}
+
+// Add By Lixu Begin
+void SceneController::addProjectile()
+{
+ throwCube();
+}
+
+void SceneController::clearProjectile()
+{
+ std::vector<PhysXSceneActor*>::iterator it;
+ for (it = m_Projectiles.begin(); it != m_Projectiles.end(); it++)
+ {
+ std::vector<SceneActor*>& actors = m_scene->getActors();
+ std::map<SceneActor*, int> ActorIndexMap;
+ int actorSize = actors.size();
+ for (int i = 0; i < actorSize; i++)
+ {
+ ActorIndexMap[actors[i]] = i;
+ }
+
+ m_scene->removeSceneActor(Scene::ActorIndex(ActorIndexMap[*it], -1));
+ }
+ m_Projectiles.clear();
+ m_UsedNames.clear();
+ m_ReusedNames.clear();
+}
+
+void SceneController::ResetScene()
+{
+ clearProjectile();
+ m_scene->reloadAllActors();
+ getManager()->m_bNeedRefreshTree = true;
+}
+
+void SceneController::ClearScene()
+{
+ clearProjectile();
+ m_scene->releaseAll();
+ // Add By Lixu Begin
+ PhysXController& pc = getPhysXController();
+ pc.ClearOldCOllisions();
+ // Add By Lixu End
+}
+
+bool SceneController::GetAssetDesc(const BlastAsset* asset, AssetList::ModelAsset& desc)
+{
+ SampleManager* pSampleManager = getManager();
+ SampleConfig* config = (SampleConfig*)&(pSampleManager->getConfig());
+ std::vector<AssetList::ModelAsset>& modelAssets = config->additionalAssetList.models;
+ std::vector<AssetList::ModelAsset>::iterator itModelAssets;
+ std::vector<SceneAsset*>& sceneAssets = m_scene->getAssets();
+ std::vector<SceneAsset*>::iterator itSceneAssets;
+
+ bool find = false;
+ for (itSceneAssets = sceneAssets.begin(); itSceneAssets != sceneAssets.end(); itSceneAssets++)
+ {
+ SceneAsset* sceneAsset = *itSceneAssets;
+ std::string id = sceneAsset->getID();
+ for (itModelAssets = modelAssets.begin(); itModelAssets != modelAssets.end(); itModelAssets++)
+ {
+ AssetList::ModelAsset& modelAsset = *itModelAssets;
+ if (modelAsset.id == id)
+ {
+ if (!modelAsset.isSkinned)
+ {
+ SimpleModelSceneAsset* pSimpleModelSceneAsset = (SimpleModelSceneAsset*)sceneAsset;
+ if (pSimpleModelSceneAsset->getAsset() == asset)
+ {
+ desc = modelAsset;
+ find = true;
+ break;
+ }
+ }
+ else
+ {
+ SkinnedModelSceneAsset* pSkinnedModelSceneAsset = (SkinnedModelSceneAsset*)sceneAsset;
+ if (pSkinnedModelSceneAsset->getAsset() == asset)
+ {
+ desc = modelAsset;
+ find = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (find)
+ {
+ break;
+ }
+ }
+
+ return find;
+}
+
+void SceneController::GetProjectilesNames(std::vector<std::string>& projectilesNames)
+{
+ projectilesNames.clear();
+ std::vector<std::string>::iterator it = m_UsedNames.begin();
+ for (; it != m_UsedNames.end(); it++)
+ {
+ projectilesNames.push_back(*it);
+ }
+}
+// Add By Lixu End \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.h
new file mode 100644
index 0000000..82f08d8
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.h
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SCENE_CONTROLLER_H
+#define SCENE_CONTROLLER_H
+
+#include "SampleManager.h"
+#include <map>
+
+
+class CFirstPersonCamera;
+class BlastAssetBoxes;
+class SceneActor;
+class BlastAsset;
+class SingleSceneAsset;
+class Scene;
+// Add By Lixu Begin
+class PhysXSceneActor;
+// Add By Lixu End
+class SceneController : public ISampleController
+{
+public:
+
+ SceneController();
+ virtual ~SceneController();
+
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Animate(double dt);
+ void drawUI();
+ void drawStatsUI();
+
+ virtual void onInitialize();
+ virtual void onSampleStart();
+ virtual void onSampleStop();
+ virtual void onTerminate();
+
+ // commands
+ int releaseAll();
+ void spawnAsset(int32_t);
+
+// Add By Lixu Begin
+ void addProjectile();
+ void clearProjectile();
+ void ResetScene();
+ void ClearScene();
+ bool GetAssetDesc(const BlastAsset* asset, AssetList::ModelAsset& desc);
+ void GetProjectilesNames(std::vector<std::string>& projectilesNames);
+// Add By Lixu End
+
+private:
+ void addAssets(const AssetList& assetList, bool loadModels = true);
+ void throwCube();
+
+ SceneController& operator= (SceneController&);
+
+ //////// used controllers ////////
+
+ Renderer& getRenderer() const
+ {
+ return getManager()->getRenderer();
+ }
+
+ PhysXController& getPhysXController() const
+ {
+ return getManager()->getPhysXController();
+ }
+
+ BlastController& getBlastController() const
+ {
+ return getManager()->getBlastController();
+ }
+
+ CommonUIController& getCommonUIController() const
+ {
+ return getManager()->getCommonUIController();
+ }
+
+
+ //////// internal data ////////
+
+ Scene* m_scene;
+
+ float m_cubeScale;
+
+// Add By Lixu Begin
+ std::vector<std::string> m_UsedNames;
+ std::vector<std::string> m_ReusedNames;
+ std::vector<PhysXSceneActor*> m_Projectiles;
+// Add By Lixu End
+};
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/CommonUIController.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/CommonUIController.cpp
new file mode 100644
index 0000000..e56a124
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/CommonUIController.cpp
@@ -0,0 +1,621 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "CommonUIController.h"
+
+#include "Renderer.h"
+#include "BlastController.h"
+#include "DamageToolController.h"
+#include "SceneController.h"
+#include "SampleController.h"
+#include "PhysXController.h"
+#include "SampleProfiler.h"
+
+#include "PxVisualizationParameter.h"
+#include "PxScene.h"
+
+#include <imgui.h>
+#include "imgui_impl_dx11.h"
+#include "UIHelpers.h"
+
+#include <cstdio>
+#include <inttypes.h>
+
+
+inline float memorySizeOutput(const char*& prefix, float value)
+{
+ for (prefix = "\0\0k\0M\0G\0T\0P\0E"; value >= 1024 && *prefix != 'E'; value /= 1024, prefix += 2);
+ return value;
+}
+
+CommonUIController::CommonUIController()
+{
+}
+
+HRESULT CommonUIController::DeviceCreated(ID3D11Device* pDevice)
+{
+ DeviceManager* manager = GetDeviceManager();
+ ID3D11DeviceContext* pd3dDeviceContext;
+ pDevice->GetImmediateContext(&pd3dDeviceContext);
+ ImGui_ImplDX11_Init(manager->GetHWND(), pDevice, pd3dDeviceContext);
+
+ ImGuiStyle& style = ImGui::GetStyle();
+ style.WindowRounding = 8.0f;
+ style.ScrollbarRounding = 8.0f;
+ style.FrameRounding = 8.0f;
+ //style.IndentSpacing = 20;
+ int mainColor[3] = { 110, 110, 110 }; // previous green one { 50, 110, 30 }
+ style.Colors[ImGuiCol_TitleBg] = ImColor(mainColor[0], mainColor[1], mainColor[2], 62);
+ style.Colors[ImGuiCol_TitleBgCollapsed] = ImColor(mainColor[0], mainColor[1], mainColor[2], 52);
+ style.Colors[ImGuiCol_TitleBgActive] = ImColor(mainColor[0], mainColor[1], mainColor[2], 87);
+ style.Colors[ImGuiCol_Header] = ImColor(mainColor[0], mainColor[1], mainColor[2], 52);
+ style.Colors[ImGuiCol_HeaderHovered] = ImColor(mainColor[0], mainColor[1], mainColor[2], 92);
+ style.Colors[ImGuiCol_HeaderActive] = ImColor(mainColor[0], mainColor[1], mainColor[2], 72);
+ style.Colors[ImGuiCol_ScrollbarBg] = ImColor(mainColor[0], mainColor[1], mainColor[2], 12);
+ style.Colors[ImGuiCol_ScrollbarGrab] = ImColor(mainColor[0], mainColor[1], mainColor[2], 52);
+ style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImColor(mainColor[0], mainColor[1], mainColor[2], 92);
+ style.Colors[ImGuiCol_ScrollbarGrabActive] = ImColor(mainColor[0], mainColor[1], mainColor[2], 72);
+ style.Colors[ImGuiCol_Button] = ImColor(40, 100, 80, 30);
+ style.Colors[ImGuiCol_ButtonHovered] = ImColor(40, 100, 80, 100);
+ style.Colors[ImGuiCol_ButtonActive] = ImColor(40, 100, 80, 70);
+ style.Colors[ImGuiCol_PopupBg] = ImColor(10, 23, 18, 230);
+ style.Colors[ImGuiCol_TextSelectedBg] = ImColor(10, 23, 18, 180);
+ style.Colors[ImGuiCol_FrameBg] = ImColor(70, 70, 70, 30);
+ style.Colors[ImGuiCol_FrameBgHovered] = ImColor(70, 70, 70, 70);
+ style.Colors[ImGuiCol_FrameBgActive] = ImColor(70, 70, 70, 50);
+ style.Colors[ImGuiCol_ComboBg] = ImColor(20, 20, 20, 252);
+
+ return S_OK;
+}
+
+void CommonUIController::DeviceDestroyed()
+{
+ ImGui_ImplDX11_Shutdown();
+}
+
+extern LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+LRESULT CommonUIController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ PX_UNUSED(hWnd);
+ PX_UNUSED(wParam);
+ PX_UNUSED(lParam);
+
+ ImGui_ImplDX11_WndProcHandler(hWnd, uMsg, wParam, lParam);
+
+ if (uMsg == WM_KEYDOWN && !ImGui::GetIO().WantCaptureKeyboard)
+ {
+ int iKeyPressed = static_cast<int>(wParam);
+ switch (iKeyPressed)
+ {
+ case 'P':
+ {
+ getPhysXController().setPaused(!getPhysXController().isPaused());
+ break;
+ }
+ case 'O':
+ {
+ getRenderer().setWireframeMode(!getRenderer().getWireframeMode());
+ break;
+ }
+ case 'I':
+ {
+ getBlastController().debugRenderMode = (BlastFamily::DebugRenderMode)(((int)getBlastController().debugRenderMode + 1) % BlastFamily::DebugRenderMode::DEBUG_RENDER_MODES_COUNT);
+ break;
+ }
+ case VK_F5:
+ {
+ getRenderer().reloadShaders();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (ImGui::GetIO().WantCaptureMouse)
+ return 0;
+
+ return 1;
+}
+
+void CommonUIController::Animate(double fElapsedTimeSeconds)
+{
+ m_dt = (float)fElapsedTimeSeconds;
+}
+
+void CommonUIController::Render(ID3D11Device*, ID3D11DeviceContext*, ID3D11RenderTargetView*, ID3D11DepthStencilView*)
+{
+ ImGui_ImplDX11_NewFrame();
+ drawUI();
+ ImGui::Render();
+}
+
+void CommonUIController::addDelayedCall(const char* title, const char* message, std::function<void()> func, float delay)
+{
+ DelayedCall call = { func, title, message, delay, delay };
+ m_delayedCalls.emplace(call);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// IMGUI UI
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void CommonUIController::drawUI()
+{
+ const float padding = 8.0f;
+ ImGui::SetNextWindowPos(ImVec2(padding, padding), ImGuiSetCond_Once/*ImGuiSetCond_FirstUseEver*/);
+ ImGui::SetNextWindowSize(ImVec2(420, getRenderer().getScreenHeight() - 2 * padding), ImGuiSetCond_Once/*ImGuiSetCond_FirstUseEver*/);
+ ImGui::SetNextWindowCollapsed(false, ImGuiSetCond_Once);
+ ImGui::Begin("New Shiny UI", 0, ImGuiWindowFlags_NoTitleBar);
+ {
+ ImGui::PushItemWidth(ImGui::GetWindowSize().x * 0.5f);
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Scene
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ if (ImGui::CollapsingHeader("Scene"))
+ {
+ getSceneController().drawUI();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Blast
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ if (ImGui::CollapsingHeader("Blast"))
+ {
+ getBlastController().drawUI();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Damage Tool
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ if (ImGui::CollapsingHeader("Damage Tool"))
+ {
+ getDamageToolController().drawUI();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Stats
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ if (ImGui::CollapsingHeader("Stats"))
+ {
+ BlastController& blastController = getBlastController();
+
+ const char* prefix;
+ float sizeVal;
+
+ // FPS
+ double averageTime = GetDeviceManager()->GetAverageFrameTime();
+ float fps = (averageTime > 0) ? 1.0 / averageTime : 0.0;
+ float frameMs = 1000.0f / fps;
+ ImGui::Text("Frame Time %.3f ms (%.1f FPS)", frameMs, fps);
+
+ static PlotLinesInstance<> fpsPlot;
+ fpsPlot.plot("FPS", frameMs, "ms/frame", 0.0f, 100.0f);
+
+ // Render stats
+ ImGui::PushStyleColor(ImGuiCol_Text, ImColor(0xFF, 0x3B, 0xD8, 0xFF));
+ ImGui::Text("Draw Calls (Opaque/Transparent): %d/%d", getRenderer().getVisibleOpaqueRenderablesCount(), getRenderer().getVisibleTransparentRenderablesCount());
+ ImGui::PopStyleColor();
+
+ // Blast stats
+ const BlastTimers& timers = blastController.getLastBlastTimers();
+
+ ImGui::Text("Simulation Time: %.2f ms ", getPhysXController().getLastSimulationTime() * 1000);
+ ImGui::Text("Actor Count: %d", blastController.getActorCount());
+ ImGui::Text("Visible Chunk Count: %d", blastController.getTotalVisibleChunkCount());
+
+ getManager()->getSceneController().drawStatsUI();
+
+ sizeVal = memorySizeOutput(prefix, (float)blastController.getFamilySize());
+ ImGui::Text("Family Size: %.3g %sB", sizeVal, prefix);
+ sizeVal = memorySizeOutput(prefix, (float)blastController.getBlastAssetsSize());
+ ImGui::Text("Blast asset Data size: %.3g %sB", sizeVal, prefix);
+
+ //ImGui::Text(" Last Blast Extern Time: %8.3f ms", timers.mLastExternalTime * 1000);
+// ImGui::Text(" Last Damage Time: %8.3f ms", timers.blastDamage * 1000);
+#if NV_PROFILE
+ ImGui::Text("Last Material Time: %8.3f ms", timers.blastDamageMaterial * 1000);
+ ImGui::Text("Last Fracture Time: %8.3f ms", timers.blastDamageFracture * 1000);
+#endif
+// ImGui::Text("Last Physics Split Time: %.3f ms", timers.physicsSplit * 1000);
+#if NV_PROFILE
+ ImGui::Text("Last Island Time: %8.3f ms", timers.blastSplitIsland * 1000);
+ ImGui::Text("Last Partition Time: %8.3f ms", timers.blastSplitPartition * 1000);
+ ImGui::Text("Last Visibility Time: %8.3f ms", timers.blastSplitVisibility * 1000);
+#endif
+
+#if NV_PROFILE
+ // Sample Profiler
+ static bool s_showProfilerWindow = false;
+ if (ImGui::Button("Code Profiler"))
+ {
+ s_showProfilerWindow = !s_showProfilerWindow;
+ }
+ if (s_showProfilerWindow)
+ {
+ drawCodeProfiler(&s_showProfilerWindow);
+ }
+#endif
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Application
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ if (ImGui::CollapsingHeader("Application"))
+ {
+ // Paused
+ bool isPaused = getPhysXController().isPaused();
+ if (ImGui::Checkbox("Pause (P)", &isPaused))
+ {
+ getPhysXController().setPaused(isPaused);
+ }
+
+ // Reload Shaders
+ if (ImGui::Button("Reload Shaders (F5)"))
+ {
+ getRenderer().reloadShaders();
+ }
+
+ // ImGui Test Window (just in case)
+ static bool s_showTestWindow = false;
+ if (ImGui::Button("ImGui Test Window"))
+ {
+ s_showTestWindow = !s_showTestWindow;
+ }
+ if (s_showTestWindow)
+ {
+ ImGui::ShowTestWindow();
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Debug Render
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ if (ImGui::CollapsingHeader("Debug Render"))
+ {
+ // WireFrame
+ bool wireFrameEnabled = getRenderer().getWireframeMode();
+ if (ImGui::Checkbox("WireFrame (O)", &wireFrameEnabled))
+ {
+ getRenderer().setWireframeMode(wireFrameEnabled);
+ }
+
+ // - - - - - - - -
+ ImGui::Spacing();
+
+ // Blast Debug Render Mode
+ const char* debugRenderItems[] =
+ {
+ "Disabled", // DEBUG_RENDER_DISABLED
+ "Health Graph", // DEBUG_RENDER_HEALTH_GRAPH
+ "Centroids", // DEBUG_RENDER_CENTROIDS
+ "Health Graph + Centroids", // DEBUG_RENDER_HEALTH_GRAPH_CENTROIDS
+ "Joints", // DEBUG_RENDER_JOINTS
+ "Stress Graph", // DEBUG_RENDER_STRESS_GRAPH
+ "Stress Graph + Nodes Impulses", // DEBUG_RENDER_STRESS_GRAPH_NODES_IMPULSES
+ "Stress Graph + Bonds Impulses" // DEBUG_RENDER_STRESS_GRAPH_BONDS_IMPULSES
+ };
+ ImGui::Combo("Blast Debug Render Mode (I)", (int*)&getBlastController().debugRenderMode, debugRenderItems, IM_ARRAYSIZE(debugRenderItems), -1);
+
+ // Blast Debug Render Scale
+ ImGui::DragFloat("Blast Debug Render Scale", &getBlastController().debugRenderScale, 0.01f, 0.0f, 10.0f, "%.3f", 4.0f);
+
+ // - - - - - - - -
+ ImGui::Spacing();
+
+ // PhysX Debug Render
+ if (ImGui::TreeNode("PhysX Debug Render"))
+ {
+ auto addParam = [&](physx::PxVisualizationParameter::Enum param, const char* uiName)
+ {
+ bool enabled = getPhysXController().getPhysXScene().getVisualizationParameter(param) != 0;
+ if (ImGui::Checkbox(uiName, &enabled))
+ {
+ getPhysXController().getPhysXScene().setVisualizationParameter(param, enabled ? 1.0f : 0.0f);
+ }
+ };
+
+ addParam(PxVisualizationParameter::eSCALE, "Scale");
+ addParam(PxVisualizationParameter::eBODY_AXES, "Body Axes");
+ addParam(PxVisualizationParameter::eWORLD_AXES, "World Axes");
+ addParam(PxVisualizationParameter::eBODY_MASS_AXES, "Body Mass Axes");
+ addParam(PxVisualizationParameter::eBODY_LIN_VELOCITY, "Body Lin Velocity");
+ addParam(PxVisualizationParameter::eBODY_ANG_VELOCITY, "Body Ang Velocity");
+ addParam(PxVisualizationParameter::eBODY_JOINT_GROUPS, "Body Joint");
+ addParam(PxVisualizationParameter::eCONTACT_POINT, "Contact Point");
+ addParam(PxVisualizationParameter::eCONTACT_NORMAL, "Contact Normal");
+ addParam(PxVisualizationParameter::eCONTACT_ERROR, "Contact Error");
+ addParam(PxVisualizationParameter::eCONTACT_FORCE, "Contact Force");
+ addParam(PxVisualizationParameter::eACTOR_AXES, "Actor Axes");
+ addParam(PxVisualizationParameter::eCOLLISION_AABBS, "Collision AABBs");
+ addParam(PxVisualizationParameter::eCOLLISION_SHAPES, "Collision Shapes");
+ addParam(PxVisualizationParameter::eCOLLISION_AXES, "Collision Axes");
+ addParam(PxVisualizationParameter::eCOLLISION_COMPOUNDS, "Collision Compounds");
+ addParam(PxVisualizationParameter::eCOLLISION_FNORMALS, "Collision FNormals");
+ addParam(PxVisualizationParameter::eCOLLISION_EDGES, "Collision Edges");
+ addParam(PxVisualizationParameter::eCOLLISION_STATIC, "Collision Static");
+ addParam(PxVisualizationParameter::eCOLLISION_DYNAMIC, "Collision Dynamic");
+ //addParam(PxVisualizationParameter::eDEPRECATED_COLLISION_PAIRS, "Collision Pairs");
+ addParam(PxVisualizationParameter::eJOINT_LOCAL_FRAMES, "Joint Local Frames");
+ addParam(PxVisualizationParameter::eJOINT_LIMITS, "Joint Limits");
+ //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_POSITION, "PS Position");
+ //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_VELOCITY, "PS Velocity");
+ //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_COLLISION_NORMAL, "PS Collision Normal");
+ //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_BOUNDS, "PS Bounds");
+ //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_GRID, "PS Grid");
+ //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_BROADPHASE_BOUNDS, "PS Broadphase Bounds");
+ //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_MAX_MOTION_DISTANCE, "PS Max Motion Distance");
+ addParam(PxVisualizationParameter::eCULL_BOX, "Cull Box");
+ //addParam(PxVisualizationParameter::eCLOTH_VERTICAL, "Cloth Vertical");
+ //addParam(PxVisualizationParameter::eCLOTH_HORIZONTAL, "Cloth Horizontal");
+ //addParam(PxVisualizationParameter::eCLOTH_BENDING, "Cloth Bending");
+ //addParam(PxVisualizationParameter::eCLOTH_SHEARING, "Cloth Shearing");
+ //addParam(PxVisualizationParameter::eCLOTH_VIRTUAL_PARTICLES, "Cloth Virtual Particles");
+ addParam(PxVisualizationParameter::eMBP_REGIONS, "MBP Regions");
+
+ ImGui::TreePop();
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // PhysX
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ if (ImGui::CollapsingHeader("PhysX"))
+ {
+ // PhysX
+ getPhysXController().drawUI();
+
+ // GPU
+ getSampleController().drawPhysXGpuUI();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Renderer
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ if (ImGui::CollapsingHeader("Renderer"))
+ {
+ getRenderer().drawUI();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Hints
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ if (ImGui::CollapsingHeader("Hints / Help"))
+ {
+ ImGui::BulletText("Rotate camera - RMB");
+ ImGui::BulletText("Move camera - WASDQE(SHIFT)");
+ ImGui::BulletText("Play/Pause - P");
+ ImGui::BulletText("Reload shaders - F5");
+ ImGui::BulletText("Wireframe - O");
+ ImGui::BulletText("Blast Debug Render - I");
+ ImGui::BulletText("Apply damage - LMB");
+ ImGui::BulletText("Damage radius - +/-/wheel");
+ ImGui::BulletText("Damage profile - 1-9");
+ ImGui::BulletText("Explosive - X");
+ ImGui::BulletText("Throw cube - F");
+ ImGui::BulletText("Restart - R");
+ }
+
+ ImGui::PopItemWidth();
+ }
+ ImGui::End();
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Mode Text
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4());
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0,0));
+
+ const char* text = getDamageToolController().isDamageMode() ? "DAMAGE MODE (PRESS SPACE)" : "DRAG MODE (PRESS SPACE)";
+ ImVec2 size = ImGui::CalcTextSize(text);
+ ImGui::SetNextWindowPos(ImVec2((getRenderer().getScreenWidth() - size.x) / 2, 0));
+ ImGui::Begin("Mode Text", 0, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar);
+ ImGui::Text(text);
+ ImGui::End();
+
+ ImGui::PopStyleVar();
+ ImGui::PopStyleColor();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // FPS
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4());
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
+
+ double averageTime = GetDeviceManager()->GetAverageFrameTime();
+ float fps = (averageTime > 0) ? 1.0 / averageTime : 0.0;
+ static char buf[32];
+ std::sprintf(buf, "%.1f FPS", fps);
+ ImVec2 size = ImGui::CalcTextSize(buf);
+
+ size.x += 20.0;
+ ImGui::SetNextWindowSize(size);
+ ImGui::SetNextWindowPos(ImVec2(getRenderer().getScreenWidth() - size.x, 0));
+ ImGui::Begin("FPS", 0, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar);
+ ImGui::Text(buf);
+ ImGui::End();
+
+ ImGui::PopStyleVar();
+ ImGui::PopStyleColor();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Loading overlay
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ if (!m_delayedCalls.empty())
+ {
+ DelayedCall& call = m_delayedCalls.front();
+ if (call.delay > 0)
+ {
+ const int height = 50;
+ const char* message = call.message;
+ const float alpha = PxClamp(lerp(0.0f, 1.0f, (call.delayTotal - call.delay) * 10.0f), 0.0f, 1.0f);
+
+ ImGui::PushStyleColor(ImGuiCol_WindowBg, ImColor(0, 0, 0, 200));
+ ImGui::PushStyleVar(ImGuiStyleVar_Alpha, alpha);
+ ImGui::SetNextWindowPosCenter();
+ ImVec2 size = ImGui::CalcTextSize(message);
+ int width = std::max<float>(200, size.x) + 50;
+ ImGui::SetNextWindowSize(ImVec2(width, height));
+ ImGui::Begin(call.title, 0, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar);
+ ImGui::SetCursorPos(ImVec2((width - size.x) * 0.5f, (height - size.y) * 0.5f));
+ ImGui::Text(message);
+ ImGui::End();
+ ImGui::PopStyleVar();
+ ImGui::PopStyleColor();
+
+ call.delay -= PxClamp(m_dt, 0.0f, 0.1f);
+ }
+ else
+ {
+ call.func();
+ m_delayedCalls.pop();
+ }
+ }
+}
+
+
+void CommonUIController::drawCodeProfiler(bool* open)
+{
+ ImGuiWindowFlags window_flags = 0;
+ const float padding = 8.0f;
+ const float width = 550;
+ const float height = 580;
+ ImGui::SetNextWindowPos(ImVec2(getRenderer().getScreenWidth() - width - padding, padding), ImGuiSetCond_Once/*ImGuiSetCond_FirstUseEver*/);
+ ImGui::SetNextWindowSize(ImVec2(width, height), ImGuiSetCond_Once);
+ if (!ImGui::Begin("Code Profiler", open, window_flags))
+ {
+ // Early out if the window is collapsed, as an optimization.
+ ImGui::End();
+ return;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Control/Main Bar
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ if (ImGui::Button("Reset"))
+ {
+ PROFILER_INIT();
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("Dump To File (profile.txt)"))
+ {
+ SampleProfilerDumpToFile("profile.txt");
+ }
+ ImGui::SameLine();
+ ImGui::Text("Profiler overhead: %2.3f ms", SampleProfilerGetOverhead().count() * 0.001f);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Legend
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing();
+ ImGui::Text("Legend: name | calls | time | max time");
+ ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Stats Tree
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ ImGui::SetNextTreeNodeOpen(true, ImGuiSetCond_Once);
+ float plotMS = 0.0f;
+ float plotMaxMS = 0.0f;
+ const char* plotName = nullptr;
+ if (ImGui::TreeNode("Root"))
+ {
+ auto treeIt = SampleProfilerCreateTreeIterator();
+ if (treeIt)
+ {
+ uint32_t depth = 1;
+ uint32_t openeDepth = 1;
+ while (!treeIt->isDone())
+ {
+ const auto data = treeIt->data();
+
+ while (data->depth < depth)
+ {
+ ImGui::TreePop();
+ depth--;
+ }
+
+ const uint32_t maxLen = 30;
+ auto hash = data->hash;
+ static uint64_t selectedNodeHash = 0;
+ if (selectedNodeHash == hash)
+ {
+ plotMS = data->time.count() * 0.001f;
+ plotMaxMS = data->maxTime.count() * 0.001f;
+ plotName = data->name;
+ }
+ if (ImGui::TreeNodeEx(data->name, data->hasChilds ? 0 : ImGuiTreeNodeFlags_Leaf, "%-*.*s | %d | %2.3f ms | %2.3f ms",
+ maxLen, maxLen, data->name, data->calls, data->time.count() * 0.001f, data->maxTime.count() * 0.001f))
+ {
+ depth++;
+ treeIt->next();
+ }
+ else
+ {
+ treeIt->next();
+ while (!treeIt->isDone() && treeIt->data()->depth > depth)
+ treeIt->next();
+ }
+
+ if (ImGui::IsItemClicked())
+ {
+ selectedNodeHash = hash;
+ }
+ }
+
+ while (depth > 0)
+ {
+ ImGui::TreePop();
+ depth--;
+ }
+
+ treeIt->release();
+ }
+ else
+ {
+ ImGui::Text("Profiler Is Broken. Begin/End Mismatch.");
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Selected Item Plot
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing();
+ if (plotName)
+ {
+ static PlotLinesInstance<> selectedNodePlot;
+ selectedNodePlot.plot("", plotMS, plotName, 0.0f, plotMaxMS);
+ }
+ else
+ {
+ ImGui::Text("Select item to plot.");
+ }
+ }
+
+ ImGui::End();
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/CommonUIController.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/CommonUIController.h
new file mode 100644
index 0000000..da62674
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/CommonUIController.h
@@ -0,0 +1,106 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef COMMON_UI_CONTROLLER_H
+#define COMMON_UI_CONTROLLER_H
+
+#include "SampleManager.h"
+#include <DirectXMath.h>
+#include <string>
+#include <list>
+#include <queue>
+#include <functional>
+
+
+class Renderer;
+class PhysXController;
+class BlastController;
+
+
+class CommonUIController : public ISampleController
+{
+ public:
+ CommonUIController();
+ virtual ~CommonUIController() {};
+
+ virtual HRESULT DeviceCreated(ID3D11Device* pDevice);
+ virtual void DeviceDestroyed();
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Animate(double fElapsedTimeSeconds);
+ virtual void Render(ID3D11Device*, ID3D11DeviceContext*, ID3D11RenderTargetView*, ID3D11DepthStencilView*);
+
+ void addDelayedCall(std::function<void()> func, const char* message)
+ {
+ addDelayedCall("PLEASE WAIT...", message, func);
+ }
+
+ void addPopupMessage(const char* title, const char* message, float duration = 2.f)
+ {
+ addDelayedCall(title, message, [] {}, duration);
+ }
+
+ private:
+ void addDelayedCall(const char* title, const char* message, std::function<void()> func, float delay = 0.1f);
+
+ void drawUI();
+ void drawCodeProfiler(bool*);
+
+
+ //////// used controllers ////////
+
+ Renderer& getRenderer() const
+ {
+ return getManager()->getRenderer();
+ }
+
+ PhysXController& getPhysXController() const
+ {
+ return getManager()->getPhysXController();
+ }
+
+ BlastController&getBlastController() const
+ {
+ return getManager()->getBlastController();
+ }
+
+ DamageToolController& getDamageToolController() const
+ {
+ return getManager()->getDamageToolController();
+ }
+
+ SceneController& getSceneController() const
+ {
+ return getManager()->getSceneController();
+ }
+
+ SampleController& getSampleController() const
+ {
+ return getManager()->getSampleController();
+ }
+
+
+ //////// internal data ////////
+
+ struct DelayedCall
+ {
+ std::function<void()> func;
+ const char* title;
+ const char* message;
+ float delay;
+ float delayTotal;
+ };
+
+ std::queue<DelayedCall> m_delayedCalls;
+
+ float m_dt;
+
+};
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/DamageToolController.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/DamageToolController.cpp
new file mode 100644
index 0000000..fba1227
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/DamageToolController.cpp
@@ -0,0 +1,294 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "DamageToolController.h"
+#include "RenderUtils.h"
+#include "BlastController.h"
+#include "Renderer.h"
+#include "PhysXController.h"
+#include "SampleProfiler.h"
+
+#include <imgui.h>
+
+#include "NvBlastTkActor.h"
+#include "NvBlastExtDamageShaders.h"
+#include "NvBlastExtPxActor.h"
+
+#include "PxRigidDynamic.h"
+#include "PxScene.h"
+
+
+using namespace Nv::Blast;
+using namespace physx;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Setup
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+const DirectX::XMFLOAT4 PICK_POINTER_ACTIVE_COLOR(1.0f, 0.f, 0.f, 0.6f);
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+DamageToolController::DamageToolController()
+ : m_damageRadius(5.0f), m_compressiveDamage(1.0f), m_pickPointerColor(1.0f, 1.0f, 1.0f, 0.4f),
+ m_pickPointerRenderMaterial(nullptr), m_pickPointerRenderable(nullptr), m_explosiveImpulse(100), m_damageProfile(0), m_stressForceFactor(1.0f)
+{
+ // Damage functions
+ auto radialDamageExecute = [&](const Damager* damager, ExtPxActor* actor, PxVec3 position, PxVec3 normal)
+ {
+ NvBlastExtRadialDamageDesc desc =
+ {
+ m_compressiveDamage,
+ { position.x, position.y, position.z },
+ m_damageRadius,
+ m_damageRadius + 2.0f
+ };
+
+ actor->getTkActor().damage(damager->program, &desc, sizeof(desc));
+ };
+ auto shearDamageExecute = [&](const Damager* damager, ExtPxActor* actor, PxVec3 position, PxVec3 normal)
+ {
+ PxVec3 force = -2 * normal;
+
+ NvBlastExtShearDamageDesc desc =
+ {
+ { force.x, force.y, force.z },
+ { position.x, position.y, position.z }
+ };
+
+ actor->getTkActor().damage(damager->program, &desc, sizeof(desc));
+ };
+ auto stressDamageExecute = [&](const Damager* damager, ExtPxActor* actor, PxVec3 position, PxVec3 normal)
+ {
+ PxVec3 force = -m_stressForceFactor * normal * actor->getPhysXActor().getMass();
+
+ getBlastController().stressDamage(actor, position, force);
+ };
+
+ // Damage Tools:
+ {
+ Damager dam;
+ dam.uiName = "Radial Damage (Falloff)";
+ dam.program = NvBlastDamageProgram { NvBlastExtFalloffGraphShader, NvBlastExtFalloffSubgraphShader };
+ dam.pointerColor = DirectX::XMFLOAT4(1.0f, 1.0f, 1.0f, 0.4f);
+ dam.executeFunction = radialDamageExecute;
+ m_armory.push_back(dam);
+ }
+ {
+ Damager dam;
+ dam.uiName = "Radial Damage (Cutter)";
+ dam.program = NvBlastDamageProgram { NvBlastExtCutterGraphShader, NvBlastExtCutterSubgraphShader };
+ dam.pointerColor = DirectX::XMFLOAT4(0.5f, 0.5f, 1.0f, 0.4f);
+ dam.executeFunction = radialDamageExecute;
+ m_armory.push_back(dam);
+ }
+
+ {
+ Damager dam;
+ dam.uiName = "Shear Damage";
+ dam.program = NvBlastDamageProgram { NvBlastExtShearGraphShader, NvBlastExtShearSubgraphShader };
+ dam.pointerColor = DirectX::XMFLOAT4(0.5f, 1.0f, 0.5f, 0.4f);
+ dam.executeFunction = shearDamageExecute;
+ m_armory.push_back(dam);
+ }
+
+ {
+ Damager dam;
+ dam.uiName = "Stress Damage";
+ dam.program = { nullptr, nullptr };
+ dam.pointerColor = DirectX::XMFLOAT4(0.5f, 0.5f, 1.0f, 0.4f);
+ dam.executeFunction = stressDamageExecute;
+ m_armory.push_back(dam);
+ }
+
+ for (const Damager& d : m_armory)
+ {
+ m_armoryNames.push_back(d.uiName);
+ }
+}
+
+DamageToolController::~DamageToolController()
+{
+}
+
+void DamageToolController::onSampleStart()
+{
+ // pick pointer
+// Add By Lixu Begin
+ m_pickPointerRenderMaterial = new RenderMaterial("", getRenderer().getResourceManager(), "physx_primitive_transparent", "", RenderMaterial::BLEND_ALPHA_BLENDING);
+// Add By Lixu End
+ IRenderMesh* mesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Sphere);
+ m_pickPointerRenderable = getRenderer().createRenderable(*mesh, *m_pickPointerRenderMaterial);
+ m_pickPointerRenderable->setScale(PxVec3(m_damageRadius));
+
+ // default tool
+ setDamageProfile(0);
+
+ // start with damage mode by default
+ setDamageMode(true);
+}
+
+void DamageToolController::onInitialize()
+{
+}
+
+
+void DamageToolController::onSampleStop()
+{
+ getRenderer().removeRenderable(m_pickPointerRenderable);
+ SAFE_DELETE(m_pickPointerRenderMaterial);
+}
+
+void DamageToolController::Animate(double dt)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ m_pickPointerColor = XMFLOAT4Lerp(m_pickPointerColor, m_armory[m_damageProfile].pointerColor, dt * 5.0f);
+ m_pickPointerRenderable->setColor(m_pickPointerColor);
+}
+
+
+LRESULT DamageToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP)
+ {
+ float mouseX = (short)LOWORD(lParam) / getRenderer().getScreenWidth();
+ float mouseY = (short)HIWORD(lParam) / getRenderer().getScreenHeight();
+ bool press = uMsg == WM_LBUTTONDOWN;
+
+ // damage mode
+ if (m_damageMode && m_pickPointerRenderable)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ PxRaycastHit hit; hit.shape = NULL;
+ PxRaycastBuffer hit1;
+ getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL);
+ hit = hit1.block;
+
+ if (hit.shape)
+ {
+ PxRigidActor* actor = hit.actor;
+ m_pickPointerRenderable->setHidden(false);
+ m_pickPointerRenderable->setTransform(PxTransform(hit.position));
+
+ if (press)
+ {
+ damage(hit.position, hit.normal);
+ m_pickPointerColor = PICK_POINTER_ACTIVE_COLOR;
+ }
+ }
+ else
+ {
+ m_pickPointerRenderable->setHidden(true);
+ }
+ }
+ }
+
+ if (uMsg == WM_MOUSEWHEEL)
+ {
+ int delta = int((short)HIWORD(wParam)) / WHEEL_DELTA;
+ changeDamageRadius(delta * 0.3f);
+ }
+
+ if (uMsg == WM_KEYDOWN)
+ {
+ int iKeyPressed = static_cast<int>(wParam);
+ if (iKeyPressed == VK_OEM_PLUS)
+ {
+ changeDamageRadius(0.2f);
+ }
+ else if (iKeyPressed == VK_OEM_MINUS)
+ {
+ changeDamageRadius(-0.2f);
+ }
+ else if (iKeyPressed >= '1' && iKeyPressed <= '9')
+ {
+ uint32_t num = PxClamp<uint32_t>(iKeyPressed - '1', 0, (uint32_t)m_armory.size() - 1);
+ setDamageProfile(num);
+ }
+ else if (iKeyPressed == VK_SPACE)
+ {
+ setDamageMode(!isDamageMode());
+ }
+
+ }
+
+ return 1;
+}
+
+void DamageToolController::drawUI()
+{
+ ImGui::DragFloat("Compressive Damage", &m_compressiveDamage, 0.05f);
+ ImGui::DragFloat("Explosive Impulse", &m_explosiveImpulse);
+ ImGui::DragFloat("Damage Radius (Mouse WH)", &m_damageRadius);
+ ImGui::DragFloat("Stress Damage Force", &m_stressForceFactor);
+
+ // - - - - - - - -
+ ImGui::Spacing();
+
+ // Armory
+ if (ImGui::Combo("Damage Profile", (int*)&m_damageProfile, m_armoryNames.data(), (int)m_armoryNames.size(), -1))
+ {
+ setDamageProfile(m_damageProfile);
+ }
+}
+
+
+void DamageToolController::setDamageMode(bool enabled)
+{
+ m_damageMode = enabled;
+
+ getPhysXController().setDraggingEnabled(!m_damageMode);
+
+ if (!m_damageMode)
+ {
+ m_pickPointerRenderable->setHidden(true);
+ }
+}
+
+
+void DamageToolController::setDamageProfile(uint32_t profile)
+{
+ m_damageProfile = profile;
+}
+
+
+void DamageToolController::changeDamageRadius(float dr)
+{
+ m_damageRadius += dr;
+ m_damageRadius = PxMax(1.0f, m_damageRadius);
+ m_pickPointerRenderable->setScale(PxVec3(m_damageRadius));
+}
+
+
+void DamageToolController::damage(physx::PxVec3 position, physx::PxVec3 normal)
+{
+ auto damageFunction = [&](ExtPxActor* actor)
+ {
+ auto t0 = actor->getPhysXActor().getGlobalPose();
+ PxTransform t(t0.getInverse());
+ PxVec3 localNormal = t.rotate(normal);
+ PxVec3 localPosition = t.transform(position);
+ Damager& damager = m_armory[m_damageProfile];
+ damager.execute(actor, localPosition, localNormal);
+ };
+
+ this->getBlastController().blast(position, m_damageRadius, m_explosiveImpulse, damageFunction);
+
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/DamageToolController.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/DamageToolController.h
new file mode 100644
index 0000000..b6712f2
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/DamageToolController.h
@@ -0,0 +1,129 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef DAMAGE_TOOL_CONTROLLER_H
+#define DAMAGE_TOOL_CONTROLLER_H
+
+#include "SampleManager.h"
+#include "NvBlastTypes.h"
+#include <DirectXMath.h>
+#include <functional>
+#include "PxVec3.h"
+
+
+class Renderable;
+class RenderMaterial;
+
+namespace Nv
+{
+namespace Blast
+{
+class ExtPxActor;
+}
+}
+
+
+
+class DamageToolController : public ISampleController
+{
+public:
+ DamageToolController();
+ virtual ~DamageToolController();
+
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Animate(double dt);
+ void drawUI();
+
+
+ virtual void onInitialize();
+ virtual void onSampleStart();
+ virtual void onSampleStop();
+
+ bool isDamageMode() const
+ {
+ return m_damageMode;
+ }
+
+// Add By Lixu Begin
+ Renderable* getPickPointer()
+ {
+ return m_pickPointerRenderable;
+ }
+// Add By Lixu End
+
+private:
+ DamageToolController& operator= (DamageToolController&);
+
+
+ //////// private methods ////////
+
+ void damage(physx::PxVec3 position, physx::PxVec3 normal);
+
+ void setDamageProfile(uint32_t profile);
+ uint32_t getDamageProfile() const
+ {
+ return m_damageProfile;
+ }
+
+ void changeDamageRadius(float dr);
+
+ void setDamageMode(bool enabled);
+
+
+ //////// used controllers ////////
+
+ Renderer& getRenderer() const
+ {
+ return getManager()->getRenderer();
+ }
+
+ PhysXController& getPhysXController() const
+ {
+ return getManager()->getPhysXController();
+ }
+
+ BlastController& getBlastController() const
+ {
+ return getManager()->getBlastController();
+ }
+
+
+ //////// internal data ////////
+
+ Renderable* m_pickPointerRenderable;
+ RenderMaterial* m_pickPointerRenderMaterial;
+ DirectX::XMFLOAT4 m_pickPointerColor;
+
+ float m_damageRadius;
+ float m_compressiveDamage;
+ float m_explosiveImpulse;
+ float m_stressForceFactor;
+ uint32_t m_damageProfile;
+
+ struct Damager
+ {
+ const char* uiName;
+ NvBlastDamageProgram program;
+ DirectX::XMFLOAT4 pointerColor;
+ std::function<void(const Damager* damager, Nv::Blast::ExtPxActor* actor, physx::PxVec3 position, physx::PxVec3 normal)> executeFunction;
+
+ void execute(Nv::Blast::ExtPxActor* actor, physx::PxVec3 position, physx::PxVec3 normal)
+ {
+ executeFunction(this, actor, position, normal);
+ }
+ };
+
+ std::vector<Damager> m_armory;
+ std::vector<const char*> m_armoryNames;
+
+ bool m_damageMode;
+};
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/EditionToolController.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/EditionToolController.cpp
new file mode 100644
index 0000000..b02044b
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/EditionToolController.cpp
@@ -0,0 +1,156 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "EditionToolController.h"
+#include "BlastController.h"
+#include "Renderer.h"
+#include "PhysXController.h"
+#include "SampleProfiler.h"
+#include "PxRigidDynamic.h"
+#include "PxScene.h"
+#include "NvBlastExtPxManager.h"
+#include "SceneController.h"
+#include "NvBlastExtPxActor.h"
+using namespace Nv::Blast;
+using namespace physx;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Setup
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+EditionToolController::EditionToolController()
+{
+}
+
+EditionToolController::~EditionToolController()
+{
+}
+
+void EditionToolController::onSampleStart()
+{
+}
+
+void EditionToolController::onInitialize()
+{
+}
+
+
+void EditionToolController::onSampleStop()
+{
+}
+
+void EditionToolController::Animate(double dt)
+{
+ PROFILER_SCOPED_FUNCTION();
+}
+
+
+LRESULT EditionToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP)
+ {
+ float mouseX = (short)LOWORD(lParam) / getRenderer().getScreenWidth();
+ float mouseY = (short)HIWORD(lParam) / getRenderer().getScreenHeight();
+ bool press = uMsg == WM_LBUTTONDOWN;
+
+ if (uMsg == WM_LBUTTONUP)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ PxRaycastHit hit; hit.shape = NULL;
+ PxRaycastBuffer hit1;
+ getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL);
+ hit = hit1.block;
+
+ PxRigidActor* actor = NULL;
+ if (hit.shape)
+ {
+ actor = hit.actor;
+ }
+ fracture(actor);
+ }
+ }
+
+ return 1;
+}
+
+void EditionToolController::drawUI()
+{
+}
+
+void EditionToolController::fracture(PxActor* actor)
+{
+ if (NULL == actor)
+ {
+ return;
+ }
+
+ BlastController& blastController = getBlastController();
+ std::vector<BlastFamilyPtr>& families = blastController.getFamilies();
+ if (families.size() == 0)
+ {
+ return;
+ }
+
+ ExtPxActor* extActor = NULL;
+ PxRigidDynamic* rigidDynamic = actor->is<PxRigidDynamic>();
+ if (NULL != rigidDynamic)
+ {
+ extActor = blastController.getExtPxManager().getActorFromPhysXActor(*rigidDynamic);
+ }
+ if (NULL == extActor)
+ {
+ return;
+ }
+
+ uint32_t chunkCount = extActor->getChunkCount();
+ if (chunkCount <= 0)
+ {
+ return;
+ }
+
+ BlastFamilyPtr pBlastFamily = NULL;
+ std::vector<BlastFamilyPtr>::iterator it = families.begin();
+ for (; it != families.end(); it++)
+ {
+ BlastFamilyPtr f = *it;
+ if (f->find(extActor))
+ {
+ pBlastFamily = f;
+ break;
+ }
+ }
+ if (NULL == pBlastFamily)
+ {
+ return;
+ }
+
+ const uint32_t* chunkIndices = extActor->getChunkIndices();
+
+ const BlastAsset& blastAsset = pBlastFamily->getBlastAsset();
+ const BlastAsset* pBlastAsset = &blastAsset;
+
+ SceneController& sceneController = getManager()->getSceneController();
+ AssetList::ModelAsset desc;
+ sceneController.GetAssetDesc(pBlastAsset, desc);
+
+ std::string assetname = desc.id;
+ getManager()->fractureAsset(assetname, pBlastAsset, chunkIndices[0]);
+ getManager()->addModelAsset(assetname, desc.isSkinned, desc.transform, false);
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/EditionToolController.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/EditionToolController.h
new file mode 100644
index 0000000..b1e88d1
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/EditionToolController.h
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef EDITION_TOOL_CONTROLLER_H
+#define EDITION_TOOL_CONTROLLER_H
+
+#include "SampleManager.h"
+
+namespace physx
+{
+ class PxActor;
+}
+
+class EditionToolController : public ISampleController
+{
+public:
+ EditionToolController();
+ virtual ~EditionToolController();
+
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Animate(double dt);
+ void drawUI();
+
+ virtual void onInitialize();
+ virtual void onSampleStart();
+ virtual void onSampleStop();
+
+ void fracture(physx::PxActor* actor);
+
+private:
+ EditionToolController& operator= (EditionToolController&);
+
+ //////// private methods ////////
+
+ //////// used controllers ////////
+
+ Renderer& getRenderer() const
+ {
+ return getManager()->getRenderer();
+ }
+
+ PhysXController& getPhysXController() const
+ {
+ return getManager()->getPhysXController();
+ }
+
+ BlastController& getBlastController() const
+ {
+ return getManager()->getBlastController();
+ }
+
+ //////// internal data ////////
+};
+
+#endif // EDITION_TOOL_CONTROLLER_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/GizmoToolController.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/GizmoToolController.cpp
new file mode 100644
index 0000000..ff0ffa9
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/GizmoToolController.cpp
@@ -0,0 +1,1210 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "GizmoToolController.h"
+#include "RenderUtils.h"
+#include "BlastController.h"
+#include "SelectionToolController.h"
+#include "Renderer.h"
+#include "PhysXController.h"
+#include "SampleProfiler.h"
+
+#include <imgui.h>
+
+#include "NvBlastTkActor.h"
+#include "NvBlastExtDamageShaders.h"
+
+#include "PxRigidDynamic.h"
+#include "PxScene.h"
+#include <AppMainWindow.h>
+
+
+using namespace Nv::Blast;
+using namespace physx;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Setup
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const DirectX::XMFLOAT4 X_DIRECTION_COLOR_F = DirectX::XMFLOAT4(1, 0, 0, 1);
+const DirectX::XMFLOAT4 Y_DIRECTION_COLOR_F = DirectX::XMFLOAT4(0, 1, 0, 1);
+const DirectX::XMFLOAT4 Z_DIRECTION_COLOR_F = DirectX::XMFLOAT4(0, 0, 1, 1);
+const DirectX::XMFLOAT4 HIGHLIGHT_COLOR_F = DirectX::XMFLOAT4(1, 1, 0, 1);
+
+const physx::PxU32 X_DIRECTION_COLOR_U = XMFLOAT4ToU32Color(X_DIRECTION_COLOR_F);
+const physx::PxU32 Y_DIRECTION_COLOR_U = XMFLOAT4ToU32Color(Y_DIRECTION_COLOR_F);
+const physx::PxU32 Z_DIRECTION_COLOR_U = XMFLOAT4ToU32Color(Z_DIRECTION_COLOR_F);
+const physx::PxU32 HIGHLIGHT_COLOR_U = XMFLOAT4ToU32Color(HIGHLIGHT_COLOR_F);
+
+const float defaultAxisLength = 10.0;
+const float defaultAxisModifier = -1.0;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+GizmoToolController::GizmoToolController()
+{
+ m_bGizmoFollowed = false;
+
+ int segment = 36;
+ double span = PxTwoPi / segment;
+ PxVec3* vertex = new PxVec3[segment];
+
+ for (int i = 0; i < segment; i++)
+ {
+ vertex[i].x = 0;
+ vertex[i].y = 10 * PxSin(i * span);
+ vertex[i].z = 10 * PxCos(i * span);
+ }
+ // x
+ for (int i = 0; i < segment - 1; i++)
+ {
+ m_CircleRenderData.push_back(PxDebugLine(vertex[i], vertex[i + 1], X_DIRECTION_COLOR_U));
+ }
+ m_CircleRenderData.push_back(PxDebugLine(vertex[segment - 1], vertex[0], X_DIRECTION_COLOR_U));
+
+ for (int i = 0; i < segment; i++)
+ {
+ vertex[i].x = 10 * PxCos(i * span);
+ vertex[i].y = 0;
+ vertex[i].z = 10 * PxSin(i * span);
+ }
+ // y
+ for (int i = 0; i < segment - 1; i++)
+ {
+ m_CircleRenderData.push_back(PxDebugLine(vertex[i], vertex[i + 1], Y_DIRECTION_COLOR_U));
+ }
+ m_CircleRenderData.push_back(PxDebugLine(vertex[segment - 1], vertex[0], Y_DIRECTION_COLOR_U));
+
+ for (int i = 0; i < segment; i++)
+ {
+ vertex[i].x = 10 * PxCos(i * span);
+ vertex[i].y = 10 * PxSin(i * span);
+ vertex[i].z = 0;
+ }
+ // z
+ for (int i = 0; i < segment - 1; i++)
+ {
+ m_CircleRenderData.push_back(PxDebugLine(vertex[i], vertex[i + 1], Z_DIRECTION_COLOR_U));
+ }
+ m_CircleRenderData.push_back(PxDebugLine(vertex[segment - 1], vertex[0], Z_DIRECTION_COLOR_U));
+
+ delete[] vertex;
+ vertex = NULL;
+
+ resetPos();
+}
+
+GizmoToolController::~GizmoToolController()
+{
+}
+
+void GizmoToolController::onSampleStart()
+{
+ m_AxisRenderMaterial = new RenderMaterial("", getRenderer().getResourceManager(), "physx_primitive_transparent");
+
+ IRenderMesh* coneMesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Cone);
+ m_AxisConeRenderable[AT_X] = getRenderer().createRenderable(*coneMesh, *m_AxisRenderMaterial);
+ m_AxisConeRenderable[AT_Y] = getRenderer().createRenderable(*coneMesh, *m_AxisRenderMaterial);
+ m_AxisConeRenderable[AT_Z] = getRenderer().createRenderable(*coneMesh, *m_AxisRenderMaterial);
+ m_AxisConeRenderable[AT_X]->setColor(X_DIRECTION_COLOR_F);
+ m_AxisConeRenderable[AT_Y]->setColor(Y_DIRECTION_COLOR_F);
+ m_AxisConeRenderable[AT_Z]->setColor(Z_DIRECTION_COLOR_F);
+ m_AxisConeRenderable[AT_X]->setScale(PxVec3(0.5, 1, 0.5));
+ m_AxisConeRenderable[AT_Y]->setScale(PxVec3(0.5, 1, 0.5));
+ m_AxisConeRenderable[AT_Z]->setScale(PxVec3(0.5, 1, 0.5));
+ m_AxisConeRenderable[AT_X]->setHidden(true);
+ m_AxisConeRenderable[AT_Y]->setHidden(true);
+ m_AxisConeRenderable[AT_Z]->setHidden(true);
+
+ IRenderMesh* boxMesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Box);
+ m_AxisBoxRenderable[AT_X] = getRenderer().createRenderable(*boxMesh, *m_AxisRenderMaterial);
+ m_AxisBoxRenderable[AT_Y] = getRenderer().createRenderable(*boxMesh, *m_AxisRenderMaterial);
+ m_AxisBoxRenderable[AT_Z] = getRenderer().createRenderable(*boxMesh, *m_AxisRenderMaterial);
+ m_AxisBoxRenderable[AT_X]->setColor(X_DIRECTION_COLOR_F);
+ m_AxisBoxRenderable[AT_Y]->setColor(Y_DIRECTION_COLOR_F);
+ m_AxisBoxRenderable[AT_Z]->setColor(Z_DIRECTION_COLOR_F);
+ m_AxisBoxRenderable[AT_X]->setScale(PxVec3(0.5, 0.5, 0.5));
+ m_AxisBoxRenderable[AT_Y]->setScale(PxVec3(0.5, 0.5, 0.5));
+ m_AxisBoxRenderable[AT_Z]->setScale(PxVec3(0.5, 0.5, 0.5));
+ m_AxisBoxRenderable[AT_X]->setHidden(true);
+ m_AxisBoxRenderable[AT_Y]->setHidden(true);
+ m_AxisBoxRenderable[AT_Z]->setHidden(true);
+
+ m_Axis[AT_X] = PxVec3(defaultAxisLength, 0.0, 0.0);
+ m_Axis[AT_Y] = PxVec3(0.0, defaultAxisLength, 0.0);
+ m_Axis[AT_Z] = PxVec3(0.0, 0.0, defaultAxisLength);
+}
+
+void GizmoToolController::onInitialize()
+{
+}
+
+
+void GizmoToolController::onSampleStop()
+{
+}
+
+void GizmoToolController::Animate(double dt)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ if (NULL == m_CurrentActor)
+ {
+ m_AxisConeRenderable[AT_X]->setHidden(true);
+ m_AxisConeRenderable[AT_Y]->setHidden(true);
+ m_AxisConeRenderable[AT_Z]->setHidden(true);
+ m_AxisBoxRenderable[AT_X]->setHidden(true);
+ m_AxisBoxRenderable[AT_Y]->setHidden(true);
+ m_AxisBoxRenderable[AT_Z]->setHidden(true);
+
+ return;
+ }
+
+ bool isTranslation = m_GizmoToolMode == GTM_Translate;
+ bool isScale = m_GizmoToolMode == GTM_Scale;
+ bool isRotation = m_GizmoToolMode == GTM_Rotation;
+ bool isLocal = AppMainWindow::Inst().m_bGizmoWithLocal;
+
+ bool showLine = isTranslation || isScale || (isRotation && isLocal);
+ bool showCone = isTranslation || (isRotation && isLocal);
+ bool showBox = isScale;
+ bool showCircle = isRotation;
+
+ m_AxisConeRenderable[AT_X]->setHidden(!isTranslation);
+ m_AxisConeRenderable[AT_Y]->setHidden(!isTranslation);
+ m_AxisConeRenderable[AT_Z]->setHidden(!isTranslation);
+ m_AxisBoxRenderable[AT_X]->setHidden(!isScale);
+ m_AxisBoxRenderable[AT_Y]->setHidden(!isScale);
+ m_AxisBoxRenderable[AT_Z]->setHidden(!isScale);
+
+ if (showLine)
+ {
+ if (m_bNeedResetPos)
+ {
+ m_AxisRenderBuffer.clear();
+ m_AxisRenderBuffer.m_lines.push_back(PxDebugLine(m_TargetPos, m_TargetPos + m_Axis[AT_X] * defaultAxisModifier, X_DIRECTION_COLOR_U));
+ m_AxisRenderBuffer.m_lines.push_back(PxDebugLine(m_TargetPos, m_TargetPos + m_Axis[AT_Y], Y_DIRECTION_COLOR_U));
+ m_AxisRenderBuffer.m_lines.push_back(PxDebugLine(m_TargetPos, m_TargetPos + m_Axis[AT_Z], Z_DIRECTION_COLOR_U));
+ }
+
+ if (m_bNeedResetColor)
+ {
+ if (m_AxisSelected == AT_X)
+ {
+ m_AxisRenderBuffer.m_lines[0].color0 = HIGHLIGHT_COLOR_U;
+ m_AxisRenderBuffer.m_lines[0].color1 = HIGHLIGHT_COLOR_U;
+ }
+ else
+ {
+ m_AxisRenderBuffer.m_lines[0].color0 = X_DIRECTION_COLOR_U;
+ m_AxisRenderBuffer.m_lines[0].color1 = X_DIRECTION_COLOR_U;
+ }
+ if (m_AxisSelected == AT_Y)
+ {
+ m_AxisRenderBuffer.m_lines[1].color0 = HIGHLIGHT_COLOR_U;
+ m_AxisRenderBuffer.m_lines[1].color1 = HIGHLIGHT_COLOR_U;
+ }
+ else
+ {
+ m_AxisRenderBuffer.m_lines[1].color0 = Y_DIRECTION_COLOR_U;
+ m_AxisRenderBuffer.m_lines[1].color1 = Y_DIRECTION_COLOR_U;
+ }
+ if (m_AxisSelected == AT_Z)
+ {
+ m_AxisRenderBuffer.m_lines[2].color0 = HIGHLIGHT_COLOR_U;
+ m_AxisRenderBuffer.m_lines[2].color1 = HIGHLIGHT_COLOR_U;
+ }
+ else
+ {
+ m_AxisRenderBuffer.m_lines[2].color0 = Z_DIRECTION_COLOR_U;
+ m_AxisRenderBuffer.m_lines[2].color1 = Z_DIRECTION_COLOR_U;
+ }
+ }
+
+ getRenderer().queueRenderBuffer(&m_AxisRenderBuffer);
+ }
+
+ if (showCone)
+ {
+ if (m_bNeedResetPos)
+ {
+ PxTransform transform;
+
+ transform.p = m_TargetPos + m_Axis[AT_X] * defaultAxisModifier;
+ transform.q = CalDirectionQuat(AT_X);
+ m_AxisConeRenderable[AT_X]->setTransform(transform);
+
+ transform.p = m_TargetPos + m_Axis[AT_Y];
+ transform.q = CalDirectionQuat(AT_Y);
+ m_AxisConeRenderable[AT_Y]->setTransform(transform);
+
+ transform.p = m_TargetPos + m_Axis[AT_Z];
+ transform.q = CalDirectionQuat(AT_Z);
+ m_AxisConeRenderable[AT_Z]->setTransform(transform);
+ }
+
+ if (m_bNeedResetColor)
+ {
+ if (m_AxisSelected == AT_X)
+ {
+ m_AxisConeRenderable[AT_X]->setColor(HIGHLIGHT_COLOR_F);
+ }
+ else
+ {
+ m_AxisConeRenderable[AT_X]->setColor(X_DIRECTION_COLOR_F);
+ }
+ if (m_AxisSelected == AT_Y)
+ {
+ m_AxisConeRenderable[AT_Y]->setColor(HIGHLIGHT_COLOR_F);
+ }
+ else
+ {
+ m_AxisConeRenderable[AT_Y]->setColor(Y_DIRECTION_COLOR_F);
+ }
+ if (m_AxisSelected == AT_Z)
+ {
+ m_AxisConeRenderable[AT_Z]->setColor(HIGHLIGHT_COLOR_F);
+ }
+ else
+ {
+ m_AxisConeRenderable[AT_Z]->setColor(Z_DIRECTION_COLOR_F);
+ }
+ }
+ }
+
+ if (showBox)
+ {
+ if (m_bNeedResetPos)
+ {
+ PxTransform transform;
+
+ transform.p = m_TargetPos + m_Axis[AT_X] * defaultAxisModifier;
+ transform.q = CalDirectionQuat(AT_X);
+ m_AxisBoxRenderable[AT_X]->setTransform(transform);
+
+ transform.p = m_TargetPos + m_Axis[AT_Y];
+ transform.q = CalDirectionQuat(AT_Y);
+ m_AxisBoxRenderable[AT_Y]->setTransform(transform);
+
+ transform.p = m_TargetPos + m_Axis[AT_Z];
+ transform.q = CalDirectionQuat(AT_Z);
+ m_AxisBoxRenderable[AT_Z]->setTransform(transform);
+ }
+
+ if (m_bNeedResetColor)
+ {
+ if (m_AxisSelected == AT_X)
+ {
+ m_AxisBoxRenderable[AT_X]->setColor(HIGHLIGHT_COLOR_F);
+ }
+ else
+ {
+ m_AxisBoxRenderable[AT_X]->setColor(X_DIRECTION_COLOR_F);
+ }
+ if (m_AxisSelected == AT_Y)
+ {
+ m_AxisBoxRenderable[AT_Y]->setColor(HIGHLIGHT_COLOR_F);
+ }
+ else
+ {
+ m_AxisBoxRenderable[AT_Y]->setColor(Y_DIRECTION_COLOR_F);
+ }
+ if (m_AxisSelected == AT_Z)
+ {
+ m_AxisBoxRenderable[AT_Z]->setColor(HIGHLIGHT_COLOR_F);
+ }
+ else
+ {
+ m_AxisBoxRenderable[AT_Z]->setColor(Z_DIRECTION_COLOR_F);
+ }
+ }
+ }
+
+ if (showCircle)
+ {
+ if (m_bNeedResetPos)
+ {
+ PxQuat q = CalConvertQuat();
+
+ m_CircleRenderBuffer.clear();
+ std::vector<PxDebugLine>::iterator it;
+ for (it = m_CircleRenderData.begin(); it != m_CircleRenderData.end(); it++)
+ {
+ PxDebugLine line = (*it);
+
+ line.pos0 = q.rotate(line.pos0);
+ line.pos1 = q.rotate(line.pos1);
+
+ line.pos0 += m_TargetPos;
+ line.pos1 += m_TargetPos;
+
+ m_CircleRenderBuffer.m_lines.push_back(line);
+ }
+ }
+
+ if (m_bNeedResetColor)
+ {
+ std::vector<PxDebugLine>& datas = m_CircleRenderData;
+ std::vector<PxDebugLine>& lines = m_CircleRenderBuffer.m_lines;
+ int linesize = lines.size();
+ int linesize_per_axis = linesize / 3;
+ float multiply;
+ physx::PxU32 color;
+
+ if (m_AxisSelected == AT_X)
+ {
+ for (int l = 0; l < linesize_per_axis; l++)
+ {
+ multiply = 1.0 * (l + 1) / linesize_per_axis;
+ color = XMFLOAT4ToU32Color(DirectX::XMFLOAT4(multiply, multiply, 0, 1));
+ lines[l].color0 = color;
+ lines[l].color1 = color;
+ }
+ }
+ else
+ {
+ for (int l = 0; l < linesize_per_axis; l++)
+ {
+ multiply = 1.0 * (l + 1) / linesize_per_axis;
+ color = XMFLOAT4ToU32Color(DirectX::XMFLOAT4(multiply, 0, 0, 1));
+ lines[l].color0 = color;
+ lines[l].color1 = color;
+ }
+ }
+ if (m_AxisSelected == AT_Y)
+ {
+ for (int l = linesize_per_axis; l < linesize_per_axis * 2; l++)
+ {
+ multiply = 1.0 * (l + 1 - linesize_per_axis) / linesize_per_axis;
+ color = XMFLOAT4ToU32Color(DirectX::XMFLOAT4(multiply, multiply, 0, 1));
+ lines[l].color0 = color;
+ lines[l].color1 = color;
+ }
+ }
+ else
+ {
+ for (int l = linesize_per_axis; l < linesize_per_axis * 2; l++)
+ {
+ multiply = 1.0 * (l + 1 - linesize_per_axis) / linesize_per_axis;
+ color = XMFLOAT4ToU32Color(DirectX::XMFLOAT4(0, multiply, 0, 1));
+ lines[l].color0 = color;
+ lines[l].color1 = color;
+ }
+ }
+ if (m_AxisSelected == AT_Z)
+ {
+ for (int l = linesize_per_axis * 2; l < linesize; l++)
+ {
+ multiply = 1.0 * (l + 1 - linesize_per_axis * 2) / linesize_per_axis;
+ color = XMFLOAT4ToU32Color(DirectX::XMFLOAT4(multiply, multiply, 0, 1));
+ lines[l].color0 = color;
+ lines[l].color1 = color;
+ }
+ }
+ else
+ {
+ for (int l = linesize_per_axis * 2; l < linesize; l++)
+ {
+ multiply = 1.0 * (l + 1 - linesize_per_axis * 2) / linesize_per_axis;
+ color = XMFLOAT4ToU32Color(DirectX::XMFLOAT4(0, 0, multiply, 1));
+ lines[l].color0 = color;
+ lines[l].color1 = color;
+ }
+ }
+ }
+
+ getRenderer().queueRenderBuffer(&m_CircleRenderBuffer);
+ }
+
+ m_bNeedResetPos = false;
+ m_bNeedResetColor = false;
+}
+
+#include "PxPhysics.h"
+#include "cooking/PxCooking.h"
+LRESULT GizmoToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP)
+ {
+ float mouseX = (short)LOWORD(lParam) / getRenderer().getScreenWidth();
+ float mouseY = (short)HIWORD(lParam) / getRenderer().getScreenHeight();
+ bool press = uMsg == WM_LBUTTONDOWN;
+
+ if (m_GizmoToolMode == GTM_Translate)
+ {
+ if (uMsg == WM_LBUTTONDOWN)
+ {
+ if (m_AxisSelected == AT_Num)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ PxRaycastHit hit; hit.shape = NULL;
+ PxRaycastBuffer hit1;
+ getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL);
+ hit = hit1.block;
+
+ if (hit.shape)
+ {
+ PxRigidActor* actor = hit.actor;
+ PxRigidDynamic* rigidDynamic = actor->is<PxRigidDynamic>();
+ if (NULL != rigidDynamic)
+ {
+ m_CurrentActor = actor;
+ getSelectionToolController().pointSelect(m_CurrentActor);
+
+ PxTransform gp = m_CurrentActor->getGlobalPose();
+
+ m_TargetPos = gp.p;
+ m_Axis[AT_X] = gp.q.rotate(PxVec3(defaultAxisLength, 0, 0));
+ m_Axis[AT_Y] = gp.q.rotate(PxVec3(0, defaultAxisLength, 0));
+ m_Axis[AT_Z] = gp.q.rotate(PxVec3(0, 0, defaultAxisLength));
+
+ m_bNeedResetPos = true;
+ }
+ else
+ {
+ m_CurrentActor = NULL;
+ getSelectionToolController().clearSelect();
+ }
+ }
+ }
+ else
+ {
+ m_bGizmoFollowed = (m_CurrentActor != NULL);
+ }
+ }
+ else if (uMsg == WM_MOUSEMOVE)
+ {
+ if (m_bGizmoFollowed)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ PxVec3 axis = m_Axis[m_AxisSelected];
+ axis = axis.getNormalized();
+ PxVec3 samplepoint = eyePos + pickDir;
+ PxVec3 normal = m_LastEyeRay.cross(axis);
+ normal = normal.getNormalized();
+ PxVec3 foot;
+ GetFootFromPointToPlane(samplepoint, eyePos, normal, foot);
+ PxVec3 direction = foot - eyePos;
+ direction = direction.getNormalized();
+ PxVec3 target;
+ GetIntersectBetweenLines(m_LastFoot, axis, eyePos, direction, target);
+ PxVec3 delta = target - m_LastFoot;
+
+ m_LastEyeRay = direction;
+ m_LastFoot = target;
+
+ PxTransform gp_old = m_CurrentActor->getGlobalPose();
+ PxTransform gp_new(gp_old.p + delta, gp_old.q);;
+ m_CurrentActor->setGlobalPose(gp_new);
+
+ m_TargetPos = gp_new.p;
+
+ bool local = AppMainWindow::Inst().m_bGizmoWithLocal;
+ if (local)
+ {
+ uint32_t shapesCount = m_CurrentActor->getNbShapes();
+ if (shapesCount > 0)
+ {
+ PxTransform gp_newInv = gp_new.getInverse();
+
+ PxTransform lp_old;
+ PxTransform lp_new;
+
+ std::vector<PxShape*> shapes(shapesCount);
+ m_CurrentActor->getShapes(&shapes[0], shapesCount);
+ getPhysXController().getPhysXScene().removeActor(*m_CurrentActor);
+ for (uint32_t i = 0; i < shapesCount; i++)
+ {
+ PxShape* shape = shapes[i];
+
+ m_CurrentActor->detachShape(*shape);
+
+ lp_old = shape->getLocalPose();
+ lp_new = gp_newInv * gp_old * lp_old;
+ shape->setLocalPose(lp_new);
+
+ m_CurrentActor->attachShape(*shape);
+ }
+ getPhysXController().getPhysXScene().addActor(*m_CurrentActor);
+ }
+ }
+
+ m_bNeedResetPos = true;
+ m_bNeedResetColor = true;
+ }
+ else if(m_CurrentActor != NULL)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ m_LastEyeRay = pickDir;
+
+ // get axis which intersect with this eye ray
+ AxisType as = AT_Num;
+ {
+ double distanceMin = PX_MAX_F32;
+ double tolerance = 1;
+ int line_index = -1;
+ PxVec3 foot;
+ std::vector<PxDebugLine>& lines = m_AxisRenderBuffer.m_lines;
+ int linesize = lines.size();
+ for (int l = 0; l < linesize; l++)
+ {
+ PxVec3 start = lines[l].pos0;
+ PxVec3 end = lines[l].pos1;
+ PxVec3 dir = end - start;
+ double length = dir.magnitude();
+ // separate the line to 10 segment
+ double delta = length * 0.1;
+ for (int segment = 0; segment <= 10; segment++)
+ {
+ PxVec3 vertex = start + 0.1 * segment * dir;
+ double distance = DistanceFromPointToLine(vertex, eyePos, pickDir, foot);
+
+ if (distance < distanceMin)
+ {
+ distanceMin = distance;
+ line_index = l;
+ m_LastFoot = foot;
+ }
+ }
+ }
+ if (distanceMin < tolerance)
+ {
+ int axis_index = line_index * 3 / linesize;
+ as = (AxisType)axis_index;
+ }
+ }
+ setAxisSelected(as);
+ }
+ }
+ else if (uMsg == WM_LBUTTONUP)
+ {
+ m_bNeedResetPos = true;
+ m_bNeedResetColor = true;
+ m_bGizmoFollowed = false;
+ }
+ }
+ else if (m_GizmoToolMode == GTM_Scale)
+ {
+ if (uMsg == WM_LBUTTONDOWN)
+ {
+ if (m_AxisSelected == AT_Num)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ PxRaycastHit hit; hit.shape = NULL;
+ PxRaycastBuffer hit1;
+ getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL);
+ hit = hit1.block;
+
+ if (hit.shape)
+ {
+ PxRigidActor* actor = hit.actor;
+ PxRigidDynamic* rigidDynamic = actor->is<PxRigidDynamic>();
+ if (NULL != rigidDynamic)
+ {
+ m_CurrentActor = actor;
+ getSelectionToolController().pointSelect(m_CurrentActor);
+
+ PxTransform gp = m_CurrentActor->getGlobalPose();
+
+ m_TargetPos = gp.p;
+ m_Axis[AT_X] = gp.q.rotate(PxVec3(defaultAxisLength, 0, 0));
+ m_Axis[AT_Y] = gp.q.rotate(PxVec3(0, defaultAxisLength, 0));
+ m_Axis[AT_Z] = gp.q.rotate(PxVec3(0, 0, defaultAxisLength));
+
+ m_bNeedResetPos = true;
+ }
+ else
+ {
+ m_CurrentActor = NULL;
+ getSelectionToolController().clearSelect();
+ }
+ }
+ }
+ else
+ {
+ m_bGizmoFollowed = (m_CurrentActor != NULL);
+ m_LastAxis[AT_X] = m_Axis[AT_X].getNormalized();
+ m_LastAxis[AT_Y] = m_Axis[AT_Y].getNormalized();
+ m_LastAxis[AT_Z] = m_Axis[AT_Z].getNormalized();
+ }
+ }
+ else if (uMsg == WM_MOUSEMOVE)
+ {
+ if (m_bGizmoFollowed)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ PxVec3 axis = m_LastAxis[m_AxisSelected];
+ PxVec3 samplepoint = eyePos + pickDir;
+ PxVec3 normal = m_LastEyeRay.cross(axis);
+ normal = normal.getNormalized();
+ PxVec3 foot;
+ GetFootFromPointToPlane(samplepoint, eyePos, normal, foot);
+ PxVec3 direction = foot - eyePos;
+ direction = direction.getNormalized();
+ PxVec3 target;
+ GetIntersectBetweenLines(m_LastFoot, axis, eyePos, direction, target);
+ PxVec3 delta = target - m_LastFoot;
+
+ if (m_AxisSelected == AT_X)
+ {
+ delta *= defaultAxisModifier;
+ }
+ m_Axis[m_AxisSelected] = m_LastAxis[m_AxisSelected] * defaultAxisLength + delta;
+
+ bool isShift = (GetAsyncKeyState(VK_SHIFT) && 0x8000);
+ if (isShift)
+ {
+ float length = m_Axis[m_AxisSelected].magnitude();
+ m_Axis[AT_X] = m_LastAxis[AT_X] * length;
+ m_Axis[AT_Y] = m_LastAxis[AT_Y] * length;
+ m_Axis[AT_Z] = m_LastAxis[AT_Z] * length;
+ }
+
+ ScaleActor(false);
+
+ m_bNeedResetPos = true;
+ m_bNeedResetColor = true;
+ }
+ else if (m_CurrentActor != NULL)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ m_LastEyeRay = pickDir;
+
+ // get axis which intersect with this eye ray
+ AxisType as = AT_Num;
+ {
+ double distanceMin = PX_MAX_F32;
+ double tolerance = 1;
+ int line_index = -1;
+ std::vector<PxDebugLine>& lines = m_AxisRenderBuffer.m_lines;
+ int linesize = lines.size();
+ PxVec3 foot;
+ for (int l = 0; l < linesize; l++)
+ {
+ PxVec3 vertex = lines[l].pos1;
+ double distance = DistanceFromPointToLine(vertex, eyePos, pickDir, foot);
+
+ if (distance < distanceMin)
+ {
+ distanceMin = distance;
+ line_index = l;
+ m_LastFoot = foot;
+ }
+ }
+ if (distanceMin < tolerance)
+ {
+ as = (AxisType)line_index;
+ }
+ }
+ setAxisSelected(as);
+ }
+ }
+ else if (uMsg == WM_LBUTTONUP)
+ {
+ if (m_AxisSelected != AT_Num)
+ {
+ if (NULL != m_CurrentActor)
+ {
+ ScaleActor(true);
+ }
+
+ m_Axis[AT_X] = m_LastAxis[AT_X] * defaultAxisLength;
+ m_Axis[AT_Y] = m_LastAxis[AT_Y] * defaultAxisLength;
+ m_Axis[AT_Z] = m_LastAxis[AT_Z] * defaultAxisLength;
+ }
+
+ m_bNeedResetPos = true;
+ m_bNeedResetColor = true;
+ m_bGizmoFollowed = false;
+ }
+ }
+ else if (m_GizmoToolMode == GTM_Rotation)
+ {
+ if (uMsg == WM_LBUTTONDOWN)
+ {
+ if (m_AxisSelected == AT_Num)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ PxRaycastHit hit; hit.shape = NULL;
+ PxRaycastBuffer hit1;
+ getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL);
+ hit = hit1.block;
+
+ if (hit.shape)
+ {
+ PxRigidActor* actor = hit.actor;
+ PxRigidDynamic* rigidDynamic = actor->is<PxRigidDynamic>();
+ if (NULL != rigidDynamic)
+ {
+ m_CurrentActor = actor;
+ getSelectionToolController().pointSelect(m_CurrentActor);
+
+ PxTransform gp = m_CurrentActor->getGlobalPose();
+
+ m_TargetPos = gp.p;
+ m_Axis[AT_X] = gp.q.rotate(PxVec3(defaultAxisLength, 0, 0));
+ m_Axis[AT_Y] = gp.q.rotate(PxVec3(0, defaultAxisLength, 0));
+ m_Axis[AT_Z] = gp.q.rotate(PxVec3(0, 0, defaultAxisLength));
+
+ m_bNeedResetPos = true;
+ }
+ else
+ {
+ m_CurrentActor = NULL;
+ getSelectionToolController().clearSelect();
+ }
+ }
+ }
+ else
+ {
+ m_bGizmoFollowed = (m_CurrentActor != NULL);
+ }
+ }
+ else if (uMsg == WM_MOUSEMOVE)
+ {
+ if (m_bGizmoFollowed)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ PxVec3 planenormal = m_Axis[m_AxisSelected];
+ planenormal = planenormal.getNormalized();
+
+ PxVec3 from, to;
+ CalPlaneLineIntersectPoint(from, planenormal, m_TargetPos, m_LastEyeRay, eyePos);
+ CalPlaneLineIntersectPoint(to, planenormal, m_TargetPos, pickDir, eyePos);
+ from = from - m_TargetPos;
+ to = to - m_TargetPos;
+ from = from.getNormalized();
+ to = to.getNormalized();
+ float cosangle = from.dot(to);
+ float angle = PxAcos(cosangle);
+ PxVec3 cross = from.cross(to);
+ cross = cross.getNormalized();
+
+ PxQuat q(angle, cross);
+ if (m_AxisSelected == AT_X)
+ {
+ m_Axis[AT_Y] = q.rotate(m_Axis[AT_Y]);
+ m_Axis[AT_Z] = q.rotate(m_Axis[AT_Z]);
+ }
+ else if (m_AxisSelected == AT_Y)
+ {
+ m_Axis[AT_X] = q.rotate(m_Axis[AT_X]);
+ m_Axis[AT_Z] = q.rotate(m_Axis[AT_Z]);
+ }
+ else if (m_AxisSelected == AT_Z)
+ {
+ m_Axis[AT_X] = q.rotate(m_Axis[AT_X]);
+ m_Axis[AT_Y] = q.rotate(m_Axis[AT_Y]);
+ }
+
+ m_LastEyeRay = pickDir;
+
+ PxTransform gp_old = m_CurrentActor->getGlobalPose();
+ PxTransform gp_new = PxTransform(gp_old.p, CalConvertQuat());
+ m_CurrentActor->setGlobalPose(gp_new);
+
+ bool local = AppMainWindow::Inst().m_bGizmoWithLocal;
+ if (local)
+ {
+ uint32_t shapesCount = m_CurrentActor->getNbShapes();
+ if (shapesCount > 0)
+ {
+ PxTransform gp_newInv = gp_new.getInverse();
+
+ PxTransform lp_old;
+ PxTransform lp_new;
+
+ std::vector<PxShape*> shapes(shapesCount);
+ m_CurrentActor->getShapes(&shapes[0], shapesCount);
+ getPhysXController().getPhysXScene().removeActor(*m_CurrentActor);
+ for (uint32_t i = 0; i < shapesCount; i++)
+ {
+ PxShape* shape = shapes[i];
+
+ m_CurrentActor->detachShape(*shape);
+
+ lp_old = shape->getLocalPose();
+ lp_new = gp_newInv * gp_old * lp_old;
+ shape->setLocalPose(lp_new);
+
+ m_CurrentActor->attachShape(*shape);
+ }
+ getPhysXController().getPhysXScene().addActor(*m_CurrentActor);
+ }
+ }
+
+ m_bNeedResetPos = true;
+ m_bNeedResetColor = true;
+ }
+ else if (m_CurrentActor != NULL)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ m_LastEyeRay = pickDir;
+
+ // get axis which intersect with this eye ray
+ AxisType as = AT_Num;
+ {
+ double distanceMin = PX_MAX_F32;
+ double tolerance = 1;
+ int line_index = -1;
+ std::vector<PxDebugLine>& lines = m_CircleRenderBuffer.m_lines;
+ int linesize = lines.size();
+ PxVec3 foot;
+ for (int l = 0; l < linesize; l++)
+ {
+ PxVec3 vertex = lines[l].pos0;
+ double distance = DistanceFromPointToLine(vertex, eyePos, pickDir, foot);
+
+ if (distance < distanceMin)
+ {
+ distanceMin = distance;
+ line_index = l;
+ m_LastFoot = foot;
+ }
+ }
+ if (distanceMin < tolerance)
+ {
+ int axis_index = line_index * 3 / linesize;
+ as = (AxisType)axis_index;
+ }
+ }
+ setAxisSelected(as);
+ }
+ }
+ else if (uMsg == WM_LBUTTONUP)
+ {
+ m_bNeedResetPos = true;
+ m_bNeedResetColor = true;
+ m_bGizmoFollowed = false;
+ }
+ }
+ }
+
+ return 1;
+}
+
+void GizmoToolController::drawUI()
+{
+}
+
+void GizmoToolController::setGizmoToolMode(GizmoToolMode mode)
+{
+ if (mode == m_GizmoToolMode)
+ {
+ return;
+ }
+
+ m_GizmoToolMode = mode;
+
+ m_bNeedResetPos = true;
+ m_bNeedResetColor = true;
+}
+
+void GizmoToolController::setAxisSelected(AxisType type)
+{
+ if (type == m_AxisSelected)
+ {
+ return;
+ }
+
+ m_AxisSelected = type;
+ m_bNeedResetColor = true;
+}
+
+void GizmoToolController::showAxisRenderables(bool show)
+{
+ bool isTranslate = m_GizmoToolMode == GTM_Translate;
+ bool isScale = m_GizmoToolMode == GTM_Scale;
+
+ m_AxisConeRenderable[AT_X]->setHidden(!show || !isTranslate);
+ m_AxisConeRenderable[AT_Y]->setHidden(!show || !isTranslate);
+ m_AxisConeRenderable[AT_Z]->setHidden(!show || !isTranslate);
+ m_AxisBoxRenderable[AT_X]->setHidden(!show || !isScale);
+ m_AxisBoxRenderable[AT_Y]->setHidden(!show || !isScale);
+ m_AxisBoxRenderable[AT_Z]->setHidden(!show || !isScale);
+}
+
+void GizmoToolController::resetPos()
+{
+ m_TargetPos = PxVec3(-100, -100, -100);
+ m_bNeedResetPos = true;
+
+ m_AxisSelected = AT_Num;
+ m_bNeedResetColor = true;
+
+ m_CurrentActor = NULL;
+}
+
+bool GizmoToolController::CalPlaneLineIntersectPoint(PxVec3& result, PxVec3 planeNormal, PxVec3 planePoint, PxVec3 linedirection, PxVec3 linePoint)
+{
+ float dot = planeNormal.dot(linedirection);
+ if (dot == 0)
+ {
+ return false;
+ }
+ else
+ {
+ float t = ((planePoint[0] - linePoint[0]) * planeNormal[0] +
+ (planePoint[1] - linePoint[1]) * planeNormal[1] +
+ (planePoint[2] - linePoint[2]) * planeNormal[2]) / dot;
+ result = linePoint + linedirection * t;
+ }
+ return true;
+}
+
+float GizmoToolController::DistanceFromPointToLine(PxVec3& point, PxVec3& origin, PxVec3& direction, PxVec3& foot)
+{
+ direction = direction.getNormalized();
+ PxVec3 sub = point - origin;
+ float t = direction.dot(sub);
+ foot = origin + direction * t;
+ PxVec3 dis = point - foot;
+ return dis.magnitude();
+}
+
+bool GizmoToolController::GetFootFromPointToPlane(PxVec3& point, PxVec3& origin, PxVec3& normal, PxVec3& foot)
+{
+ return CalPlaneLineIntersectPoint(foot, normal, origin, normal, point);
+}
+
+bool GizmoToolController::GetIntersectBetweenLines(PxVec3& origin1, PxVec3& direction1, PxVec3& origin2, PxVec3& direction2, PxVec3& intersect)
+{
+ PxVec3 normal1 = direction1.cross(direction2);
+ PxVec3 normal2 = normal1.cross(direction1);
+ normal2 = normal2.getNormalized();
+ return CalPlaneLineIntersectPoint(intersect, normal2, origin1, direction2, origin2);
+}
+
+PxQuat GizmoToolController::CalDirectionQuat(AxisType type)
+{
+ PxVec3 origin(0, 1, 0);
+ PxVec3 target = m_Axis[type];
+ if (type == AT_X)
+ {
+ target *= defaultAxisModifier;
+ }
+ target = target.getNormalized();
+ PxVec3 cross = origin.cross(target);
+ cross = cross.getNormalized();
+ float cos = origin.dot(target);
+ float angle = PxAcos(cos);
+ PxQuat q(angle, cross);
+ return q;
+}
+
+PxQuat GizmoToolController::CalConvertQuat()
+{
+ PxVec3 x_origin(1, 0, 0);
+ PxVec3 y_origin(0, 1, 0);
+ PxVec3 z_origin(0, 0, 1);
+
+ PxVec3 x_target = m_Axis[AT_X];
+ PxVec3 y_target = m_Axis[AT_Y];
+ x_target = x_target.getNormalized();
+ y_target = y_target.getNormalized();
+
+ PxVec3 x_cross = x_origin.cross(x_target);
+ x_cross = x_cross.getNormalized();
+ float x_cos = x_origin.dot(x_target);
+ float x_angle = PxAcos(x_cos);
+ PxQuat x_quat(x_angle, x_cross);
+
+ PxVec3 y_interval = x_quat.rotate(y_origin);
+
+ PxVec3 y_cross = y_interval.cross(y_target);
+ y_cross = y_cross.getNormalized();
+ float y_cos = y_interval.dot(y_target);
+ float y_angle = PxAcos(y_cos);
+ PxQuat y_quat(y_angle, y_cross);
+
+ PxQuat q = y_quat * x_quat;
+ return q;
+}
+
+void GizmoToolController::ScaleActor(bool replace)
+{
+ if (NULL == m_CurrentActor)
+ {
+ return;
+ }
+ ExtPxActor* extActor = NULL;
+ PxRigidDynamic* rigidDynamic = m_CurrentActor->is<PxRigidDynamic>();
+ if (NULL != rigidDynamic)
+ {
+ extActor = getBlastController().getExtPxManager().getActorFromPhysXActor(*rigidDynamic);
+ }
+ if (NULL == extActor)
+ {
+ return;
+ }
+
+ std::vector<BlastFamilyPtr>& families = getBlastController().getFamilies();
+ if (families.size() == 0)
+ {
+ return;
+ }
+
+ BlastFamilyPtr pBlastFamily = NULL;
+ std::vector<BlastFamilyPtr>::iterator it = families.begin();
+ for (; it != families.end(); it++)
+ {
+ BlastFamilyPtr f = *it;
+ if (f->find(extActor))
+ {
+ pBlastFamily = f;
+ break;
+ }
+ }
+ if (NULL == pBlastFamily)
+ {
+ return;
+ }
+
+ float multiply = m_Axis[m_AxisSelected].magnitude() / defaultAxisLength;
+ if (m_Axis[m_AxisSelected].dot(m_LastAxis[m_AxisSelected]) < 0)
+ {
+ multiply = -multiply;
+ }
+ PxVec3 delta(1, 1, 1);
+ bool isShift = (GetAsyncKeyState(VK_SHIFT) && 0x8000);
+ if (isShift)
+ {
+ delta *= multiply;
+ }
+ else
+ {
+ delta[m_AxisSelected] = multiply;
+ }
+ PxMat44 scale = PxMat44(PxVec4(delta, 1));
+
+ bool isLocal = AppMainWindow::Inst().m_bGizmoWithLocal;
+ if (!isLocal)
+ {
+ PxTransform gp = m_CurrentActor->getGlobalPose();
+ uint32_t shapesCount = m_CurrentActor->getNbShapes();
+ if (shapesCount > 0)
+ {
+ std::vector<PxShape*> shapes(shapesCount);
+ m_CurrentActor->getShapes(&shapes[0], shapesCount);
+ PxShape* shape = shapes[0];
+ PxTransform lp = shape->getLocalPose();
+ gp = gp * lp;
+ }
+ PxMat44 world = PxMat44(gp);
+ PxMat44 worldInv = world.inverseRT();
+ scale = world * scale * worldInv;
+ }
+
+ pBlastFamily->setActorScale(*extActor, scale, replace);
+
+ if (!replace)
+ {
+ return;
+ }
+
+ uint32_t shapesCount = m_CurrentActor->getNbShapes();
+ if (shapesCount == 0)
+ {
+ return;
+ }
+
+ std::vector<PxShape*> shapes(shapesCount);
+ m_CurrentActor->getShapes(&shapes[0], shapesCount);
+
+ getPhysXController().getPhysXScene().removeActor(*m_CurrentActor);
+
+ for (uint32_t i = 0; i < shapesCount; i++)
+ {
+ PxShape* shape = shapes[i];
+
+ PxConvexMeshGeometry mesh;
+ bool valid = shape->getConvexMeshGeometry(mesh);
+ if (!valid)
+ {
+ continue;
+ }
+
+ PxConvexMesh* pMesh = mesh.convexMesh;
+ if (NULL == pMesh)
+ {
+ continue;
+ }
+
+ PxU32 numVertex = pMesh->getNbVertices();
+ if (numVertex == 0)
+ {
+ continue;
+ }
+
+ const PxVec3* pVertex = pMesh->getVertices();
+ PxVec3* pVertexNew = new PxVec3[numVertex];
+ for (PxU32 v = 0; v < numVertex; v++)
+ {
+ pVertexNew[v] = scale.transform(pVertex[v]);
+ }
+
+ PxConvexMeshDesc convexMeshDesc;
+ convexMeshDesc.points.count = numVertex;
+ convexMeshDesc.points.data = pVertexNew;
+ convexMeshDesc.points.stride = sizeof(PxVec3);
+ convexMeshDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
+ PxPhysics& physics = getManager()->getPhysXController().getPhysics();
+ PxCooking& cooking = getManager()->getPhysXController().getCooking();
+ PxConvexMesh* convexMesh = cooking.createConvexMesh(convexMeshDesc, physics.getPhysicsInsertionCallback());
+ if (NULL == convexMesh)
+ {
+ delete[] pVertexNew;
+ continue;
+ }
+
+ mesh.convexMesh = convexMesh;
+
+ m_CurrentActor->detachShape(*shape);
+ shape->setGeometry(mesh);
+ m_CurrentActor->attachShape(*shape);
+
+ pMesh->release();
+ delete[] pVertexNew;
+ }
+
+ getPhysXController().getPhysXScene().addActor(*m_CurrentActor);
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/GizmoToolController.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/GizmoToolController.h
new file mode 100644
index 0000000..215cde5
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/GizmoToolController.h
@@ -0,0 +1,124 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef GIZMO_TOOL_CONTROLLER_H
+#define GIZMO_TOOL_CONTROLLER_H
+
+#include "SampleManager.h"
+#include "DebugRenderBuffer.h"
+#include "NvBlastExtPxManager.h"
+
+class Renderable;
+class RenderMaterial;
+
+namespace Nv
+{
+namespace Blast
+{
+class ExtPhysicsActor;
+}
+}
+
+enum AxisType
+{
+ AT_X = 0,
+ AT_Y = 1,
+ AT_Z = 2,
+ AT_Num
+};
+
+enum GizmoToolMode
+{
+ GTM_Translate = 0,
+ GTM_Scale,
+ GTM_Rotation
+};
+
+class GizmoToolController : public ISampleController
+{
+public:
+ GizmoToolController();
+ virtual ~GizmoToolController();
+
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Animate(double dt);
+ void drawUI();
+
+ virtual void onInitialize();
+ virtual void onSampleStart();
+ virtual void onSampleStop();
+
+ void setGizmoToolMode(GizmoToolMode mode);
+ void setAxisSelected(AxisType type);
+ void showAxisRenderables(bool show);
+ void resetPos();
+
+private:
+ GizmoToolController& operator= (GizmoToolController&);
+
+ //////// private methods ////////
+
+ bool CalPlaneLineIntersectPoint(PxVec3& result, PxVec3 planeNormal, PxVec3 planePoint, PxVec3 linedirection, PxVec3 linePoint);
+ float DistanceFromPointToLine(PxVec3& point, PxVec3& origin, PxVec3& direction, PxVec3& foot);
+ bool GetFootFromPointToPlane(PxVec3& point, PxVec3& origin, PxVec3& normal, PxVec3& foot);
+ bool GetIntersectBetweenLines(PxVec3& origin1, PxVec3& direction1, PxVec3& origin2, PxVec3& direction2, PxVec3& intersect);
+ PxQuat CalDirectionQuat(AxisType type);
+ PxQuat CalConvertQuat();
+ void ScaleActor(bool replace);
+ //////// used controllers ////////
+
+ Renderer& getRenderer() const
+ {
+ return getManager()->getRenderer();
+ }
+
+ PhysXController& getPhysXController() const
+ {
+ return getManager()->getPhysXController();
+ }
+
+ BlastController& getBlastController() const
+ {
+ return getManager()->getBlastController();
+ }
+
+ SelectionToolController& getSelectionToolController() const
+ {
+ return getManager()->getSelectionToolController();
+ }
+
+ //////// internal data ////////
+
+ GizmoToolMode m_GizmoToolMode;
+
+ bool m_bGizmoFollowed;
+ PxVec3 m_LastEyeRay;
+ PxVec3 m_LastFoot;
+ PxVec3 m_LastAxis[AT_Num];
+
+ PxRigidActor* m_CurrentActor;
+
+ bool m_bNeedResetPos;
+ bool m_bNeedResetColor;
+
+ PxVec3 m_TargetPos;
+ PxVec3 m_Axis[AT_Num];
+ AxisType m_AxisSelected;
+ Renderable* m_AxisConeRenderable[AT_Num];
+ Renderable* m_AxisBoxRenderable[AT_Num];
+
+ RenderMaterial* m_AxisRenderMaterial;
+ DebugRenderBuffer m_AxisRenderBuffer;
+
+ std::vector<PxDebugLine> m_CircleRenderData;
+ DebugRenderBuffer m_CircleRenderBuffer;
+};
+
+#endif // GIZMO_TOOL_CONTROLLER_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/SelectionToolController.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/SelectionToolController.cpp
new file mode 100644
index 0000000..02a511f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/SelectionToolController.cpp
@@ -0,0 +1,445 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "SelectionToolController.h"
+#include "RenderUtils.h"
+#include "BlastController.h"
+#include "Renderer.h"
+#include "PhysXController.h"
+#include "SampleProfiler.h"
+
+#include <imgui.h>
+
+#include "NvBlastTkActor.h"
+#include "NvBlastExtDamageShaders.h"
+
+#include "PxRigidDynamic.h"
+#include "PxScene.h"
+#include "BlastSceneTree.h"
+
+using namespace Nv::Blast;
+using namespace physx;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Setup
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+SelectionToolController::SelectionToolController()
+{
+ m_bRectSelecting = false;
+}
+
+SelectionToolController::~SelectionToolController()
+{
+}
+
+void SelectionToolController::onSampleStart()
+{
+}
+
+void SelectionToolController::onInitialize()
+{
+}
+
+
+void SelectionToolController::onSampleStop()
+{
+}
+
+void SelectionToolController::Animate(double dt)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ if (m_bRectSelecting)
+ {
+ getRenderer().queueRenderBuffer(&m_RectRenderBuffer);
+ }
+}
+
+
+LRESULT SelectionToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP)
+ {
+ float mouseX = (short)LOWORD(lParam) / getRenderer().getScreenWidth();
+ float mouseY = (short)HIWORD(lParam) / getRenderer().getScreenHeight();
+ bool press = uMsg == WM_LBUTTONDOWN;
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN)
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+
+ m_RectSelectScreenPos.x = mouseX;
+ m_RectSelectScreenPos.y = mouseY;
+ m_RectSelectSpaceDir = pickDir.getNormalized();
+
+ m_RectRenderBuffer.clear();
+ m_bRectSelecting = true;
+ }
+ else if (uMsg == WM_MOUSEMOVE)
+ {
+ if (m_bRectSelecting)
+ {
+ PxVec3 eyePos, pickDir[3];
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir[0]);
+ getPhysXController().getEyePoseAndPickDir(m_RectSelectScreenPos.x, mouseY, eyePos, pickDir[1]);
+ getPhysXController().getEyePoseAndPickDir(mouseX, m_RectSelectScreenPos.y, eyePos, pickDir[2]);
+ pickDir[0] = pickDir[0].getNormalized();
+ pickDir[1] = pickDir[1].getNormalized();
+ pickDir[2] = pickDir[2].getNormalized();
+
+ PxVec3 lefttop, leftbottom, righttop, rightbottom;
+
+ if (mouseX > m_RectSelectScreenPos.x) // right
+ {
+ if (mouseY > m_RectSelectScreenPos.y) // top
+ {
+ leftbottom = m_RectSelectSpaceDir;
+ righttop = pickDir[0];
+ lefttop = pickDir[2];
+ rightbottom = pickDir[1];
+ }
+ else // bottom
+ {
+ leftbottom = pickDir[1];
+ righttop = pickDir[2];
+ lefttop = m_RectSelectSpaceDir;
+ rightbottom = pickDir[0];
+ }
+ }
+ else // left
+ {
+ if (mouseY > m_RectSelectScreenPos.y) // top
+ {
+ leftbottom = pickDir[2];
+ righttop = pickDir[1];
+ lefttop = pickDir[0];
+ rightbottom = m_RectSelectSpaceDir;
+ }
+ else // bottom
+ {
+ leftbottom = pickDir[0];
+ righttop = m_RectSelectSpaceDir;
+ lefttop = pickDir[2];
+ rightbottom = pickDir[1];
+ }
+ }
+
+ float multiply = 10; // in order to draw line
+ lefttop = eyePos + lefttop * multiply;
+ righttop = eyePos + righttop * multiply;
+ leftbottom = eyePos + leftbottom * multiply;
+ rightbottom = eyePos + rightbottom * multiply;
+
+ m_RectRenderBuffer.clear();
+
+ DirectX::XMFLOAT4 LINE_COLOR(1.0f, 0.0f, 0.0f, 1.0f);
+ m_RectRenderBuffer.m_lines.push_back(PxDebugLine(lefttop, leftbottom, XMFLOAT4ToU32Color(LINE_COLOR)));
+ m_RectRenderBuffer.m_lines.push_back(PxDebugLine(lefttop, righttop, XMFLOAT4ToU32Color(LINE_COLOR)));
+ m_RectRenderBuffer.m_lines.push_back(PxDebugLine(righttop, rightbottom, XMFLOAT4ToU32Color(LINE_COLOR)));
+ m_RectRenderBuffer.m_lines.push_back(PxDebugLine(leftbottom, rightbottom, XMFLOAT4ToU32Color(LINE_COLOR)));
+ }
+ }
+ else if (uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP)
+ {
+ if (uMsg == WM_RBUTTONUP && m_actorsSelected.size() > 1)
+ {
+ return 1;
+ }
+
+ if (m_bRectSelecting)
+ {
+ bool isShift = (GetAsyncKeyState(VK_SHIFT) && 0x8000);
+ bool isCtrl = (GetAsyncKeyState(VK_CONTROL) && 0x8000);
+
+ SelectMode selectMode = SM_RESET;
+ if (isShift && isCtrl)
+ {
+ selectMode = SM_REMAIN;
+ }
+ else if (isShift)
+ {
+ selectMode = SM_ADD;
+ }
+ else if (isCtrl)
+ {
+ selectMode = SM_SUB;
+ }
+
+ int width = getRenderer().getScreenWidth();
+ int height = getRenderer().getScreenHeight();
+ int deltaX = (mouseX - m_RectSelectScreenPos.x) * width;
+ int deltaY = (mouseY - m_RectSelectScreenPos.y) * height;
+ float distance = deltaX * deltaX + deltaY * deltaY;
+ // rect select mode
+ if (distance > 1)
+ {
+ PxVec3 eyePos, pickDir[3];
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir[0]);
+ getPhysXController().getEyePoseAndPickDir(m_RectSelectScreenPos.x, mouseY, eyePos, pickDir[1]);
+ getPhysXController().getEyePoseAndPickDir(mouseX, m_RectSelectScreenPos.y, eyePos, pickDir[2]);
+ pickDir[0] = pickDir[0].getNormalized();
+ pickDir[1] = pickDir[1].getNormalized();
+ pickDir[2] = pickDir[2].getNormalized();
+
+ PxVec3 lefttop, leftbottom, righttop, rightbottom;
+
+ if (mouseX > m_RectSelectScreenPos.x) // right
+ {
+ if (mouseY > m_RectSelectScreenPos.y) // top
+ {
+ leftbottom = m_RectSelectSpaceDir;
+ righttop = pickDir[0];
+ lefttop = pickDir[2];
+ rightbottom = pickDir[1];
+ }
+ else // bottom
+ {
+ leftbottom = pickDir[1];
+ righttop = pickDir[2];
+ lefttop = m_RectSelectSpaceDir;
+ rightbottom = pickDir[0];
+ }
+ }
+ else // left
+ {
+ if (mouseY > m_RectSelectScreenPos.y) // top
+ {
+ leftbottom = pickDir[2];
+ righttop = pickDir[1];
+ lefttop = pickDir[0];
+ rightbottom = m_RectSelectSpaceDir;
+ }
+ else // bottom
+ {
+ leftbottom = pickDir[0];
+ righttop = m_RectSelectSpaceDir;
+ lefttop = pickDir[2];
+ rightbottom = pickDir[1];
+ }
+ }
+
+ rectSelect(eyePos, lefttop, leftbottom, righttop, rightbottom, selectMode);
+ }
+ // point select mode
+ else
+ {
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ PxRaycastHit hit; hit.shape = NULL;
+ PxRaycastBuffer hit1;
+ getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL);
+ hit = hit1.block;
+
+ PxRigidActor* actor = NULL;
+ if (hit.shape)
+ {
+ actor = hit.actor;
+ }
+ pointSelect(actor, selectMode);
+ }
+ }
+
+ BlastSceneTree::ins()->updateChunkItemSelection();
+ m_RectRenderBuffer.clear();
+ m_bRectSelecting = false;
+ }
+ }
+
+ return 1;
+}
+
+void SelectionToolController::drawUI()
+{
+}
+
+void SelectionToolController::pointSelect(PxActor* actor, SelectMode selectMode)
+{
+ ExtPxActor* extActor = NULL;
+ if (NULL != actor)
+ {
+ PxRigidDynamic* rigidDynamic = actor->is<PxRigidDynamic>();
+ if (NULL != rigidDynamic)
+ {
+ extActor = getBlastController().getExtPxManager().getActorFromPhysXActor(*rigidDynamic);
+ }
+ }
+
+ if (selectMode == SM_RESET)
+ {
+ clearSelect();
+
+ if (NULL != extActor)
+ {
+ setActorSelected(*extActor, true);
+ m_actorsSelected.emplace(extActor);
+ }
+ }
+ else if (selectMode == SM_ADD)
+ {
+ if (NULL != extActor)
+ {
+ setActorSelected(*extActor, true);
+ m_actorsSelected.emplace(extActor);
+ }
+ }
+ else if (selectMode == SM_SUB)
+ {
+ if (NULL != extActor)
+ {
+ setActorSelected(*extActor, false);
+ m_actorsSelected.erase(extActor);
+ }
+ }
+}
+
+#include "PxPhysics.h"
+#include "cooking/PxCooking.h"
+
+class RectSelectionCallback : public PxOverlapCallback
+{
+public:
+ RectSelectionCallback(ExtPxManager& physicsManager, std::set<ExtPxActor*>& actorBuffer)
+ : m_physicsManager(physicsManager), m_actorBuffer(actorBuffer), PxOverlapCallback(m_hitBuffer, sizeof(m_hitBuffer) / sizeof(m_hitBuffer[0])) {}
+
+ PxAgain processTouches(const PxOverlapHit* buffer, PxU32 nbHits)
+ {
+ for (PxU32 i = 0; i < nbHits; ++i)
+ {
+ PxRigidDynamic* rigidDynamic = buffer[i].actor->is<PxRigidDynamic>();
+ if (rigidDynamic)
+ {
+ ExtPxActor* actor = m_physicsManager.getActorFromPhysXActor(*rigidDynamic);
+ if (actor != nullptr)
+ {
+ m_actorBuffer.insert(actor);
+ }
+ }
+ }
+ return true;
+ }
+
+private:
+ ExtPxManager& m_physicsManager;
+ std::set<ExtPxActor*>& m_actorBuffer;
+ PxOverlapHit m_hitBuffer[1000];
+};
+
+void SelectionToolController::rectSelect(PxVec3 eyePos, PxVec3 lefttop, PxVec3 leftbottom, PxVec3 righttop, PxVec3 rightbottom, SelectMode selectMode)
+{
+ std::set<ExtPxActor*> actorsToSelect;
+
+ float nearClip = 1;
+ PxVec3 nearlefttop = lefttop * nearClip;
+ PxVec3 nearrighttop = righttop * nearClip;
+ PxVec3 nearleftbottom = leftbottom * nearClip;
+ PxVec3 nearrightbottom = rightbottom * nearClip;
+
+ float farClip = 1000;
+ PxVec3 farlefttop = lefttop * farClip;
+ PxVec3 farrighttop = righttop * farClip;
+ PxVec3 farleftbottom = leftbottom * farClip;
+ PxVec3 farrightbottom = rightbottom * farClip;
+
+ PxVec3 vertices[8] =
+ {
+ nearlefttop, nearrighttop, nearleftbottom, nearrightbottom,
+ farlefttop, farrighttop, farleftbottom, farrightbottom
+ };
+ PxConvexMeshDesc convexMeshDesc;
+ convexMeshDesc.points.count = 8;
+ convexMeshDesc.points.data = vertices;
+ convexMeshDesc.points.stride = sizeof(PxVec3);
+ convexMeshDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
+ PxPhysics& physics = getManager()->getPhysXController().getPhysics();
+ PxCooking& cooking = getManager()->getPhysXController().getCooking();
+ PxConvexMesh* convexMesh = cooking.createConvexMesh(convexMeshDesc, physics.getPhysicsInsertionCallback());
+ if (NULL != convexMesh)
+ {
+ RectSelectionCallback overlapCallback(getBlastController().getExtPxManager(), actorsToSelect);
+ getManager()->getPhysXController().getPhysXScene().overlap(PxConvexMeshGeometry(convexMesh), PxTransform(eyePos), overlapCallback);
+ convexMesh->release();
+ }
+
+ if (selectMode == SM_RESET)
+ {
+ clearSelect();
+
+ for (ExtPxActor* actor : actorsToSelect)
+ {
+ setActorSelected(*actor, true);
+ m_actorsSelected.emplace(actor);
+ }
+ }
+ else if (selectMode == SM_ADD)
+ {
+ for (ExtPxActor* actor : actorsToSelect)
+ {
+ setActorSelected(*actor, true);
+ m_actorsSelected.emplace(actor);
+ }
+ }
+ else if (selectMode == SM_SUB)
+ {
+ for (ExtPxActor* actor : actorsToSelect)
+ {
+ setActorSelected(*actor, false);
+ m_actorsSelected.erase(actor);
+ }
+ }
+}
+
+void SelectionToolController::clearSelect()
+{
+ for (ExtPxActor* actor : m_actorsSelected)
+ {
+ setActorSelected(*actor, false);
+ }
+
+ m_actorsSelected.clear();
+ SampleManager::ins()->clearChunksSelected();
+}
+
+void SelectionToolController::setActorSelected(const ExtPxActor& actor, bool selected)
+{
+ std::vector<BlastFamilyPtr>& families = getBlastController().getFamilies();
+ if (families.size() == 0)
+ {
+ return;
+ }
+
+ BlastFamilyPtr pBlastFamily = NULL;
+ std::vector<BlastFamilyPtr>::iterator it = families.begin();
+ for (; it != families.end(); it++)
+ {
+ BlastFamilyPtr f = *it;
+ if (f->find((ExtPxActor*)&actor))
+ {
+ pBlastFamily = f;
+ break;
+ }
+ }
+ if (NULL == pBlastFamily)
+ {
+ return;
+ }
+
+ pBlastFamily->setActorSelected(actor, selected);
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/SelectionToolController.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/SelectionToolController.h
new file mode 100644
index 0000000..5261b90
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/SelectionToolController.h
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SELECTION_TOOL_CONTROLLER_H
+#define SELECTION_TOOL_CONTROLLER_H
+
+#include "SampleManager.h"
+#include "PxVec2.h"
+#include "PxVec3.h"
+#include "DebugRenderBuffer.h"
+#include "BlastFamily.h"
+#include "NvBlastExtPxManager.h"
+class Renderable;
+class RenderMaterial;
+
+namespace Nv
+{
+namespace Blast
+{
+class ExtPxActor;
+}
+}
+
+class SelectionToolController : public ISampleController
+{
+public:
+ SelectionToolController();
+ virtual ~SelectionToolController();
+
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Animate(double dt);
+ void drawUI();
+
+ virtual void onInitialize();
+ virtual void onSampleStart();
+ virtual void onSampleStop();
+
+ void pointSelect(PxActor* actor, SelectMode selectMode = SM_RESET);
+ void rectSelect(PxVec3 eyePos, PxVec3 lefttop, PxVec3 leftbottom, PxVec3 righttop, PxVec3 rightbottom, SelectMode selectMode = SM_RESET);
+ void clearSelect();
+
+private:
+ SelectionToolController& operator= (SelectionToolController&);
+
+ //////// private methods ////////
+
+ //////// used controllers ////////
+
+ Renderer& getRenderer() const
+ {
+ return getManager()->getRenderer();
+ }
+
+ PhysXController& getPhysXController() const
+ {
+ return getManager()->getPhysXController();
+ }
+
+ BlastController& getBlastController() const
+ {
+ return getManager()->getBlastController();
+ }
+
+ //////// internal data ////////
+
+ PxVec2 m_RectSelectScreenPos;
+ PxVec3 m_RectSelectSpaceDir;
+ bool m_bRectSelecting;
+ DebugRenderBuffer m_RectRenderBuffer;
+
+ void setActorSelected(const ExtPxActor& actor, bool selected);
+ std::set<ExtPxActor*> m_actorsSelected;
+};
+
+#endif // SELECTION_TOOL_CONTROLLER_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/imgui_impl_dx11.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/imgui_impl_dx11.cpp
new file mode 100644
index 0000000..11f66f0
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/imgui_impl_dx11.cpp
@@ -0,0 +1,583 @@
+// ImGui Win32 + DirectX11 binding
+// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
+
+// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
+// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
+// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
+// https://github.com/ocornut/imgui
+
+#include <imgui.h>
+#include "imgui_impl_dx11.h"
+
+// DirectX
+#include <d3d11.h>
+#include <d3dcompiler.h>
+#define DIRECTINPUT_VERSION 0x0800
+#include <dinput.h>
+
+// Data
+static INT64 g_Time = 0;
+static INT64 g_TicksPerSecond = 0;
+
+static HWND g_hWnd = 0;
+static ID3D11Device* g_pd3dDevice = NULL;
+static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
+static ID3D11Buffer* g_pVB = NULL;
+static ID3D11Buffer* g_pIB = NULL;
+static ID3D10Blob * g_pVertexShaderBlob = NULL;
+static ID3D11VertexShader* g_pVertexShader = NULL;
+static ID3D11InputLayout* g_pInputLayout = NULL;
+static ID3D11Buffer* g_pVertexConstantBuffer = NULL;
+static ID3D10Blob * g_pPixelShaderBlob = NULL;
+static ID3D11PixelShader* g_pPixelShader = NULL;
+static ID3D11SamplerState* g_pFontSampler = NULL;
+static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
+static ID3D11RasterizerState* g_pRasterizerState = NULL;
+static ID3D11BlendState* g_pBlendState = NULL;
+static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
+static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
+
+struct VERTEX_CONSTANT_BUFFER
+{
+ float mvp[4][4];
+};
+
+// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
+// If text or lines are blurry when integrating ImGui in your engine:
+// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
+void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data)
+{
+ ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
+
+ // Create and grow vertex/index buffers if needed
+ if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
+ {
+ if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
+ g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
+ D3D11_BUFFER_DESC desc;
+ memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
+ desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+ if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
+ return;
+ }
+ if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
+ {
+ if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
+ g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
+ D3D11_BUFFER_DESC desc;
+ memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
+ desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)
+ return;
+ }
+
+ // Copy and convert all vertices into a single contiguous buffer
+ D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
+ if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
+ return;
+ if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
+ return;
+ ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
+ ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
+ memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx));
+ vtx_dst += cmd_list->VtxBuffer.size();
+ idx_dst += cmd_list->IdxBuffer.size();
+ }
+ ctx->Unmap(g_pVB, 0);
+ ctx->Unmap(g_pIB, 0);
+
+ // Setup orthographic projection matrix into our constant buffer
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped_resource;
+ if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
+ return;
+ VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
+ float L = 0.0f;
+ float R = ImGui::GetIO().DisplaySize.x;
+ float B = ImGui::GetIO().DisplaySize.y;
+ float T = 0.0f;
+ float mvp[4][4] =
+ {
+ { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
+ { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.5f, 0.0f },
+ { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
+ };
+ memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
+ ctx->Unmap(g_pVertexConstantBuffer, 0);
+ }
+
+ // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
+ struct BACKUP_DX11_STATE
+ {
+ UINT ScissorRectsCount, ViewportsCount;
+ D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ ID3D11RasterizerState* RS;
+ ID3D11BlendState* BlendState;
+ FLOAT BlendFactor[4];
+ UINT SampleMask;
+ UINT StencilRef;
+ ID3D11DepthStencilState* DepthStencilState;
+ ID3D11ShaderResourceView* PSShaderResource;
+ ID3D11SamplerState* PSSampler;
+ ID3D11PixelShader* PS;
+ ID3D11VertexShader* VS;
+ UINT PSInstancesCount, VSInstancesCount;
+ ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
+ D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
+ ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
+ UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
+ DXGI_FORMAT IndexBufferFormat;
+ ID3D11InputLayout* InputLayout;
+ };
+ BACKUP_DX11_STATE old;
+ old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
+ ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
+ ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
+ ctx->RSGetState(&old.RS);
+ ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
+ ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
+ ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
+ ctx->PSGetSamplers(0, 1, &old.PSSampler);
+ old.PSInstancesCount = old.VSInstancesCount = 256;
+ ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
+ ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
+ ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
+ ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
+ ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
+ ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
+ ctx->IAGetInputLayout(&old.InputLayout);
+
+ // Setup viewport
+ D3D11_VIEWPORT vp;
+ memset(&vp, 0, sizeof(D3D11_VIEWPORT));
+ vp.Width = ImGui::GetIO().DisplaySize.x;
+ vp.Height = ImGui::GetIO().DisplaySize.y;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ vp.TopLeftX = vp.TopLeftY = 0.0f;
+ ctx->RSSetViewports(1, &vp);
+
+ // Bind shader and vertex buffers
+ unsigned int stride = sizeof(ImDrawVert);
+ unsigned int offset = 0;
+ ctx->IASetInputLayout(g_pInputLayout);
+ ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
+ ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
+ ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ ctx->VSSetShader(g_pVertexShader, NULL, 0);
+ ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
+ ctx->PSSetShader(g_pPixelShader, NULL, 0);
+ ctx->PSSetSamplers(0, 1, &g_pFontSampler);
+
+ // Setup render state
+ const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
+ ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
+ ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
+ ctx->RSSetState(g_pRasterizerState);
+
+ // Render command lists
+ int vtx_offset = 0;
+ int idx_offset = 0;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
+ ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId);
+ ctx->RSSetScissorRects(1, &r);
+ ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
+ }
+ idx_offset += pcmd->ElemCount;
+ }
+ vtx_offset += cmd_list->VtxBuffer.size();
+ }
+
+ // Restore modified DX state
+ ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
+ ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
+ ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
+ ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
+ ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
+ ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
+ ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
+ ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
+ for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
+ ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
+ ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
+ for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
+ ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
+ ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
+ ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
+ ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
+}
+
+IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ switch (msg)
+ {
+ case WM_LBUTTONDOWN:
+ io.MouseDown[0] = true;
+ return true;
+ case WM_LBUTTONUP:
+ io.MouseDown[0] = false;
+ return true;
+ case WM_RBUTTONDOWN:
+ io.MouseDown[1] = true;
+ return true;
+ case WM_RBUTTONUP:
+ io.MouseDown[1] = false;
+ return true;
+ case WM_MBUTTONDOWN:
+ io.MouseDown[2] = true;
+ return true;
+ case WM_MBUTTONUP:
+ io.MouseDown[2] = false;
+ return true;
+ case WM_MOUSEWHEEL:
+ io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
+ return true;
+ case WM_MOUSEMOVE:
+ io.MousePos.x = (signed short)(lParam);
+ io.MousePos.y = (signed short)(lParam >> 16);
+ return true;
+ case WM_KEYDOWN:
+ if (wParam < 256)
+ io.KeysDown[wParam] = 1;
+ return true;
+ case WM_KEYUP:
+ if (wParam < 256)
+ io.KeysDown[wParam] = 0;
+ return true;
+ case WM_CHAR:
+ // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
+ if (wParam > 0 && wParam < 0x10000)
+ io.AddInputCharacter((unsigned short)wParam);
+ return true;
+ }
+ return 0;
+}
+
+static void ImGui_ImplDX11_CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGuiIO& io = ImGui::GetIO();
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ // Upload texture to graphics system
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.SampleDesc.Count = 1;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+
+ ID3D11Texture2D *pTexture = NULL;
+ D3D11_SUBRESOURCE_DATA subResource;
+ subResource.pSysMem = pixels;
+ subResource.SysMemPitch = desc.Width * 4;
+ subResource.SysMemSlicePitch = 0;
+ g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
+
+ // Create texture view
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ ZeroMemory(&srvDesc, sizeof(srvDesc));
+ srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MipLevels = desc.MipLevels;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
+ pTexture->Release();
+ }
+
+ // Store our identifier
+ io.Fonts->TexID = (void *)g_pFontTextureView;
+
+ // Create texture sampler
+ {
+ D3D11_SAMPLER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.MipLODBias = 0.f;
+ desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
+ desc.MinLOD = 0.f;
+ desc.MaxLOD = 0.f;
+ g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
+ }
+}
+
+bool ImGui_ImplDX11_CreateDeviceObjects()
+{
+ if (!g_pd3dDevice)
+ return false;
+ if (g_pFontSampler)
+ ImGui_ImplDX11_InvalidateDeviceObjects();
+
+ // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
+ // If you would like to use this DX11 sample code but remove this dependency you can:
+ // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [prefered solution]
+ // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
+ // See https://github.com/ocornut/imgui/pull/638 for sources and details.
+
+ // Create the vertex shader
+ {
+ static const char* vertexShader =
+ "cbuffer vertexBuffer : register(b0) \
+ {\
+ float4x4 ProjectionMatrix; \
+ };\
+ struct VS_INPUT\
+ {\
+ float2 pos : POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ PS_INPUT main(VS_INPUT input)\
+ {\
+ PS_INPUT output;\
+ output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
+ output.col = input.col;\
+ output.uv = input.uv;\
+ return output;\
+ }";
+
+ D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL);
+ if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ return false;
+ if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK)
+ return false;
+
+ // Create the input layout
+ D3D11_INPUT_ELEMENT_DESC local_layout[] = {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+ if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
+ return false;
+
+ // Create the constant buffer
+ {
+ D3D11_BUFFER_DESC desc;
+ desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+ g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
+ }
+ }
+
+ // Create the pixel shader
+ {
+ static const char* pixelShader =
+ "struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ sampler sampler0;\
+ Texture2D texture0;\
+ \
+ float4 main(PS_INPUT input) : SV_Target\
+ {\
+ float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
+ return out_col; \
+ }";
+
+ D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL);
+ if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ return false;
+ if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK)
+ return false;
+ }
+
+ // Create the blending setup
+ {
+ D3D11_BLEND_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.AlphaToCoverageEnable = false;
+ desc.RenderTarget[0].BlendEnable = true;
+ desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
+ desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
+ desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
+ desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
+ desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
+ g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
+ }
+
+ // Create the rasterizer state
+ {
+ D3D11_RASTERIZER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.FillMode = D3D11_FILL_SOLID;
+ desc.CullMode = D3D11_CULL_NONE;
+ desc.ScissorEnable = true;
+ desc.DepthClipEnable = true;
+ g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
+ }
+
+ // Create depth-stencil State
+ {
+ D3D11_DEPTH_STENCIL_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.DepthEnable = false;
+ desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
+ desc.StencilEnable = false;
+ desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+ desc.BackFace = desc.FrontFace;
+ g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
+ }
+
+ ImGui_ImplDX11_CreateFontsTexture();
+
+ return true;
+}
+
+void ImGui_ImplDX11_InvalidateDeviceObjects()
+{
+ if (!g_pd3dDevice)
+ return;
+
+ if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
+ if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = 0; }
+ if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
+ if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
+
+ if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
+ if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
+ if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
+ if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
+ if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
+ if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
+ if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }
+ if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }
+ if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; }
+}
+
+bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context)
+{
+ g_hWnd = (HWND)hwnd;
+ g_pd3dDevice = device;
+ g_pd3dDeviceContext = device_context;
+
+ if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond))
+ return false;
+ if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time))
+ return false;
+
+ ImGuiIO& io = ImGui::GetIO();
+ io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime.
+ io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
+ io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
+ io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
+ io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
+ io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
+ io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
+ io.KeyMap[ImGuiKey_Home] = VK_HOME;
+ io.KeyMap[ImGuiKey_End] = VK_END;
+ io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
+ io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
+ io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
+ io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
+ io.KeyMap[ImGuiKey_A] = 'A';
+ io.KeyMap[ImGuiKey_C] = 'C';
+ io.KeyMap[ImGuiKey_V] = 'V';
+ io.KeyMap[ImGuiKey_X] = 'X';
+ io.KeyMap[ImGuiKey_Y] = 'Y';
+ io.KeyMap[ImGuiKey_Z] = 'Z';
+
+ io.RenderDrawListsFn = ImGui_ImplDX11_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
+ io.ImeWindowHandle = g_hWnd;
+
+ return true;
+}
+
+void ImGui_ImplDX11_Shutdown()
+{
+ ImGui_ImplDX11_InvalidateDeviceObjects();
+ ImGui::Shutdown();
+ g_pd3dDevice = NULL;
+ g_pd3dDeviceContext = NULL;
+ g_hWnd = (HWND)0;
+}
+
+void ImGui_ImplDX11_NewFrame()
+{
+ if (!g_pFontSampler)
+ ImGui_ImplDX11_CreateDeviceObjects();
+
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Setup display size (every frame to accommodate for window resizing)
+ RECT rect;
+ GetClientRect(g_hWnd, &rect);
+ io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
+
+ // Setup time step
+ INT64 current_time;
+ QueryPerformanceCounter((LARGE_INTEGER *)&current_time);
+ io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond;
+ g_Time = current_time;
+
+ // Read keyboard modifiers inputs
+ io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
+ io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
+ io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
+ io.KeySuper = false;
+ // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events
+ // io.MousePos : filled by WM_MOUSEMOVE events
+ // io.MouseDown : filled by WM_*BUTTON* events
+ // io.MouseWheel : filled by WM_MOUSEWHEEL events
+
+ // Hide OS mouse cursor if ImGui is drawing it
+ SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW));
+
+ // Start the frame
+ ImGui::NewFrame();
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/imgui_impl_dx11.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/imgui_impl_dx11.h
new file mode 100644
index 0000000..7d6f710
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/ui/imgui_impl_dx11.h
@@ -0,0 +1,25 @@
+// ImGui Win32 + DirectX11 binding
+// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
+
+// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
+// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
+// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
+// https://github.com/ocornut/imgui
+
+struct ID3D11Device;
+struct ID3D11DeviceContext;
+
+IMGUI_API bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context);
+IMGUI_API void ImGui_ImplDX11_Shutdown();
+IMGUI_API void ImGui_ImplDX11_NewFrame();
+
+// Use if you want to reset your rendering device without losing ImGui state.
+IMGUI_API void ImGui_ImplDX11_InvalidateDeviceObjects();
+IMGUI_API bool ImGui_ImplDX11_CreateDeviceObjects();
+
+// Handler for Win32 messages, update mouse/keyboard data.
+// You may or not need this for your implementation, but it can serve as reference for handling inputs.
+// Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.
+/*
+IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+*/
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/PxInputDataFromPxFileBuf.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/PxInputDataFromPxFileBuf.h
new file mode 100644
index 0000000..dfa8260
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/PxInputDataFromPxFileBuf.h
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef PXINPUTDATAFROMPXFILEBUF_H
+#define PXINPUTDATAFROMPXFILEBUF_H
+
+#include <PsFileBuffer.h>
+
+
+// Copied from APEX
+class PxInputDataFromPxFileBuf : public physx::PxInputData
+{
+public:
+ PxInputDataFromPxFileBuf(physx::PxFileBuf& fileBuf) : mFileBuf(fileBuf) {}
+
+ // physx::PxInputData interface
+ virtual uint32_t getLength() const
+ {
+ return mFileBuf.getFileLength();
+ }
+
+ virtual void seek(uint32_t offset)
+ {
+ mFileBuf.seekRead(offset);
+ }
+
+ virtual uint32_t tell() const
+ {
+ return mFileBuf.tellRead();
+ }
+
+ // physx::PxInputStream interface
+ virtual uint32_t read(void* dest, uint32_t count)
+ {
+ return mFileBuf.read(dest, count);
+ }
+
+ PX_NOCOPY(PxInputDataFromPxFileBuf)
+private:
+ physx::PxFileBuf& mFileBuf;
+};
+
+
+#endif //PXINPUTDATAFROMPXFILEBUF_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleProfiler.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleProfiler.cpp
new file mode 100644
index 0000000..4df23fd
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleProfiler.cpp
@@ -0,0 +1,223 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+
+#include "SampleProfiler.h"
+#include <map>
+#include <iostream>
+#include <fstream>
+#include <stack>
+
+using namespace std::chrono;
+
+struct ProfileData
+{
+ steady_clock::time_point start;
+
+ microseconds time;
+ microseconds prevTime;
+ microseconds maxTime;
+ uint32_t calls;
+ uint32_t prevCalls;
+
+ ProfileData() : time(0), prevTime(0), maxTime(0), calls(0), prevCalls(0)
+ {}
+};
+
+struct Node
+{
+ ProfileData data;
+ std::map<const char*, Node> childs;
+ Node* parent;
+};
+
+static std::map<const char*, Node> s_roots;
+static Node* s_currentNode;
+static bool s_beginEndMismatch;
+static microseconds s_overhead;
+static microseconds s_prevOverhead;
+
+void SampleProfilerInit()
+{
+ s_roots.clear();
+ s_currentNode = nullptr;
+ s_beginEndMismatch = false;
+ s_overhead = microseconds();
+}
+
+void SampleProfilerBegin(const char* name)
+{
+ auto start = steady_clock::now();
+ {
+ Node* parent = s_currentNode;
+ if (s_currentNode == nullptr)
+ {
+ s_currentNode = &s_roots[name];
+ }
+ else
+ {
+ s_currentNode = &s_currentNode->childs[name];
+ }
+ s_currentNode->parent = parent;
+ s_currentNode->data.calls++;
+ s_currentNode->data.start = steady_clock::now();
+ }
+ s_overhead += duration_cast<microseconds>(steady_clock::now() - start);
+}
+
+void SampleProfilerEnd()
+{
+ auto start = steady_clock::now();
+ {
+ if (s_currentNode)
+ {
+ auto& data = s_currentNode->data;
+ data.time += duration_cast<microseconds>(steady_clock::now() - data.start);
+ data.maxTime = data.time > data.maxTime ? data.time : data.maxTime;
+ s_currentNode = s_currentNode->parent;
+ }
+ else
+ {
+ s_beginEndMismatch = true;
+ }
+ }
+ s_overhead += duration_cast<microseconds>(steady_clock::now() - start);
+}
+
+struct SampleProfilerTreeIteratorImpl final : public SampleProfilerTreeIterator
+{
+ struct StackNode
+ {
+ Node* node;
+ const char* name;
+ };
+
+ SampleProfilerTreeIteratorImpl(std::map<const char*, Node>& roots)
+ {
+ for (auto& root : roots)
+ {
+ m_stack.emplace(StackNode { &root.second, root.first });
+ }
+
+ next();
+ }
+
+ virtual const Data* data() const override
+ {
+ return m_valid ? &m_data : nullptr;
+ }
+
+ Node* node()
+ {
+ return m_node;
+ }
+
+ virtual bool isDone() const
+ {
+ return !m_valid;
+ }
+
+ virtual void next()
+ {
+ if (!m_stack.empty())
+ {
+ auto& e = m_stack.top();
+ m_stack.pop();
+ m_node = e.node;
+ m_data.depth = 0;
+ m_data.hash = (uint64_t)m_node;
+ for (const Node* p = m_node; p != nullptr; p = p->parent)
+ {
+ m_data.depth++;
+ }
+ m_data.name = e.name;
+ m_data.calls = m_node->data.prevCalls;
+ m_data.time = m_node->data.prevTime;
+ m_data.maxTime = m_node->data.maxTime;
+ m_data.hasChilds = !m_node->childs.empty();
+
+ for (auto it = m_node->childs.rbegin(); it != m_node->childs.rend(); ++it)
+ {
+ m_stack.emplace(StackNode { &(*it).second, (*it).first });
+ }
+ m_valid = true;
+ }
+ else
+ {
+ m_valid = false;
+ }
+ }
+
+ virtual void release()
+ {
+ delete this;
+ }
+
+ bool m_valid;
+ Data m_data;
+ Node* m_node;
+ std::stack<StackNode > m_stack;
+};
+
+void SampleProfilerReset()
+{
+ for (SampleProfilerTreeIteratorImpl it(s_roots); !it.isDone(); it.next())
+ {
+ auto& data = it.node()->data;
+ data.prevTime = data.time;
+ data.prevCalls = data.calls;
+ data.time = microseconds();
+ data.calls = 0;
+ }
+ s_currentNode = nullptr;
+ s_beginEndMismatch = false;
+ s_prevOverhead = s_overhead;
+ s_overhead = microseconds();
+}
+
+bool SampleProfilerIsValid()
+{
+ return !s_beginEndMismatch;
+}
+
+microseconds SampleProfilerGetOverhead()
+{
+ return s_prevOverhead;
+}
+
+SampleProfilerTreeIterator* SampleProfilerCreateTreeIterator()
+{
+ return SampleProfilerIsValid() ? new SampleProfilerTreeIteratorImpl(s_roots) : nullptr;
+}
+
+void SampleProfilerDumpToFile(const char* path)
+{
+ std::ofstream myfile(path, std::ios_base::out);
+ if (myfile.is_open())
+ {
+ if (s_beginEndMismatch)
+ {
+ myfile << "Error: Begin/End Mismatch.\n";
+ }
+ else
+ {
+ myfile << "[Root]\n";
+ for(SampleProfilerTreeIteratorImpl it(s_roots); !it.isDone(); it.next())
+ {
+ auto data = it.data();
+ for (uint32_t i = 0; i < data->depth; ++i)
+ myfile << "\t";
+ myfile << data->name << " --> calls: " << data->calls << ", total: " << data->time.count() * 0.001 << "ms\n";
+ }
+ }
+
+ myfile.close();
+ }
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleProfiler.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleProfiler.h
new file mode 100644
index 0000000..1ea3663
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleProfiler.h
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SAMPLEPROFILER_H
+#define SAMPLEPROFILER_H
+
+#include <chrono>
+
+#if NV_PROFILE
+
+void SampleProfilerInit();
+void SampleProfilerBegin(const char* name);
+void SampleProfilerEnd();
+void SampleProfilerReset();
+
+struct SampleProfilerScoped
+{
+ SampleProfilerScoped(const char* name)
+ {
+ SampleProfilerBegin(name);
+ }
+
+ ~SampleProfilerScoped()
+ {
+ SampleProfilerEnd();
+ }
+};
+
+#define PROFILER_INIT() SampleProfilerInit()
+#define PROFILER_BEGIN(x) SampleProfilerBegin(x)
+#define PROFILER_END() SampleProfilerEnd()
+#define PROFILER_SCOPED(x) SampleProfilerScoped __scopedProfiler__(x)
+#define PROFILER_SCOPED_FUNCTION() SampleProfilerScoped __scopedProfiler__(__FUNCTION__)
+#define PROFILER_RESET() SampleProfilerReset()
+
+#else
+
+#define PROFILER_INIT()
+#define PROFILER_BEGIN(x)
+#define PROFILER_END()
+#define PROFILER_SCOPED(x)
+#define PROFILER_SCOPED_FUNCTION()
+#define PROFILER_RESET()
+
+#endif
+
+void SampleProfilerDumpToFile(const char* path);
+bool SampleProfilerIsValid();
+std::chrono::microseconds SampleProfilerGetOverhead();
+
+struct SampleProfilerTreeIterator
+{
+ struct Data
+ {
+ uint64_t hash;
+ const char* name;
+ bool hasChilds;
+ uint32_t depth;
+ std::chrono::microseconds time;
+ std::chrono::microseconds maxTime;
+ uint32_t calls;
+ };
+
+ virtual const Data* data() const = 0;
+ virtual bool isDone() const = 0;
+ virtual void next() = 0;
+ virtual void release() = 0;
+};
+
+SampleProfilerTreeIterator* SampleProfilerCreateTreeIterator();
+
+#endif //SAMPLEPROFILER_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleTime.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleTime.h
new file mode 100644
index 0000000..c62ced2
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/SampleTime.h
@@ -0,0 +1,58 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef SAMPLE_TIME_H
+#define SAMPLE_TIME_H
+
+#include <stdint.h>
+
+class Time
+{
+public:
+ Time() : m_lastTickCount(getTimeTicks()) {}
+
+ double Time::getElapsedSeconds()
+ {
+ const int64_t lastTickCount = m_lastTickCount;
+ m_lastTickCount = getTimeTicks();
+ return (m_lastTickCount - lastTickCount) * s_secondsPerTick;
+ }
+
+ double Time::peekElapsedSeconds() const
+ {
+ return (getTimeTicks() - m_lastTickCount) * s_secondsPerTick;
+ }
+
+ double Time::getLastTime() const
+ {
+ return m_lastTickCount * s_secondsPerTick;
+ }
+
+private:
+ static double getTickDuration()
+ {
+ LARGE_INTEGER a;
+ QueryPerformanceFrequency(&a);
+ return 1.0 / (double)a.QuadPart;
+ }
+
+ int64_t getTimeTicks() const
+ {
+ LARGE_INTEGER a;
+ QueryPerformanceCounter(&a);
+ return a.QuadPart;
+ }
+
+ int64_t m_lastTickCount;
+ static const double s_secondsPerTick;
+};
+
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/UIHelpers.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/UIHelpers.h
new file mode 100644
index 0000000..b23eb84
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/UIHelpers.h
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#ifndef UI_HELPERS_H
+#define UI_HELPERS_H
+
+#include "imgui.h"
+#include "PxVec3.h"
+
+
+static void ImGui_DragFloat3Dir(const char* label, float v[3])
+{
+ if (ImGui::Button("Normalize"))
+ {
+ ((physx::PxVec3*)v)->normalize();
+ }
+ ImGui::SameLine();
+ ImGui::DragFloat3(label, v);
+};
+
+
+#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
+
+template<int valuesCount = 90>
+class PlotLinesInstance
+{
+public:
+ PlotLinesInstance()
+ {
+ memset(m_values, 0, sizeof(float) * valuesCount);
+ }
+
+ void plot(const char* label, float newValue, const char* overlay_text, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 80))
+ {
+ for (; ImGui::GetTime() > m_time + 1.0f / 60.0f; m_time += 1.0f / 60.0f)
+ {
+ m_values[m_offset] = newValue;
+ m_offset = (m_offset + 1) % valuesCount;
+ }
+ ImGui::PlotLines(label, m_values, valuesCount, m_offset, overlay_text, scale_min, scale_max, graph_size);
+ }
+
+private:
+ float m_values[valuesCount];
+ int m_offset;
+ float m_time = ImGui::GetTime();
+};
+
+#endif //UI_HELPERS_H \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/Utils.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/Utils.cpp
new file mode 100644
index 0000000..a271137
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/Utils.cpp
@@ -0,0 +1,13 @@
+#include "Utils.h"
+
+#include <string>
+#include <cstdarg>
+
+HRESULT messagebox_printf(const char* caption, UINT mb_type, const char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ char formatted_text[512];
+ _vsnprintf(formatted_text, 512, format, args);
+ return MessageBoxA(nullptr, formatted_text, caption, mb_type);
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/Utils.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/Utils.h
new file mode 100644
index 0000000..5d4addc
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/SampleBase/utils/Utils.h
@@ -0,0 +1,91 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <DeviceManager.h>
+#include <assert.h>
+
+#include "PxPreprocessor.h"
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// MACROS
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifndef V_RETURN
+#define V_RETURN(x) \
+ { \
+ hr = (x); \
+ if(FAILED(hr)) \
+ { \
+ return hr; \
+ } \
+ }
+#endif
+
+#ifndef V
+#define V(x) \
+ { \
+ HRESULT hr = (x); \
+ _ASSERT(SUCCEEDED(hr)); \
+ }
+#endif
+
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(p) \
+ { \
+ if(p) \
+ { \
+ (p)->Release(); \
+ (p) = NULL; \
+ } \
+ }
+#endif
+
+#ifndef SAFE_DELETE
+#define SAFE_DELETE(p) \
+ { \
+ if(p) \
+ { \
+ delete (p); \
+ (p) = NULL; \
+ } \
+ }
+#endif
+
+#define ASSERT_PRINT(cond, format, ...) \
+ if(!(cond)) \
+ { \
+ messagebox_printf("Assertion Failed!", MB_OK | MB_ICONERROR, #cond "\n" format, __VA_ARGS__); \
+ assert(cond); \
+ }
+
+HRESULT messagebox_printf(const char* caption, UINT mb_type, const char* format, ...);
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static const char* strext(const char* str)
+{
+ const char* ext = NULL; // by default no extension found!
+ while (str)
+ {
+ str = strchr(str, '.');
+ if (str)
+ {
+ str++;
+ ext = str;
+ }
+ }
+ return ext;
+}
+
+static inline float lerp(float a, float b, float t) { return a + (b - a) * t; }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastCompositePanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastCompositePanel.cpp
new file mode 100644
index 0000000..b42a4f5
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastCompositePanel.cpp
@@ -0,0 +1,306 @@
+#include "BlastCompositePanel.h"
+#include "ui_BlastCompositePanel.h"
+#include "ProjectParams.h"
+#include <QtCore/QFileInfo>
+#include <QtWidgets/QInputDialog>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QMessageBox>
+
+BlastCompositePanel::BlastCompositePanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::BlastCompositePanel),
+ _selectedAsset(-1)
+{
+ ui->setupUi(this);
+
+ ui->btnRemoveAsset->setEnabled(false);
+ ui->btnModifyLandmark->setEnabled(false);
+ ui->btnRemoveLandmark->setEnabled(false);
+}
+
+BlastCompositePanel::~BlastCompositePanel()
+{
+ delete ui;
+}
+
+void BlastCompositePanel::updateValues()
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPComposite& composite = projectParams.blast.composite;
+
+ ui->lineEditComposite->setText(composite.composite.buf);
+
+ _updateAssetComboBox();
+
+ _updateAssetInstanceListWidget();
+
+ ui->spinBoxBondByThreshold->setValue(composite.bondThreshold);
+ ui->spinBoxNewBondStrength->setValue(composite.bondStrength);
+
+ _updateLandmarkListWidget();
+
+ ui->checkBoxEnableLandmark->setChecked(false);
+ ui->spinBoxLandmarkRadius->setValue(false);
+}
+
+void BlastCompositePanel::on_btnCollapse_clicked()
+{
+
+}
+
+void BlastCompositePanel::on_btnSave_clicked()
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPComposite& composite = projectParams.blast.composite;
+
+ QByteArray tmp = ui->lineEditComposite->text().toUtf8();
+ copy(composite.composite, tmp.data());
+}
+
+void BlastCompositePanel::on_comboBoxAsset_currentIndexChanged(int index)
+{
+ _selectedAsset = index;
+}
+
+void BlastCompositePanel::on_btnAddAsset_clicked()
+{
+ bool ok = false;
+ QString name = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input name for new blast instance:"),
+ QLineEdit::Normal,
+ "",
+ &ok);
+ bool nameExist = BlastProject::ins().isAssetInstanceNameExist(name.toUtf8().data());
+ if (ok && !name.isEmpty() && !nameExist)
+ {
+ BlastProject::ins().addAssetInstance(_selectedAsset, name.toUtf8().data());
+ _updateAssetInstanceListWidget();
+ ui->listWidgetBlastAsset->setCurrentRow(ui->listWidgetBlastAsset->count() - 1);
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && name.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the new preset!");
+ }
+}
+
+void BlastCompositePanel::on_btnRemoveAsset_clicked()
+{
+ QList<QListWidgetItem*> items = ui->listWidgetBlastAsset->selectedItems();
+ BlastProject::ins().removeAssetInstance(items.at(0)->text().toUtf8().data());
+}
+
+void BlastCompositePanel::on_listWidgetBlastAsset_itemSelectionChanged()
+{
+ QList<QListWidgetItem*> items = ui->listWidgetBlastAsset->selectedItems();
+ if (items.count() > 0)
+ ui->btnRemoveAsset->setEnabled(true);
+ else
+ ui->btnRemoveAsset->setEnabled(false);
+}
+
+void BlastCompositePanel::on_spinBoxBondByThreshold_valueChanged(double arg1)
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPComposite& composite = projectParams.blast.composite;
+ composite.bondThreshold = arg1;
+}
+
+void BlastCompositePanel::on_spinBoxNewBondStrength_valueChanged(double arg1)
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPComposite& composite = projectParams.blast.composite;
+ composite.bondStrength = arg1;
+}
+
+void BlastCompositePanel::on_btnAddLandmark_clicked()
+{
+ bool ok = false;
+ QString name = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input name for new landmark:"),
+ QLineEdit::Normal,
+ "",
+ &ok);
+ bool nameExist = BlastProject::ins().isLandmarkNameExist(name.toUtf8().data());
+ if (ok && !name.isEmpty() && !nameExist)
+ {
+ BlastProject::ins().addLandmark(name.toUtf8().data());
+ _updateLandmarkListWidget();
+ ui->listWidgetLandmark->setCurrentRow(ui->listWidgetLandmark->count() - 1);
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && name.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the new landmark!");
+ }
+}
+
+void BlastCompositePanel::on_btnModifyLandmark_clicked()
+{
+ QList<QListWidgetItem*> items = ui->listWidgetLandmark->selectedItems();
+ QByteArray tem = items.at(0)->text().toUtf8();
+ const char* oldName = tem.data();
+
+ bool ok = false;
+ QString newName = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input new name for the selected landmark:"),
+ QLineEdit::Normal,
+ oldName,
+ &ok);
+ bool nameExist = BlastProject::ins().isLandmarkNameExist(newName.toUtf8().data());
+ if (ok && !newName.isEmpty() && !nameExist)
+ {
+ int selectIndex = ui->listWidgetLandmark->currentRow();
+ BlastProject::ins().renameLandmark(oldName, newName.toUtf8().data());
+ _updateLandmarkListWidget();
+ ui->listWidgetLandmark->setCurrentRow(selectIndex);
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && newName.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the new landmark!");
+ }
+}
+
+void BlastCompositePanel::on_btnRemoveLandmark_clicked()
+{
+ QList<QListWidgetItem*> items = ui->listWidgetLandmark->selectedItems();
+ QByteArray tem = items.at(0)->text().toUtf8();
+ const char* name = tem.data();
+ BlastProject::ins().removeLandmark(name);
+ _updateLandmarkListWidget();
+}
+
+void BlastCompositePanel::on_listWidgetLandmark_itemSelectionChanged()
+{
+ _updateLandmarkUIs();
+}
+
+void BlastCompositePanel::on_checkBoxEnableLandmark_stateChanged(int arg1)
+{
+ QList<QListWidgetItem*> items = ui->listWidgetLandmark->selectedItems();
+
+ int count = items.count();
+ for (int i = 0; i < count; ++i)
+ {
+ BPPLandmark* landmark = BlastProject::ins().getLandmark(items.at(0)->text().toUtf8().data());
+ if (landmark != nullptr)
+ {
+ landmark->enable = ui->checkBoxEnableLandmark->isChecked();
+ }
+ }
+}
+
+void BlastCompositePanel::on_spinBoxLandmarkRadius_valueChanged(double arg1)
+{
+ QList<QListWidgetItem*> items = ui->listWidgetLandmark->selectedItems();
+
+ int count = items.count();
+ for (int i = 0; i < count; ++i)
+ {
+ BPPLandmark* landmark = BlastProject::ins().getLandmark(items.at(0)->text().toUtf8().data());
+ if (landmark != nullptr)
+ {
+ landmark->radius = ui->spinBoxLandmarkRadius->value();
+ }
+ }
+}
+
+void BlastCompositePanel::_updateAssetComboBox()
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPAssetArray& blastAssetArray = projectParams.blast.blastAssets;
+ BPPComposite& composite = projectParams.blast.composite;
+
+ ui->comboBoxAsset->clear();
+ int countAssets = blastAssetArray.arraySizes[0];
+ if (countAssets > 0)
+ {
+ QStringList assets;
+ for (int i = 0; i < countAssets; ++i)
+ {
+ QFileInfo fileInfo(blastAssetArray.buf[i].path.buf);
+ assets.append(fileInfo.baseName());
+ }
+ ui->comboBoxAsset->addItems(assets);
+ }
+ else
+ {
+ ui->btnAddAsset->setEnabled(false);
+ ui->btnRemoveAsset->setEnabled(false);
+ }
+}
+
+void BlastCompositePanel::_updateAssetInstanceListWidget()
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPComposite& composite = projectParams.blast.composite;
+
+ ui->listWidgetBlastAsset->clear();
+ int countAssetInstances = composite.blastAssetInstances.arraySizes[0];
+ if (countAssetInstances > 0)
+ {
+ QStringList assetInstances;
+
+ for (int i = 0; i < countAssetInstances; ++i)
+ {
+ assetInstances.append(composite.blastAssetInstances.buf[i].name.buf);
+ }
+ ui->listWidgetBlastAsset->addItems(assetInstances);
+ }
+}
+
+void BlastCompositePanel::_updateLandmarkListWidget()
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPComposite& composite = projectParams.blast.composite;
+
+ ui->listWidgetLandmark->clear();
+ int countJoints = composite.landmarks.arraySizes[0];
+ if (countJoints > 0)
+ {
+ QStringList landmarks;
+
+ for (int i = 0; i < countJoints; ++i)
+ {
+ landmarks.append(composite.landmarks.buf[i].name.buf);
+ }
+ ui->listWidgetLandmark->addItems(landmarks);
+ }
+}
+
+void BlastCompositePanel::_updateLandmarkUIs()
+{
+ QList<QListWidgetItem*> items = ui->listWidgetLandmark->selectedItems();
+
+ if (items.count() > 0)
+ {
+ BPPLandmark* landmark = BlastProject::ins().getLandmark(items.at(0)->text().toUtf8().data());
+ if (landmark != nullptr)
+ {
+ ui->btnModifyLandmark->setEnabled(true);
+ ui->btnRemoveLandmark->setEnabled(true);
+ ui->checkBoxEnableLandmark->setChecked(landmark->enable);
+ ui->spinBoxLandmarkRadius->setValue(landmark->radius);
+ }
+ }
+ else
+ {
+ ui->btnModifyLandmark->setEnabled(false);
+ ui->btnRemoveLandmark->setEnabled(false);
+ ui->checkBoxEnableLandmark->setChecked(false);
+ ui->spinBoxLandmarkRadius->setValue(0.0f);
+ }
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastCompositePanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastCompositePanel.h
new file mode 100644
index 0000000..b4e5bcf
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastCompositePanel.h
@@ -0,0 +1,59 @@
+#ifndef BLASTCOMPOSITEPANEL_H
+#define BLASTCOMPOSITEPANEL_H
+
+#include <QtWidgets/QWidget>
+
+namespace Ui {
+class BlastCompositePanel;
+}
+
+class BlastCompositePanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit BlastCompositePanel(QWidget *parent = 0);
+ ~BlastCompositePanel();
+ void updateValues();
+
+private slots:
+ void on_btnCollapse_clicked();
+
+ void on_btnSave_clicked();
+
+ void on_comboBoxAsset_currentIndexChanged(int index);
+
+ void on_btnAddAsset_clicked();
+
+ void on_btnRemoveAsset_clicked();
+
+ void on_listWidgetBlastAsset_itemSelectionChanged();
+
+ void on_spinBoxBondByThreshold_valueChanged(double arg1);
+
+ void on_spinBoxNewBondStrength_valueChanged(double arg1);
+
+ void on_btnAddLandmark_clicked();
+
+ void on_btnModifyLandmark_clicked();
+
+ void on_btnRemoveLandmark_clicked();
+
+ void on_listWidgetLandmark_itemSelectionChanged();
+
+ void on_checkBoxEnableLandmark_stateChanged(int arg1);
+
+ void on_spinBoxLandmarkRadius_valueChanged(double arg1);
+
+private:
+ void _updateAssetComboBox();
+ void _updateAssetInstanceListWidget();
+ void _updateLandmarkListWidget();
+ void _updateLandmarkUIs();
+
+private:
+ Ui::BlastCompositePanel *ui;
+ int _selectedAsset;
+};
+
+#endif // BLASTCOMPOSITEPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.cpp
new file mode 100644
index 0000000..64a7c2f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.cpp
@@ -0,0 +1,1804 @@
+#include "BlastSceneTree.h"
+#include <QtWidgets/QMessageBox>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QMenu>
+#include <QtCore/QFileInfo>
+#include <assert.h>
+#include "ProjectParams.h"
+#include <SimpleScene.h>
+#include <BlastController.h>
+#include <SceneController.h>
+#include <NvBlastExtPxAsset.h>
+#include <NvBlastTkAsset.h>
+#include <NvBlastAsset.h>
+#include <BlastFamilyModelSimple.h>
+
+bool isChunkVisible(std::vector<BlastFamily*>& fs, uint32_t chunkIndex)
+{
+ int fsSize = fs.size();
+ if (fsSize == 0)
+ {
+ return false;
+ }
+
+ bool visible = false;
+ for (int i = 0; i < fsSize; i++)
+ {
+ if (fs[i]->isChunkVisible(chunkIndex))
+ {
+ visible = true;
+ break;
+ }
+ }
+ return visible;
+}
+
+void setChunkVisible(std::vector<BlastFamily*>& fs, uint32_t chunkIndex, bool visible)
+{
+ int fsSize = fs.size();
+ if (fsSize == 0)
+ {
+ return;
+ }
+
+ for (int i = 0; i < fsSize; i++)
+ {
+ fs[i]->setChunkVisible(chunkIndex, visible);
+ }
+}
+
+void setChunkSelected(std::vector<BlastFamily*>& fs, uint32_t chunkIndex, bool selected)
+{
+ int fsSize = fs.size();
+ if (fsSize == 0)
+ {
+ return;
+ }
+
+ for (int i = 0; i < fsSize; i++)
+ {
+ fs[i]->setChunkSelected(chunkIndex, selected);
+ }
+}
+
+void BlastChunkNode::setVisible(bool val)
+{
+ BPPChunk* pBPPChunk = (BPPChunk*)_data;
+ pBPPChunk->visible = val;
+
+ BlastAsset* pBlastAsset = (BlastAsset*)_assetPtr;
+
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+
+ std::map<BlastAsset*, std::vector<BlastFamily*>>& AssetFamiliesMap = sampleManager.getAssetFamiliesMap();
+ std::vector<BlastFamily*>& fs = AssetFamiliesMap[pBlastAsset];
+
+ setChunkVisible(fs, pBPPChunk->ID, val);
+}
+
+void BlastChunkNode::setSelected(bool val)
+{
+ BPPChunk* pBPPChunk = (BPPChunk*)_data;
+ pBPPChunk->visible = val;
+
+ BlastAsset* pBlastAsset = (BlastAsset*)_assetPtr;
+
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+
+ std::map<BlastAsset*, std::vector<BlastFamily*>>& AssetFamiliesMap = sampleManager.getAssetFamiliesMap();
+ std::vector<BlastFamily*>& fs = AssetFamiliesMap[pBlastAsset];
+
+ setChunkSelected(fs, pBPPChunk->ID, val);
+}
+
+void BlastAssetInstanceNode::setSelected(bool val)
+{
+ BPPAssetInstance* pBPPAssetInstance = (BPPAssetInstance*)_data;
+ std::string name = pBPPAssetInstance->name;
+
+ std::string strAsset = name.substr(0, name.find_first_of("_"));
+ BlastAsset* pBlastAsset = nullptr;
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ std::map<BlastAsset*, AssetList::ModelAsset>& AssetDescMap = sampleManager.getAssetDescMap();
+ std::map<BlastAsset*, AssetList::ModelAsset>::iterator itAssetDescMap;
+ for (itAssetDescMap = AssetDescMap.begin();
+ itAssetDescMap != AssetDescMap.end(); itAssetDescMap++)
+ {
+ AssetList::ModelAsset& model = itAssetDescMap->second;
+ if (model.name == strAsset)
+ {
+ pBlastAsset = itAssetDescMap->first;
+ break;
+ }
+ }
+
+ std::string strIndex = name.substr(name.find_last_of("_") + 1);
+ int nIndex = atoi(strIndex.c_str());
+
+ sampleManager.setCurrentSelectedInstance(pBlastAsset, nIndex);
+}
+
+BlastTreeData& BlastTreeData::ins()
+{
+ static BlastTreeData _ins;
+ return _ins;
+}
+
+bool BlastTreeData::isChild(BlastChunkNode* parent, BlastChunkNode* child)
+{
+ if (parent == nullptr || child == nullptr)
+ return false;
+
+ BlastNode* curParent = child->getParent();
+ while (eChunk == curParent->getType() && curParent != nullptr)
+ {
+ if (curParent == parent)
+ return true;
+ curParent = curParent->getParent();
+ }
+
+ return false;
+}
+
+std::vector<BlastChunkNode*> BlastTreeData::getTopChunkNodes(std::vector<BlastChunkNode*>& nodes)
+{
+ std::vector<BlastChunkNode*> result;
+
+ for (size_t i = 0; i < nodes.size(); ++i)
+ {
+ bool isCurNodeTop = true;
+ for (size_t j = 0; j < nodes.size(); ++j)
+ {
+ if (i != j && isChild(nodes[i], nodes[j]))
+ {
+ isCurNodeTop = false;
+ break;
+ }
+ }
+
+ if (isCurNodeTop)
+ {
+ result.push_back(nodes[i]);
+ }
+ }
+
+ return result;
+}
+
+bool BlastTreeData::isRoot(BlastChunkNode* node)
+{
+ if (node == nullptr || node->getParent() == nullptr)
+ return false;
+
+ return eAsset == node->getParent()->getType();
+}
+
+bool BlastTreeData::isLeaf(BlastChunkNode* node)
+{
+ if (node == nullptr)
+ return false;
+
+ for (BlastNode* curNode : node->children)
+ {
+ if (eChunk == curNode->getType())
+ return false;
+ }
+
+ return true;
+}
+
+void removeChunkNodeSupport(BlastChunkNode* node)
+{
+ if (node == nullptr)
+ return;
+
+ BPPChunk* chunk = static_cast<BPPChunk*>(node->getData());
+ chunk->support = false;
+
+ for (BlastNode* curNode : node->children)
+ {
+ if (eChunk == curNode->getType())
+ {
+ removeChunkNodeSupport((BlastChunkNode*)curNode);
+ }
+ }
+}
+
+void BlastTreeData::makeSupport(BlastChunkNode* node)
+{
+ if (node == nullptr)
+ return;
+ BPPChunk* chunk = static_cast<BPPChunk*>(node->getData());
+ chunk->staticFlag = false;
+ chunk->support = true;
+
+ for (BlastNode* curNode : node->children)
+ {
+ if (eChunk == curNode->getType())
+ {
+ removeChunkNodeSupport((BlastChunkNode*)curNode);
+ }
+ }
+}
+
+void BlastTreeData::makeStaticSupport(BlastChunkNode* node)
+{
+ if (node == nullptr)
+ return;
+ BPPChunk* chunk = static_cast<BPPChunk*>(node->getData());
+ chunk->staticFlag = true;
+ chunk->support = true;
+
+ for (BlastNode* curNode : node->children)
+ {
+ if (eChunk == curNode->getType())
+ {
+ removeChunkNodeSupport((BlastChunkNode*)curNode);
+ }
+ }
+}
+
+void BlastTreeData::removeSupport(BlastChunkNode* node)
+{
+ if (node == nullptr)
+ return;
+
+ if (isLeaf(node))
+ return;
+
+ BPPChunk* chunk = static_cast<BPPChunk*>(node->getData());
+ chunk->support = false;
+ chunk->staticFlag = false;
+
+ for (BlastNode* curNode : node->children)
+ {
+ if (eChunk == curNode->getType())
+ {
+ BPPChunk* curChunk = static_cast<BPPChunk*>(curNode->getData());
+ curChunk->support = true;
+ }
+ }
+}
+
+BlastNode* BlastTreeData::getBlastNodeByProjectData(void* data)
+{
+ std::map<void*, BlastNode*>::iterator itr = _blastProjectDataToNodeMap.find(data);
+ if (itr != _blastProjectDataToNodeMap.end())
+ return itr->second;
+
+ return nullptr;
+}
+
+struct ChunkSupport
+{
+ ChunkSupport()
+ {
+ m_bSupport = false;
+ }
+
+ bool m_bSupport;
+};
+
+struct BondChunkIndices
+{
+ BondChunkIndices()
+ {
+ chunkIndices[0] = -1;
+ chunkIndices[1] = -1;
+ }
+
+ void SetIndices(uint32_t chunkIndex0, uint32_t chunkIndex1)
+ {
+ if (chunkIndex0 < chunkIndex1)
+ {
+ chunkIndices[0] = chunkIndex0;
+ chunkIndices[1] = chunkIndex1;
+ }
+ else
+ {
+ chunkIndices[0] = chunkIndex1;
+ chunkIndices[1] = chunkIndex0;
+ }
+ }
+
+ uint32_t chunkIndices[2];
+};
+
+void BlastTreeData::update()
+{
+ _freeBlastNode();
+
+ BPPBlast& blast = BlastProject::ins().getParams().blast;
+ std::vector<BlastAsset*> BlastAssetVec;
+ {
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+
+ std::map<BlastAsset*, std::vector<BlastFamily*>>& AssetFamiliesMap = sampleManager.getAssetFamiliesMap();
+ std::map<BlastAsset*, AssetList::ModelAsset>& AssetDescMap = sampleManager.getAssetDescMap();
+
+ BlastController& blastController = sampleManager.getBlastController();
+ SceneController& sceneController = sampleManager.getSceneController();
+
+ std::vector<BlastFamilyPtr>& families = blastController.getFamilies();
+ int familiesSize = families.size();
+
+ std::map<BlastAsset*, AssetList::ModelAsset>::iterator it;
+ for (it = AssetDescMap.begin(); it != AssetDescMap.end(); it++)
+ {
+ BlastAssetVec.push_back(it->first);
+ }
+ int modelAssetsSize = AssetDescMap.size();
+
+ std::vector<std::string> projectilesNames;
+ sceneController.GetProjectilesNames(projectilesNames);
+
+ // compoistie
+ {
+ BPPComposite& composite = blast.composite;
+ composite.composite.buf = nullptr;
+ composite.visible = true;
+
+ copy(composite.composite, "BlastComposite");
+
+ // asset instance array
+ {
+ BPPAssetInstanceArray& instanceArray = composite.blastAssetInstances;
+ instanceArray.arraySizes[0] = familiesSize;
+ if (familiesSize > 0)
+ {
+ instanceArray.buf = new BPPAssetInstance[familiesSize];
+ int curInstanceIndex = 0;
+ char instancename[50];
+ std::map<BlastAsset*, std::vector<BlastFamily*>>::iterator itAssetFamiliesMap;
+ for (itAssetFamiliesMap = AssetFamiliesMap.begin();
+ itAssetFamiliesMap != AssetFamiliesMap.end(); itAssetFamiliesMap++)
+ {
+ BlastAsset* pBlastAsset = itAssetFamiliesMap->first;
+ std::vector<BlastFamily*>& fs = itAssetFamiliesMap->second;
+ int fsSize = fs.size();
+ for (int i = 0; i < fsSize; i++)
+ {
+ BPPAssetInstance& instance = instanceArray.buf[curInstanceIndex];
+ instance.name.buf = nullptr;
+ instance.source.buf = nullptr;
+ instance.visible = true;
+
+ AssetList::ModelAsset desc = AssetDescMap[pBlastAsset];
+ sprintf(instancename, "%s_Instance_%d", desc.name.c_str(), i);
+ copy(instance.name, instancename);
+
+ std::string assetFilePath = SampleManager::ins()->getConfig().additionalResourcesDir.back() + "/models/" + desc.file + ".bpxa";
+ sprintf(instancename, "%s", assetFilePath.c_str());
+ copy(instance.source, instancename);
+
+ PxVec3 p = desc.transform.p;
+ PxQuat q = desc.transform.q;
+ instanceArray.buf[curInstanceIndex].transform.position = nvidia::NvVec3(p.x, p.y, p.z);
+ instanceArray.buf[curInstanceIndex].transform.rotation = nvidia::NvVec4(q.x, q.y, q.z, q.w);
+
+ curInstanceIndex++;
+ }
+ }
+ }
+ }
+
+ // landmark array
+ if (0)
+ {
+ BPPLandmarkArray& landmarkArray = composite.landmarks;
+ landmarkArray.buf = new BPPLandmark[2];
+ landmarkArray.arraySizes[0] = 2;
+ landmarkArray.buf[0].name.buf = nullptr;
+ landmarkArray.buf[1].name.buf = nullptr;
+
+ copy(landmarkArray.buf[0].name, "Landmark_1");
+ copy(landmarkArray.buf[1].name, "Landmark_2");
+ }
+ }
+
+ // asset array
+ {
+ BPPAssetArray& assetArray = blast.blastAssets;
+ assetArray.arraySizes[0] = modelAssetsSize;
+ if (modelAssetsSize > 0)
+ {
+ assetArray.buf = new BPPAsset[modelAssetsSize];
+ int curAssetIndex = 0;
+
+ blast.chunks.buf = nullptr;
+ blast.chunks.arraySizes[0] = 0;
+ blast.bonds.buf = nullptr;
+ blast.bonds.arraySizes[0] = 0;
+
+ std::map<BlastAsset*, AssetList::ModelAsset>::iterator itAssetDescMap;
+ for (itAssetDescMap = AssetDescMap.begin();
+ itAssetDescMap != AssetDescMap.end(); itAssetDescMap++)
+ {
+ BlastAsset* pBlastAsset = itAssetDescMap->first;
+ AssetList::ModelAsset& desc = itAssetDescMap->second;
+ std::vector<BlastFamily*>& fs = AssetFamiliesMap[pBlastAsset];
+
+ BPPAsset& asset = assetArray.buf[curAssetIndex];
+ asset.path.buf = nullptr;
+ asset.activePreset.buf = nullptr;
+ std::string assetFilePath = SampleManager::ins()->getConfig().additionalResourcesDir.back() + "/models/" + desc.file + ".bpxa";
+ copy(asset.path, assetFilePath.c_str());
+
+ const ExtPxAsset* pExtPxAsset = pBlastAsset->getPxAsset();
+ const ExtPxChunk* pExtPxChunk = pExtPxAsset->getChunks();
+
+ const TkAsset& tkAsset = pExtPxAsset->getTkAsset();
+ uint32_t chunkCount = tkAsset.getChunkCount();
+ const NvBlastChunk* pNvBlastChunk = tkAsset.getChunks();
+ uint32_t bondCount = tkAsset.getBondCount();
+ const NvBlastBond* pNvBlastBond = tkAsset.getBonds();
+
+ const NvBlastSupportGraph supportGraph = tkAsset.getGraph();
+ uint32_t* chunkIndices = supportGraph.chunkIndices;
+ uint32_t* adjacencyPartition = supportGraph.adjacencyPartition;
+ uint32_t* adjacentNodeIndices = supportGraph.adjacentNodeIndices;
+ uint32_t* adjacentBondIndices = supportGraph.adjacentBondIndices;
+
+ ChunkSupport* pSupport = new ChunkSupport[chunkCount];
+ BondChunkIndices* pBCIndices = new BondChunkIndices[bondCount];
+
+ for (uint32_t node0 = 0; node0 < supportGraph.nodeCount; ++node0)
+ {
+ const uint32_t chunkIndex0 = supportGraph.chunkIndices[node0];
+
+ pSupport[chunkIndex0].m_bSupport = true;
+
+ for (uint32_t adjacencyIndex = adjacencyPartition[node0]; adjacencyIndex < adjacencyPartition[node0 + 1]; adjacencyIndex++)
+ {
+ uint32_t node1 = supportGraph.adjacentNodeIndices[adjacencyIndex];
+
+ // add this condition if you don't want to iterate all bonds twice
+ if (node0 > node1)
+ continue;
+
+ const uint32_t chunkIndex1 = supportGraph.chunkIndices[node1];
+
+ uint32_t bondIndex = supportGraph.adjacentBondIndices[adjacencyIndex];
+
+ pBCIndices[bondIndex].SetIndices(chunkIndex0, chunkIndex1);
+ }
+ }
+
+ // chunks
+ {
+ BPPChunkArray curArray;
+ curArray.buf = new BPPChunk[chunkCount];
+ curArray.arraySizes[0] = chunkCount;
+ char chunkname[10];
+ for (int cc = 0; cc < chunkCount; ++cc)
+ {
+ BPPChunk& chunk = curArray.buf[cc];
+ chunk.name.buf = nullptr;
+ chunk.asset.buf = nullptr;
+
+ std::vector<uint32_t> parentChunkIndexes;
+ parentChunkIndexes.push_back(cc);
+ uint32_t parentChunkIndex = cc;
+ while ((parentChunkIndex = pNvBlastChunk[parentChunkIndex].parentChunkIndex) != -1)
+ {
+ parentChunkIndexes.push_back(parentChunkIndex);
+ }
+
+ std::string strChunkName = "Chunk";
+ for (int pcIndex = parentChunkIndexes.size() - 1; pcIndex >= 0; pcIndex--)
+ {
+ sprintf(chunkname, "_%d", parentChunkIndexes[pcIndex]);
+ strChunkName += chunkname;
+ }
+ copy(chunk.name, strChunkName.c_str());
+
+ copy(chunk.asset, asset.path);
+ chunk.ID = cc;
+ chunk.parentID = pNvBlastChunk[cc].parentChunkIndex;
+ chunk.staticFlag = pExtPxChunk[cc].isStatic;
+ chunk.visible = isChunkVisible(fs, cc);
+ chunk.support = pSupport[cc].m_bSupport;
+ }
+
+ merge(blast.chunks, curArray);
+ freeBlast(curArray);
+ }
+
+ // bonds
+ {
+ BPPBondArray curArray;
+ curArray.buf = new BPPBond[bondCount];
+ curArray.arraySizes[0] = bondCount;
+ char bondname[10];
+ bool visible;
+ for (int bc = 0; bc < bondCount; ++bc)
+ {
+ BPPBond& bond = curArray.buf[bc];
+ bond.name.buf = nullptr;
+ bond.asset.buf = nullptr;
+
+ visible = isChunkVisible(fs, pBCIndices[bc].chunkIndices[0])
+ || isChunkVisible(fs, pBCIndices[bc].chunkIndices[1]);
+ bond.visible = visible;
+ bond.support.healthMask.buf = nullptr; // ?
+ bond.fromChunk = pBCIndices[bc].chunkIndices[0];
+ bond.toChunk = pBCIndices[bc].chunkIndices[1];
+
+ sprintf(bondname, "Bond_%d_%d", bond.fromChunk, bond.toChunk);
+ copy(bond.name, bondname);
+ copy(bond.asset, asset.path);
+ }
+
+ merge(blast.bonds, curArray);
+ freeBlast(curArray);
+ }
+
+ delete[] pSupport;
+ pSupport = nullptr;
+ delete[] pBCIndices;
+ pBCIndices = nullptr;
+
+ curAssetIndex++;
+ }
+ }
+ }
+
+ // projectile
+ {
+ BPPProjectileArray& projectileArray = blast.projectiles;
+ int BPPProjectileSize = projectilesNames.size();
+ projectileArray.arraySizes[0] = BPPProjectileSize;
+ if (BPPProjectileSize > 0)
+ {
+ projectileArray.buf = new BPPProjectile[BPPProjectileSize];
+ for (int i = 0; i < BPPProjectileSize; i++)
+ {
+ projectileArray.buf[i].name.buf = nullptr;
+ copy(projectileArray.buf[i].name, projectilesNames[i].c_str());
+ projectileArray.buf[i].visible = true;
+ }
+ }
+ }
+
+ // graphics meshes
+ if (0)
+ {
+ BPPGraphicsMeshArray& graphicsMeshArray = blast.graphicsMeshes;
+ graphicsMeshArray.buf = new BPPGraphicsMesh[3];
+ graphicsMeshArray.arraySizes[0] = 3;
+ graphicsMeshArray.buf[0].name.buf = nullptr;
+ copy(graphicsMeshArray.buf[0].name, "SurfaceMesh1");
+ graphicsMeshArray.buf[0].visible = true;
+
+ graphicsMeshArray.buf[1].name.buf = nullptr;
+ copy(graphicsMeshArray.buf[1].name, "SurfaceMesh2");
+ graphicsMeshArray.buf[1].visible = true;
+
+ graphicsMeshArray.buf[2].name.buf = nullptr;
+ copy(graphicsMeshArray.buf[2].name, "DisplayMesh1");
+ graphicsMeshArray.buf[2].visible = true;
+ }
+ }
+
+ BPPAssetArray& assetArray = blast.blastAssets;
+
+ int count = assetArray.arraySizes[0];
+ for (int c = 0; c < count; ++c)
+ {
+ BPPAsset& asset = assetArray.buf[c];
+ QFileInfo fileInfo(asset.path.buf);
+ BlastAssetNode* assetNode = new BlastAssetNode(fileInfo.baseName().toUtf8().data(), asset);
+ _assets.push_back(assetNode);
+ _blastProjectDataToNodeMap.insert(std::make_pair((void*)&asset, assetNode));
+
+ // get the firlst level chunks whose parentID is -1
+ std::vector<BPPChunk*> childChunks = BlastProject::ins().getChildrenChunks(asset, -1);
+
+ for (size_t i = 0; i < childChunks.size(); ++i)
+ {
+ BPPChunk& chunk = *(childChunks[i]);
+ BlastChunkNode* chunkNode = new BlastChunkNode(chunk.name.buf, chunk, BlastAssetVec[c]);
+ assetNode->children.push_back(chunkNode);
+ chunkNode->setParent(assetNode);
+ _blastProjectDataToNodeMap.insert(std::make_pair((void*)&chunk, chunkNode));
+ _addChunkNode(chunk, asset, chunkNode, BlastAssetVec[c]);
+ }
+ }
+
+ BPPComposite& composite = blast.composite;
+ _composite = new BlastCompositeNode(composite.composite.buf, composite);
+ _blastProjectDataToNodeMap.insert(std::make_pair((void*)&composite, _composite));
+ BPPAssetInstanceArray& assetInstanceArray = composite.blastAssetInstances;
+ count = assetInstanceArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPAssetInstance& blastAssetInstance = composite.blastAssetInstances.buf[i];
+ BlastAssetInstanceNode* blastAssetInstanceNode = new BlastAssetInstanceNode(blastAssetInstance.name.buf, blastAssetInstance);
+ _composite->children.push_back(blastAssetInstanceNode);
+ blastAssetInstanceNode->setParent(_composite);
+ _blastProjectDataToNodeMap.insert(std::make_pair((void*)&blastAssetInstance, blastAssetInstanceNode));
+ }
+
+ BPPLandmarkArray& landmarkArray = composite.landmarks;
+ count = landmarkArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPLandmark& landmark = composite.landmarks.buf[i];
+ BlastLandmarkNode* landmarkNode = new BlastLandmarkNode(landmark.name.buf, landmark);
+ _composite->children.push_back(landmarkNode);
+ landmarkNode->setParent(_composite);
+ _blastProjectDataToNodeMap.insert(std::make_pair((void*)&landmark, landmarkNode));
+ }
+
+ BPPProjectileArray& projectileArray = blast.projectiles;
+ count = projectileArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPProjectile& projectile = projectileArray.buf[i];
+ BlastProjectileNode* projectileNode = new BlastProjectileNode(projectile.name.buf, projectile);
+ _projectiles.push_back(projectileNode);
+ _blastProjectDataToNodeMap.insert(std::make_pair((void*)&projectile, projectileNode));
+ }
+
+ BPPGraphicsMeshArray& graphicsMeshArray = blast.graphicsMeshes;
+ count = graphicsMeshArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPGraphicsMesh& graphicsMesh = graphicsMeshArray.buf[i];
+ BlastGraphicsMeshNode* projectileNode = new BlastGraphicsMeshNode(graphicsMesh.name.buf, graphicsMesh);
+ _graphicsMeshes.push_back(projectileNode);
+ }
+}
+
+void BlastTreeData::updateVisible(uint32_t assetIndex, uint32_t chunkIndex, bool visible)
+{
+ BPPBlast& blast = BlastProject::ins().getParams().blast;
+ BPPAssetArray& assetArray = blast.blastAssets;
+ if (assetIndex < assetArray.arraySizes[0])
+ {
+ BPPAsset& asset = assetArray.buf[assetIndex];
+
+ std::vector<BPPChunk*> childChunks = BlastProject::ins().getChildrenChunks(asset);
+ if (chunkIndex < childChunks.size())
+ {
+ BPPChunk& chunk = *(childChunks[chunkIndex]);
+ chunk.visible = visible;
+ }
+ }
+}
+
+
+BlastChunkNode* findChunkNode(BlastChunkNode* chunkNode, uint32_t chunkIndex)
+{
+ if (chunkNode == nullptr)
+ return nullptr;
+
+ if (((BPPChunk*)chunkNode->getData())->ID == chunkIndex)
+ return chunkNode;
+
+ std::vector<BlastNode*>& children = chunkNode->children;
+ for (size_t i = 0; i < children.size(); ++i)
+ {
+ BlastNode* node = children[i];
+ if (node->getType() == eChunk)
+ {
+ BlastChunkNode* chunkNode = findChunkNode(static_cast<BlastChunkNode*>(node), chunkIndex);
+ if (chunkNode)
+ {
+ return chunkNode;
+ }
+ else
+ continue;
+ }
+
+ else
+ continue;
+ }
+
+ return nullptr;
+}
+
+std::vector<BlastChunkNode*> BlastTreeData::getChunkNodeByBlastChunk(const BlastAsset* asset, const std::vector<uint32_t>& chunkIndexes)
+{
+ std::vector<BlastChunkNode*> chunkNodes;
+ if (asset == nullptr || chunkIndexes.size() == 0)
+ {
+ return chunkNodes;
+ }
+
+ BlastAssetNode* assetNode = _getAssetNode(asset);
+ if (assetNode)
+ {
+ std::vector<BlastNode*>& children = assetNode->children;
+ for (BlastNode* node : children)
+ {
+ if (node->getType() == eChunk)
+ {
+ for (uint32_t chunkId : chunkIndexes)
+ {
+ BlastChunkNode* chunkNode = findChunkNode(static_cast<BlastChunkNode*>(node), chunkId);
+ if (chunkNode)
+ {
+ chunkNodes.push_back(chunkNode);
+ }
+ }
+ }
+ }
+ }
+
+ return chunkNodes;
+}
+
+bool isCompleteSupport(BlastChunkNode* node)
+{
+ if (node == nullptr)
+ return false;
+
+ if (node->isSupport())
+ return true;
+
+ const std::vector<BlastNode*>& children = node->children;
+ for (BlastNode* curNode : children)
+ {
+ if (eChunk == curNode->getType())
+ {
+ BlastChunkNode* chunkNode = (BlastChunkNode*)curNode;
+ if (0 == chunkNode->children.size())
+ {
+ if (!chunkNode->isSupport())
+ return false;
+ }
+
+ if (!isCompleteSupport(chunkNode))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool BlastTreeData::isCompleteSupportAsset(const BlastAsset* asset)
+{
+ BlastAssetNode* assetNode = _getAssetNode(asset);
+ return isCompleteSupportAsset(assetNode);
+}
+
+bool BlastTreeData::isCompleteSupportAsset(const BlastAssetNode* node)
+{
+ if (node == nullptr)
+ return false;
+
+ const std::vector<BlastNode*>& children = node->children;
+ for (BlastNode* curNode : children)
+ {
+ if (eChunk == curNode->getType())
+ {
+ BlastChunkNode* chunkNode = (BlastChunkNode*)curNode;
+ if (!isCompleteSupport(chunkNode))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool BlastTreeData::isOverlapSupportAsset(const BlastAsset* asset)
+{
+ BlastAssetNode* assetNode = _getAssetNode(asset);
+ return isOverlapSupportAsset(assetNode);
+}
+
+bool isOverlapSupport(BlastChunkNode* node)
+{
+ if (node == nullptr)
+ return false;
+
+ bool isParentSupport = node->isSupport();
+
+ const std::vector<BlastNode*>& children = node->children;
+ for (BlastNode* curNode : children)
+ {
+ if (eChunk == curNode->getType())
+ {
+ BlastChunkNode* chunkNode = (BlastChunkNode*)curNode;
+ if (0 == chunkNode->children.size())
+ {
+ if (isParentSupport && chunkNode->isSupport())
+ return true;
+ }
+
+ if (isParentSupport && isOverlapSupport(chunkNode))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool BlastTreeData::isOverlapSupportAsset(const BlastAssetNode* node)
+{
+ if (node == nullptr)
+ return false;
+
+ const std::vector<BlastNode*>& children = node->children;
+ for (BlastNode* curNode : children)
+ {
+ if (eChunk == curNode->getType())
+ {
+ BlastChunkNode* chunkNode = (BlastChunkNode*)curNode;
+ if (isOverlapSupport(chunkNode))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+BlastTreeData::BlastTreeData()
+{
+
+}
+
+void BlastTreeData::_addChunkNode(const BPPChunk& parentData, BPPAsset& asset, BlastChunkNode* parentNode, void* assetPtr)
+{
+ if (parentNode != nullptr)
+ {
+ std::vector<BPPBond*> bonds = BlastProject::ins().getBondsByChunk(asset, parentData.ID);
+ for (size_t i = 0; i < bonds.size(); ++i)
+ {
+ BPPBond* bond = bonds[i];
+ BlastBondNode* bondNode = new BlastBondNode(bond->name.buf, *bond);
+ parentNode->children.push_back(bondNode);
+ bondNode->setParent(parentNode);
+ _blastProjectDataToNodeMap.insert(std::make_pair((void*)bond, bondNode));
+ }
+
+ std::vector<BPPChunk*> childChunks = BlastProject::ins().getChildrenChunks(asset, parentData.ID);
+
+ for (size_t i = 0; i < childChunks.size(); ++i)
+ {
+ BPPChunk& chunk = *(childChunks[i]);
+ BlastChunkNode* chunkNode = new BlastChunkNode(chunk.name.buf, chunk, assetPtr);
+ parentNode->children.push_back(chunkNode);
+ chunkNode->setParent(parentNode);
+ _blastProjectDataToNodeMap.insert(std::make_pair((void*)&chunk, chunkNode));
+ _addChunkNode(chunk, asset, chunkNode, assetPtr);
+ }
+ }
+}
+
+void freeChunkNode(BlastChunkNode* chunkNode)
+{
+ if (chunkNode == nullptr)
+ return;
+
+ std::vector<BlastNode*>& children = chunkNode->children;
+ for (size_t i = 0; i < children.size(); ++i)
+ {
+ BlastNode* node = children[i];
+ if (node->getType() == eChunk)
+ freeChunkNode(static_cast<BlastChunkNode*>(node));
+ else
+ {
+ delete node;
+ node = nullptr;
+ }
+ }
+
+ delete chunkNode;
+ chunkNode = nullptr;
+}
+
+void BlastTreeData::_freeBlastNode()
+{
+ if (_composite)
+ {
+ size_t count = _composite->children.size();
+ for (size_t i = 0; i < count; ++i)
+ {
+ delete _composite->children[i];
+ }
+ delete _composite;
+ _composite = nullptr;
+ }
+
+ size_t count = _assets.size();
+ for (size_t i = 0; i < count; ++i)
+ {
+ std::vector<BlastNode*>& children = _assets[i]->children;
+ for (size_t j = 0; j < children.size(); ++j)
+ {
+ freeChunkNode(static_cast<BlastChunkNode*>(children[j]));
+ }
+ delete _assets[i];
+ }
+ _assets.clear();
+
+ count = _projectiles.size();
+ for (size_t i = 0; i < count; ++i)
+ {
+ delete _projectiles[i];
+ }
+ _projectiles.clear();
+
+ count = _graphicsMeshes.size();
+ for (size_t i = 0; i < count; ++i)
+ {
+ delete _graphicsMeshes[i];
+ }
+ _graphicsMeshes.clear();
+
+ _blastProjectDataToNodeMap.clear();
+}
+
+BlastAssetNode* BlastTreeData::_getAssetNode(const BlastAsset* asset)
+{
+ std::map<BlastAsset*, AssetList::ModelAsset>& assetDescMap = SampleManager::ins()->getAssetDescMap();
+ std::map<BlastAsset*, AssetList::ModelAsset>::iterator itrAssetDesc = assetDescMap.find(const_cast<BlastAsset*>(asset));
+
+ BlastAssetNode* foundAssetNode = nullptr;
+ for (BlastAssetNode* assetNode : _assets)
+ {
+ if (itrAssetDesc->second.name == assetNode->name)
+ {
+ foundAssetNode = assetNode;
+ break;
+ }
+ }
+
+ return foundAssetNode;
+}
+
+VisualButton::VisualButton(QWidget* parent, BlastNode* blastItem)
+ : QWidget(parent)
+ , _button(new QPushButton(parent))
+ , _blastItem(blastItem)
+{
+ connect(_button, SIGNAL(toggled(bool)), this, SLOT(on_visualbility_toggled(bool)));
+ _button->setCheckable(true);
+ _button->setChecked(blastItem->getVisible());
+ if (blastItem->getVisible())
+ _button->setIcon(QIcon(":/AppMainWindow/images/visibilityToggle_visible.png"));
+ else
+ _button->setIcon(QIcon(":/AppMainWindow/images/visibilityToggle_notVisible.png"));
+ _button->setFixedSize(20, 20);
+ this->setLayoutDirection(Qt::RightToLeft);
+ this->setLayout(new QHBoxLayout);
+ this->layout()->setMargin(0);
+ this->layout()->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
+ this->layout()->addWidget(_button);
+}
+
+void VisualButton::on_visualbility_toggled(bool checked)
+{
+ if (checked)
+ {
+ _button->setIcon(QIcon(":/AppMainWindow/images/visibilityToggle_visible.png"));
+ }
+ else
+ {
+ _button->setIcon(QIcon(":/AppMainWindow/images/visibilityToggle_notVisible.png"));
+ }
+
+ if (_blastItem)
+ {
+ _blastItem->setVisible(checked);
+ }
+}
+
+void VisualButton::_updateBlast(bool visible)
+{
+ EBlastNodeType type = _blastItem->getType();
+
+ switch (type)
+ {
+ case eBond:
+ ((BPPBond*)_blastItem->getData())->visible = visible;
+ break;
+ case eChunk:
+ ((BPPChunk*)_blastItem->getData())->visible = visible;
+ break;
+ case eAsset:
+ ((BPPAsset*)_blastItem->getData())->visible = visible;
+ break;
+ case eProjectile:
+ ((BPPBond*)_blastItem->getData())->visible = visible;
+ break;
+ case eGraphicsMesh:
+ ((BPPGraphicsMesh*)_blastItem->getData())->visible = visible;
+ break;
+ case eAssetInstance:
+ ((BPPAssetInstance*)_blastItem->getData())->visible = visible;
+ break;
+ case eLandmark:
+ ((BPPLandmark*)_blastItem->getData())->visible = visible;
+ break;
+ case eComposite:
+ ((BPPComposite*)_blastItem->getData())->visible = visible;
+ break;
+ default:
+ break;
+ }
+}
+
+static BlastSceneTree* sBlastSceneTree = nullptr;
+BlastSceneTree* BlastSceneTree::ins()
+{
+ return sBlastSceneTree;
+}
+
+BlastSceneTree::BlastSceneTree(QWidget *parent)
+ : QDockWidget(parent)
+{
+ ui.setupUi(this);
+ _updateData = true;
+ sBlastSceneTree = this;
+
+ ui.blastSceneTree->setStyleSheet("QTreeWidget::item{height:24px}");
+ ui.blastSceneTree->setColumnWidth(0, 260);
+ ui.blastSceneTree->setColumnWidth(1, 20);
+
+ ui.blastSceneTree->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ _treeChunkContextMenu = new QMenu(this);
+ _makeSupportAction = new QAction(tr("Make Support"), this);
+ _treeChunkContextMenu->addAction(_makeSupportAction);
+ connect(_makeSupportAction, SIGNAL(triggered()), this, SLOT(onMakeSupportMenuItemClicked()));
+
+ _makeStaticSupportAction = new QAction(tr("Make Static Support"), this);
+ _treeChunkContextMenu->addAction(_makeStaticSupportAction);
+ connect(_makeStaticSupportAction, SIGNAL(triggered()), this, SLOT(onMakeStaticSupportMenuItemClicked()));
+
+ _removeSupportAction = new QAction(tr("Remove Support"), this);
+ _treeChunkContextMenu->addAction(_removeSupportAction);
+ connect(_removeSupportAction, SIGNAL(triggered()), this, SLOT(onRemoveSupportMenuItemClicked()));
+
+ _treeBondContextMenu = new QMenu(this);
+ _bondChunksAction = new QAction(tr("Bond Chunks"), this);
+ _treeBondContextMenu->addAction(_bondChunksAction);
+ connect(_bondChunksAction, SIGNAL(triggered()), this, SLOT(onBondChunksMenuItemClicked()));
+
+ _bondChunksWithJointsAction = new QAction(tr("Bond Chunks With Joints"), this);
+ _treeBondContextMenu->addAction(_bondChunksWithJointsAction);
+ connect(_bondChunksWithJointsAction, SIGNAL(triggered()), this, SLOT(onBondChunksWithJointsMenuItemClicked()));
+
+ _removeAllBondsAction = new QAction(tr("Remove All Bonds"), this);
+ _treeBondContextMenu->addAction(_removeAllBondsAction);
+ connect(_removeAllBondsAction, SIGNAL(triggered()), this, SLOT(onRemoveAllBondsMenuItemClicked()));
+}
+
+BlastSceneTree::~BlastSceneTree()
+{
+
+}
+
+void BlastSceneTree::updateValues(bool updataData)
+{
+ if (updataData)
+ {
+ BlastTreeData::ins().update();
+ }
+
+ _updateTreeUIs();
+}
+
+void BlastSceneTree::dataSelected(std::vector<BlastNode*> selections)
+{
+ for (size_t i = 0; i < selections.size(); ++i)
+ {
+ _selectTreeItem(selections[i]);
+ }
+}
+
+void BlastSceneTree::addObserver(ISceneObserver* observer)
+{
+ std::vector<ISceneObserver*>::iterator itr = std::find(_observers.begin(), _observers.end(), observer);
+ if (itr == _observers.end())
+ {
+ _observers.push_back(observer);
+ }
+}
+
+void BlastSceneTree::removeObserver(ISceneObserver* observer)
+{
+ std::vector<ISceneObserver*>::iterator itr = std::find(_observers.begin(), _observers.end(), observer);
+ _observers.erase(itr);
+}
+
+void BlastSceneTree::updateVisible(uint32_t assetIndex, uint32_t chunkIndex, bool visible)
+{
+ BlastTreeData::ins().updateVisible(assetIndex, chunkIndex, visible);
+}
+
+void BlastSceneTree::updateChunkItemSelection()
+{
+ _updateData = false;
+
+ ui.blastSceneTree->clearSelection();
+ BlastTreeData& treeData = BlastTreeData::ins();
+ std::vector<BlastChunkNode*> chunkNodes;
+
+ std::map<BlastAsset*, std::vector<uint32_t>> selectedChunks = SampleManager::ins()->getSelectedChunks();
+ std::map<BlastAsset*, std::vector<uint32_t>>::iterator itrAssetSelectedChunks = selectedChunks.begin();
+ for (; itrAssetSelectedChunks != selectedChunks.end(); ++itrAssetSelectedChunks)
+ {
+ std::vector<BlastChunkNode*> aseetNodes = treeData.getChunkNodeByBlastChunk(itrAssetSelectedChunks->first, itrAssetSelectedChunks->second);
+ chunkNodes.insert(chunkNodes.end(), aseetNodes.begin(), aseetNodes.end());
+ }
+
+ for (BlastChunkNode* node : chunkNodes)
+ {
+ _selectTreeItem(node);
+ }
+
+ _updateData = true;
+}
+
+void BlastSceneTree::makeSupport()
+{
+ std::vector<BlastChunkNode*> selectedChunkNodes;
+ QList<QTreeWidgetItem*> selectedItems = ui.blastSceneTree->selectedItems();
+ for (int i = 0; i < selectedItems.size(); ++i)
+ {
+ QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(selectedItems.at(i));
+
+ if (eChunk == itr.value()->getType())
+ {
+ selectedChunkNodes.push_back((BlastChunkNode*)itr.value());
+ }
+ }
+
+ std::vector<BlastChunkNode*> topChunkNodes = BlastTreeData::getTopChunkNodes(selectedChunkNodes);
+ for (size_t i = 0; i < topChunkNodes.size(); ++i)
+ {
+ BlastChunkNode* chunkNode = topChunkNodes[i];
+ BlastTreeData::makeSupport(chunkNode);
+ }
+
+ _updateChunkTreeItems();
+}
+
+void BlastSceneTree::makeStaticSupport()
+{
+ std::vector<BlastChunkNode*> selectedChunkNodes;
+ QList<QTreeWidgetItem*> selectedItems = ui.blastSceneTree->selectedItems();
+ for (int i = 0; i < selectedItems.size(); ++i)
+ {
+ QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(selectedItems.at(i));
+
+ if (eChunk == itr.value()->getType())
+ {
+ selectedChunkNodes.push_back((BlastChunkNode*)itr.value());
+ }
+ }
+
+ std::vector<BlastChunkNode*> topChunkNodes = BlastTreeData::getTopChunkNodes(selectedChunkNodes);
+ for (size_t i = 0; i < topChunkNodes.size(); ++i)
+ {
+ BlastChunkNode* chunkNode = topChunkNodes[i];
+ BlastTreeData::makeStaticSupport(chunkNode);
+ }
+
+ _updateChunkTreeItems();
+}
+
+void BlastSceneTree::removeSupport()
+{
+ std::vector<BlastChunkNode*> selectedChunkNodes;
+ QList<QTreeWidgetItem*> selectedItems = ui.blastSceneTree->selectedItems();
+ for (int i = 0; i < selectedItems.size(); ++i)
+ {
+ QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(selectedItems.at(i));
+
+ if (eChunk == itr.value()->getType())
+ {
+ selectedChunkNodes.push_back((BlastChunkNode*)itr.value());
+ }
+ }
+
+ std::vector<BlastChunkNode*> topChunkNodes = BlastTreeData::getTopChunkNodes(selectedChunkNodes);
+ for (size_t i = 0; i < topChunkNodes.size(); ++i)
+ {
+ BlastChunkNode* chunkNode = topChunkNodes[i];
+ BlastTreeData::removeSupport(chunkNode);
+ }
+
+ _updateChunkTreeItems();
+}
+
+void BlastSceneTree::bondChunks()
+{
+
+}
+
+void BlastSceneTree::bondChunksWithJoints()
+{
+
+}
+
+void BlastSceneTree::removeAllBonds()
+{
+
+}
+
+void BlastSceneTree::on_btnAsset_clicked()
+{
+ QMessageBox::information(NULL, "test", "on_btnAsset_clicked");
+}
+
+void BlastSceneTree::on_assetComposite_clicked()
+{
+ QMessageBox::information(NULL, "test", "on_assetComposite_clicked");
+}
+
+void BlastSceneTree::on_btnChunk_clicked()
+{
+ QMessageBox::information(NULL, "test", "on_btnChunk_clicked");
+}
+
+void BlastSceneTree::on_btnBond_clicked()
+{
+ QMessageBox::information(NULL, "test", "on_btnBond_clicked");
+}
+
+void BlastSceneTree::on_btnProjectile_clicked()
+{
+ QMessageBox::information(NULL, "test", "on_btnProjectile_clicked");
+}
+
+void BlastSceneTree::on_blastSceneTree_customContextMenuRequested(const QPoint &pos)
+{
+ QList<QTreeWidgetItem*> items = ui.blastSceneTree->selectedItems();
+
+ if (items.count() == 1)
+ {
+ QTreeWidgetItem* curItem = items.at(0);
+
+ QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(curItem);
+ if (itr != _treeItemDataMap.end())
+ {
+ if (eChunk == itr.value()->getType() || eBond == itr.value()->getType())
+ {
+ _treeChunkContextMenu->exec(QCursor::pos());
+ }
+ }
+ }
+ else if (items.count() > 1)
+ {
+ bool allSupportChunk = true;
+ for (int i = 0; i < items.count(); ++i)
+ {
+ QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(items.at(i));
+ if (itr != _treeItemDataMap.end())
+ {
+ if (eChunk != itr.value()->getType())
+ {
+ allSupportChunk = false;
+ break;
+ }
+ }
+ }
+
+ if (allSupportChunk)
+ {
+ _treeBondContextMenu->exec(QCursor::pos());
+ }
+ }
+
+}
+
+void BlastSceneTree::on_blastSceneTree_itemSelectionChanged()
+{
+ if (!_updateData)
+ return;
+
+ SampleManager::ins()->clearChunksSelected();
+
+ QList<QTreeWidgetItem*> selectedItems = ui.blastSceneTree->selectedItems();
+ std::vector<BlastNode*> nodes;
+ for (int i = 0; i < selectedItems.count(); ++i)
+ {
+ QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(selectedItems.at(i));
+ if (itr != _treeItemDataMap.end())
+ {
+ nodes.push_back(itr.value());
+
+ BlastNode* node = itr.value();
+ if (eChunk == node->getType())
+ {
+ ((BlastChunkNode*)node)->setSelected(true);
+ }
+ else if (eAssetInstance == node->getType())
+ {
+ ((BlastAssetInstanceNode*)node)->setSelected(true);
+ }
+ }
+ }
+
+ for (size_t i = 0; i < _observers.size(); ++i)
+ {
+ _observers[i]->dataSelected(nodes);
+ }
+}
+
+void BlastSceneTree::onMakeSupportMenuItemClicked()
+{
+ makeSupport();
+}
+
+void BlastSceneTree::onMakeStaticSupportMenuItemClicked()
+{
+ makeStaticSupport();
+}
+
+void BlastSceneTree::onRemoveSupportMenuItemClicked()
+{
+ removeSupport();
+}
+
+void BlastSceneTree::onBondChunksMenuItemClicked()
+{
+ bondChunks();
+}
+
+void BlastSceneTree::onBondChunksWithJointsMenuItemClicked()
+{
+ bondChunksWithJoints();
+}
+
+void BlastSceneTree::onRemoveAllBondsMenuItemClicked()
+{
+ removeAllBonds();
+}
+
+void BlastSceneTree::_updateTreeUIs()
+{
+ ui.blastSceneTree->clear();
+ _treeItemDataMap.clear();
+ _treeDataItemMap.clear();
+
+ BlastCompositeNode* compositeNode = BlastTreeData::ins().getCompsiteNode();
+ if (compositeNode != nullptr)
+ {
+ QTreeWidgetItem* compositeTreeWidgetItem = new QTreeWidgetItem(ui.blastSceneTree);
+ compositeTreeWidgetItem->setText(0, compositeNode->name.c_str());
+ compositeTreeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/AssetComposite.png"));
+ VisualButton* btn = new VisualButton(this, compositeNode);
+ ui.blastSceneTree->setItemWidget(compositeTreeWidgetItem, 1, btn);
+ _treeItemDataMap.insert(compositeTreeWidgetItem, compositeNode);
+ _treeDataItemMap.insert(compositeNode, compositeTreeWidgetItem);
+
+ size_t count = compositeNode->children.size();
+ for (size_t i = 0; i < count; ++i)
+ {
+ BlastNode* assetInstanceNode = compositeNode->children[i];
+ QTreeWidgetItem* assetInstanceWidgetItem = new QTreeWidgetItem(compositeTreeWidgetItem);
+ assetInstanceWidgetItem->setText(0, assetInstanceNode->name.c_str());
+ if (assetInstanceNode->getType() == eAssetInstance)
+ assetInstanceWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Asset.png"));
+ VisualButton* btn = new VisualButton(this, assetInstanceNode);
+ ui.blastSceneTree->setItemWidget(assetInstanceWidgetItem, 1, btn);
+ _treeItemDataMap.insert(assetInstanceWidgetItem, assetInstanceNode);
+ _treeDataItemMap.insert(assetInstanceNode, assetInstanceWidgetItem);
+ }
+ }
+
+ std::vector<BlastAssetNode*>& assets = BlastTreeData::ins().getAssetNodes();
+ size_t count = assets.size();
+ for (size_t i = 0; i < count; ++i)
+ {
+ BlastAssetNode* assetNode = assets[i];
+
+ QTreeWidgetItem* assetTreeWidgetItem = new QTreeWidgetItem(ui.blastSceneTree);
+ assetTreeWidgetItem->setText(0, assetNode->name.c_str());
+ assetTreeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Asset.png"));
+ VisualButton* btn = new VisualButton(this, assetNode);
+ ui.blastSceneTree->setItemWidget(assetTreeWidgetItem, 1, btn);
+ _treeItemDataMap.insert(assetTreeWidgetItem, assetNode);
+ _treeDataItemMap.insert(assetNode, assetTreeWidgetItem);
+
+ _addChunkUI(assetNode, assetTreeWidgetItem);
+ }
+
+ std::vector<BlastProjectileNode*>& projectiles = BlastTreeData::ins().getProjectileNodes();
+ count = projectiles.size();
+ for (int i = 0; i < count; ++i)
+ {
+ BlastProjectileNode* projectileNode = projectiles[i];
+
+ QTreeWidgetItem* projectileTreeWidgetItem = new QTreeWidgetItem(ui.blastSceneTree);
+ projectileTreeWidgetItem->setText(0, projectileNode->name.c_str());
+ projectileTreeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Projectile.png"));
+ VisualButton* btn = new VisualButton(this, projectileNode);
+ ui.blastSceneTree->setItemWidget(projectileTreeWidgetItem, 1, btn);
+ _treeItemDataMap.insert(projectileTreeWidgetItem, projectileNode);
+ _treeDataItemMap.insert(projectileNode, projectileTreeWidgetItem);
+ }
+
+ std::vector<BlastGraphicsMeshNode*>& graphicsMeshes = BlastTreeData::ins().getGraphicsMeshNodes();
+ count = graphicsMeshes.size();
+ for (int i = 0; i < count; ++i)
+ {
+ BlastGraphicsMeshNode* graphicsMesheNode = graphicsMeshes[i];
+
+ QTreeWidgetItem* graphicsMesheTreeWidgetItem = new QTreeWidgetItem(ui.blastSceneTree);
+ graphicsMesheTreeWidgetItem->setText(0, graphicsMesheNode->name.c_str());
+ VisualButton* btn = new VisualButton(this, graphicsMesheNode);
+ ui.blastSceneTree->setItemWidget(graphicsMesheTreeWidgetItem, 1, btn);
+ _treeItemDataMap.insert(graphicsMesheTreeWidgetItem, graphicsMesheNode);
+ _treeDataItemMap.insert(graphicsMesheNode, graphicsMesheTreeWidgetItem);
+ }
+
+ //for (int j = 0; j < ui.blastSceneTree->topLevelItemCount(); ++j)
+ //{
+ // QTreeWidgetItem* topLevelItem = ui.blastSceneTree->topLevelItem(j);
+ // ui.blastSceneTree->expandItem(topLevelItem);
+ //}
+ ui.blastSceneTree->expandAll();
+}
+
+void BlastSceneTree::_addChunkUI(const BlastNode* parentNode, QTreeWidgetItem* parentTreeItem)
+{
+ if (parentNode != nullptr && parentTreeItem != nullptr)
+ {
+ for (size_t i = 0; i < parentNode->children.size(); ++i)
+ {
+ BlastNode* node = parentNode->children[i];
+ if (node == nullptr)
+ continue;
+
+ QTreeWidgetItem* treeWidgetItem = nullptr;
+
+ if (node->getType() == eChunk)
+ {
+ BlastChunkNode* chunk = static_cast<BlastChunkNode*>(node);
+ treeWidgetItem = new QTreeWidgetItem(parentTreeItem);
+ treeWidgetItem->setText(0, chunk->name.c_str());
+ if (chunk->isSupport())
+ {
+ treeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Support_Unstatic.png"));
+ }
+ else
+ {
+ treeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Unsupport_Unstatic.png"));
+ }
+
+ _addChunkUI(chunk, treeWidgetItem);
+ }
+ else if (node->getType() == eBond)
+ {
+ BlastBondNode* bond = static_cast<BlastBondNode*>(node);
+ treeWidgetItem = new QTreeWidgetItem(parentTreeItem);
+ treeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Bond.png"));
+ treeWidgetItem->setText(0, bond->name.c_str());
+ }
+
+ if (treeWidgetItem == nullptr)
+ continue;
+ VisualButton* btn = new VisualButton(this, node);
+ ui.blastSceneTree->setItemWidget(treeWidgetItem, 1, btn);
+ _treeItemDataMap.insert(treeWidgetItem, node);
+ _treeDataItemMap.insert(node, treeWidgetItem);
+ }
+ }
+}
+
+void BlastSceneTree::_updateChunkTreeItemAndMenu(BPPChunk* chunk, QTreeWidgetItem* chunkItem)
+{
+ assert(chunk != nullptr);
+
+ _removeSupportAction->setEnabled(true);
+ _makeSupportAction->setEnabled(true);
+ _makeStaticSupportAction->setEnabled(true);
+
+ if (!chunk->support && !chunk->staticFlag)
+ {
+ _removeSupportAction->setEnabled(false);
+ chunkItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Unsupport_Unstatic.png"));
+ }
+ else if (chunk->support && !chunk->staticFlag)
+ {
+ _makeSupportAction->setEnabled(false);
+ chunkItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Support_Unstatic.png"));
+ }
+ else if (chunk->support && chunk->staticFlag)
+ {
+ _makeStaticSupportAction->setEnabled(false);
+ chunkItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Support_Static.png"));
+ }
+}
+
+void BlastSceneTree::_updateChunkTreeItems()
+{
+ for (QMap<BlastNode*, QTreeWidgetItem*>::iterator itr = _treeDataItemMap.begin(); itr != _treeDataItemMap.end(); ++itr)
+ {
+ BlastNode* node = itr.key();
+ QTreeWidgetItem* treeItem = itr.value();
+ if (eChunk == node->getType())
+ {
+ BPPChunk* chunk = static_cast<BPPChunk*>(node->getData());
+ if (!chunk->support && !chunk->staticFlag)
+ {
+ treeItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Unsupport_Unstatic.png"));
+ }
+ else if (chunk->support && !chunk->staticFlag)
+ {
+ treeItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Support_Unstatic.png"));
+ }
+ else if (chunk->support && chunk->staticFlag)
+ {
+ treeItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Support_Static.png"));
+ }
+ }
+ }
+}
+
+void BlastSceneTree::_selectTreeItem(BlastNode* node)
+{
+ QMap<BlastNode*, QTreeWidgetItem*>::iterator itr = _treeDataItemMap.find(node);
+ if (itr != _treeDataItemMap.end())
+ {
+ ui.blastSceneTree->setItemSelected(itr.value(), true);
+ }
+}
+
+//void BlastSceneTree::_createTestData()
+//{
+// BPPBlast& blast = BlastProject::ins().getParams().blast;
+//
+// // compoistie
+// {
+// BPPComposite& composite = blast.composite;
+// composite.composite.buf = nullptr;
+// composite.visible = true;
+//
+// copy(composite.composite, "BlastComposite");
+//
+// // asset instance array
+// {
+// BPPAssetInstanceArray& instanceArray = composite.blastAssetInstances;
+// instanceArray.buf = new BPPAssetInstance[4];
+// instanceArray.arraySizes[0] = 4;
+// instanceArray.buf[0].name.buf = nullptr;
+// instanceArray.buf[1].name.buf = nullptr;
+// instanceArray.buf[2].name.buf = nullptr;
+// instanceArray.buf[3].name.buf = nullptr;
+// instanceArray.buf[0].source.buf = nullptr;
+// instanceArray.buf[1].source.buf = nullptr;
+// instanceArray.buf[2].source.buf = nullptr;
+// instanceArray.buf[3].source.buf = nullptr;
+//
+// copy(instanceArray.buf[0].name, "BlastAsset_instance1");
+// instanceArray.buf[0].visible = true;
+//
+// copy(instanceArray.buf[1].name, "BlastAsset_instance2");
+// instanceArray.buf[1].visible = true;
+//
+// copy(instanceArray.buf[2].name, "BlastAsset1_instance1");
+// instanceArray.buf[2].visible = true;
+//
+// copy(instanceArray.buf[3].name, "BlastAsset1_instance2");
+// instanceArray.buf[3].visible = true;
+// }
+//
+// // landmark array
+// {
+// BPPLandmarkArray& landmarkArray = composite.landmarks;
+// landmarkArray.buf = new BPPLandmark[2];
+// landmarkArray.arraySizes[0] = 2;
+// landmarkArray.buf[0].name.buf = nullptr;
+// landmarkArray.buf[1].name.buf = nullptr;
+//
+// copy(landmarkArray.buf[0].name, "Landmark_1");
+// copy(landmarkArray.buf[1].name, "Landmark_2");
+// }
+// }
+//
+// // asset array
+// {
+// BPPAssetArray& assetArray = blast.blastAssets;
+// assetArray.buf = new BPPAsset[2];
+// assetArray.arraySizes[0] = 2;
+//
+// // asset 0
+// {
+// BPPAsset& asset = assetArray.buf[0];
+// asset.path.buf = nullptr;
+// asset.activePreset.buf = nullptr;
+// asset.bonds.buf = nullptr;
+// asset.chunks.buf = nullptr;
+//
+// copy(asset.path, "c:/temp/BlastAsset.asset");
+//
+// // chunks
+// {
+// asset.chunks.buf = new BPPChunk[10];
+// asset.chunks.arraySizes[0] = 10;
+// for (int i = 0; i < 10; ++i)
+// {
+// asset.chunks.buf[i].name.buf = nullptr;
+// asset.chunks.buf[i].visible = true;
+// asset.chunks.buf[i].staticFlag = false;
+// }
+//
+// copy(asset.chunks.buf[0].name, "Chunk_L0_00");
+// asset.chunks.buf[0].ID = 0;
+// asset.chunks.buf[0].parentID = -1;
+// asset.chunks.buf[0].support = false;
+//
+// copy(asset.chunks.buf[1].name, "Chunk_L0_01");
+// asset.chunks.buf[1].ID = 1;
+// asset.chunks.buf[1].parentID = -1;
+// asset.chunks.buf[1].support = false;
+//
+// copy(asset.chunks.buf[2].name, "Chunk_L1_02");
+// asset.chunks.buf[2].ID = 2;
+// asset.chunks.buf[2].parentID = 0;
+// asset.chunks.buf[2].support = false;
+//
+// copy(asset.chunks.buf[3].name, "Chunk_L1_03");
+// asset.chunks.buf[3].ID = 3;
+// asset.chunks.buf[3].parentID = 0;
+// asset.chunks.buf[3].support = false;
+//
+// copy(asset.chunks.buf[4].name, "Chunk_L1_04");
+// asset.chunks.buf[4].ID = 4;
+// asset.chunks.buf[4].parentID = 1;
+// asset.chunks.buf[4].support = false;
+//
+// copy(asset.chunks.buf[5].name, "Chunk_L1_05");
+// asset.chunks.buf[5].ID = 5;
+// asset.chunks.buf[5].parentID = 1;
+// asset.chunks.buf[5].support = false;
+//
+// copy(asset.chunks.buf[6].name, "Chunk_L2_06");
+// asset.chunks.buf[6].ID = 6;
+// asset.chunks.buf[6].parentID = 2;
+// asset.chunks.buf[6].support = true;
+//
+// copy(asset.chunks.buf[7].name, "Chunk_L2_07");
+// asset.chunks.buf[7].ID = 7;
+// asset.chunks.buf[7].parentID = 2;
+// asset.chunks.buf[7].support = true;
+//
+// copy(asset.chunks.buf[8].name, "Chunk_L2_08");
+// asset.chunks.buf[8].ID = 8;
+// asset.chunks.buf[8].parentID = 3;
+// asset.chunks.buf[8].support = true;
+//
+// copy(asset.chunks.buf[9].name, "Chunk_L2_09");
+// asset.chunks.buf[9].ID = 9;
+// asset.chunks.buf[9].parentID = 3;
+// asset.chunks.buf[9].support = true;
+// }
+//
+// // bonds
+// {
+// asset.bonds.buf = new BPPBond[4];
+// asset.bonds.arraySizes[0] = 4;
+// for (int i = 0; i < 4; ++i)
+// {
+// asset.bonds.buf[i].name.buf = nullptr;
+// asset.bonds.buf[i].visible = true;
+// asset.bonds.buf[i].support.healthMask.buf = nullptr;
+// }
+//
+// copy(asset.bonds.buf[0].name, "Chunk_L2_08");
+// asset.bonds.buf[0].fromChunk = 6;
+// asset.bonds.buf[0].toChunk = 8;
+//
+// copy(asset.bonds.buf[1].name, "Chunk_L2_06");
+// asset.bonds.buf[1].fromChunk = 6;
+// asset.bonds.buf[1].toChunk = 8;
+//
+// copy(asset.bonds.buf[2].name, "Chunk_L2_09");
+// asset.bonds.buf[2].fromChunk = 7;
+// asset.bonds.buf[2].toChunk = 9;
+//
+// copy(asset.bonds.buf[3].name, "Chunk_L2_07");
+// asset.bonds.buf[3].fromChunk = 7;
+// asset.bonds.buf[3].toChunk = 9;
+// }
+// }
+//
+// // asset 1
+// {
+// BPPAsset& asset = assetArray.buf[1];
+// asset.path.buf = nullptr;
+// asset.activePreset.buf = nullptr;
+// asset.bonds.buf = nullptr;
+// asset.chunks.buf = nullptr;
+//
+// copy(asset.path, "c:/temp/BlastAsset1.asset");
+// {
+// asset.chunks.buf = new BPPChunk[10];
+// asset.chunks.arraySizes[0] = 10;
+// for (int i = 0; i < 10; ++i)
+// {
+// asset.chunks.buf[i].name.buf = nullptr;
+// asset.chunks.buf[i].visible = true;
+// }
+//
+// copy(asset.chunks.buf[0].name, "Chunk_L0_00");
+// asset.chunks.buf[0].ID = 0;
+// asset.chunks.buf[0].parentID = -1;
+// asset.chunks.buf[0].support = false;
+//
+// copy(asset.chunks.buf[1].name, "Chunk_L0_01");
+// asset.chunks.buf[1].ID = 1;
+// asset.chunks.buf[1].parentID = -1;
+// asset.chunks.buf[1].support = false;
+//
+// copy(asset.chunks.buf[2].name, "Chunk_L1_02");
+// asset.chunks.buf[2].ID = 2;
+// asset.chunks.buf[2].parentID = 0;
+// asset.chunks.buf[2].support = false;
+//
+// copy(asset.chunks.buf[3].name, "Chunk_L1_03");
+// asset.chunks.buf[3].ID = 3;
+// asset.chunks.buf[3].parentID = 0;
+// asset.chunks.buf[3].support = false;
+//
+// copy(asset.chunks.buf[4].name, "Chunk_L1_04");
+// asset.chunks.buf[4].ID = 4;
+// asset.chunks.buf[4].parentID = 1;
+// asset.chunks.buf[4].support = false;
+//
+// copy(asset.chunks.buf[5].name, "Chunk_L1_05");
+// asset.chunks.buf[5].ID = 5;
+// asset.chunks.buf[5].parentID = 1;
+// asset.chunks.buf[5].support = false;
+//
+// copy(asset.chunks.buf[6].name, "Chunk_L2_06");
+// asset.chunks.buf[6].ID = 6;
+// asset.chunks.buf[6].parentID = 2;
+// asset.chunks.buf[6].support = true;
+//
+// copy(asset.chunks.buf[7].name, "Chunk_L2_07");
+// asset.chunks.buf[7].ID = 7;
+// asset.chunks.buf[7].parentID = 2;
+// asset.chunks.buf[7].support = true;
+//
+// copy(asset.chunks.buf[8].name, "Chunk_L2_08");
+// asset.chunks.buf[8].ID = 8;
+// asset.chunks.buf[8].parentID = 3;
+// asset.chunks.buf[8].support = true;
+//
+// copy(asset.chunks.buf[9].name, "Chunk_L2_09");
+// asset.chunks.buf[9].ID = 9;
+// asset.chunks.buf[9].parentID = 3;
+// asset.chunks.buf[9].support = true;
+// }
+// }
+// }
+//
+// // projectile
+// {
+// BPPProjectileArray& projectileArray = blast.projectiles;
+// projectileArray.buf = new BPPProjectile[1];
+// projectileArray.arraySizes[0] = 1;
+// projectileArray.buf[0].name.buf = nullptr;
+// copy(projectileArray.buf[0].name, "Projectile");
+// projectileArray.buf[0].visible = true;
+// }
+//
+// // graphics meshes
+// {
+// BPPGraphicsMeshArray& graphicsMeshArray = blast.graphicsMeshes;
+// graphicsMeshArray.buf = new BPPGraphicsMesh[3];
+// graphicsMeshArray.arraySizes[0] = 3;
+// graphicsMeshArray.buf[0].name.buf = nullptr;
+// copy(graphicsMeshArray.buf[0].name, "SurfaceMesh1");
+// graphicsMeshArray.buf[0].visible = true;
+//
+// graphicsMeshArray.buf[1].name.buf = nullptr;
+// copy(graphicsMeshArray.buf[1].name, "SurfaceMesh2");
+// graphicsMeshArray.buf[1].visible = true;
+//
+// graphicsMeshArray.buf[2].name.buf = nullptr;
+// copy(graphicsMeshArray.buf[2].name, "DisplayMesh1");
+// graphicsMeshArray.buf[2].visible = true;
+// }
+//}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.h
new file mode 100644
index 0000000..540f420
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.h
@@ -0,0 +1,284 @@
+#ifndef BLASTSCENETREE_H
+#define BLASTSCENETREE_H
+
+#include <QtWidgets/QDockWidget>
+#include "ui_BlastSceneTree.h"
+#include "ProjectParams.h"
+#include <vector>
+#include <string>
+#include <QtCore/QMap>
+
+class QTreeWidgetItem;
+class BlastAsset;
+
+enum EBlastNodeType
+{
+ eBond,
+ eChunk,
+ eAsset,
+ eProjectile,
+ eGraphicsMesh,
+ eAssetInstance,
+ eLandmark,
+ eComposite,
+};
+
+class BlastNode
+{
+public:
+ BlastNode(const std::string& inName, void* inData)
+ : name(inName)
+ , _data(inData)
+ {
+ }
+
+ void* getData() { return _data; }
+ void setParent(BlastNode* parent) { _parent = parent; }
+ BlastNode* getParent() { return _parent; }
+ virtual EBlastNodeType getType() = 0;
+ virtual bool getVisible() = 0;
+ virtual void setVisible(bool val) = 0;
+
+ std::string name;
+ std::vector<BlastNode*> children;
+
+protected:
+ void* _data;
+ BlastNode* _parent;
+};
+
+class BlastBondNode : public BlastNode
+{
+public:
+ BlastBondNode(const std::string& inName, BPPBond& inData)
+ : BlastNode(inName, &inData)
+ {
+ }
+ virtual EBlastNodeType getType() { return eBond; }
+ virtual bool getVisible() { return ((BPPBond*)_data)->visible; }
+ virtual void setVisible(bool val) { ((BPPBond*)_data)->visible = val; }
+
+private:
+ std::vector<BlastNode*> children;
+};
+
+class BlastChunkNode : public BlastNode
+{
+public:
+ BlastChunkNode(const std::string& inName, BPPChunk& inData, void* assetPtr)
+ : BlastNode(inName, &inData)
+ {
+ _assetPtr = assetPtr;
+ }
+ virtual EBlastNodeType getType() { return eChunk; }
+ virtual bool getVisible() { return ((BPPChunk*)_data)->visible; }
+ virtual void setVisible(bool val);// { ((BPPChunk*)_data)->visible = val; }
+ void setSelected(bool val);
+ bool isSupport() { return ((BPPChunk*)_data)->support; }
+ void* _assetPtr;
+};
+
+class BlastAssetNode : public BlastNode
+{
+public:
+ BlastAssetNode(const std::string& inName, BPPAsset& inData)
+ : BlastNode(inName, &inData)
+ {
+ }
+ virtual EBlastNodeType getType() { return eAsset; }
+ virtual bool getVisible() { return ((BPPAsset*)_data)->visible; }
+ virtual void setVisible(bool val) { ((BPPAsset*)_data)->visible = val; }
+};
+
+class BlastProjectileNode : public BlastNode
+{
+public:
+ BlastProjectileNode(const std::string& inName, BPPProjectile& inData)
+ : BlastNode(inName, &inData)
+ {
+ }
+ virtual EBlastNodeType getType() { return eProjectile; }
+ virtual bool getVisible() { return ((BPPProjectile*)_data)->visible; }
+ virtual void setVisible(bool val) { ((BPPProjectile*)_data)->visible = val; }
+};
+
+class BlastGraphicsMeshNode : public BlastNode
+{
+public:
+ BlastGraphicsMeshNode(const std::string& inName, BPPGraphicsMesh& inData)
+ : BlastNode(inName, &inData)
+ {
+ }
+ virtual EBlastNodeType getType() { return eGraphicsMesh; }
+ virtual bool getVisible() { return ((BPPGraphicsMesh*)_data)->visible; }
+ virtual void setVisible(bool val) { ((BPPGraphicsMesh*)_data)->visible = val; }
+};
+
+class BlastAssetInstanceNode : public BlastNode
+{
+public:
+ BlastAssetInstanceNode(const std::string& inName, BPPAssetInstance& inData)
+ : BlastNode(inName, &inData)
+ {
+ }
+ virtual EBlastNodeType getType() { return eAssetInstance; }
+ virtual bool getVisible() { return ((BPPAssetInstance*)_data)->visible; }
+ virtual void setVisible(bool val) { ((BPPAssetInstance*)_data)->visible = val; }
+ void setSelected(bool val);
+};
+
+class BlastLandmarkNode : public BlastNode
+{
+public:
+ BlastLandmarkNode(const std::string& inName, BPPLandmark& inData)
+ : BlastNode(inName, &inData)
+ {
+ }
+ virtual EBlastNodeType getType() { return eLandmark; }
+ virtual bool getVisible() { return ((BPPLandmark*)_data)->visible; }
+ virtual void setVisible(bool val) { ((BPPLandmark*)_data)->visible = val; }
+};
+
+class BlastCompositeNode : public BlastNode
+{
+public:
+ BlastCompositeNode(const std::string& inName, BPPComposite& inData)
+ : BlastNode(inName, &inData)
+ {
+ }
+ virtual EBlastNodeType getType() { return eComposite; }
+ virtual bool getVisible() { return ((BPPComposite*)_data)->visible; }
+ virtual void setVisible(bool val) { ((BPPComposite*)_data)->visible = val; }
+};
+
+class BlastTreeData
+{
+public:
+ static BlastTreeData& ins();
+ static bool isChild(BlastChunkNode* parent, BlastChunkNode* child);
+ static std::vector<BlastChunkNode*> getTopChunkNodes(std::vector<BlastChunkNode*>& nodes);
+ static bool isRoot(BlastChunkNode* node);
+ static bool isLeaf(BlastChunkNode* node);
+ static void makeSupport(BlastChunkNode* node);
+ static void makeStaticSupport(BlastChunkNode* node);
+ static void removeSupport(BlastChunkNode* node);
+
+ BlastNode* getBlastNodeByProjectData(void* blastProjectData);
+ BlastCompositeNode* getCompsiteNode() { return _composite; }
+ std::vector<BlastAssetNode*>& getAssetNodes() { return _assets; }
+ std::vector<BlastProjectileNode*>& getProjectileNodes() { return _projectiles; }
+ std::vector<BlastGraphicsMeshNode*>& getGraphicsMeshNodes() { return _graphicsMeshes; }
+ std::vector<BlastChunkNode*> getChunkNodeByBlastChunk(const BlastAsset* asset, const std::vector<uint32_t>& chunkIndexes);
+ bool isCompleteSupportAsset(const BlastAsset* asset);
+ bool isCompleteSupportAsset(const BlastAssetNode* node);
+ bool isOverlapSupportAsset(const BlastAsset* asset);
+ bool isOverlapSupportAsset(const BlastAssetNode* node);
+ void update();
+
+ void updateVisible(uint32_t assetIndex, uint32_t chunkIndex, bool visible);
+
+private:
+ BlastTreeData();
+ void _addChunkNode(const BPPChunk& parentData, BPPAsset& asset, BlastChunkNode* parentNode, void* assetPtr);
+ void _freeBlastNode();
+ BlastAssetNode* _getAssetNode(const BlastAsset* asset);
+
+private:
+ BlastCompositeNode* _composite;
+ std::vector<BlastAssetNode*> _assets;
+ std::vector<BlastProjectileNode*> _projectiles;
+ std::vector<BlastGraphicsMeshNode*> _graphicsMeshes;
+ std::map<void*, BlastNode*> _blastProjectDataToNodeMap;
+};
+
+class ISceneObserver
+{
+public:
+ virtual void dataSelected(std::vector<BlastNode*> selections) = 0;
+};
+
+class VisualButton : public QWidget
+{
+ Q_OBJECT
+public:
+ VisualButton(QWidget* parent, BlastNode* blastItem);
+
+protected slots:
+ void on_visualbility_toggled(bool checked);
+private:
+ void _updateBlast(bool visible);
+
+private:
+ QPushButton* _button;
+ BlastNode* _blastItem;
+};
+
+class BlastSceneTree : public QDockWidget, public ISceneObserver
+{
+ Q_OBJECT
+
+public:
+ static BlastSceneTree* ins();
+
+ BlastSceneTree(QWidget *parent = 0);
+ ~BlastSceneTree();
+
+ void updateValues(bool updataData = true);
+
+ virtual void dataSelected(std::vector<BlastNode*> selections);
+
+ void addObserver(ISceneObserver* observer);
+ void removeObserver(ISceneObserver* observer);
+
+ void updateVisible(uint32_t assetIndex, uint32_t chunkIndex, bool visible);
+ void updateChunkItemSelection();
+
+ void makeSupport();
+ void makeStaticSupport();
+ void removeSupport();
+ void bondChunks();
+ void bondChunksWithJoints();
+ void removeAllBonds();
+
+protected slots:
+ void on_btnAsset_clicked();
+ void on_assetComposite_clicked();
+ void on_btnChunk_clicked();
+ void on_btnBond_clicked();
+ void on_btnProjectile_clicked();
+ void on_blastSceneTree_customContextMenuRequested(const QPoint &pos);
+ void on_blastSceneTree_itemSelectionChanged();
+ void onMakeSupportMenuItemClicked();
+ void onMakeStaticSupportMenuItemClicked();
+ void onRemoveSupportMenuItemClicked();
+ void onBondChunksMenuItemClicked();
+ void onBondChunksWithJointsMenuItemClicked();
+ void onRemoveAllBondsMenuItemClicked();
+
+private:
+ void _updateTreeUIs();
+ void _addChunkUI(const BlastNode* parentNode, QTreeWidgetItem* parentTreeItem);
+ void _updateChunkTreeItemAndMenu(BPPChunk* chunk, QTreeWidgetItem* chunkItem);
+ void _updateChunkTreeItems();
+
+ void _selectTreeItem(BlastNode* node);
+
+ //void _createTestData();
+
+private:
+ Ui::BlastSceneTree ui;
+ QMap<QTreeWidgetItem*, BlastNode*> _treeItemDataMap;
+ QMap<BlastNode*, QTreeWidgetItem*> _treeDataItemMap;
+ QMenu* _treeChunkContextMenu;
+ QMenu* _treeBondContextMenu;
+ QAction* _makeSupportAction;
+ QAction* _makeStaticSupportAction;
+ QAction* _removeSupportAction;
+ QAction* _bondChunksAction;
+ QAction* _bondChunksWithJointsAction;
+ QAction* _removeAllBondsAction;
+ std::vector<ISceneObserver*> _observers;
+ bool _updateData;
+};
+
+#endif // BLASTSCENETREE_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastToolBar.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastToolBar.cpp
new file mode 100644
index 0000000..98b5646
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastToolBar.cpp
@@ -0,0 +1,523 @@
+#include "BlastToolbar.h"
+
+#include <QtWidgets/QFileDialog>
+#include "AppMainWindow.h"
+#include "PhysXController.h"
+#include "QtUtil.h"
+
+BlastToolbar::BlastToolbar(QWidget* parent)
+ : QDockWidget(parent)
+{
+ // to hide the title bar completely must replace the default widget with a generic one
+ QWidget* titleWidget = new QWidget(this);
+ this->setTitleBarWidget(titleWidget);
+ this->setObjectName(QString::fromUtf8("AppMainToolbar"));
+ this->setMinimumSize(QSize(0, 50));
+ this->setMaximumSize(QSize(16777215, 80));
+
+ if (this->objectName().isEmpty())
+ this->setObjectName(QStringLiteral("AppMainToolbar"));
+ this->resize(1330, 54);
+
+ QWidget* widget = new QWidget();
+ hLayout = new QHBoxLayout(widget);
+ hLayout->setObjectName(QStringLiteral("hLayout"));
+ hLayout->setContentsMargins(-1, 3, -1, 3);
+
+ QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ sizePolicy1.setHorizontalStretch(0);
+ sizePolicy1.setVerticalStretch(0);
+
+ btnOpenProject = new QPushButton(widget);
+ setStyledToolTip(btnOpenProject, "Open Blast Asset");
+ const QFont& font = btnOpenProject->font();
+ QFont fontCopy(font);
+ fontCopy.setPixelSize(9);
+
+ btnOpenProject->setObjectName(QStringLiteral("btnOpenProject"));
+ sizePolicy1.setHeightForWidth(btnOpenProject->sizePolicy().hasHeightForWidth());
+ btnOpenProject->setSizePolicy(sizePolicy1);
+ btnOpenProject->setMinimumSize(QSize(40, 40));
+ btnOpenProject->setMaximumSize(QSize(40, 40));
+ btnOpenProject->setText(QApplication::translate("AppMainToolbar", "Open", 0));
+ hLayout->addWidget(btnOpenProject);
+
+ btnSaveProject = new QPushButton(widget);
+ setStyledToolTip(btnSaveProject, "Not Implement");
+ btnSaveProject->setObjectName(QStringLiteral("btnSaveProject"));
+ sizePolicy1.setHeightForWidth(btnOpenProject->sizePolicy().hasHeightForWidth());
+ btnSaveProject->setSizePolicy(sizePolicy1);
+ btnSaveProject->setMinimumSize(QSize(40, 40));
+ btnSaveProject->setMaximumSize(QSize(40, 40));
+ btnSaveProject->setText(QApplication::translate("AppMainToolbar", "Save\nAll", 0));
+ hLayout->addWidget(btnSaveProject);
+
+ btnExportAssets = new QPushButton(widget);
+ setStyledToolTip(btnExportAssets, "Not Implement");
+ btnExportAssets->setObjectName(QStringLiteral("btnExportAssets"));
+ sizePolicy1.setHeightForWidth(btnExportAssets->sizePolicy().hasHeightForWidth());
+ btnExportAssets->setSizePolicy(sizePolicy1);
+ btnExportAssets->setMinimumSize(QSize(40, 40));
+ btnExportAssets->setMaximumSize(QSize(40, 40));
+ btnExportAssets->setText(QApplication::translate("AppMainToolbar", "Export", 0));
+ hLayout->addWidget(btnExportAssets);
+
+ vLayoutExport = new QVBoxLayout();
+ vLayoutExport->setObjectName(QStringLiteral("vLayoutExport"));
+
+ hLayoutExport = new QHBoxLayout();
+ hLayoutExport->setObjectName(QStringLiteral("hLayoutExport"));
+
+ lExportFilepath = new QLabel(widget);
+ lExportFilepath->setObjectName(QStringLiteral("lExportFilepath"));
+ lExportFilepath->setText(QApplication::translate("AppMainToolbar", "Export Path", 0));
+ hLayoutExport->addWidget(lExportFilepath);
+
+ btnExportFilepath = new QPushButton(widget);
+ btnExportFilepath->setObjectName(QStringLiteral("btnExportFilepath"));
+ sizePolicy1.setHeightForWidth(btnExportFilepath->sizePolicy().hasHeightForWidth());
+ btnExportFilepath->setSizePolicy(sizePolicy1);
+ btnExportFilepath->setMinimumSize(QSize(14, 14));
+ btnExportFilepath->setMaximumSize(QSize(14, 14));
+ btnExportFilepath->setText(QApplication::translate("AppMainToolbar", "", 0));
+ btnExportFilepath->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnExportFilepath.png"));
+ btnExportFilepath->setIconSize(QSize(14, 14));
+ hLayoutExport->addWidget(btnExportFilepath);
+
+ vLayoutExport->addLayout(hLayoutExport);
+
+ leExportFilepath = new QLineEdit(widget);
+ leExportFilepath->setObjectName(QStringLiteral("leExportFilepath"));
+ sizePolicy1.setHeightForWidth(leExportFilepath->sizePolicy().hasHeightForWidth());
+ leExportFilepath->setSizePolicy(sizePolicy1);
+ leExportFilepath->setMinimumSize(QSize(150, 20));
+ leExportFilepath->setMaximumSize(QSize(150, 20));
+ leExportFilepath->setText(QApplication::translate("AppMainToolbar", "", 0));
+ vLayoutExport->addWidget(leExportFilepath);
+
+ hLayout->addLayout(vLayoutExport);
+
+ fSeparate = new QFrame(widget);
+ fSeparate->setObjectName(QStringLiteral("fSeparate"));
+ fSeparate->setFrameShape(QFrame::VLine);
+ fSeparate->setFrameShadow(QFrame::Sunken);
+ hLayout->addWidget(fSeparate);
+
+ vLayoutDepthCoverage = new QVBoxLayout();
+ vLayoutDepthCoverage->setObjectName(QStringLiteral("vLayoutDepthCoverage"));
+
+ hlDepthPreview = new QHBoxLayout();
+ hlDepthPreview->setObjectName(QStringLiteral("hlDepthPreview"));
+
+ lbDepthPreview = new QLabel(widget);
+ lbDepthPreview->setObjectName(QStringLiteral("lbDepthPreview"));
+ lbDepthPreview->setText(QApplication::translate("AppMainToolbar", "Depth Preview", 0));
+ hlDepthPreview->addWidget(lbDepthPreview);
+
+ ssbiDepthPreview = new SlideSpinBoxInt(widget);
+ ssbiDepthPreview->setObjectName(QStringLiteral("ssbiDepthPreview"));
+ QSizePolicy sizePolicy2(QSizePolicy::Minimum, QSizePolicy::Fixed);
+ sizePolicy2.setHorizontalStretch(0);
+ sizePolicy2.setVerticalStretch(0);
+ sizePolicy2.setHeightForWidth(ssbiDepthPreview->sizePolicy().hasHeightForWidth());
+ ssbiDepthPreview->setSizePolicy(sizePolicy2);
+ ssbiDepthPreview->setMinimumSize(QSize(40, 20));
+ ssbiDepthPreview->setMaximumSize(QSize(100, 16777215));
+ hlDepthPreview->addWidget(ssbiDepthPreview);
+
+ vLayoutDepthCoverage->addLayout(hlDepthPreview);
+
+ hlExactCoverage = new QHBoxLayout();
+ hlExactCoverage->setObjectName(QStringLiteral("hlExactCoverage"));
+
+ lbDepthPreview = new QLabel(widget);
+ lbDepthPreview->setObjectName(QStringLiteral("hlExactCoverage"));
+ lbDepthPreview->setText(QApplication::translate("AppMainToolbar", "Exact Coverage", 0));
+ hlExactCoverage->addWidget(lbDepthPreview);
+
+ cbExactCoverage = new QCheckBox(widget);
+ cbExactCoverage->setObjectName(QStringLiteral("cbExactCoverage"));
+ sizePolicy1.setHeightForWidth(cbExactCoverage->sizePolicy().hasHeightForWidth());
+ cbExactCoverage->setSizePolicy(sizePolicy1);
+ cbExactCoverage->setLayoutDirection(Qt::RightToLeft);
+ hlExactCoverage->addWidget(cbExactCoverage);
+
+ vLayoutDepthCoverage->addLayout(hlExactCoverage);
+
+ hLayout->addLayout(vLayoutDepthCoverage);
+
+ fSeparate = new QFrame(widget);
+ fSeparate->setObjectName(QStringLiteral("fSeparate"));
+ fSeparate->setFrameShape(QFrame::VLine);
+ fSeparate->setFrameShadow(QFrame::Sunken);
+ hLayout->addWidget(fSeparate);
+
+ btnSelectTool = new QPushButton(widget);
+ setStyledToolTip(btnSelectTool, "Switch to Selection Mode");
+ btnSelectTool->setObjectName(QStringLiteral("btnSelectTool"));
+ sizePolicy1.setHeightForWidth(btnSelectTool->sizePolicy().hasHeightForWidth());
+ btnSelectTool->setSizePolicy(sizePolicy1);
+ btnSelectTool->setMinimumSize(QSize(40, 40));
+ btnSelectTool->setMaximumSize(QSize(40, 40));
+ btnSelectTool->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnSelectTool.png"));
+ btnSelectTool->setIconSize(QSize(40, 40));
+ QAction* pointselect_action = new QAction(tr("point select"), this);
+ QAction* rectselect_action = new QAction(tr("rect select"), this);
+ QAction* drawselect_action = new QAction(tr("draw select"), this);
+ connect(pointselect_action, SIGNAL(triggered()), this, SLOT(on_pointselect_action()));
+ connect(rectselect_action, SIGNAL(triggered()), this, SLOT(on_rectselect_action()));
+ connect(drawselect_action, SIGNAL(triggered()), this, SLOT(on_drawselect_action()));
+ QMenu* menu = new QMenu(btnSelectTool);
+ menu->addAction(pointselect_action);
+ menu->addAction(rectselect_action);
+ menu->addAction(drawselect_action);
+ btnSelectTool->setMenu(menu);
+ hLayout->addWidget(btnSelectTool);
+
+ btnPaintbrush = new QPushButton(widget);
+ setStyledToolTip(btnPaintbrush, "Not Implement");
+ btnPaintbrush->setObjectName(QStringLiteral("btnPaintbrush"));
+ sizePolicy1.setHeightForWidth(btnPaintbrush->sizePolicy().hasHeightForWidth());
+ btnPaintbrush->setSizePolicy(sizePolicy1);
+ btnPaintbrush->setMinimumSize(QSize(40, 40));
+ btnPaintbrush->setMaximumSize(QSize(40, 40));
+ btnPaintbrush->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnPaintbrush.png"));
+ btnPaintbrush->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnPaintbrush);
+
+ btnFractureTool = new QPushButton(widget);
+ setStyledToolTip(btnFractureTool, "Not Implement");
+ btnFractureTool->setObjectName(QStringLiteral("btnFractureTool"));
+ sizePolicy1.setHeightForWidth(btnFractureTool->sizePolicy().hasHeightForWidth());
+ btnFractureTool->setSizePolicy(sizePolicy1);
+ btnFractureTool->setMinimumSize(QSize(40, 40));
+ btnFractureTool->setMaximumSize(QSize(40, 40));
+ btnFractureTool->setText(QApplication::translate("AppMainToolbar", "Fracture", 0));
+ btnFractureTool->setFont(fontCopy);
+ hLayout->addWidget(btnFractureTool);
+
+ btnExplodedViewTool = new QPushButton(widget);
+ setStyledToolTip(btnExplodedViewTool, "Not Implement");
+ btnExplodedViewTool->setObjectName(QStringLiteral("btnExplodedViewTool"));
+ sizePolicy1.setHeightForWidth(btnExplodedViewTool->sizePolicy().hasHeightForWidth());
+ btnExplodedViewTool->setSizePolicy(sizePolicy1);
+ btnExplodedViewTool->setMinimumSize(QSize(40, 40));
+ btnExplodedViewTool->setMaximumSize(QSize(40, 40));
+ btnExplodedViewTool->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnExplodedViewTool.png"));
+ btnExplodedViewTool->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnExplodedViewTool);
+
+ btnJointsTool = new QPushButton(widget);
+ setStyledToolTip(btnJointsTool, "Not Implement");
+ btnJointsTool->setObjectName(QStringLiteral("btnJointsTool"));
+ sizePolicy1.setHeightForWidth(btnJointsTool->sizePolicy().hasHeightForWidth());
+ btnJointsTool->setSizePolicy(sizePolicy1);
+ btnJointsTool->setMinimumSize(QSize(40, 40));
+ btnJointsTool->setMaximumSize(QSize(40, 40));
+ btnJointsTool->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnJointsTool.png"));
+ btnJointsTool->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnJointsTool);
+
+ btnFuseSelectedChunks = new QPushButton(widget);
+ setStyledToolTip(btnFuseSelectedChunks, "Not Implement");
+ btnFuseSelectedChunks->setObjectName(QStringLiteral("btnFuseSelectedChunks"));
+ sizePolicy1.setHeightForWidth(btnFuseSelectedChunks->sizePolicy().hasHeightForWidth());
+ btnFuseSelectedChunks->setSizePolicy(sizePolicy1);
+ btnFuseSelectedChunks->setMinimumSize(QSize(40, 40));
+ btnFuseSelectedChunks->setMaximumSize(QSize(40, 40));
+ btnFuseSelectedChunks->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnFuseSelectedChunks.png"));
+ btnFuseSelectedChunks->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnFuseSelectedChunks);
+
+ fSeparate = new QFrame(widget);
+ fSeparate->setObjectName(QStringLiteral("fSeparate"));
+ fSeparate->setFrameShape(QFrame::VLine);
+ fSeparate->setFrameShadow(QFrame::Sunken);
+ hLayout->addWidget(fSeparate);
+
+ btnReset = new QPushButton(widget);
+ setStyledToolTip(btnReset, "Reset Chunks and Switch to Edition Mode");
+ btnReset->setObjectName(QStringLiteral("btnReset"));
+ sizePolicy1.setHeightForWidth(btnReset->sizePolicy().hasHeightForWidth());
+ btnReset->setSizePolicy(sizePolicy1);
+ btnReset->setMinimumSize(QSize(40, 40));
+ btnReset->setMaximumSize(QSize(40, 40));
+ btnReset->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnReset.png"));
+ btnReset->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnReset);
+
+ btnSimulatePlay = new QPushButton(widget);
+ setStyledToolTip(btnSimulatePlay, "Switch to Simulate Mode");
+ btnSimulatePlay->setObjectName(QStringLiteral("btnSimulatePlay"));
+ sizePolicy1.setHeightForWidth(btnSimulatePlay->sizePolicy().hasHeightForWidth());
+ btnSimulatePlay->setSizePolicy(sizePolicy1);
+ btnSimulatePlay->setMinimumSize(QSize(40, 40));
+ btnSimulatePlay->setMaximumSize(QSize(40, 40));
+ btnSimulatePlay->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnSimulatePlay.png"));
+ btnSimulatePlay->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnSimulatePlay);
+
+ btnFrameStepForward = new QPushButton(widget);
+ setStyledToolTip(btnFrameStepForward, "Switch to StepForward Mode");
+ btnFrameStepForward->setObjectName(QStringLiteral("btnFrameStepForward"));
+ sizePolicy1.setHeightForWidth(btnFrameStepForward->sizePolicy().hasHeightForWidth());
+ btnFrameStepForward->setSizePolicy(sizePolicy1);
+ btnFrameStepForward->setMinimumSize(QSize(40, 40));
+ btnFrameStepForward->setMaximumSize(QSize(40, 40));
+ btnFrameStepForward->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnFrameStepForward.png"));
+ btnFrameStepForward->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnFrameStepForward);
+
+ fSeparate = new QFrame(widget);
+ fSeparate->setObjectName(QStringLiteral("fSeparate"));
+ fSeparate->setFrameShape(QFrame::VLine);
+ fSeparate->setFrameShadow(QFrame::Sunken);
+ hLayout->addWidget(fSeparate);
+
+ btnBomb = new QPushButton(widget);
+ setStyledToolTip(btnBomb, "Not Implement");
+ btnBomb->setObjectName(QStringLiteral("btnBomb"));
+ sizePolicy1.setHeightForWidth(btnBomb->sizePolicy().hasHeightForWidth());
+ btnBomb->setSizePolicy(sizePolicy1);
+ btnBomb->setMinimumSize(QSize(40, 40));
+ btnBomb->setMaximumSize(QSize(40, 40));
+ btnBomb->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnBomb.png"));
+ btnBomb->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnBomb);
+
+ btnProjectile = new QPushButton(widget);
+ setStyledToolTip(btnProjectile, "Throw a Box to Chunks");
+ btnProjectile->setObjectName(QStringLiteral("btnProjectile"));
+ sizePolicy1.setHeightForWidth(btnProjectile->sizePolicy().hasHeightForWidth());
+ btnProjectile->setSizePolicy(sizePolicy1);
+ btnProjectile->setMinimumSize(QSize(40, 40));
+ btnProjectile->setMaximumSize(QSize(40, 40));
+ btnProjectile->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnProjectile.png"));
+ btnProjectile->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnProjectile);
+
+ btnDropObject = new QPushButton(widget);
+ setStyledToolTip(btnDropObject, "Not Implement");
+ btnDropObject->setObjectName(QStringLiteral("btnDropObject"));
+ sizePolicy1.setHeightForWidth(btnDropObject->sizePolicy().hasHeightForWidth());
+ btnDropObject->setSizePolicy(sizePolicy1);
+ btnDropObject->setMinimumSize(QSize(40, 40));
+ btnDropObject->setMaximumSize(QSize(40, 40));
+ btnDropObject->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnDropObject.png"));
+ btnDropObject->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnDropObject);
+
+ fSeparate = new QFrame(widget);
+ fSeparate->setObjectName(QStringLiteral("fSeparate"));
+ fSeparate->setFrameShape(QFrame::VLine);
+ fSeparate->setFrameShadow(QFrame::Sunken);
+ hLayout->addWidget(fSeparate);
+
+ btnPreferences = new QPushButton(widget);
+ setStyledToolTip(btnPreferences, "Save Blast Asset");
+ btnPreferences->setObjectName(QStringLiteral("btnPreferences"));
+ sizePolicy1.setHeightForWidth(btnPreferences->sizePolicy().hasHeightForWidth());
+ btnPreferences->setSizePolicy(sizePolicy1);
+ btnPreferences->setMinimumSize(QSize(40, 40));
+ btnPreferences->setMaximumSize(QSize(40, 40));
+ btnPreferences->setIcon(QIcon(":/AppMainWindow/images/Blast_ToolBar_btnPreferences.png"));
+ btnPreferences->setIconSize(QSize(40, 40));
+ hLayout->addWidget(btnPreferences);
+
+ QSpacerItem *horizontalSpacer;
+ horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ hLayout->addItem(horizontalSpacer);
+
+ this->setWidget(widget);
+
+ connect(btnOpenProject, SIGNAL(clicked()), this, SLOT(on_btnOpenProject_clicked()));
+ connect(btnSaveProject, SIGNAL(clicked()), this, SLOT(on_btnSaveProject_clicked()));
+ connect(btnExportAssets, SIGNAL(clicked()), this, SLOT(on_btnExportAssets_clicked()));
+ connect(btnExportFilepath, SIGNAL(clicked()), this, SLOT(on_btnExportFilepath_clicked()));
+ connect(ssbiDepthPreview, SIGNAL(valueChanged(int)), this, SLOT(on_ssbiDepthPreview_valueChanged(int)));
+ connect(cbExactCoverage, SIGNAL(stateChanged(int)), this, SLOT(on_cbExactCoverage_stateChanged(int)));
+ connect(btnSelectTool, SIGNAL(clicked()), this, SLOT(on_btnSelectTool_clicked()));
+ connect(btnPaintbrush, SIGNAL(clicked()), this, SLOT(on_btnPaintbrush_clicked()));
+ connect(btnFractureTool, SIGNAL(clicked()), this, SLOT(on_btnFractureTool_clicked()));
+ connect(btnExplodedViewTool, SIGNAL(clicked()), this, SLOT(on_btnExplodedViewTool_clicked()));
+ connect(btnJointsTool, SIGNAL(clicked()), this, SLOT(on_btnJointsTool_clicked()));
+ connect(btnFuseSelectedChunks, SIGNAL(clicked()), this, SLOT(on_btnFuseSelectedChunks_clicked()));
+ connect(btnReset, SIGNAL(clicked()), this, SLOT(on_btnReset_clicked()));
+ connect(btnSimulatePlay, SIGNAL(clicked()), this, SLOT(on_btnSimulatePlay_clicked()));
+ connect(btnFrameStepForward, SIGNAL(clicked()), this, SLOT(on_btnFrameStepForward_clicked()));
+ connect(btnBomb, SIGNAL(clicked()), this, SLOT(on_btnBomb_clicked()));
+ connect(btnProjectile, SIGNAL(clicked()), this, SLOT(on_btnProjectile_clicked()));
+ connect(btnDropObject, SIGNAL(clicked()), this, SLOT(on_btnDropObject_clicked()));
+ connect(btnPreferences, SIGNAL(clicked()), this, SLOT(on_btnPreferences_clicked()));
+}
+
+void BlastToolbar::updateValues()
+{
+}
+
+#include <Sample.h>
+#include <SimpleScene.h>
+#include <SampleManager.h>
+#include <SceneController.h>
+#include <SourceAssetOpenDlg.h>
+
+void BlastToolbar::on_btnOpenProject_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+
+ SourceAssetOpenDlg dlg(true, &AppMainWindow::Inst());
+ int res = dlg.exec();
+ if (res != QDialog::Accepted || dlg.getFile().isEmpty())
+ return;
+
+ QFileInfo fileInfo(dlg.getFile());
+ std::string dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ std::string file = fileInfo.baseName().toLocal8Bit();
+
+ physx::PxTransform t(physx::PxIdentity);
+ {
+ QVector3D Position = dlg.getPosition();
+ t.p = physx::PxVec3(Position.x(), Position.y(), Position.z());
+
+ QVector3D RotationAxis = dlg.getRotationAxis();
+ physx::PxVec3 Axis = physx::PxVec3(RotationAxis.x(), RotationAxis.y(), RotationAxis.z());
+ Axis = Axis.getNormalized();
+ float RotationDegree = dlg.getRotationDegree();
+ float DEGREE_TO_RAD = acos(-1.0) / 180.0;
+ RotationDegree = RotationDegree * DEGREE_TO_RAD;
+ t.q = physx::PxQuat(RotationDegree, Axis);
+ }
+
+ SimpleScene::Inst()->GetSampleManager().addModelAsset(file, dlg.getSkinned(), t, !dlg.isAppend());
+}
+
+void BlastToolbar::on_btnSaveProject_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnExportAssets_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnExportFilepath_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_ssbiDepthPreview_valueChanged(int v)
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_cbExactCoverage_stateChanged(int state)
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnSelectTool_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_pointselect_action()
+{
+ qDebug("%s", __FUNCTION__);
+
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ sampleManager.setBlastToolType(BTT_Select);
+}
+
+void BlastToolbar::on_rectselect_action()
+{
+ qDebug("%s", __FUNCTION__);
+
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ sampleManager.setBlastToolType(BTT_Select);
+}
+
+void BlastToolbar::on_drawselect_action()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnPaintbrush_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnFractureTool_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnExplodedViewTool_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnJointsTool_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnFuseSelectedChunks_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnReset_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+
+ SampleManager* pSampleManager = SampleManager::ins();
+ SceneController& sceneController = pSampleManager->getSceneController();
+ sceneController.ResetScene();
+ pSampleManager->setBlastToolType(BTT_Edit);
+}
+
+void BlastToolbar::on_btnSimulatePlay_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+
+ SampleManager* pSampleManager = SampleManager::ins();
+ pSampleManager->setBlastToolType(BTT_Damage);
+}
+
+void BlastToolbar::on_btnFrameStepForward_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+
+ SampleManager* pSampleManager = SampleManager::ins();
+ pSampleManager->setBlastToolType(BTT_Damage);
+ PhysXController& physXController = pSampleManager->getPhysXController();
+ physXController.m_bForce = true;
+}
+
+void BlastToolbar::on_btnBomb_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnProjectile_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+
+ SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager();
+ SceneController& sceneController = sampleManager.getSceneController();
+ sceneController.addProjectile();
+}
+
+void BlastToolbar::on_btnDropObject_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+}
+
+void BlastToolbar::on_btnPreferences_clicked()
+{
+ qDebug("%s", __FUNCTION__);
+
+ SampleManager* pSampleManager = SampleManager::ins();
+ pSampleManager->saveAsset();
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastToolBar.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastToolBar.h
new file mode 100644
index 0000000..f44dcfb
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastToolBar.h
@@ -0,0 +1,94 @@
+#ifndef BlastToolbar_h__
+#define BlastToolbar_h__
+
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QDockWidget>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QMenu>
+#include <QtWidgets/QVBoxLayout>
+#include <QtWidgets/QLineEdit>
+
+#include "SlideSpinBox.h"
+
+class BlastToolbar : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ BlastToolbar(QWidget* parent);
+
+ void updateValues();
+
+public slots:
+ void on_btnOpenProject_clicked();
+ void on_btnSaveProject_clicked();
+ void on_btnExportAssets_clicked();
+
+ void on_btnExportFilepath_clicked();
+ void on_ssbiDepthPreview_valueChanged(int v);
+ void on_cbExactCoverage_stateChanged(int state);
+
+ void on_btnSelectTool_clicked();
+ void on_pointselect_action();
+ void on_rectselect_action();
+ void on_drawselect_action();
+
+ void on_btnPaintbrush_clicked();
+ void on_btnFractureTool_clicked();
+ void on_btnExplodedViewTool_clicked();
+ void on_btnJointsTool_clicked();
+ void on_btnFuseSelectedChunks_clicked();
+
+ void on_btnReset_clicked();
+ void on_btnSimulatePlay_clicked();
+ void on_btnFrameStepForward_clicked();
+
+ void on_btnBomb_clicked();
+ void on_btnProjectile_clicked();
+ void on_btnDropObject_clicked();
+
+ void on_btnPreferences_clicked();
+
+private:
+ QHBoxLayout *hLayout;
+ QFrame *fSeparate;
+
+ QPushButton *btnOpenProject;
+ QPushButton *btnSaveProject;
+ QPushButton *btnExportAssets;
+
+ QVBoxLayout *vLayoutExport;
+ QHBoxLayout *hLayoutExport;
+ QLabel *lExportFilepath;
+ QPushButton *btnExportFilepath;
+ QLineEdit* leExportFilepath;
+
+ QVBoxLayout *vLayoutDepthCoverage;
+ QHBoxLayout *hlDepthPreview;
+ QLabel *lbDepthPreview;
+ SlideSpinBoxInt* ssbiDepthPreview;
+ QHBoxLayout *hlExactCoverage;
+ QLabel *lbExactCoverage;
+ QCheckBox* cbExactCoverage;
+
+ QPushButton *btnSelectTool;
+ QPushButton *btnPaintbrush;
+ QPushButton *btnFractureTool;
+ QPushButton *btnExplodedViewTool;
+ QPushButton *btnJointsTool;
+ QPushButton *btnFuseSelectedChunks;
+
+ QPushButton *btnReset;
+ QPushButton *btnSimulatePlay;
+ QPushButton *btnFrameStepForward;
+
+ QPushButton *btnBomb;
+ QPushButton *btnProjectile;
+ QPushButton *btnDropObject;
+
+ QPushButton *btnPreferences;
+};
+#endif // BlastToolbar_h__
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/CollisionToolsDlg.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/CollisionToolsDlg.cpp
new file mode 100644
index 0000000..4aa2b79
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/CollisionToolsDlg.cpp
@@ -0,0 +1,54 @@
+#include "CollisionToolsDlg.h"
+#include "ui_CollisionToolsDlg.h"
+
+CollisionToolsDlg::CollisionToolsDlg(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::CollisionToolsDlg)
+{
+ ui->setupUi(this);
+}
+
+CollisionToolsDlg::~CollisionToolsDlg()
+{
+ delete ui;
+}
+
+void CollisionToolsDlg::on_comboBoxApplyFilter_currentIndexChanged(int index)
+{
+
+}
+
+void CollisionToolsDlg::on_comboBoxCollisionShape_currentIndexChanged(int index)
+{
+
+}
+
+void CollisionToolsDlg::on_spinBoxQuality_valueChanged(int arg1)
+{
+
+}
+
+void CollisionToolsDlg::on_spinBoxMaxHulls_valueChanged(int arg1)
+{
+
+}
+
+void CollisionToolsDlg::on_spinBoxTrimHulls_valueChanged(int arg1)
+{
+
+}
+
+void CollisionToolsDlg::on_comboBoxTargetPlatform_currentIndexChanged(int index)
+{
+
+}
+
+void CollisionToolsDlg::on_btnReset_clicked()
+{
+
+}
+
+void CollisionToolsDlg::on_btnApply_clicked()
+{
+
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/CollisionToolsDlg.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/CollisionToolsDlg.h
new file mode 100644
index 0000000..d3c8c00
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/CollisionToolsDlg.h
@@ -0,0 +1,39 @@
+#ifndef COLLISIONTOOLSDLG_H
+#define COLLISIONTOOLSDLG_H
+
+#include <QtWidgets/QDialog>
+
+namespace Ui {
+class CollisionToolsDlg;
+}
+
+class CollisionToolsDlg : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit CollisionToolsDlg(QWidget *parent = 0);
+ ~CollisionToolsDlg();
+
+private slots:
+ void on_comboBoxApplyFilter_currentIndexChanged(int index);
+
+ void on_comboBoxCollisionShape_currentIndexChanged(int index);
+
+ void on_spinBoxQuality_valueChanged(int arg1);
+
+ void on_spinBoxMaxHulls_valueChanged(int arg1);
+
+ void on_spinBoxTrimHulls_valueChanged(int arg1);
+
+ void on_comboBoxTargetPlatform_currentIndexChanged(int index);
+
+ void on_btnReset_clicked();
+
+ void on_btnApply_clicked();
+
+private:
+ Ui::CollisionToolsDlg *ui;
+};
+
+#endif // COLLISIONTOOLSDLG_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/DefaultDamagePanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/DefaultDamagePanel.cpp
new file mode 100644
index 0000000..e52dfb2
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/DefaultDamagePanel.cpp
@@ -0,0 +1,104 @@
+#include "DefaultDamagePanel.h"
+#include "ui_DefaultDamagePanel.h"
+#include "ProjectParams.h"
+#include "BlastSceneTree.h"
+
+DefaultDamagePanel::DefaultDamagePanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::DefaultDamagePanel)
+{
+ ui->setupUi(this);
+}
+
+DefaultDamagePanel::~DefaultDamagePanel()
+{
+ delete ui;
+}
+
+void DefaultDamagePanel::updateValues()
+{
+ if (_selectedAssets.size() > 0)
+ {
+ BPPDefaultDamage& damage = _selectedAssets[0]->defaultDamage;
+
+ ui->spinBoxMinRadius->setValue(damage.minRadius);
+ ui->spinBoxMaxRadius->setValue(damage.maxRadius);
+ ui->comboBoxFallOff->setCurrentIndex(damage.FallOff);
+ ui->spinBoxMaxChunkSpeed->setValue(damage.maxChunkSpeed);
+ }
+ else
+ {
+ ui->spinBoxMinRadius->setValue(0.0f);
+ ui->spinBoxMaxRadius->setValue(0.0f);
+ ui->checkBoxMaxRadius->setChecked(false);
+ ui->comboBoxFallOff->setCurrentIndex(-1);
+ ui->spinBoxMaxChunkSpeed->setValue(0.0f);
+ }
+}
+
+void DefaultDamagePanel::dataSelected(std::vector<BlastNode*> selections)
+{
+ _selectedAssets.clear();
+
+ for (BlastNode* node: selections)
+ {
+ if (eAsset == node->getType())
+ {
+ BPPAsset* asset = static_cast<BPPAsset*>(node->getData());
+ _selectedAssets.push_back(asset);
+ }
+ }
+
+ updateValues();
+}
+
+void DefaultDamagePanel::on_spinBoxMinRadius_valueChanged(double arg1)
+{
+ for (size_t i = 0; i < _selectedAssets.size(); ++i)
+ {
+ BPPDefaultDamage& damage = _selectedAssets[i]->defaultDamage;
+ damage.minRadius = arg1;
+ }
+}
+
+void DefaultDamagePanel::on_spinBoxMaxRadius_valueChanged(double arg1)
+{
+ for (size_t i = 0; i < _selectedAssets.size(); ++i)
+ {
+ BPPDefaultDamage& damage = _selectedAssets[i]->defaultDamage;
+
+ damage.maxRadius = arg1;
+
+ if (arg1 < damage.minRadius)
+ {
+ damage.maxRadius = damage.minRadius;
+ }
+ }
+}
+
+void DefaultDamagePanel::on_checkBoxMaxRadius_stateChanged(int arg1)
+{
+ for (size_t i = 0; i < _selectedAssets.size(); ++i)
+ {
+ BPPDefaultDamage& damage = _selectedAssets[i]->defaultDamage;
+ damage.maxRadiusEnable = (arg1 != 0 ? true: false);
+ }
+}
+
+void DefaultDamagePanel::on_comboBoxFallOff_currentIndexChanged(int index)
+{
+ for (size_t i = 0; i < _selectedAssets.size(); ++i)
+ {
+ BPPDefaultDamage& damage = _selectedAssets[i]->defaultDamage;
+ damage.FallOff = index;
+ }
+}
+
+void DefaultDamagePanel::on_spinBoxMaxChunkSpeed_valueChanged(double arg1)
+{
+ for (size_t i = 0; i < _selectedAssets.size(); ++i)
+ {
+ BPPDefaultDamage& damage = _selectedAssets[i]->defaultDamage;
+ damage.maxChunkSpeed = arg1;
+ }
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/DefaultDamagePanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/DefaultDamagePanel.h
new file mode 100644
index 0000000..bbd4d3e
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/DefaultDamagePanel.h
@@ -0,0 +1,38 @@
+#ifndef DEFAULTDAMAGEPANEL_H
+#define DEFAULTDAMAGEPANEL_H
+
+#include <QtWidgets/QWidget>
+#include "BlastSceneTree.h"
+
+namespace Ui {
+class DefaultDamagePanel;
+}
+
+class DefaultDamagePanel : public QWidget, public ISceneObserver
+{
+ Q_OBJECT
+
+public:
+ explicit DefaultDamagePanel(QWidget *parent = 0);
+ ~DefaultDamagePanel();
+ void updateValues();
+
+ virtual void dataSelected(std::vector<BlastNode*> selections);
+
+private slots:
+ void on_spinBoxMinRadius_valueChanged(double arg1);
+
+ void on_spinBoxMaxRadius_valueChanged(double arg1);
+
+ void on_checkBoxMaxRadius_stateChanged(int arg1);
+
+ void on_comboBoxFallOff_currentIndexChanged(int index);
+
+ void on_spinBoxMaxChunkSpeed_valueChanged(double arg1);
+
+private:
+ Ui::DefaultDamagePanel *ui;
+ std::vector<BPPAsset*> _selectedAssets;
+};
+
+#endif // DEFAULTDAMAGEPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FileReferencesPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FileReferencesPanel.cpp
new file mode 100644
index 0000000..62b294c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FileReferencesPanel.cpp
@@ -0,0 +1,148 @@
+#include "FileReferencesPanel.h"
+#include "ui_FileReferencesPanel.h"
+#include "AppMainWindow.h"
+#include <QtWidgets/QFileDialog>
+#include "ProjectParams.h"
+#include <QtCore/QFile>
+#include <QtCore/QDebug>
+#include "GlobalSettings.h"
+
+FileReferencesPanel::FileReferencesPanel(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::FileReferencesPanel)
+ , _saveFBX(true)
+ , _saveBlast(true)
+ , _saveCollision(true)
+{
+ ui->setupUi(this);
+ ui->lineEditFBXSourceAsset->setReadOnly(true);
+
+ ui->checkBoxFBX->setChecked(_saveFBX);
+ ui->checkBoxBlast->setChecked(_saveBlast);
+ ui->checkBoxCollision->setChecked(_saveCollision);
+
+ updateValues();
+}
+
+FileReferencesPanel::~FileReferencesPanel()
+{
+ delete ui;
+}
+
+void FileReferencesPanel::updateValues()
+{
+ AppMainWindow& window = AppMainWindow::Inst();
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPFileReferences& fileReferences = projectParams.blast.fileReferences;
+ if (fileReferences.fbxSourceAsset.buf != nullptr)
+ ui->lineEditFBXSourceAsset->setText(fileReferences.fbxSourceAsset.buf);
+ else
+ ui->lineEditFBXSourceAsset->setText("");
+
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+ QString projectFileName = globalSettings.m_projectFileName.c_str();
+
+ if (projectFileName.isEmpty())
+ {
+ ui->lineEditFBX->setText("New.fbx");
+ ui->lineEditBlast->setText("New.Blast");
+ ui->lineEditCollision->setText("New.repx");
+ }
+ else
+ {
+ QFileInfo fileInfo(projectFileName);
+
+ if (fileReferences.fbx.buf != nullptr)
+ ui->lineEditFBX->setText(fileReferences.fbx.buf);
+ else
+ {
+ ui->lineEditFBX->setText(fileInfo.baseName() + " New.fbx");
+ }
+
+ if (fileReferences.blast.buf != nullptr)
+ ui->lineEditBlast->setText(fileReferences.blast.buf);
+ else
+ {
+ ui->lineEditBlast->setText(fileInfo.baseName() + " New.Blast");
+ }
+
+ if (fileReferences.collision.buf != nullptr)
+ ui->lineEditCollision->setText(fileReferences.collision.buf);
+ else
+ {
+ ui->lineEditCollision->setText(fileInfo.baseName() + " New.repX");
+ }
+ }
+}
+
+void FileReferencesPanel::on_btnOpenFile_clicked()
+{
+ AppMainWindow& window = AppMainWindow::Inst();
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPFileReferences& fileReferences = projectParams.blast.fileReferences;
+ const char* fbxSourceAsset = fileReferences.fbxSourceAsset.buf;
+ QString lastDir = (fbxSourceAsset != nullptr ? fbxSourceAsset : window._lastFilePath);
+ QString fileName = QFileDialog::getOpenFileName(&window, "Open FBX File", lastDir, "FBX File (*.FBX)");
+
+ ui->lineEditFBXSourceAsset->setText(fileName);
+}
+
+void FileReferencesPanel::on_btnReload_clicked()
+{
+
+}
+
+void FileReferencesPanel::on_btnRemove_clicked()
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPFileReferences& fileReferences = projectParams.blast.fileReferences;
+ if (fileReferences.fbxSourceAsset.buf != nullptr)
+ {
+ ui->lineEditFBXSourceAsset->setText("");
+ freeString(fileReferences.fbxSourceAsset);
+ // to do: remove source fbx file
+ }
+}
+
+void FileReferencesPanel::on_checkBoxFBX_stateChanged(int arg1)
+{
+ _saveFBX = (arg1 == 0 ? false : true);
+}
+
+void FileReferencesPanel::on_checkBoxBlast_stateChanged(int arg1)
+{
+ _saveBlast = (arg1 == 0 ? false : true);
+}
+
+void FileReferencesPanel::on_checkBoxCollision_stateChanged(int arg1)
+{
+ _saveCollision = (arg1 == 0 ? false : true);
+}
+
+void FileReferencesPanel::on_btnSave_clicked()
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPFileReferences& fileReferences = projectParams.blast.fileReferences;
+
+ copy(fileReferences.fbxSourceAsset, ui->lineEditFBXSourceAsset->text().toUtf8().data());
+
+ if (_saveFBX)
+ {
+ copy(fileReferences.fbx, ui->lineEditFBX->text().toUtf8().data());
+ // to do: save fbx file
+ }
+
+ if (_saveBlast)
+ {
+ copy(fileReferences.blast, ui->lineEditBlast->text().toUtf8().data());
+ // to do: save blast file
+ }
+
+ if (_saveCollision)
+ {
+ copy(fileReferences.collision, ui->lineEditCollision->text().toUtf8().data());
+ // to do: save collision file
+ }
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FileReferencesPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FileReferencesPanel.h
new file mode 100644
index 0000000..e393f33
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FileReferencesPanel.h
@@ -0,0 +1,41 @@
+#ifndef FILEREFERENCESPANEL_H
+#define FILEREFERENCESPANEL_H
+
+#include <QtWidgets/QWidget>
+
+namespace Ui {
+class FileReferencesPanel;
+}
+
+class FileReferencesPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit FileReferencesPanel(QWidget *parent = 0);
+ ~FileReferencesPanel();
+ void updateValues();
+
+private slots:
+ void on_btnOpenFile_clicked();
+
+ void on_btnReload_clicked();
+
+ void on_btnRemove_clicked();
+
+ void on_checkBoxFBX_stateChanged(int arg1);
+
+ void on_checkBoxBlast_stateChanged(int arg1);
+
+ void on_checkBoxCollision_stateChanged(int arg1);
+
+ void on_btnSave_clicked();
+
+private:
+ Ui::FileReferencesPanel *ui;
+ bool _saveFBX;
+ bool _saveBlast;
+ bool _saveCollision;
+};
+
+#endif // FILEREFERENCESPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FiltersDockWidget.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FiltersDockWidget.cpp
new file mode 100644
index 0000000..a537140
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FiltersDockWidget.cpp
@@ -0,0 +1,389 @@
+#include "FiltersDockWidget.h"
+#include "ui_FiltersDockWidget.h"
+#include "ProjectParams.h"
+#include <QtWidgets/QInputDialog>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QMessageBox>
+#include "SampleManager.h"
+
+const QString LISTITEM_NORMAL_STYLESHEET = ":enabled { background: rgb(68,68,68); }";
+
+const QString LISTITEM_SELECTED_STYLESHEET = ":enabled { background: rgba(118,185,0, 250); }";
+
+const QString LISTITEM_BUTTON_STYLESHEET = ":enabled { border: 0px; }";
+
+class FilterItemWidget;
+
+struct FilterItemInfo
+{
+public:
+ FilterItemInfo(FilterItemWidget* inWidget, const QString& inText)
+ : itemWidget(inWidget)
+ , text(inText)
+ {
+ }
+
+ FilterItemWidget* itemWidget;
+ QString text;
+};
+
+FilterItemWidget::FilterItemWidget(FiltersDockWidget* parent, QListWidgetItem* item, const QString& filterPreset, int depth)
+ : QWidget(parent)
+ , _relatedListWidgetItem(item)
+ , _filterPreset(filterPreset)
+ , _depth(depth)
+{
+ QHBoxLayout* layout = new QHBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ _label = new QLabel(this);
+
+ _removeBtn = new QPushButton(this);
+ _removeBtn->setMaximumSize(20, 20);
+ _removeBtn->setText("X");
+ _removeBtn->setStyleSheet(LISTITEM_BUTTON_STYLESHEET);
+
+ layout->addWidget(_label);
+ layout->addWidget(_removeBtn);
+
+ this->setLayout(layout);
+
+ QObject::connect(_removeBtn, SIGNAL(clicked()), this, SLOT(onRemoveButtonClicked()));
+ QObject::connect(this, SIGNAL(RemoveItem(QListWidgetItem*)), parent, SLOT(onListWidgetRemoveBtnClicked(QListWidgetItem*)));
+
+ deSelect();
+}
+
+void FilterItemWidget::setText(const QString& title)
+{
+ _label->setText(title);
+}
+
+void FilterItemWidget::select()
+{
+ _label->setStyleSheet(LISTITEM_SELECTED_STYLESHEET);
+}
+
+void FilterItemWidget::deSelect()
+{
+ _label->setStyleSheet(LISTITEM_NORMAL_STYLESHEET);
+}
+
+void FilterItemWidget::onRemoveButtonClicked()
+{
+ emit RemoveItem(_relatedListWidgetItem);
+}
+
+FiltersDockWidget::FiltersDockWidget(QWidget *parent) :
+ QDockWidget(parent),
+ ui(new Ui::FiltersDockWidget),
+ _filterUIItems(),
+ _filterItemWidgets(),
+ _lastSelectRow(-1)
+{
+ ui->setupUi(this);
+
+ _depthButtons.push_back(ui->btnDepth0);
+ _depthButtons.push_back(ui->btnDepth1);
+ _depthButtons.push_back(ui->btnDepth2);
+ _depthButtons.push_back(ui->btnDepth3);
+ _depthButtons.push_back(ui->btnDepth4);
+ _depthButtons.push_back(ui->btnDepth5);
+
+ _updateFilterItemList();
+ _updateFilterDepthBtns();
+}
+
+FiltersDockWidget::~FiltersDockWidget()
+{
+ delete ui;
+}
+
+void FiltersDockWidget::updateValues()
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPFilterPresetArray& filterPresetArray = projectParams.filter.filters;
+
+ ui->comboBoxFilterPreset->clear();
+ QStringList filterNames;
+ int count = filterPresetArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ filterNames.append(filterPresetArray.buf[i].name.buf);
+ }
+ ui->comboBoxFilterPreset->addItems(filterNames);
+
+ if (count > 0)
+ {
+ ui->btnModifyFilterPreset->setEnabled(true);
+ ui->btnRemoveFilterPreset->setEnabled(true);
+ }
+ else
+ {
+ ui->btnModifyFilterPreset->setEnabled(false);
+ ui->btnRemoveFilterPreset->setEnabled(false);
+ }
+}
+
+void FiltersDockWidget::on_comboBoxFilterPreset_currentIndexChanged(int index)
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ projectParams.filter.activeFilter = index;
+
+ _updateFilterItemList();
+ _updateFilterDepthBtns();
+}
+
+void FiltersDockWidget::on_btnAddFilterPrest_clicked()
+{
+ bool ok = false;
+ QString name = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input name for new filter preset:"),
+ QLineEdit::Normal,
+ "",
+ &ok);
+ bool nameExist = BlastProject::ins().isFilterPresetNameExist(name.toUtf8().data());
+ if (ok && !name.isEmpty() && !nameExist)
+ {
+ BlastProject::ins().addFilterPreset(name.toUtf8().data());
+ updateValues();
+ ui->comboBoxFilterPreset->setCurrentIndex(ui->comboBoxFilterPreset->count() - 1);
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && name.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the new filter preset!");
+ }
+}
+
+void FiltersDockWidget::on_btnModifyFilterPreset_clicked()
+{
+ QByteArray tmp = ui->comboBoxFilterPreset->currentText().toUtf8();
+ const char* oldName = tmp.data();
+
+ bool ok = false;
+ QString newName = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input new name for the selected filter preset:"),
+ QLineEdit::Normal,
+ oldName,
+ &ok);
+ bool nameExist = BlastProject::ins().isFilterPresetNameExist(newName.toUtf8().data());
+ if (ok && !newName.isEmpty() && !nameExist)
+ {
+ int index = ui->comboBoxFilterPreset->currentIndex();
+ BlastProject::ins().renameFilterPreset(oldName, newName.toUtf8().data());
+ updateValues();
+ ui->comboBoxFilterPreset->setCurrentIndex(index);
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && newName.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the selected filter preset!");
+ }
+}
+
+void FiltersDockWidget::on_btnRemoveFilterPreset_clicked()
+{
+ QByteArray tmp = ui->comboBoxFilterPreset->currentText().toUtf8();
+ const char* name = tmp.data();
+ BlastProject::ins().removeFilterPreset(name);
+ updateValues();
+}
+
+void FiltersDockWidget::on_btnDepth0_clicked(bool val)
+{
+ _addRemoveDepthFilter(0, val);
+}
+
+void FiltersDockWidget::on_btnDepth1_clicked(bool val)
+{
+ _addRemoveDepthFilter(1, val);
+}
+
+void FiltersDockWidget::on_btnDepth2_clicked(bool val)
+{
+ _addRemoveDepthFilter(2, val);
+}
+
+void FiltersDockWidget::on_btnDepth3_clicked(bool val)
+{
+ _addRemoveDepthFilter(3, val);
+}
+
+void FiltersDockWidget::on_btnDepth4_clicked(bool val)
+{
+ _addRemoveDepthFilter(4, val);
+}
+
+void FiltersDockWidget::on_btnDepth5_clicked(bool val)
+{
+ _addRemoveDepthFilter(5, val);
+}
+
+void FiltersDockWidget::on_btnAddDepthFilter_clicked()
+{
+
+}
+
+void FiltersDockWidget::on_btnAddFilter_clicked()
+{
+
+}
+
+void FiltersDockWidget::on_btnSelect_clicked()
+{
+ std::vector<uint32_t> depths;
+ int row = ui->listWidget->currentRow();
+ if (-1 != row)
+ {
+ depths.push_back(_filterItemWidgets[row]->_depth);
+ }
+ SampleManager::ins()->setChunkSelected(depths, true);
+}
+
+void FiltersDockWidget::on_btnVisible_clicked()
+{
+ std::vector<uint32_t> depths;
+ int row = ui->listWidget->currentRow();
+ if (-1 != row)
+ {
+ depths.push_back(_filterItemWidgets[row]->_depth);
+ }
+ SampleManager::ins()->setChunkVisible(depths, true);
+}
+
+void FiltersDockWidget::on_btnInVisible_clicked()
+{
+ std::vector<uint32_t> depths;
+ int row = ui->listWidget->currentRow();
+ if (-1 != row)
+ {
+ depths.push_back(_filterItemWidgets[row]->_depth);
+ }
+ SampleManager::ins()->setChunkVisible(depths, false);
+}
+
+void FiltersDockWidget::on_listWidget_currentRowChanged(int index)
+{
+ if (-1 != _lastSelectRow && _lastSelectRow < _filterItemWidgets.size())
+ static_cast<FilterItemWidget*>(_filterItemWidgets[_lastSelectRow])->deSelect();
+
+ if (-1 != index && index < _filterItemWidgets.size())
+ static_cast<FilterItemWidget*>(_filterItemWidgets[index])->select();
+
+ _lastSelectRow = index;
+}
+
+void FiltersDockWidget::onListWidgetRemoveBtnClicked(QListWidgetItem* item)
+{
+ /// remove former ui info
+ map<QListWidgetItem*, FilterItemInfo*>::iterator toRemoveItem = _filterUIItems.find(item);
+ if (toRemoveItem != _filterUIItems.end())
+ {
+ FilterItemWidget* itemWidget = toRemoveItem->second->itemWidget;
+ itemWidget->setParent(nullptr);
+
+ _filterItemWidgets.erase(std::find(_filterItemWidgets.begin(), _filterItemWidgets.end(), toRemoveItem->second->itemWidget));
+
+ if (ui->comboBoxFilterPreset->currentIndex() != -1)
+ {
+ QByteArray filterPreset = itemWidget->_filterPreset.toUtf8();
+ BlastProject::ins().removeFilterDepth(filterPreset.data(), itemWidget->_depth);
+ }
+
+ ui->listWidget->takeItem(ui->listWidget->row(item));
+ ui->listWidget->removeItemWidget(item);
+ delete item;
+ delete itemWidget;
+ _filterUIItems.erase(toRemoveItem);
+
+ //_updateFilterItemList();
+ _updateFilterDepthBtns();
+ }
+}
+
+void FiltersDockWidget::_updateFilterItemList()
+{
+ /// remove former ui info
+ map<QListWidgetItem*, FilterItemInfo*>::iterator theEnd = _filterUIItems.end();
+ for (map<QListWidgetItem*, FilterItemInfo*>::iterator itr = _filterUIItems.begin(); itr != theEnd; ++itr)
+ {
+ itr->second->itemWidget->setParent(nullptr);
+ delete itr->first;
+ delete itr->second->itemWidget;
+ delete itr->second;
+ }
+ _filterUIItems.clear();
+ ui->listWidget->clear();
+ _filterItemWidgets.clear();
+
+ int filterPresetIndex = ui->comboBoxFilterPreset->currentIndex();
+ if (filterPresetIndex < 0)
+ return;
+
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPFilterPresetArray& filterPresetArray = projectParams.filter.filters;
+ BPPFilterPreset& filterPresset = filterPresetArray.buf[filterPresetIndex];
+
+ int filterCount = filterPresset.depthFilters.arraySizes[0];
+
+ for (int i = 0; i < filterCount; ++i)
+ {
+ QListWidgetItem* item = new QListWidgetItem(NULL);
+ int depth = filterPresset.depthFilters.buf[i];
+ FilterItemWidget* itemWidget = new FilterItemWidget(this, item, filterPresset.name.buf, depth);
+
+ QString depthFilterLabel = QString(QObject::tr("Depth-%1")).arg(depth);
+ _filterUIItems.insert(std::make_pair(item, new FilterItemInfo(itemWidget, depthFilterLabel)));
+ itemWidget->setText(depthFilterLabel);
+ _filterItemWidgets.push_back(itemWidget);
+
+ ui->listWidget->addItem(item);
+ ui->listWidget->setItemWidget(item, itemWidget);
+ }
+}
+
+void FiltersDockWidget::_updateFilterDepthBtns()
+{
+ for (int i = 0; i <= 5; ++i)
+ _depthButtons[i]->setChecked(false);
+
+ int filterPresetIndex = ui->comboBoxFilterPreset->currentIndex();
+ if (filterPresetIndex < 0)
+ return;
+
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPFilterPresetArray& filterPresetArray = projectParams.filter.filters;
+ BPPFilterPreset& filterPresset = filterPresetArray.buf[filterPresetIndex];
+
+ int filterCount = filterPresset.depthFilters.arraySizes[0];
+
+ for (int i = 0; i < filterCount; ++i)
+ {
+ int depth = filterPresset.depthFilters.buf[i];
+
+ _depthButtons[depth]->setChecked(true);
+ }
+}
+
+void FiltersDockWidget::_addRemoveDepthFilter(int depth, bool add)
+{
+ if (ui->comboBoxFilterPreset->currentIndex() != -1)
+ {
+ QByteArray filterPreset = ui->comboBoxFilterPreset->currentText().toUtf8();
+
+ if (add)
+ BlastProject::ins().addFilterDepth(filterPreset.data(), depth);
+ else
+ BlastProject::ins().removeFilterDepth(filterPreset.data(), depth);
+
+ _updateFilterItemList();
+ }
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FiltersDockWidget.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FiltersDockWidget.h
new file mode 100644
index 0000000..cf25073
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FiltersDockWidget.h
@@ -0,0 +1,104 @@
+#ifndef FILTERSDOCKWIDGET_H
+#define FILTERSDOCKWIDGET_H
+
+#include <QtWidgets/QDockWidget>
+#include <vector>
+#include <map>
+using namespace std;
+
+namespace Ui {
+class FiltersDockWidget;
+}
+
+class QLabel;
+class QPushButton;
+class QListWidgetItem;
+struct FilterItemInfo;
+class FilterItemWidget;
+class FiltersDockWidget;
+
+class FilterItemWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ FilterItemWidget(FiltersDockWidget* parent, QListWidgetItem* item, const QString& filterPreset, int depth);
+ ~FilterItemWidget()
+ {
+ }
+
+ void setText(const QString& title);
+ void select();
+ void deSelect();
+
+signals:
+ void RemoveItem(QListWidgetItem* item);
+
+private slots:
+ void onRemoveButtonClicked();
+
+public:
+ QLabel* _label;
+ QPushButton* _removeBtn;
+ QListWidgetItem* _relatedListWidgetItem;
+ QString _filterPreset;
+ int _depth;
+};
+
+class FiltersDockWidget : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ explicit FiltersDockWidget(QWidget *parent = 0);
+ ~FiltersDockWidget();
+ void updateValues();
+
+private slots:
+ void on_comboBoxFilterPreset_currentIndexChanged(int index);
+
+ void on_btnAddFilterPrest_clicked();
+
+ void on_btnModifyFilterPreset_clicked();
+
+ void on_btnRemoveFilterPreset_clicked();
+
+ void on_btnDepth0_clicked(bool val);
+
+ void on_btnDepth1_clicked(bool val);
+
+ void on_btnDepth2_clicked(bool val);
+
+ void on_btnDepth3_clicked(bool val);
+
+ void on_btnDepth4_clicked(bool val);
+
+ void on_btnDepth5_clicked(bool val);
+
+ void on_btnAddDepthFilter_clicked();
+
+ void on_btnAddFilter_clicked();
+
+ void on_btnSelect_clicked();
+
+ void on_btnVisible_clicked();
+
+ void on_btnInVisible_clicked();
+
+ void on_listWidget_currentRowChanged(int index);
+
+ void onListWidgetRemoveBtnClicked(QListWidgetItem* item);
+
+private:
+ void _updateFilterItemList();
+ void _updateFilterDepthBtns();
+ void _addRemoveDepthFilter(int depth, bool add);
+
+private:
+ Ui::FiltersDockWidget *ui;
+ map<QListWidgetItem*, FilterItemInfo*> _filterUIItems;
+ vector<FilterItemWidget*> _filterItemWidgets;
+ int _lastSelectRow;
+ vector<QPushButton*> _depthButtons;
+};
+
+#endif // FILTERSDOCKWIDGET_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureCutoutSettingsPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureCutoutSettingsPanel.cpp
new file mode 100644
index 0000000..ea24278
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureCutoutSettingsPanel.cpp
@@ -0,0 +1,155 @@
+#include "FractureCutoutSettingsPanel.h"
+#include "ui_FractureCutoutSettingsPanel.h"
+#include "ProjectParams.h"
+#include <QtWidgets/QInputDialog>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QMessageBox>
+#include <QtCore/QFileInfo>
+#include "AppMainWindow.h"
+
+FractureCutoutSettingsPanel::FractureCutoutSettingsPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::FractureCutoutSettingsPanel)
+{
+ ui->setupUi(this);
+}
+
+FractureCutoutSettingsPanel::~FractureCutoutSettingsPanel()
+{
+ delete ui;
+}
+
+void FractureCutoutSettingsPanel::updateValues()
+{
+ BPPCutoutProjection& cutoutProjection = BlastProject::ins().getParams().fracture.cutoutProjection;
+
+ _updateTextureListWidget();
+
+ ui->comboBoxCutoutType->setCurrentIndex(cutoutProjection.cutoutType);
+ ui->spinBoxPixelThreshold->setValue(cutoutProjection.pixelThreshold);
+ ui->checkBoxTiled->setChecked(cutoutProjection.tiled);
+ ui->checkBoxInvertU->setChecked(cutoutProjection.invertU);
+ ui->checkBoxInvertV->setChecked(cutoutProjection.invertV);
+}
+
+void FractureCutoutSettingsPanel::on_btnAddTexture_clicked()
+{
+ QString texName = AppMainWindow::Inst().OpenTextureFile();
+
+ if (texName.isEmpty())
+ return;
+
+ QFileInfo fileInfo(texName);
+ QByteArray ba = fileInfo.absoluteFilePath().toLocal8Bit();
+ const char* filePath = (const char*)(ba);
+
+ if (!BlastProject::ins().isCutoutTextureNameExist(texName.toUtf8().data()))
+ {
+ BlastProject::ins().addCutoutTexture(filePath);
+ _updateTextureListWidget();
+ ui->listWidget->setCurrentRow(ui->listWidget->count() - 1);
+ }
+ else
+ {
+ QMessageBox::warning(this, "Blast Tool", "The texture you selected is already exist!");
+ }
+}
+
+void FractureCutoutSettingsPanel::on_btnReloadTexture_clicked()
+{
+
+}
+
+void FractureCutoutSettingsPanel::on_btnRemoveTexture_clicked()
+{
+ if (ui->listWidget->currentRow() != -1)
+ {
+ QListWidgetItem *item = ui->listWidget->currentItem();
+ QString texture = _getTexturePathByName(item->text());
+ QByteArray ba = texture.toLocal8Bit();
+ BlastProject::ins().removeCutoutTexture(ba.data());
+ _updateTextureListWidget();
+ }
+}
+
+void FractureCutoutSettingsPanel::on_listWidget_currentRowChanged(int currentRow)
+{
+
+}
+
+void FractureCutoutSettingsPanel::on_btnTextureMap_clicked()
+{
+
+}
+
+void FractureCutoutSettingsPanel::on_comboBoxCutoutType_currentIndexChanged(int index)
+{
+ BPPCutoutProjection& cutoutProjection = BlastProject::ins().getParams().fracture.cutoutProjection;
+ cutoutProjection.cutoutType = index;
+}
+
+void FractureCutoutSettingsPanel::on_spinBoxPixelThreshold_valueChanged(int arg1)
+{
+ BPPCutoutProjection& cutoutProjection = BlastProject::ins().getParams().fracture.cutoutProjection;
+ cutoutProjection.pixelThreshold = arg1;
+}
+
+void FractureCutoutSettingsPanel::on_checkBoxTiled_stateChanged(int arg1)
+{
+ BPPCutoutProjection& cutoutProjection = BlastProject::ins().getParams().fracture.cutoutProjection;
+ cutoutProjection.tiled = (arg1 != 0 ? true : false);
+}
+
+void FractureCutoutSettingsPanel::on_checkBoxInvertU_stateChanged(int arg1)
+{
+ BPPCutoutProjection& cutoutProjection = BlastProject::ins().getParams().fracture.cutoutProjection;
+ cutoutProjection.invertU = (arg1 != 0 ? true : false);
+}
+
+void FractureCutoutSettingsPanel::on_checkBoxInvertV_stateChanged(int arg1)
+{
+ BPPCutoutProjection& cutoutProjection = BlastProject::ins().getParams().fracture.cutoutProjection;
+ cutoutProjection.invertV = (arg1 != 0 ? true : false);
+}
+
+void FractureCutoutSettingsPanel::on_btnFitToObject_clicked()
+{
+
+}
+
+void FractureCutoutSettingsPanel::on_btnApplyFracture_clicked()
+{
+
+}
+
+QString FractureCutoutSettingsPanel::_getTexturePathByName(const QString& name)
+{
+ BPPCutoutProjection& cutoutProjection = BlastProject::ins().getParams().fracture.cutoutProjection;
+ BPPStringArray& textureArray = cutoutProjection.textures;
+
+ int count = textureArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ QFileInfo fileInfo(textureArray.buf[i].buf);
+ if (fileInfo.baseName() == name)
+ return textureArray.buf[i].buf;
+ }
+
+ return "";
+}
+
+void FractureCutoutSettingsPanel::_updateTextureListWidget()
+{
+ BPPCutoutProjection& cutoutProjection = BlastProject::ins().getParams().fracture.cutoutProjection;
+
+ ui->listWidget->clear();
+ QStringList items;
+ for (int i = 0; i < cutoutProjection.textures.arraySizes[0]; ++i)
+ {
+ QFileInfo fileInfo(cutoutProjection.textures.buf[i].buf);
+ QByteArray ba = fileInfo.baseName().toLocal8Bit();
+ const char* texture = (const char*)(ba);
+ items.append(texture);
+ }
+ ui->listWidget->addItems(items);
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureCutoutSettingsPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureCutoutSettingsPanel.h
new file mode 100644
index 0000000..7faf2ae
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureCutoutSettingsPanel.h
@@ -0,0 +1,52 @@
+#ifndef FRACTURECUTOUTSETTINGSPANEL_H
+#define FRACTURECUTOUTSETTINGSPANEL_H
+
+#include <QtWidgets/QWidget>
+
+namespace Ui {
+class FractureCutoutSettingsPanel;
+}
+
+class FractureCutoutSettingsPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit FractureCutoutSettingsPanel(QWidget *parent = 0);
+ ~FractureCutoutSettingsPanel();
+ void updateValues();
+
+private slots:
+ void on_btnAddTexture_clicked();
+
+ void on_btnReloadTexture_clicked();
+
+ void on_btnRemoveTexture_clicked();
+
+ void on_listWidget_currentRowChanged(int currentRow);
+
+ void on_btnTextureMap_clicked();
+
+ void on_comboBoxCutoutType_currentIndexChanged(int index);
+
+ void on_spinBoxPixelThreshold_valueChanged(int arg1);
+
+ void on_checkBoxTiled_stateChanged(int arg1);
+
+ void on_checkBoxInvertU_stateChanged(int arg1);
+
+ void on_checkBoxInvertV_stateChanged(int arg1);
+
+ void on_btnFitToObject_clicked();
+
+ void on_btnApplyFracture_clicked();
+
+private:
+ QString _getTexturePathByName(const QString& name);
+ void _updateTextureListWidget();
+
+private:
+ Ui::FractureCutoutSettingsPanel *ui;
+};
+
+#endif // FRACTURECUTOUTSETTINGSPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureGeneralPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureGeneralPanel.cpp
new file mode 100644
index 0000000..1f7068d
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureGeneralPanel.cpp
@@ -0,0 +1,63 @@
+#include "FractureGeneralPanel.h"
+#include "ui_FractureGeneralPanel.h"
+#include "ProjectParams.h"
+
+FractureGeneralPanel::FractureGeneralPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::FractureGeneralPanel)
+{
+ ui->setupUi(this);
+}
+
+FractureGeneralPanel::~FractureGeneralPanel()
+{
+ delete ui;
+}
+
+void FractureGeneralPanel::updateValues()
+{
+ BPPFractureGeneral& fractureGeneral = BlastProject::ins().getParams().fracture.general;
+
+ ui->comboBoxFracturePreset->setCurrentIndex(fractureGeneral.fracturePreset);
+ ui->comboBoxFractureType->setCurrentIndex(fractureGeneral.fractureType);
+ ui->checkBoxAddDepth->setChecked(fractureGeneral.addDepth);
+ ui->checkBoxPerChunk->setChecked(fractureGeneral.perChunk);
+ ui->checkBoxNewMatID->setChecked(fractureGeneral.newMatID);
+ ui->comboBoxApplyMaterial->setCurrentIndex(fractureGeneral.applyMaterial);
+}
+
+void FractureGeneralPanel::on_comboBoxFracturePreset_currentIndexChanged(int index)
+{
+ BPPFractureGeneral& fractureGeneral = BlastProject::ins().getParams().fracture.general;
+ fractureGeneral.fracturePreset = index;
+}
+
+void FractureGeneralPanel::on_comboBoxFractureType_currentIndexChanged(int index)
+{
+ BPPFractureGeneral& fractureGeneral = BlastProject::ins().getParams().fracture.general;
+ fractureGeneral.fractureType = index;
+}
+
+void FractureGeneralPanel::on_checkBoxAddDepth_stateChanged(int arg1)
+{
+ BPPFractureGeneral& fractureGeneral = BlastProject::ins().getParams().fracture.general;
+ fractureGeneral.addDepth = (arg1 != 0 ? true : false);
+}
+
+void FractureGeneralPanel::on_checkBoxPerChunk_stateChanged(int arg1)
+{
+ BPPFractureGeneral& fractureGeneral = BlastProject::ins().getParams().fracture.general;
+ fractureGeneral.perChunk = (arg1 != 0 ? true : false);
+}
+
+void FractureGeneralPanel::on_checkBoxNewMatID_stateChanged(int arg1)
+{
+ BPPFractureGeneral& fractureGeneral = BlastProject::ins().getParams().fracture.general;
+ fractureGeneral.newMatID = (arg1 != 0 ? true:false);
+}
+
+void FractureGeneralPanel::on_comboBoxApplyMaterial_currentIndexChanged(int index)
+{
+ BPPFractureGeneral& fractureGeneral = BlastProject::ins().getParams().fracture.general;
+ fractureGeneral.applyMaterial = index;
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureGeneralPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureGeneralPanel.h
new file mode 100644
index 0000000..4b51f5e
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureGeneralPanel.h
@@ -0,0 +1,36 @@
+#ifndef FRACTUREGENERALPANEL_H
+#define FRACTUREGENERALPANEL_H
+
+#include <QtWidgets/QWidget>
+
+namespace Ui {
+class FractureGeneralPanel;
+}
+
+class FractureGeneralPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit FractureGeneralPanel(QWidget *parent = 0);
+ ~FractureGeneralPanel();
+ void updateValues();
+
+private slots:
+ void on_comboBoxFracturePreset_currentIndexChanged(int index);
+
+ void on_comboBoxFractureType_currentIndexChanged(int index);
+
+ void on_checkBoxAddDepth_stateChanged(int arg1);
+
+ void on_checkBoxPerChunk_stateChanged(int arg1);
+
+ void on_checkBoxNewMatID_stateChanged(int arg1);
+
+ void on_comboBoxApplyMaterial_currentIndexChanged(int index);
+
+private:
+ Ui::FractureGeneralPanel *ui;
+};
+
+#endif // FRACTUREGENERALPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureShellCutSettingsPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureShellCutSettingsPanel.cpp
new file mode 100644
index 0000000..c08e3ba
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureShellCutSettingsPanel.cpp
@@ -0,0 +1,40 @@
+#include "FractureShellCutSettingsPanel.h"
+#include "ui_FractureShellCutSettingsPanel.h"
+#include "ProjectParams.h"
+
+FractureShellCutSettingsPanel::FractureShellCutSettingsPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::FractureShellCutSettingsPanel)
+{
+ ui->setupUi(this);
+}
+
+FractureShellCutSettingsPanel::~FractureShellCutSettingsPanel()
+{
+ delete ui;
+}
+
+void FractureShellCutSettingsPanel::updateValues()
+{
+ BPPShellCut& shellCut = BlastProject::ins().getParams().fracture.shellCut;
+
+ ui->spinBoxThickness->setValue(shellCut.thickness);
+ ui->spinBoxThicknessVariation->setValue(shellCut.thicknessVariation);
+}
+
+void FractureShellCutSettingsPanel::on_spinBoxThickness_valueChanged(double arg1)
+{
+ BPPShellCut& shellCut = BlastProject::ins().getParams().fracture.shellCut;
+ shellCut.thickness = arg1;
+}
+
+void FractureShellCutSettingsPanel::on_spinBoxThicknessVariation_valueChanged(double arg1)
+{
+ BPPShellCut& shellCut = BlastProject::ins().getParams().fracture.shellCut;
+ shellCut.thicknessVariation = arg1;
+}
+
+void FractureShellCutSettingsPanel::on_btnApplyFracture_clicked()
+{
+
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureShellCutSettingsPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureShellCutSettingsPanel.h
new file mode 100644
index 0000000..a664adb
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureShellCutSettingsPanel.h
@@ -0,0 +1,30 @@
+#ifndef FRACTURESHELLCUTSETTINGSPANEL_H
+#define FRACTURESHELLCUTSETTINGSPANEL_H
+
+#include <QtWidgets/QWidget>
+
+namespace Ui {
+class FractureShellCutSettingsPanel;
+}
+
+class FractureShellCutSettingsPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit FractureShellCutSettingsPanel(QWidget *parent = 0);
+ ~FractureShellCutSettingsPanel();
+ void updateValues();
+
+private slots:
+void on_spinBoxThickness_valueChanged(double arg1);
+
+ void on_spinBoxThicknessVariation_valueChanged(double arg1);
+
+ void on_btnApplyFracture_clicked();
+
+private:
+ Ui::FractureShellCutSettingsPanel *ui;
+};
+
+#endif // FRACTURESHELLCUTSETTINGSPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureSliceSettingsPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureSliceSettingsPanel.cpp
new file mode 100644
index 0000000..fa82ee2
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureSliceSettingsPanel.cpp
@@ -0,0 +1,105 @@
+#include "FractureSliceSettingsPanel.h"
+#include "ui_FractureSliceSettingsPanel.h"
+#include "ProjectParams.h"
+#include "SimpleScene.h"
+#include "SampleManager.h"
+#include <QtWidgets/QMessageBox>
+
+FractureSliceSettingsPanel::FractureSliceSettingsPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::FractureSliceSettingsPanel)
+{
+ ui->setupUi(this);
+}
+
+FractureSliceSettingsPanel::~FractureSliceSettingsPanel()
+{
+ delete ui;
+}
+
+void FractureSliceSettingsPanel::updateValues()
+{
+ BPPSlice& slice = BlastProject::ins().getParams().fracture.slice;
+
+ ui->spinBoxNumSlices->setValue(slice.numSlices);
+ ui->spinBoxOffsetVariation->setValue(slice.offsetVariation);
+ ui->spinBoxRotationVariation->setValue(slice.rotationVariation);
+ ui->spinBoxNoiseAmplitude->setValue(slice.noiseAmplitude);
+ ui->spinBoxNoiseFrequency->setValue(slice.noiseFrequency);
+ ui->spinBoxNoiseSeed->setValue(slice.noiseSeed);
+}
+
+void FractureSliceSettingsPanel::on_spinBoxNumSlices_valueChanged(int arg1)
+{
+ BPPSlice& slice = BlastProject::ins().getParams().fracture.slice;
+ slice.numSlices = arg1;
+}
+
+void FractureSliceSettingsPanel::on_spinBoxOffsetVariation_valueChanged(double arg1)
+{
+ BPPSlice& slice = BlastProject::ins().getParams().fracture.slice;
+ slice.offsetVariation = arg1;
+}
+
+void FractureSliceSettingsPanel::on_spinBoxRotationVariation_valueChanged(double arg1)
+{
+ BPPSlice& slice = BlastProject::ins().getParams().fracture.slice;
+ slice.rotationVariation = arg1;
+}
+
+void FractureSliceSettingsPanel::on_spinBoxNoiseAmplitude_valueChanged(double arg1)
+{
+ BPPSlice& slice = BlastProject::ins().getParams().fracture.slice;
+ slice.noiseAmplitude = arg1;
+}
+
+void FractureSliceSettingsPanel::on_spinBoxNoiseFrequency_valueChanged(double arg1)
+{
+ BPPSlice& slice = BlastProject::ins().getParams().fracture.slice;
+ slice.noiseFrequency = arg1;
+}
+
+void FractureSliceSettingsPanel::on_spinBoxNoiseSeed_valueChanged(int arg1)
+{
+ BPPSlice& slice = BlastProject::ins().getParams().fracture.slice;
+ slice.noiseSeed = arg1;
+}
+
+void FractureSliceSettingsPanel::on_btnApplyFracture_clicked()
+{
+ BPPSlice& slice = BlastProject::ins().getParams().fracture.slice;
+ SliceFractureExecutor executor;
+ executor.applyNoise(slice.noiseAmplitude, slice.noiseAmplitude, 0, 0, 0, slice.noiseSeed);
+ executor.applyConfig(slice.numSlices, slice.numSlices, slice.numSlices, slice.offsetVariation, slice.rotationVariation);
+
+ bool multiplyChunksSelected = false;
+ std::map<BlastAsset*, std::vector<uint32_t>> selectedChunks = SampleManager::ins()->getSelectedChunks();
+ std::map<BlastAsset*, std::vector<uint32_t>>::iterator itrAssetSelectedChunks = selectedChunks.begin();
+
+ if (selectedChunks.size() > 1)
+ {
+ multiplyChunksSelected = true;
+ }
+ else if (selectedChunks.size() == 1 && itrAssetSelectedChunks->second.size() > 1)
+ {
+ multiplyChunksSelected = true;
+ }
+ else if((selectedChunks.size() == 1 && itrAssetSelectedChunks->second.size() == 0) || (selectedChunks.size() == 0))
+ {
+ return;
+ }
+
+ if (multiplyChunksSelected)
+ {
+ QMessageBox::warning(NULL, "Blast Tool", "Now, this tool can only fracture one chunk!");
+ return;
+ }
+
+ executor.setSourceAsset(itrAssetSelectedChunks->first);
+ executor.setTargetChunk(itrAssetSelectedChunks->second.at(0));
+ executor.execute();
+
+ //VoronoiFractureExecutor executor;
+ //executor.setTargetChunk(0);
+ //executor.execute();
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureSliceSettingsPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureSliceSettingsPanel.h
new file mode 100644
index 0000000..b85b58f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureSliceSettingsPanel.h
@@ -0,0 +1,38 @@
+#ifndef FRACTURESLICESETTINGSPANEL_H
+#define FRACTURESLICESETTINGSPANEL_H
+
+#include <QtWidgets/QWidget>
+
+namespace Ui {
+class FractureSliceSettingsPanel;
+}
+
+class FractureSliceSettingsPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit FractureSliceSettingsPanel(QWidget *parent = 0);
+ ~FractureSliceSettingsPanel();
+ void updateValues();
+
+private slots:
+ void on_spinBoxNumSlices_valueChanged(int arg1);
+
+ void on_spinBoxOffsetVariation_valueChanged(double arg1);
+
+ void on_spinBoxRotationVariation_valueChanged(double arg1);
+
+ void on_spinBoxNoiseAmplitude_valueChanged(double arg1);
+
+ void on_spinBoxNoiseFrequency_valueChanged(double arg1);
+
+ void on_spinBoxNoiseSeed_valueChanged(int arg1);
+
+ void on_btnApplyFracture_clicked();
+
+private:
+ Ui::FractureSliceSettingsPanel *ui;
+};
+
+#endif // FRACTURESLICESETTINGSPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVisualizersPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVisualizersPanel.cpp
new file mode 100644
index 0000000..0f77e27
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVisualizersPanel.cpp
@@ -0,0 +1,36 @@
+#include "FractureVisualizersPanel.h"
+#include "ui_FractureVisualizersPanel.h"
+#include "ProjectParams.h"
+
+FractureVisualizersPanel::FractureVisualizersPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::FractureVisualizersPanel)
+{
+ ui->setupUi(this);
+}
+
+FractureVisualizersPanel::~FractureVisualizersPanel()
+{
+ delete ui;
+}
+
+void FractureVisualizersPanel::updateValues()
+{
+ BPPFractureVisualization& fractureVisualization = BlastProject::ins().getParams().fracture.visualization;
+
+ ui->checkBoxFracturePreview->setChecked(fractureVisualization.fracturePreview);
+ ui->checkBoxDisplayFractureWidget->setChecked(fractureVisualization.displayFractureWidget);
+}
+
+void FractureVisualizersPanel::on_checkBoxFracturePreview_stateChanged(int arg1)
+{
+ BPPFractureVisualization& fractureVisualization = BlastProject::ins().getParams().fracture.visualization;
+ fractureVisualization.fracturePreview = (arg1 != 0 ? true : false);
+}
+
+void FractureVisualizersPanel::on_checkBoxDisplayFractureWidget_stateChanged(int arg1)
+{
+ BPPFractureVisualization& fractureVisualization = BlastProject::ins().getParams().fracture.visualization;
+ fractureVisualization.displayFractureWidget = (arg1 != 0 ? true : false);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVisualizersPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVisualizersPanel.h
new file mode 100644
index 0000000..d542d7f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVisualizersPanel.h
@@ -0,0 +1,28 @@
+#ifndef FRACTUREVISUALIZERSPANEL_H
+#define FRACTUREVISUALIZERSPANEL_H
+
+#include <QtWidgets/QWidget>
+
+namespace Ui {
+class FractureVisualizersPanel;
+}
+
+class FractureVisualizersPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit FractureVisualizersPanel(QWidget *parent = 0);
+ ~FractureVisualizersPanel();
+ void updateValues();
+
+private slots:
+ void on_checkBoxFracturePreview_stateChanged(int arg1);
+
+ void on_checkBoxDisplayFractureWidget_stateChanged(int arg1);
+
+private:
+ Ui::FractureVisualizersPanel *ui;
+};
+
+#endif // FRACTUREVISUALIZERSPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVoronoiSettingsPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVoronoiSettingsPanel.cpp
new file mode 100644
index 0000000..2142f80
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVoronoiSettingsPanel.cpp
@@ -0,0 +1,354 @@
+#include "FractureVoronoiSettingsPanel.h"
+#include "ui_FractureVoronoiSettingsPanel.h"
+#include "ProjectParams.h"
+#include <QtWidgets/QInputDialog>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QMessageBox>
+#include <QtCore/QFileInfo>
+#include "AppMainWindow.h"
+#include "ProjectParams.h"
+#include "SimpleScene.h"
+#include "SampleManager.h"
+
+FractureVoronoiSettingsPanel::FractureVoronoiSettingsPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::FractureVoronoiSettingsPanel),
+ _updateData(true)
+{
+ ui->setupUi(this);
+
+ ui->groupBoxVisualizers->hide();
+}
+
+FractureVoronoiSettingsPanel::~FractureVoronoiSettingsPanel()
+{
+ delete ui;
+}
+
+void FractureVoronoiSettingsPanel::updateValues()
+{
+ _updateData = false;
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+
+ ui->spinBoxNumberOfSites->setValue(voronoi.numSites);
+ ui->comboBoxSiteGeneration->setCurrentIndex(voronoi.siteGeneration);
+ ui->spinBoxGridSize->setValue(voronoi.gridSize);
+ ui->spinBoxGridScale->setValue(voronoi.gridScale);
+ ui->spinBoxAmplitude->setValue(voronoi.amplitude);
+ ui->spinBoxFrequency->setValue(voronoi.frequency);
+
+ _updatePaintMaskComboBox();
+
+ _updateMeshCutterComboBox();
+ ui->checkBoxFractureInsideCutter->setChecked(voronoi.fractureInsideCutter);
+ ui->checkBoxFractureOutsideCutter->setChecked(voronoi.fractureOutsideCutter);
+
+ ui->spinBoxTextureSites->setValue(voronoi.numTextureSites);
+
+ _updateTextureListWidget();
+ _updateData = true;
+}
+
+void FractureVoronoiSettingsPanel::on_checkBoxGridPreview_stateChanged(int arg1)
+{
+
+}
+
+void FractureVoronoiSettingsPanel::on_checkBoxFracturePreview_stateChanged(int arg1)
+{
+
+}
+
+void FractureVoronoiSettingsPanel::on_checkBoxCutterMesh_stateChanged(int arg1)
+{
+
+}
+
+void FractureVoronoiSettingsPanel::on_spinBoxNumberOfSites_valueChanged(int arg1)
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.numSites = arg1;
+}
+
+void FractureVoronoiSettingsPanel::on_comboBoxSiteGeneration_currentIndexChanged(int index)
+{
+ if (!_updateData)
+ return;
+
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.siteGeneration = index;
+}
+
+void FractureVoronoiSettingsPanel::on_spinBoxGridSize_valueChanged(int arg1)
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.gridSize = arg1;
+}
+
+void FractureVoronoiSettingsPanel::on_spinBoxGridScale_valueChanged(double arg1)
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.gridScale = arg1;
+}
+
+void FractureVoronoiSettingsPanel::on_spinBoxAmplitude_valueChanged(double arg1)
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.amplitude = arg1;
+}
+
+void FractureVoronoiSettingsPanel::on_spinBoxFrequency_valueChanged(int arg1)
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.frequency = arg1;
+}
+
+void FractureVoronoiSettingsPanel::on_comboBoxPaintMasks_currentIndexChanged(int index)
+{
+ if (!_updateData)
+ return;
+
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.activePaintMask = index;
+}
+
+void FractureVoronoiSettingsPanel::on_btnAddPaintMasks_clicked()
+{
+ bool ok = false;
+ QString name = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input name for new paint mask:"),
+ QLineEdit::Normal,
+ "",
+ &ok);
+ bool nameExist = BlastProject::ins().isPaintMaskNameExist(name.toUtf8().data());
+ if (ok && !name.isEmpty() && !nameExist)
+ {
+ BlastProject::ins().addPaintMasks(name.toUtf8().data());
+ _updatePaintMaskComboBox();
+ ui->comboBoxPaintMasks->setCurrentIndex(ui->comboBoxPaintMasks->count() - 1);
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && name.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the new paint mask!");
+ }
+}
+
+void FractureVoronoiSettingsPanel::on_btnRemovePaintMasks_clicked()
+{
+ if (ui->comboBoxPaintMasks->currentIndex() > -1)
+ {
+ BlastProject::ins().removePaintMasks(ui->comboBoxPaintMasks->currentText().toUtf8().data());
+ _updatePaintMaskComboBox();
+ }
+}
+
+void FractureVoronoiSettingsPanel::on_comboBoxMeshCutter_currentIndexChanged(int index)
+{
+ if (!_updateData)
+ return;
+
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.activeMeshCutter = index;
+}
+
+void FractureVoronoiSettingsPanel::on_btnAddMeshCutter_clicked()
+{
+ bool ok = false;
+ QString name = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input name for new mesh cutter:"),
+ QLineEdit::Normal,
+ "",
+ &ok);
+ bool nameExist = BlastProject::ins().isMeshCutterNameExist(name.toUtf8().data());
+ if (ok && !name.isEmpty() && !nameExist)
+ {
+ BlastProject::ins().addMeshCutter(name.toUtf8().data());
+ _updateMeshCutterComboBox();
+ ui->comboBoxMeshCutter->setCurrentIndex(ui->comboBoxMeshCutter->count() - 1);
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && name.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the new cutter mesh!");
+ }
+}
+
+void FractureVoronoiSettingsPanel::on_btnRemoveMeshCutter_clicked()
+{
+ if (ui->comboBoxMeshCutter->currentIndex() > -1)
+ {
+ BlastProject::ins().removeMeshCutter(ui->comboBoxMeshCutter->currentText().toUtf8().data());
+ _updateMeshCutterComboBox();
+ }
+}
+
+void FractureVoronoiSettingsPanel::on_checkBoxFractureInsideCutter_stateChanged(int arg1)
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.fractureInsideCutter = (arg1 != 0 ? true : false);
+}
+
+void FractureVoronoiSettingsPanel::on_checkBoxFractureOutsideCutter_stateChanged(int arg1)
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.fractureOutsideCutter = (arg1 != 0 ? true : false);
+}
+
+void FractureVoronoiSettingsPanel::on_btnAddTexture_clicked()
+{
+ QString texName = AppMainWindow::Inst().OpenTextureFile();
+
+ if (texName.isEmpty())
+ return;
+
+ QFileInfo fileInfo(texName);
+ QByteArray ba = fileInfo.absoluteFilePath().toLocal8Bit();
+ const char* filePath = (const char*)(ba);
+
+ if (!BlastProject::ins().isVoronoiTextureNameExist(texName.toUtf8().data()))
+ {
+ BlastProject::ins().addVoronoiTexture(filePath);
+ _updateTextureListWidget();
+ ui->listWidgetTexture->setCurrentRow(ui->listWidgetTexture->count() - 1);
+ }
+ else
+ {
+ QMessageBox::warning(this, "Blast Tool", "The texture you selected is already exist!");
+ }
+}
+
+void FractureVoronoiSettingsPanel::on_btnReloadTexture_clicked()
+{
+
+}
+
+void FractureVoronoiSettingsPanel::on_btnRemoveTexture_clicked()
+{
+ if (ui->listWidgetTexture->currentRow() != -1)
+ {
+ QListWidgetItem *item = ui->listWidgetTexture->currentItem();
+ QString texture = _getTexturePathByName(item->text());
+ QByteArray ba = texture.toLocal8Bit();
+ BlastProject::ins().removeVoronoiTexture(ba.data());
+ _updateTextureListWidget();
+ }
+}
+
+void FractureVoronoiSettingsPanel::on_spinBoxTextureSites_valueChanged(int arg1)
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ voronoi.numTextureSites = arg1;
+}
+
+void FractureVoronoiSettingsPanel::on_listWidgetTexture_itemSelectionChanged()
+{
+
+}
+
+void FractureVoronoiSettingsPanel::on_btnTextureMap_clicked()
+{
+
+}
+
+void FractureVoronoiSettingsPanel::on_btnApplyFracture_clicked()
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ VoronoiFractureExecutor executor;
+ executor.setCellsCount(voronoi.numSites);
+
+ bool multiplyChunksSelected = false;
+ std::map<BlastAsset*, std::vector<uint32_t>> selectedChunks = SampleManager::ins()->getSelectedChunks();
+ std::map<BlastAsset*, std::vector<uint32_t>>::iterator itrAssetSelectedChunks = selectedChunks.begin();
+
+ if (selectedChunks.size() > 1)
+ {
+ multiplyChunksSelected = true;
+ }
+ else if (selectedChunks.size() == 1 && itrAssetSelectedChunks->second.size() > 1)
+ {
+ multiplyChunksSelected = true;
+ }
+ else if ((selectedChunks.size() == 1 && itrAssetSelectedChunks->second.size() == 0) || (selectedChunks.size() == 0))
+ {
+ return;
+ }
+
+ if (multiplyChunksSelected)
+ {
+ QMessageBox::warning(NULL, "Blast Tool", "Now, this tool can only fracture one chunk!");
+ return;
+ }
+
+ executor.setSourceAsset(itrAssetSelectedChunks->first);
+ executor.setTargetChunk(itrAssetSelectedChunks->second.at(0));
+ executor.execute();
+}
+
+QString FractureVoronoiSettingsPanel::_getTexturePathByName(const QString& name)
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+ BPPStringArray& textureArray = voronoi.textureSites;
+
+ int count = textureArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ QFileInfo fileInfo(textureArray.buf[i].buf);
+ if (fileInfo.baseName() == name)
+ return textureArray.buf[i].buf;
+ }
+
+ return "";
+}
+
+void FractureVoronoiSettingsPanel::_updatePaintMaskComboBox()
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+
+ ui->comboBoxPaintMasks->clear();
+ QStringList items;
+ for (int i = 0; i < voronoi.paintMasks.arraySizes[0]; ++i)
+ {
+ items.append(voronoi.paintMasks.buf[i].buf);
+ }
+ ui->comboBoxPaintMasks->addItems(items);
+ ui->comboBoxPaintMasks->setCurrentIndex(voronoi.activePaintMask);
+}
+
+void FractureVoronoiSettingsPanel::_updateMeshCutterComboBox()
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+
+ ui->comboBoxMeshCutter->clear();
+ QStringList items;
+ for (int i = 0; i < voronoi.meshCutters.arraySizes[0]; ++i)
+ {
+ items.append(voronoi.meshCutters.buf[i].buf);
+ }
+ ui->comboBoxMeshCutter->addItems(items);
+ ui->comboBoxMeshCutter->setCurrentIndex(voronoi.activeMeshCutter);
+}
+
+void FractureVoronoiSettingsPanel::_updateTextureListWidget()
+{
+ BPPVoronoi& voronoi = BlastProject::ins().getParams().fracture.voronoi;
+
+ ui->listWidgetTexture->clear();
+ QStringList items;
+ for (int i = 0; i < voronoi.textureSites.arraySizes[0]; ++i)
+ {
+ QFileInfo fileInfo(voronoi.textureSites.buf[i].buf);
+ QByteArray ba = fileInfo.baseName().toLocal8Bit();
+ const char* texture = (const char*)(ba);
+ items.append(texture);
+ }
+ ui->listWidgetTexture->addItems(items);
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVoronoiSettingsPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVoronoiSettingsPanel.h
new file mode 100644
index 0000000..6a0668d
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/FractureVoronoiSettingsPanel.h
@@ -0,0 +1,79 @@
+#ifndef FRACTUREVORONOISETTINGSPANEL_H
+#define FRACTUREVORONOISETTINGSPANEL_H
+
+#include <QtWidgets/QWidget>
+
+namespace Ui {
+class FractureVoronoiSettingsPanel;
+}
+
+class FractureVoronoiSettingsPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit FractureVoronoiSettingsPanel(QWidget *parent = 0);
+ ~FractureVoronoiSettingsPanel();
+ void updateValues();
+
+private slots:
+ void on_checkBoxGridPreview_stateChanged(int arg1);
+
+ void on_checkBoxFracturePreview_stateChanged(int arg1);
+
+ void on_checkBoxCutterMesh_stateChanged(int arg1);
+
+ void on_spinBoxNumberOfSites_valueChanged(int arg1);
+
+ void on_comboBoxSiteGeneration_currentIndexChanged(int index);
+
+ void on_spinBoxGridSize_valueChanged(int arg1);
+
+ void on_spinBoxGridScale_valueChanged(double arg1);
+
+ void on_spinBoxAmplitude_valueChanged(double arg1);
+
+ void on_spinBoxFrequency_valueChanged(int arg1);
+
+ void on_comboBoxPaintMasks_currentIndexChanged(int index);
+
+ void on_btnAddPaintMasks_clicked();
+
+ void on_btnRemovePaintMasks_clicked();
+
+ void on_comboBoxMeshCutter_currentIndexChanged(int index);
+
+ void on_btnAddMeshCutter_clicked();
+
+ void on_btnRemoveMeshCutter_clicked();
+
+ void on_checkBoxFractureInsideCutter_stateChanged(int arg1);
+
+ void on_checkBoxFractureOutsideCutter_stateChanged(int arg1);
+
+ void on_btnAddTexture_clicked();
+
+ void on_btnReloadTexture_clicked();
+
+ void on_btnRemoveTexture_clicked();
+
+ void on_spinBoxTextureSites_valueChanged(int arg1);
+
+ void on_listWidgetTexture_itemSelectionChanged();
+
+ void on_btnTextureMap_clicked();
+
+ void on_btnApplyFracture_clicked();
+
+private:
+ QString _getTexturePathByName(const QString& name);
+ void _updatePaintMaskComboBox();
+ void _updateMeshCutterComboBox();
+ void _updateTextureListWidget();
+
+private:
+ Ui::FractureVoronoiSettingsPanel *ui;
+ bool _updateData;
+};
+
+#endif // FRACTUREVORONOISETTINGSPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/GeneralPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/GeneralPanel.cpp
new file mode 100644
index 0000000..88915f1
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/GeneralPanel.cpp
@@ -0,0 +1,281 @@
+#include "GeneralPanel.h"
+#include "ui_GeneralPanel.h"
+#include <QtWidgets/QInputDialog>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QMessageBox>
+
+GeneralPanel::GeneralPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::GeneralPanel)
+{
+ ui->setupUi(this);
+}
+
+GeneralPanel::~GeneralPanel()
+{
+ delete ui;
+}
+
+void GeneralPanel::updateValues()
+{
+ std::vector<StressSolverUserPreset> presets = BlastProject::ins().getUserPresets();
+ ui->comboBoxUserPreset->clear();
+ int countUserPresets = (int)presets.size();
+ if (countUserPresets > 0)
+ {
+ QStringList userPresets;
+ for (int i = 0; i < countUserPresets; ++i)
+ {
+ userPresets.append(presets[i].name.c_str());
+ }
+ ui->comboBoxUserPreset->addItems(userPresets);
+ }
+
+ std::vector<BPPAsset*> selectedAssets = BlastProject::ins().getSelectedBlastAssets();
+ if (selectedAssets.size() > 0)
+ {
+ ui->comboBoxUserPreset->setCurrentText(selectedAssets[0]->activePreset.buf);
+
+ _updateStressSolverUIs();
+ }
+ else
+ {
+ ui->comboBoxUserPreset->setCurrentIndex(-1);
+
+ }
+}
+
+void GeneralPanel::on_comboBoxUserPreset_currentIndexChanged(int index)
+{
+ std::vector<BPPAsset*> assets = BlastProject::ins().getSelectedBlastAssets();
+ for (size_t i = 0; i < assets.size(); ++i)
+ {
+ QByteArray tem = ui->comboBoxUserPreset->currentText().toUtf8();
+ copy(assets[i]->activePreset, tem.data());
+
+ BPPStressSolver* preset = _getUserPreset(tem.data());
+ if (preset)
+ {
+ copy(assets[i]->stressSolver, *preset);
+ }
+ }
+ _updateStressSolverUIs();
+}
+
+void GeneralPanel::on_btnAddUserPreset_clicked()
+{
+ bool ok = false;
+ QString name = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input name for new User preset:"),
+ QLineEdit::Normal,
+ "",
+ &ok);
+ bool nameExist = BlastProject::ins().isUserPresetNameExist(name.toUtf8().data());
+ if (ok && !name.isEmpty() && !nameExist)
+ {
+ BlastProject::ins().addUserPreset(name.toUtf8().data());
+ updateValues();
+ ui->comboBoxUserPreset->setCurrentIndex(ui->comboBoxUserPreset->count() - 1);
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && name.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the new preset!");
+ }
+}
+
+void GeneralPanel::on_btnModifyUserPreset_clicked()
+{
+ if (ui->comboBoxUserPreset->currentIndex() == -1)
+ {
+ QMessageBox::warning(this, "Blast Tool", "You should select an user preset!");
+ return;
+ }
+
+ QByteArray tmp = ui->comboBoxUserPreset->currentText().toUtf8();
+ const char* oldName = tmp.data();
+
+ bool ok = false;
+ QString newName = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input new name for the selected user preset:"),
+ QLineEdit::Normal,
+ oldName,
+ &ok);
+ bool nameExist = BlastProject::ins().isUserPresetNameExist(newName.toUtf8().data());
+ if (ok && !newName.isEmpty() && !nameExist)
+ {
+ int curIndex = ui->comboBoxUserPreset->currentIndex();
+
+ std::vector<StressSolverUserPreset>& presets = BlastProject::ins().getUserPresets();
+ presets[curIndex].name = newName.toUtf8().data();
+ updateValues();
+ ui->comboBoxUserPreset->setCurrentIndex(curIndex);
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && newName.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the selected graphics material!");
+ }
+}
+
+void GeneralPanel::on_btnSaveUserPreset_clicked()
+{
+ int currentUserPreset = ui->comboBoxUserPreset->currentIndex();
+ if (-1 != currentUserPreset)
+ {
+ std::vector<StressSolverUserPreset>& presets = BlastProject::ins().getUserPresets();
+ BPPStressSolver& stressSolver = presets[currentUserPreset].stressSolver;
+ stressSolver.solverMode = ui->comboBoxSolverMode->currentIndex();
+ stressSolver.linearFactor = ui->spinBoxLinearFactor->value();
+ stressSolver.angularFactor = ui->spinBoxAngularFactor->value();
+ stressSolver.meanError = ui->spinBoxMeanError->value();
+ stressSolver.varianceError = ui->spinBoxVarianceError->value();
+ stressSolver.bondsPerFrame = ui->spinBoxBondsPerFrame->value();
+ stressSolver.bondsIterations = ui->spinBoxBondsIterations->value();
+ }
+
+ BlastProject::ins().saveUserPreset();
+}
+
+void GeneralPanel::on_comboBoxSolverMode_currentIndexChanged(int index)
+{
+ BPPStressSolver* stressSolver = _getCurrentStressSolver();
+
+ if (stressSolver)
+ {
+ stressSolver->solverMode = index;
+ }
+}
+
+void GeneralPanel::on_spinBoxLinearFactor_valueChanged(double arg1)
+{
+ BPPStressSolver* stressSolver = _getCurrentStressSolver();
+
+ if (stressSolver)
+ {
+ stressSolver->linearFactor = arg1;
+ }
+
+}
+
+void GeneralPanel::on_spinBoxAngularFactor_valueChanged(double arg1)
+{
+ BPPStressSolver* stressSolver = _getCurrentStressSolver();
+
+ if (stressSolver)
+ {
+ stressSolver->angularFactor = arg1;
+ }
+}
+
+void GeneralPanel::on_spinBoxMeanError_valueChanged(double arg1)
+{
+ BPPStressSolver* stressSolver = _getCurrentStressSolver();
+
+ if (stressSolver)
+ {
+ stressSolver->meanError = arg1;
+ }
+}
+
+void GeneralPanel::on_spinBoxVarianceError_valueChanged(double arg1)
+{
+ BPPStressSolver* stressSolver = _getCurrentStressSolver();
+
+ if (stressSolver)
+ {
+ stressSolver->varianceError = arg1;
+ }
+}
+
+void GeneralPanel::on_spinBoxBondsPerFrame_valueChanged(int arg1)
+{
+ BPPStressSolver* stressSolver = _getCurrentStressSolver();
+
+ if (stressSolver)
+ {
+ stressSolver->bondsPerFrame = arg1;
+ }
+}
+
+void GeneralPanel::on_spinBoxBondsIterations_valueChanged(int arg1)
+{
+ BPPStressSolver* stressSolver = _getCurrentStressSolver();
+
+ if (stressSolver)
+ {
+ stressSolver->bondsIterations = arg1;
+ }
+}
+
+BPPStressSolver* GeneralPanel::_getCurrentStressSolver()
+{
+ int currentUserPreset = ui->comboBoxUserPreset->currentIndex();
+
+ if (-1 != currentUserPreset)
+ {
+ std::vector<StressSolverUserPreset>& presets = BlastProject::ins().getUserPresets();
+ return &(presets[currentUserPreset].stressSolver);
+ }
+ else
+ {
+ std::vector<BPPAsset*> assets = BlastProject::ins().getSelectedBlastAssets();
+
+ if (assets.size() > 0)
+ {
+ return &(assets[0]->stressSolver);
+ }
+ }
+
+ return nullptr;
+}
+
+BPPStressSolver* GeneralPanel::_getUserPreset(const char* name)
+{
+ std::vector<StressSolverUserPreset>& presets = BlastProject::ins().getUserPresets();
+
+ for (size_t i = 0; i < presets.size(); ++i)
+ {
+ if (presets[i].name == name)
+ return &(presets[i].stressSolver);
+ }
+
+ return nullptr;
+}
+
+void GeneralPanel::_updateStressSolverUIs()
+{
+ BPPStressSolver* stressSolver = _getCurrentStressSolver();
+ if (stressSolver != nullptr)
+ {
+ ui->comboBoxSolverMode->setCurrentIndex(stressSolver->solverMode);
+ ui->spinBoxLinearFactor->setValue(stressSolver->linearFactor);
+ ui->spinBoxAngularFactor->setValue(stressSolver->angularFactor);
+ ui->spinBoxMeanError->setValue(stressSolver->meanError);
+ ui->spinBoxVarianceError->setValue(stressSolver->varianceError);
+ ui->spinBoxBondsPerFrame->setValue(stressSolver->bondsPerFrame);
+ ui->spinBoxBondsIterations->setValue(stressSolver->bondsIterations);
+ }
+ else
+ {
+ BPPStressSolver noStressSolver;
+ init(noStressSolver);
+
+ ui->comboBoxSolverMode->setCurrentIndex(noStressSolver.solverMode);
+ ui->spinBoxLinearFactor->setValue(noStressSolver.linearFactor);
+ ui->spinBoxAngularFactor->setValue(noStressSolver.angularFactor);
+ ui->spinBoxMeanError->setValue(noStressSolver.meanError);
+ ui->spinBoxVarianceError->setValue(noStressSolver.varianceError);
+ ui->spinBoxBondsPerFrame->setValue(noStressSolver.bondsPerFrame);
+ ui->spinBoxBondsIterations->setValue(noStressSolver.bondsIterations);
+ }
+
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/GeneralPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/GeneralPanel.h
new file mode 100644
index 0000000..a7a52e3
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/GeneralPanel.h
@@ -0,0 +1,52 @@
+#ifndef GENERALPANEL_H
+#define GENERALPANEL_H
+
+#include <QtWidgets/QWidget>
+#include "ProjectParams.h"
+
+namespace Ui {
+class GeneralPanel;
+}
+
+class GeneralPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit GeneralPanel(QWidget *parent = 0);
+ ~GeneralPanel();
+ void updateValues();
+
+private slots:
+ void on_comboBoxUserPreset_currentIndexChanged(int index);
+
+ void on_btnAddUserPreset_clicked();
+
+ void on_btnModifyUserPreset_clicked();
+
+ void on_btnSaveUserPreset_clicked();
+
+ void on_comboBoxSolverMode_currentIndexChanged(int index);
+
+ void on_spinBoxLinearFactor_valueChanged(double arg1);
+
+ void on_spinBoxAngularFactor_valueChanged(double arg1);
+
+ void on_spinBoxMeanError_valueChanged(double arg1);
+
+ void on_spinBoxVarianceError_valueChanged(double arg1);
+
+ void on_spinBoxBondsPerFrame_valueChanged(int arg1);
+
+ void on_spinBoxBondsIterations_valueChanged(int arg1);
+
+private:
+ BPPStressSolver* _getCurrentStressSolver();
+ BPPStressSolver* _getUserPreset(const char* name);
+ void _updateStressSolverUIs();
+
+private:
+ Ui::GeneralPanel *ui;
+};
+
+#endif // GENERALPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialAssignmentsPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialAssignmentsPanel.cpp
new file mode 100644
index 0000000..6095f67
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialAssignmentsPanel.cpp
@@ -0,0 +1,265 @@
+#include "MaterialAssignmentsPanel.h"
+#include "ui_MaterialAssignmentsPanel.h"
+#include "ProjectParams.h"
+#include "RenderMaterial.h"
+#include "SampleManager.h"
+#include "MaterialLibraryPanel.h"
+
+MaterialAssignmentsPanel* pMaterialAssignmentsPanel = nullptr;
+MaterialAssignmentsPanel* MaterialAssignmentsPanel::ins()
+{
+ return pMaterialAssignmentsPanel;
+}
+
+MaterialAssignmentsPanel::MaterialAssignmentsPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MaterialAssignmentsPanel),
+ _selectedGraphicsMesh(-1)
+{
+ ui->setupUi(this);
+ pMaterialAssignmentsPanel = this;
+ m_bValid = true;
+}
+
+void MaterialAssignmentsPanel::getMaterialNameAndPaths(std::vector<std::string>& materialNames, std::vector<std::string>& materialPaths)
+{
+ QString m1 = ui->comboBoxMaterialID1->currentText();
+ QString m2 = ui->comboBoxMaterialID2->currentText();
+ std::string name1 = m1.toUtf8().data();
+ std::string name2 = m2.toUtf8().data();
+ std::string path1 = "";
+ std::string path2 = "";
+
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPGraphicsMaterialArray& theArray = projectParams.graphicsMaterials;
+ int count = theArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPGraphicsMaterial& item = theArray.buf[i];
+ std::string name = item.name.buf;
+ std::string path = item.diffuseTextureFilePath.buf;
+ if (name1 == name)
+ {
+ path1 = path;
+ }
+ else if (name2 == name)
+ {
+ path2 = path;
+ }
+ else if (path1 != "" && path2 != "")
+ {
+ break;
+ }
+ }
+
+ materialNames.push_back(name1);
+ materialNames.push_back(name2);
+ materialPaths.push_back(path1);
+ materialPaths.push_back(path2);
+}
+
+MaterialAssignmentsPanel::~MaterialAssignmentsPanel()
+{
+ delete ui;
+}
+
+void MaterialAssignmentsPanel::updateValues()
+{
+ m_bValid = false;
+ ui->comboBoxMaterialID1->clear();
+ ui->comboBoxMaterialID2->clear();
+ m_bValid = true;
+
+ QStringList materialNames;
+ materialNames.append("None");
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPGraphicsMaterialArray& theArray = projectParams.graphicsMaterials;
+ int count = theArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ BPPGraphicsMaterial& item = theArray.buf[i];
+ materialNames.append(item.name.buf);
+ }
+
+ m_bValid = false;
+ ui->comboBoxMaterialID1->insertItems(0, materialNames);
+ ui->comboBoxMaterialID2->insertItems(0, materialNames);
+ m_bValid = true;
+
+ SampleManager* pSampleManager = SampleManager::ins();
+ if (pSampleManager == nullptr)
+ {
+ return;
+ }
+
+ BlastAsset* pBlastAsset = nullptr;
+ int index = -1;
+ pSampleManager->getCurrentSelectedInstance(&pBlastAsset, index);
+ if (pBlastAsset == nullptr || index == -1)
+ {
+ return;
+ }
+
+ RenderMaterial* pRenderMaterial[] = { nullptr, nullptr };
+ std::string strMaterialNames[] = { "None", "None" };
+ bool ex[] = { true, false };
+ for (int i = 0; i < 2; i++)
+ {
+ pSampleManager->getMaterialForCurrentFamily(&pRenderMaterial[i], ex[i]);
+ if (pRenderMaterial[i] != nullptr)
+ {
+ std::string m = pRenderMaterial[i]->getMaterialName();
+ if (m != "")
+ {
+ strMaterialNames[i] = m;
+ }
+ }
+ }
+
+ m_bValid = false;
+ ui->comboBoxMaterialID1->setCurrentText(strMaterialNames[0].c_str());
+ ui->comboBoxMaterialID2->setCurrentText(strMaterialNames[1].c_str());
+ m_bValid = true;
+
+ return;
+
+ if (_selectedGraphicsMesh > -1)
+ {
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPBlast& blast = projectParams.blast;
+ BPPGraphicsMaterialArray& graphicsMaterialsArray = projectParams.graphicsMaterials;
+
+ BPPMaterialAssignments& assignment = blast.graphicsMeshes.buf[_selectedGraphicsMesh].materialAssignments;
+
+ ui->comboBoxMaterialID1->clear();
+ ui->comboBoxMaterialID2->clear();
+ ui->comboBoxMaterialID3->clear();
+ ui->comboBoxMaterialID4->clear();
+
+ QStringList materialNames;
+ materialNames.append("None");
+ int count = graphicsMaterialsArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ materialNames.append(graphicsMaterialsArray.buf[i].name.buf);
+ }
+
+ ui->comboBoxMaterialID1->insertItems(0, materialNames);
+ ui->comboBoxMaterialID2->insertItems(0, materialNames);
+ ui->comboBoxMaterialID3->insertItems(0, materialNames);
+ ui->comboBoxMaterialID4->insertItems(0, materialNames);
+
+ ui->comboBoxMaterialID1->setCurrentIndex(assignment.materialIndexes[0] + 1);
+ ui->comboBoxMaterialID2->setCurrentIndex(assignment.materialIndexes[1] + 1);
+ ui->comboBoxMaterialID3->setCurrentIndex(assignment.materialIndexes[2] + 1);
+ ui->comboBoxMaterialID4->setCurrentIndex(assignment.materialIndexes[3] + 1);
+ }
+
+
+}
+
+void MaterialAssignmentsPanel::on_comboBoxMaterialID1_currentIndexChanged(int index)
+{
+ if (index < 0 || !m_bValid)
+ return;
+
+ RenderMaterial* pRenderMaterial = nullptr;
+
+ QString currentText = ui->comboBoxMaterialID1->currentText();
+ std::string name = currentText.toUtf8().data();
+
+ SampleManager* pSampleManager = SampleManager::ins();
+ if (pSampleManager == nullptr)
+ {
+ return;
+ }
+ std::map<std::string, RenderMaterial*>& renderMaterials = pSampleManager->getRenderMaterials();
+ std::map<std::string, RenderMaterial*>::iterator it = renderMaterials.find(name);
+ if (it != renderMaterials.end())
+ {
+ pRenderMaterial = it->second;
+ }
+ else
+ {
+ MaterialLibraryPanel* pMaterialLibraryPanel = MaterialLibraryPanel::ins();
+ std::map<std::string, RenderMaterial*>& renderMaterials2 = pMaterialLibraryPanel->getRenderMaterials();
+ it = renderMaterials2.find(name);
+ if (it != renderMaterials2.end())
+ {
+ pRenderMaterial = it->second;
+ }
+ }
+
+ pSampleManager->setMaterialForCurrentFamily(pRenderMaterial, true);
+
+ return;
+ assignMaterialToMaterialID(0, index - 1);
+}
+
+void MaterialAssignmentsPanel::on_comboBoxMaterialID2_currentIndexChanged(int index)
+{
+ if (index < 0 || !m_bValid)
+ return;
+
+ RenderMaterial* pRenderMaterial = nullptr;
+
+ QString currentText = ui->comboBoxMaterialID2->currentText();
+ std::string name = currentText.toUtf8().data();
+
+ SampleManager* pSampleManager = SampleManager::ins();
+ if (pSampleManager == nullptr)
+ {
+ return;
+ }
+ std::map<std::string, RenderMaterial*>& renderMaterials = pSampleManager->getRenderMaterials();
+ std::map<std::string, RenderMaterial*>::iterator it = renderMaterials.find(name);
+ if (it != renderMaterials.end())
+ {
+ pRenderMaterial = it->second;
+ }
+ else
+ {
+ MaterialLibraryPanel* pMaterialLibraryPanel = MaterialLibraryPanel::ins();
+ std::map<std::string, RenderMaterial*>& renderMaterials2 = pMaterialLibraryPanel->getRenderMaterials();
+ it = renderMaterials2.find(name);
+ if (it != renderMaterials2.end())
+ {
+ pRenderMaterial = it->second;
+ }
+ }
+
+ pSampleManager->setMaterialForCurrentFamily(pRenderMaterial, false);
+
+ return;
+ assignMaterialToMaterialID(1, index - 1);
+}
+
+void MaterialAssignmentsPanel::on_comboBoxMaterialID3_currentIndexChanged(int index)
+{
+ assignMaterialToMaterialID(2, index - 1);
+}
+
+void MaterialAssignmentsPanel::on_comboBoxMaterialID4_currentIndexChanged(int index)
+{
+ assignMaterialToMaterialID(3, index - 1);
+}
+
+void MaterialAssignmentsPanel::assignMaterialToMaterialID(int materialID, int materialIndex)
+{
+ if (materialID < 0 || materialID > 3 || materialIndex < 0)
+ return;
+
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPGraphicsMaterialArray& graphicsMaterialArray = projectParams.graphicsMaterials;
+ BPPBlast& blast = projectParams.blast;
+
+ if (materialIndex >= graphicsMaterialArray.arraySizes[0])
+ return;
+
+ BPPGraphicsMeshArray& graphicsMeshArray = blast.graphicsMeshes;
+
+ if (_selectedGraphicsMesh > -1 && _selectedGraphicsMesh < graphicsMeshArray.arraySizes[0])
+ {
+ graphicsMeshArray.buf[_selectedGraphicsMesh].materialAssignments.materialIndexes[materialID] = materialIndex;
+ }
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialAssignmentsPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialAssignmentsPanel.h
new file mode 100644
index 0000000..782baa8
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialAssignmentsPanel.h
@@ -0,0 +1,40 @@
+#ifndef MATERIALASSIGNMENTSPANEL_H
+#define MATERIALASSIGNMENTSPANEL_H
+
+#include <QtWidgets/QWidget>
+
+namespace Ui {
+class MaterialAssignmentsPanel;
+}
+
+class MaterialAssignmentsPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MaterialAssignmentsPanel(QWidget *parent = 0);
+ ~MaterialAssignmentsPanel();
+ void updateValues();
+
+ static MaterialAssignmentsPanel* ins();
+ void getMaterialNameAndPaths(std::vector<std::string>& materialNames, std::vector<std::string>& materialPaths);
+
+private slots:
+ void on_comboBoxMaterialID1_currentIndexChanged(int index);
+
+ void on_comboBoxMaterialID2_currentIndexChanged(int index);
+
+ void on_comboBoxMaterialID3_currentIndexChanged(int index);
+
+ void on_comboBoxMaterialID4_currentIndexChanged(int index);
+
+private:
+ void assignMaterialToMaterialID(int materialID, int materialIndex);
+
+private:
+ Ui::MaterialAssignmentsPanel *ui;
+ int _selectedGraphicsMesh;
+ bool m_bValid;
+};
+
+#endif // MATERIALASSIGNMENTSPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialLibraryPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialLibraryPanel.cpp
new file mode 100644
index 0000000..963326c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialLibraryPanel.cpp
@@ -0,0 +1,473 @@
+#include "MaterialLibraryPanel.h"
+#include "ui_MaterialLibraryPanel.h"
+#include <QtCore/QFileInfo>
+#include <QtWidgets/QInputDialog>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QMessageBox>
+#include "QtUtil.h"
+#include "AppMainWindow.h"
+#include "SimpleScene.h"
+#include "RenderMaterial.h"
+#include "ResourceManager.h"
+#include "SampleManager.h"
+#include "MaterialAssignmentsPanel.h"
+#include "Renderable.h"
+enum ETextureType
+{
+ eDiffuseTexture,
+ eSpecularTexture,
+ eNormalTexture
+};
+
+void OnTextureButtonClicked(BPPGraphicsMaterial& material, ETextureType t, QPushButton* pButton)
+{
+ QString texName = AppMainWindow::Inst().OpenTextureFile();
+
+ QFileInfo fileInfo(texName);
+ QByteArray ba = fileInfo.absoluteFilePath().toLocal8Bit();
+ const char* filePath = (const char*)(ba);
+
+ switch (t)
+ {
+ case eDiffuseTexture:
+ copy(material.diffuseTextureFilePath, filePath);
+ break;
+ case eSpecularTexture:
+ copy(material.specularTextureFilePath, filePath);
+ break;
+ case eNormalTexture:
+ copy(material.normalTextureFilePath, filePath);
+ break;
+ }
+
+ if (texName.isEmpty())
+ pButton->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ else
+ pButton->setIcon(QIcon(":/AppMainWindow/images/TextureIsUsed_icon.png"));
+
+ SimpleScene::Inst()->SetFurModified(true);
+}
+
+void OnTextureReload(BPPGraphicsMaterial& material, ETextureType t, QPushButton* pButton)
+{
+ QString texName;
+ switch (t)
+ {
+ case eDiffuseTexture:
+ texName = material.diffuseTextureFilePath.buf;
+ // to do: reload texture
+ break;
+ case eSpecularTexture:
+ texName = material.specularTextureFilePath.buf;
+ // to do: reload texture
+ break;
+ case eNormalTexture:
+ texName = material.normalTextureFilePath.buf;
+ // to do: reload texture
+ break;
+ }
+
+ if (texName.isEmpty())
+ pButton->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ else
+ pButton->setIcon(QIcon(":/AppMainWindow/images/TextureIsUsed_icon.png"));
+
+ SimpleScene::Inst()->SetFurModified(true);
+}
+
+void OnTextureClear(BPPGraphicsMaterial& material, ETextureType t, QPushButton* pButton)
+{
+ switch (t)
+ {
+ case eDiffuseTexture:
+ freeString(material.diffuseTextureFilePath);
+ // to do: clear texture
+ break;
+ case eSpecularTexture:
+ freeString(material.specularTextureFilePath);
+ // to do: clear texture
+ break;
+ case eNormalTexture:
+ freeString(material.normalTextureFilePath);
+ // to do: clear texture
+ break;
+ }
+
+ pButton->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+
+ SimpleScene::Inst()->SetFurModified(true);
+}
+
+MaterialLibraryPanel* pMaterialLibraryPanel = nullptr;
+MaterialLibraryPanel* MaterialLibraryPanel::ins()
+{
+ return pMaterialLibraryPanel;
+}
+
+void MaterialLibraryPanel::addMaterial(std::string materialName, std::string diffuseTexture)
+{
+ if (!BlastProject::ins().isGraphicsMaterialNameExist(materialName.c_str()))
+ {
+ BlastProject::ins().addGraphicsMaterial(materialName.c_str(), diffuseTexture.c_str());
+ updateValues();
+ ui->listWidget->setCurrentRow(ui->listWidget->count() - 1);
+ }
+}
+
+void MaterialLibraryPanel::removeMaterial(std::string name)
+{
+ BlastProject::ins().removeGraphicsMaterial(name.c_str());
+ updateValues();
+ ui->listWidget->setCurrentRow(ui->listWidget->count() - 1);
+}
+
+void MaterialLibraryPanel::deleteMaterials()
+{
+ std::vector<std::string>::iterator itStr;
+ std::vector<Renderable*>::iterator itRenderable;
+
+ for (itStr = m_NeedDeleteRenderMaterials.begin(); itStr != m_NeedDeleteRenderMaterials.end(); itStr++)
+ {
+ std::string materialName = *itStr;
+ RenderMaterial* pRenderMaterial = m_RenderMaterialMap[materialName];
+ std::vector<Renderable*>& renderables = pRenderMaterial->getRelatedRenderables();
+ for (itRenderable = renderables.begin(); itRenderable != renderables.end(); itRenderable++)
+ {
+ Renderable* pRenderable = *itRenderable;
+ pRenderable->setMaterial(*RenderMaterial::getDefaultRenderMaterial());
+ }
+
+ std::map<std::string, RenderMaterial*>::iterator it = m_RenderMaterialMap.find(materialName);
+ if (it != m_RenderMaterialMap.end())
+ {
+ m_RenderMaterialMap.erase(it);
+ MaterialLibraryPanel::ins()->removeMaterial(materialName);
+ }
+ }
+
+ m_NeedDeleteRenderMaterials.clear();
+}
+
+MaterialLibraryPanel::MaterialLibraryPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MaterialLibraryPanel)
+{
+ ui->setupUi(this);
+
+ pMaterialLibraryPanel = this;
+}
+
+MaterialLibraryPanel::~MaterialLibraryPanel()
+{
+ delete ui;
+}
+
+void MaterialLibraryPanel::updateValues()
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPGraphicsMaterialArray& graphicsMaterialArray = projectParams.graphicsMaterials;
+
+ ui->listWidget->clear();
+ QStringList materialNames;
+ int count = graphicsMaterialArray.arraySizes[0];
+ for (int i = 0; i < count; ++i)
+ {
+ materialNames.append(graphicsMaterialArray.buf[i].name.buf);
+ }
+ ui->listWidget->addItems(materialNames);
+
+ if (count > 0)
+ {
+ ui->btnModifyMat->setEnabled(true);
+ ui->btnRemoveMat->setEnabled(true);
+ }
+ else
+ {
+ ui->btnModifyMat->setEnabled(false);
+ ui->btnRemoveMat->setEnabled(false);
+ }
+
+ MaterialAssignmentsPanel::ins()->updateValues();
+}
+
+void MaterialLibraryPanel::on_btnAddMat_clicked()
+{
+ bool ok = false;
+ QString name = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input name for new graphics material:"),
+ QLineEdit::Normal,
+ "",
+ &ok);
+ bool nameExist = BlastProject::ins().isGraphicsMaterialNameExist(name.toUtf8().data());
+ if (ok && !name.isEmpty() && !nameExist)
+ {
+ ResourceManager* pResourceManager = ResourceManager::ins();
+ std::string strName = name.toUtf8().data();
+ RenderMaterial* pRenderMaterial = new RenderMaterial(strName.c_str(), *pResourceManager, "model_simple_textured_ex");
+ m_RenderMaterialMap[strName] = pRenderMaterial;
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && name.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the new graphics material!");
+ }
+}
+
+void MaterialLibraryPanel::on_btnModifyMat_clicked()
+{
+ QList<QListWidgetItem*> items = ui->listWidget->selectedItems();
+ if (items.size() == 0)
+ {
+ SampleManager::ins()->output("please select a material first !");
+ return;
+ }
+ QByteArray tmp = items.at(0)->text().toUtf8();
+ const char* oldName = tmp.data();
+
+ bool ok = false;
+ QString newName = QInputDialog::getText(this,
+ tr("Blast Tool"),
+ tr("Please input new name for the selected graphics material:"),
+ QLineEdit::Normal,
+ oldName,
+ &ok);
+ bool nameExist = BlastProject::ins().isGraphicsMaterialNameExist(newName.toUtf8().data());
+ if (ok && !newName.isEmpty() && !nameExist)
+ {
+ std::string strOldName = oldName;
+ std::string strNewName = newName.toUtf8().data();
+
+ std::map<std::string, RenderMaterial*>::iterator it = m_RenderMaterialMap.find(strOldName);
+ if (it != m_RenderMaterialMap.end())
+ {
+ RenderMaterial* pRenderMaterial = it->second;
+ m_RenderMaterialMap.erase(it);
+ m_RenderMaterialMap[strNewName] = pRenderMaterial;
+ }
+
+ SampleManager::ins()->renameRenderMaterial(strOldName, strNewName);
+
+ BlastProject::ins().renameGraphicsMaterial(oldName, newName.toUtf8().data());
+ updateValues();
+ }
+ else if (ok && nameExist)
+ {
+ QMessageBox::warning(this, "Blast Tool", "The name you input is already exist!");
+ }
+ else if (ok && newName.isEmpty())
+ {
+ QMessageBox::warning(this, "Blast Tool", "You need input a name for the selected graphics material!");
+ }
+}
+
+void MaterialLibraryPanel::on_btnRemoveMat_clicked()
+{
+ QList<QListWidgetItem*> items = ui->listWidget->selectedItems();
+ if (items.size() == 0)
+ {
+ SampleManager::ins()->output("please select a material first !");
+ return;
+ }
+ QByteArray tem = items.at(0)->text().toUtf8();
+
+ std::string strName = tem.data();
+ std::map<std::string, RenderMaterial*>::iterator it = m_RenderMaterialMap.find(strName);
+ if (it != m_RenderMaterialMap.end())
+ {
+ m_NeedDeleteRenderMaterials.push_back(it->second->getMaterialName());
+ }
+ else
+ {
+ SampleManager::ins()->deleteRenderMaterial(strName);
+ }
+}
+
+void MaterialLibraryPanel::on_listWidget_currentRowChanged(int currentRow)
+{
+ _refreshMaterialValues(currentRow);
+}
+
+void MaterialLibraryPanel::on_btnDiffuseColor_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ atcore_float4* color = (atcore_float4*)&(material->diffuseColor);
+ pickColor(*color);
+ setButtonColor(ui->btnDiffuseColor, color->x, color->y, color->z);
+ }
+}
+
+void MaterialLibraryPanel::on_btnDiffuseColorTex_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ OnTextureButtonClicked(*material, eDiffuseTexture, ui->btnDiffuseColorTex);
+ }
+}
+
+void MaterialLibraryPanel::on_btnDiffuseColorTexReload_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ OnTextureReload(*material, eDiffuseTexture, ui->btnDiffuseColorTex);
+
+ QString qName = material->name.buf;
+ std::string strName = qName.toUtf8().data();
+ QString qTexture = material->diffuseTextureFilePath.buf;
+ std::string strTexture = qTexture.toUtf8().data();
+
+ std::map<std::string, RenderMaterial*>& renderMaterials = SampleManager::ins()->getRenderMaterials();
+ std::map<std::string, RenderMaterial*>::iterator it = renderMaterials.find(strName);
+ if (it != renderMaterials.end())
+ {
+ it->second->setTextureFileName(strTexture);
+ }
+ }
+}
+
+void MaterialLibraryPanel::on_btnDiffuseColorTexClear_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ OnTextureClear(*material, eDiffuseTexture, ui->btnDiffuseColorTex);
+
+ QString qName = material->name.buf;
+ std::string strName = qName.toUtf8().data();
+ QString qTexture = material->diffuseTextureFilePath.buf;
+ std::string strTexture = qTexture.toUtf8().data();
+
+ std::map<std::string, RenderMaterial*>& renderMaterials = SampleManager::ins()->getRenderMaterials();
+ std::map<std::string, RenderMaterial*>::iterator it = renderMaterials.find(strName);
+ if (it != renderMaterials.end())
+ {
+ it->second->setTextureFileName(strTexture);
+ }
+ }
+}
+
+void MaterialLibraryPanel::on_btnSpecularColor_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ atcore_float4* color = (atcore_float4*)&(material->specularColor);
+ pickColor(*color);
+ setButtonColor(ui->btnSpecularColor, color->x, color->y, color->z);
+ }
+}
+
+void MaterialLibraryPanel::on_btnSpecularColorTex_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ OnTextureButtonClicked(*material, eSpecularTexture, ui->btnSpecularColorTex);
+ }
+}
+
+void MaterialLibraryPanel::on_btnSpecularColorTexReload_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ OnTextureReload(*material, eSpecularTexture, ui->btnSpecularColorTex);
+ }
+}
+
+void MaterialLibraryPanel::on_btnSpecularColorTexClear_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ OnTextureClear(*material, eSpecularTexture, ui->btnSpecularColorTex);
+ }
+}
+
+void MaterialLibraryPanel::on_spinSpecularShin_valueChanged(double arg1)
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ material->specularShininess = (float)arg1;
+ }
+}
+
+void MaterialLibraryPanel::on_btnNormalColorTex_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ OnTextureButtonClicked(*material, eNormalTexture, ui->btnNormalColorTex);
+ }
+}
+
+void MaterialLibraryPanel::on_btnNormalColorTexReload_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ OnTextureReload(*material, eNormalTexture, ui->btnNormalColorTex);
+ }
+}
+
+void MaterialLibraryPanel::on_btnNormalColorTexClear_clicked()
+{
+ BPPGraphicsMaterial* material = _getSelectedMaterial();
+ if (material)
+ {
+ OnTextureClear(*material, eNormalTexture, ui->btnNormalColorTex);
+ }
+}
+
+void MaterialLibraryPanel::_refreshMaterialValues(int idx)
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPGraphicsMaterialArray& graphicsMaterialArray = projectParams.graphicsMaterials;
+ int count = graphicsMaterialArray.arraySizes[0];
+ if (idx >= 0 && idx < count)
+ {
+ const BPPGraphicsMaterial& material = graphicsMaterialArray.buf[idx];
+
+ ui->spinSpecularShin->setValue(material.specularShininess);
+
+ const nvidia::NvVec4& diffuseColor = material.diffuseColor;
+ const nvidia::NvVec4& specularColor = material.specularColor;
+ setButtonColor(ui->btnDiffuseColor, diffuseColor.x, diffuseColor.y, diffuseColor.z);
+ setButtonColor(ui->btnSpecularColor, specularColor.x, specularColor.y, specularColor.z);
+
+ updateTextureButton(ui->btnDiffuseColorTex, material.diffuseTextureFilePath.buf);
+ updateTextureButton(ui->btnSpecularColorTex, material.specularTextureFilePath.buf);
+ updateTextureButton(ui->btnNormalColorTex, material.normalTextureFilePath.buf);
+ }
+ else
+ {
+ ui->spinSpecularShin->setValue(0.0f);
+
+ setButtonColor(ui->btnDiffuseColor, 0, 0, 0);
+ setButtonColor(ui->btnSpecularColor, 0, 0, 0);
+ updateTextureButton(ui->btnDiffuseColorTex, "");
+ updateTextureButton(ui->btnSpecularColorTex, "");
+ updateTextureButton(ui->btnNormalColorTex, "");
+ }
+}
+
+BPPGraphicsMaterial* MaterialLibraryPanel::_getSelectedMaterial()
+{
+ BPParams& projectParams = BlastProject::ins().getParams();
+ BPPGraphicsMaterialArray& graphicsMaterialArray = projectParams.graphicsMaterials;
+
+ int idx = ui->listWidget->currentRow();
+ int count = graphicsMaterialArray.arraySizes[0];
+ if (idx < 0 || idx > count)
+ return nullptr;
+
+ return &(graphicsMaterialArray.buf[idx]);
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialLibraryPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialLibraryPanel.h
new file mode 100644
index 0000000..5c2c970
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/MaterialLibraryPanel.h
@@ -0,0 +1,72 @@
+#ifndef MATERIALLIBRARYPANEL_H
+#define MATERIALLIBRARYPANEL_H
+
+#include <QtWidgets/QWidget>
+#include "ProjectParams.h"
+
+class RenderMaterial;
+
+namespace Ui {
+class MaterialLibraryPanel;
+}
+
+class MaterialLibraryPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MaterialLibraryPanel(QWidget *parent = 0);
+ ~MaterialLibraryPanel();
+ void updateValues();
+
+ static MaterialLibraryPanel* ins();
+ void addMaterial(std::string materialName, std::string diffuseTexture);
+ void removeMaterial(std::string name);
+ std::map<std::string, RenderMaterial*>& getRenderMaterials(){ return m_RenderMaterialMap; }
+ void deleteMaterials();
+
+private slots:
+ void on_btnAddMat_clicked();
+
+ void on_btnModifyMat_clicked();
+
+ void on_btnRemoveMat_clicked();
+
+ void on_listWidget_currentRowChanged(int currentRow);
+
+ void on_btnDiffuseColor_clicked();
+
+ void on_btnDiffuseColorTex_clicked();
+
+ void on_btnDiffuseColorTexReload_clicked();
+
+ void on_btnDiffuseColorTexClear_clicked();
+
+ void on_btnSpecularColor_clicked();
+
+ void on_btnSpecularColorTex_clicked();
+
+ void on_btnSpecularColorTexReload_clicked();
+
+ void on_btnSpecularColorTexClear_clicked();
+
+ void on_spinSpecularShin_valueChanged(double arg1);
+
+ void on_btnNormalColorTex_clicked();
+
+ void on_btnNormalColorTexReload_clicked();
+
+ void on_btnNormalColorTexClear_clicked();
+
+private:
+ void _refreshMaterialValues(int idx);
+ BPPGraphicsMaterial* _getSelectedMaterial();
+
+ std::map<std::string, RenderMaterial*> m_RenderMaterialMap;
+ std::vector<std::string> m_NeedDeleteRenderMaterials;
+
+private:
+ Ui::MaterialLibraryPanel *ui;
+};
+
+#endif // MATERIALLIBRARYPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/NoiseToolsDlg.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/NoiseToolsDlg.cpp
new file mode 100644
index 0000000..748002c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/NoiseToolsDlg.cpp
@@ -0,0 +1,39 @@
+#include "NoiseToolsDlg.h"
+#include "ui_NoiseToolsDlg.h"
+
+NoiseToolsDlg::NoiseToolsDlg(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::NoiseToolsDlg)
+{
+ ui->setupUi(this);
+}
+
+NoiseToolsDlg::~NoiseToolsDlg()
+{
+ delete ui;
+}
+
+void NoiseToolsDlg::on_comboBoxApplyByMaterial_currentIndexChanged(int index)
+{
+
+}
+
+void NoiseToolsDlg::on_spinBoxAmplitude_valueChanged(double arg1)
+{
+
+}
+
+void NoiseToolsDlg::on_spinBoxFrequency_valueChanged(double arg1)
+{
+
+}
+
+void NoiseToolsDlg::on_spinBoxAmplitude_3_valueChanged(double arg1)
+{
+
+}
+
+void NoiseToolsDlg::on_btnApply_clicked()
+{
+
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/NoiseToolsDlg.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/NoiseToolsDlg.h
new file mode 100644
index 0000000..057dd42
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/NoiseToolsDlg.h
@@ -0,0 +1,33 @@
+#ifndef NOISETOOLSDLG_H
+#define NOISETOOLSDLG_H
+
+#include <QtWidgets/QDialog>
+
+namespace Ui {
+class NoiseToolsDlg;
+}
+
+class NoiseToolsDlg : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit NoiseToolsDlg(QWidget *parent = 0);
+ ~NoiseToolsDlg();
+
+private slots:
+ void on_comboBoxApplyByMaterial_currentIndexChanged(int index);
+
+ void on_spinBoxAmplitude_valueChanged(double arg1);
+
+ void on_spinBoxFrequency_valueChanged(double arg1);
+
+ void on_spinBoxAmplitude_3_valueChanged(double arg1);
+
+ void on_btnApply_clicked();
+
+private:
+ Ui::NoiseToolsDlg *ui;
+};
+
+#endif // NOISETOOLSDLG_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/QtUtil.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/QtUtil.cpp
new file mode 100644
index 0000000..b2fdd75
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/QtUtil.cpp
@@ -0,0 +1,155 @@
+#include "QtUtil.h"
+
+#include <QtWidgets/QLabel>
+#include "AppMainWindow.h"
+
+#include "SimpleScene.h"
+
+//////////////////////////////////////////////////////////
+void setStyledToolTip(QPushButton *pButton, const char *tooltip)
+{
+ char styledString[1024];
+ sprintf(styledString, "<span style=\"color:black;\">%s</span>", tooltip);
+ pButton->setToolTip(styledString);
+}
+
+//////////////////////////////////////////////////////////
+QString addStar(QString text, bool add)
+{
+ QByteArray ba = text.toUtf8();
+
+ const char* in = ba.data();
+ char out[1024];
+
+ int i = 0;
+ for (i = 0; i < strlen(in); i++)
+ {
+ if (in[i] == '*')
+ break;
+ out[i] = in[i];
+ }
+ out[i] = 0;
+
+ QString newtext;
+ if (add)
+ newtext = QString((const char*)out) + QString("*");
+ else
+ newtext = QString((const char*)out) ;
+ return newtext;
+}
+
+//////////////////////////////////////////////////////////
+void setFocusColor(QWidget* qWidget, bool sameAsDefault, bool sameForAllAssets)
+{
+ if (!qWidget)
+ return;
+
+ QString sameStyle = QString("font: ; color: rgb(150,150,150);") ;
+ QString differentStyle = QString("font: bold; color: rgb(255,55,55);");
+ QString style = (sameForAllAssets) ? sameStyle : differentStyle;
+
+ qWidget->setStyleSheet(style);
+
+ QLabel* label = dynamic_cast<QLabel*>(qWidget);
+ if (label)
+ {
+ QString newtext = addStar(label->text(), !sameAsDefault);
+
+ label->setFrameStyle(0);
+ label->setText(newtext);
+ }
+}
+
+//////////////////////////////////////////////////////////
+void pickColor(atcore_float4& color)
+{
+ QColor currentColor;
+ currentColor.setRgbF(color.x, color.y, color.z);
+
+ QColor newColor = QColorDialog::getColor(currentColor, NV_NULL);
+ if(newColor.isValid())
+ {
+ qreal r,g,b;
+ newColor.getRgbF(&r, &g, &b);
+
+ color.x = r;
+ color.y = g;
+ color.z = b;
+ }
+}
+
+//////////////////////////////////////////////////////////
+void setButtonColor(QPushButton *button, float r, float g, float b)
+{
+ QColor specColor;
+ specColor.setRgbF(r,g,b);
+ QString specBtnStyle = QString("background-color: rgb(%1,%2,%3);")
+ .arg(specColor.red())
+ .arg(specColor.green())
+ .arg(specColor.blue());
+
+ button->setStyleSheet(specBtnStyle);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+void updateColorButton(QPushButton* button, int paramID, QLabel* label)
+{
+ //atcore_float4 v;
+ //SimpleScene::Inst()->GetFurCharacter().GetHairParam(paramID, &v);
+
+ //setButtonColor(button, v.x, v.y, v.z);
+
+ //if (label)
+ // setFocusColor(label, paramID);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+void setClearButtonIcon(QPushButton *pButton)
+{
+ pButton->setIcon(QIcon(":/AppMainWindow/images/Remove_icon.png"));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+void setTextureButtons(QPushButton *pTex, QPushButton *pReload, QPushButton *pClear)
+{
+ pTex->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ pReload->setIcon(QIcon(":/AppMainWindow/images/Refresh_icon.png"));
+ pClear->setIcon(QIcon(":/AppMainWindow/images/Remove_icon.png"));
+
+ pTex->setIconSize(QSize(12,12));
+ pReload->setIconSize(QSize(12,12));
+ pClear->setIconSize(QSize(12,12));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+void updateTextureButton(QPushButton* pButton, const QString& texturePath)
+{
+ if (!texturePath.isEmpty()) setStyledToolTip(pButton, texturePath.toUtf8().data());
+
+ bool isTextureUsed = true;
+ QIcon notUsedIcon = QIcon(":/AppMainWindow/images/TextureEnabled_icon.png");
+ QIcon isUsedIcon = QIcon(":/AppMainWindow/images/TextureIsUsed_icon.png");
+ QIcon disabledIcon = QIcon(":/AppMainWindow/images/TextureDisabled_icon.png");
+
+ pButton->setIcon(!texturePath.isEmpty() ? isUsedIcon : notUsedIcon);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+//bool LoadHairTexture(NvHair::TextureType::Enum textureType)
+//{
+// QString texName = AppMainWindow::Inst().OpenTextureFile();
+// return SimpleScene::Inst()->GetFurCharacter().LoadHairTexture(textureType, texName.toLocal8Bit());
+//}
+//
+///////////////////////////////////////////////////////////////////////////////////////
+//bool ReloadHairTexture(NvHair::TextureType::Enum textureType)
+//{
+// return SimpleScene::Inst()->GetFurCharacter().ReloadHairTexture(textureType);
+//}
+//
+///////////////////////////////////////////////////////////////////////////////////////
+//bool ClearHairTexture(NvHair::TextureType::Enum textureType)
+//{
+// return SimpleScene::Inst()->GetFurCharacter().ClearHairTexture(textureType);
+//}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/QtUtil.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/QtUtil.h
new file mode 100644
index 0000000..2372b06
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/QtUtil.h
@@ -0,0 +1,37 @@
+#ifndef QtUtil_h__
+#define QtUtil_h__
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtWidgets/QColorDialog>
+#include <QtGui/QPalette>
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QSpinBox>
+#include <QtWidgets/QDoubleSpinBox>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QComboBox>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QSlider>
+#include "corelib_global.h"
+
+// utility functions to quickly set and update UI
+
+void setStyledToolTip(QPushButton *pButton, const char *tooltip);
+void pickColor(atcore_float4& color);
+void setButtonColor(QPushButton *button, float r, float g, float b);
+
+void setFocusColor(QWidget* qWidget, bool sameAsDefault, bool sameForAllAssets);
+
+void updateColorButton(QPushButton* pButton, int paramID, QLabel* label = 0);
+
+void setTextureButtons(QPushButton *pButton, QPushButton *pReload, QPushButton *pClear);
+void updateTextureButton(QPushButton* pButton, const QString& texturePath);
+
+void setClearButtonIcon(QPushButton *pButton);
+
+//bool LoadHairTexture(NvHair::TextureType::Enum textureType);
+//bool ReloadHairTexture(NvHair::TextureType::Enum textureType);
+//bool ClearHairTexture(NvHair::TextureType::Enum textureType);
+
+#endif
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SourceAssetOpenDlg.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SourceAssetOpenDlg.cpp
new file mode 100644
index 0000000..db40407
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SourceAssetOpenDlg.cpp
@@ -0,0 +1,82 @@
+#include "SourceAssetOpenDlg.h"
+#include "ui_SourceAssetOpenDlg.h"
+#include <QtWidgets/QFileDialog>
+#include "AppMainWindow.h"
+
+SourceAssetOpenDlg::SourceAssetOpenDlg(bool bOpenBlastFile, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::SourceAssetOpenDlg)
+{
+ ui->setupUi(this);
+
+ m_bOpenBlastFile = bOpenBlastFile;
+ ui->buttonBox->button(QDialogButtonBox::Ok)->setFixedWidth(100);
+ ui->buttonBox->button(QDialogButtonBox::Cancel)->setFixedWidth(100);
+ ui->spinBoxDegree->setMaximum(180);
+ ui->spinBoxDegree->setMinimum(-180);
+}
+
+SourceAssetOpenDlg::~SourceAssetOpenDlg()
+{
+ delete ui;
+}
+
+QString SourceAssetOpenDlg::getFile()
+{
+ return ui->lineEditFile->text();
+}
+
+bool SourceAssetOpenDlg::getSkinned()
+{
+ return ui->checkBoxSkinned->isChecked();
+}
+
+QVector3D SourceAssetOpenDlg::getPosition()
+{
+ return QVector3D(ui->spinBoxXPosition->value(), ui->spinBoxYPosition->value(), ui->spinBoxZPosition->value());
+}
+
+QVector3D SourceAssetOpenDlg::getRotationAxis()
+{
+ return QVector3D(ui->spinBoxXAxis->value(), ui->spinBoxYAxis->value(), ui->spinBoxZAxis->value());
+}
+
+double SourceAssetOpenDlg::getRotationDegree()
+{
+ return ui->spinBoxDegree->value();
+}
+
+bool SourceAssetOpenDlg::isAppend()
+{
+ return ui->checkBoxAppend->isChecked();
+}
+
+void SourceAssetOpenDlg::on_btnOpenFile_clicked()
+{
+ QString lastDir = AppMainWindow::Inst()._lastFilePath;
+ QString titleStr = "Open Source Asset File";
+
+ QString filetype = "Source Asset (*.fbx)";
+ if (m_bOpenBlastFile)
+ {
+ filetype = "Source Asset (*.bpxa)";
+ }
+ QString fileName = QFileDialog::getOpenFileName(this, titleStr, lastDir, filetype);
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ AppMainWindow::Inst()._lastFilePath = fileInfo.absoluteDir().absolutePath();
+ }
+
+ ui->lineEditFile->setText(fileName);
+}
+
+void SourceAssetOpenDlg::on_buttonBox_accepted()
+{
+
+}
+
+void SourceAssetOpenDlg::on_buttonBox_rejected()
+{
+
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SourceAssetOpenDlg.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SourceAssetOpenDlg.h
new file mode 100644
index 0000000..ec03ee9
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SourceAssetOpenDlg.h
@@ -0,0 +1,38 @@
+#ifndef SOURCEASSETOPENDLG_H
+#define SOURCEASSETOPENDLG_H
+
+#include <QtWidgets/QDialog>
+#include <QtGui/QVector3D>
+
+namespace Ui {
+class SourceAssetOpenDlg;
+}
+
+class SourceAssetOpenDlg : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit SourceAssetOpenDlg(bool bOpenBlastFile = true, QWidget *parent = 0);
+ ~SourceAssetOpenDlg();
+
+ QString getFile();
+ bool getSkinned();
+ QVector3D getPosition();
+ QVector3D getRotationAxis();
+ double getRotationDegree();
+ bool isAppend();
+
+private slots:
+ void on_btnOpenFile_clicked();
+
+ void on_buttonBox_accepted();
+
+ void on_buttonBox_rejected();
+
+private:
+ Ui::SourceAssetOpenDlg *ui;
+ bool m_bOpenBlastFile;
+};
+
+#endif // SOURCEASSETOPENDLG_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SupportPanel.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SupportPanel.cpp
new file mode 100644
index 0000000..1057402
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SupportPanel.cpp
@@ -0,0 +1,49 @@
+#include "SupportPanel.h"
+#include "ui_SupportPanel.h"
+
+SupportPanel::SupportPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::SupportPanel)
+{
+ ui->setupUi(this);
+}
+
+SupportPanel::~SupportPanel()
+{
+ delete ui;
+}
+
+void SupportPanel::updateValues()
+{
+
+}
+
+void SupportPanel::on_comboBoxHealthMask_currentIndexChanged(int index)
+{
+
+}
+
+void SupportPanel::on_btnAddHealthMask_clicked()
+{
+
+}
+
+void SupportPanel::on_btnPen_clicked()
+{
+
+}
+
+void SupportPanel::on_btnRemove_clicked()
+{
+
+}
+
+void SupportPanel::on_spinBoxBondStrength_valueChanged(double arg1)
+{
+
+}
+
+void SupportPanel::on_checkBoxEnableJoint_stateChanged(int arg1)
+{
+
+}
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SupportPanel.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SupportPanel.h
new file mode 100644
index 0000000..518d2cd
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/SupportPanel.h
@@ -0,0 +1,36 @@
+#ifndef SUPPORTPANEL_H
+#define SUPPORTPANEL_H
+
+#include <QtWidgets/QWidget>
+
+namespace Ui {
+class SupportPanel;
+}
+
+class SupportPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit SupportPanel(QWidget *parent = 0);
+ ~SupportPanel();
+ void updateValues();
+
+private slots:
+ void on_comboBoxHealthMask_currentIndexChanged(int index);
+
+ void on_btnAddHealthMask_clicked();
+
+ void on_btnPen_clicked();
+
+ void on_btnRemove_clicked();
+
+ void on_spinBoxBondStrength_valueChanged(double arg1);
+
+ void on_checkBoxEnableJoint_stateChanged(int arg1);
+
+private:
+ Ui::SupportPanel *ui;
+};
+
+#endif // SUPPORTPANEL_H
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/blastplugin_global.h b/NvBlast/tools/ArtistTools/source/BlastPlugin/blastplugin_global.h
new file mode 100644
index 0000000..082519a
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/blastplugin_global.h
@@ -0,0 +1,11 @@
+#ifdef PLUGINBT_LIB
+# define PLUGINBT_EXPORT Q_DECL_EXPORT
+#else
+# define PLUGINBT_EXPORT Q_DECL_IMPORT
+#endif
+
+#ifdef PLUGINBTRENDER_LIB
+# define PLUGINBTRENDER_EXPORT Q_DECL_EXPORT
+#else
+# define PLUGINBTRENDER_EXPORT Q_DECL_IMPORT
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Anim/AnimUtil.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Anim/AnimUtil.cpp
new file mode 100644
index 0000000..5ab1563
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Anim/AnimUtil.cpp
@@ -0,0 +1,419 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// This file contains wrapper functions to make hair lib easy to setup and use
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#include <vector>
+#include <string>
+
+#include "AnimUtil.h"
+#include "MathUtil.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AnimationCache::~AnimationCache()
+{
+ Release();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AnimationCache::Initialize(int numBones, NvInt32 frameStart, NvInt32 frameEnd)
+{
+ m_numBones = numBones;
+ m_frameStart = frameStart;
+ m_frameEnd = frameEnd;
+
+ m_numFrames = frameEnd - frameStart + 1;
+
+ Release();
+ Allocate();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AnimationCache::Allocate()
+{
+ m_pBoneMatrices = new atcore_float4x4[m_numFrames * m_numBones];
+// m_pBoneNames = new char[NV_HAIR_MAX_STRING * m_numBones];
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AnimationCache::Release()
+{
+ if (m_pBoneMatrices)
+ delete []m_pBoneMatrices;
+
+ if (m_pBoneNames)
+ delete []m_pBoneNames;
+
+ m_pBoneMatrices = 0;
+ m_pBoneNames = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AnimationCache::GetInterpolationInfo(float frame, int& indexStart, int& indexEnd, float &fracFrame)
+{
+ if (frame < m_frameStart)
+ return false;
+
+ if (frame > m_frameEnd)
+ return false;
+
+ int startFrame = (int)frame;
+
+ fracFrame = frame - startFrame;
+
+ indexStart = (int)(frame - m_frameStart);
+ indexEnd = indexStart + 1;
+
+ if (indexEnd >= (int)m_numFrames)
+ {
+ indexEnd = indexStart;
+ fracFrame = 0.0f;
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+int AnimationCache::FindBone(const char *toFind) const
+{
+ if (!toFind)
+ return -1;
+ /*
+ for (int i = 0; i < m_numBones; i++)
+ {
+ const char* boneName = GetBoneName(i);
+ if (!strcmp(boneName, toFind))
+ return i;
+ }
+ */
+ return -1;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AnimationCache::FindBoneMapping( int numBones, const NvChar* boneNames, int* mappedBoneId) const
+{
+ // mappedBoneId must be pre-allocated
+
+ for (int i = 0; i < numBones; i++)
+ {
+ //mappedBoneId[i] = FindBone(boneNames + i * NV_HAIR_MAX_STRING);
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void BoneData::Allocate(NvUInt32 numBones)
+{
+ Release();
+
+ m_numBones = numBones;
+
+ m_pPoseMatrices = new atcore_float4x4[numBones];
+ m_pSkinMatrices = new atcore_float4x4[numBones];
+ m_pBoneMatrices = new atcore_float4x4[numBones];
+
+ m_pSkinDQs = new atcore_dualquaternion[numBones];
+ //m_pBoneNames = new char[NV_HAIR_MAX_STRING * m_numBones];
+ m_pMappedBoneId = new int[numBones];
+
+ for (int i = 0; i < numBones; i++)
+ {
+ gfsdk_makeIdentity(m_pPoseMatrices[i]);
+ gfsdk_makeIdentity(m_pSkinMatrices[i]);
+ m_pMappedBoneId[i] = -1;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void BoneData::Release()
+{
+ if (m_pPoseMatrices)
+ {
+ delete []m_pPoseMatrices;
+ m_pPoseMatrices = 0;
+ }
+
+ if (m_pBoneMatrices)
+ {
+ delete []m_pBoneMatrices;
+ m_pBoneMatrices = 0;
+ }
+
+ if (m_pSkinMatrices)
+ {
+ delete []m_pSkinMatrices;
+ m_pSkinMatrices = 0;
+ }
+
+ if (m_pSkinDQs)
+ {
+ delete []m_pSkinDQs;
+ m_pSkinDQs = 0;
+ }
+
+ if (m_pBoneNames)
+ {
+ delete []m_pBoneNames;
+ m_pBoneNames = 0;
+ }
+
+ if (m_pMappedBoneId)
+ {
+ delete []m_pMappedBoneId;
+ m_pMappedBoneId = 0;
+ }
+
+ m_numBones = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void BoneData::InitializeAnimationCache(AnimationCache* pGlobalCache, const char* nodeName)
+{
+ if (!pGlobalCache || !pGlobalCache->isValid())
+ return;
+
+ pGlobalCache->FindBoneMapping(m_numBones, m_pBoneNames, m_pMappedBoneId);
+
+ m_nodeId = pGlobalCache->FindBone(nodeName);
+
+ m_pAnimationCache = pGlobalCache;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool BoneData::Update(float frameTime, const char* rootBoneName, bool bindPose, bool zup)
+{
+ if (!m_pAnimationCache || !m_pAnimationCache->isValid() )
+ bindPose = true;
+
+ atcore_float4x4 model;
+ gfsdk_makeIdentity(model);
+
+ if (bindPose)
+ {
+ for (int i = 0; i < m_numBones; i++)
+ {
+ m_pBoneMatrices[i] = m_pPoseMatrices[i];
+ m_pSkinMatrices[i] = model;
+ m_pSkinDQs[i] = gfsdk_makeDQ(m_pSkinMatrices[i]);
+ }
+ return true;
+ }
+
+ int indexStart, indexEnd;
+ float fracFrame = 0.0f;
+ if (false == m_pAnimationCache->GetInterpolationInfo(frameTime, indexStart, indexEnd, fracFrame))
+ return false;
+
+ atcore_float4x4* pBoneStart = m_pAnimationCache->GetNodeMatrices(indexStart);
+ atcore_float4x4* pBoneEnd = m_pAnimationCache->GetNodeMatrices(indexEnd);
+
+ int numBones = m_numBones;
+
+ atcore_float4x4 root;
+ gfsdk_makeIdentity(root);
+
+ if (rootBoneName)
+ {
+ int rootIndex = m_pAnimationCache->FindBone(rootBoneName);
+
+ if (rootIndex >= 0)
+ {
+ root = gfsdk_lerp(pBoneStart[rootIndex], pBoneEnd[rootIndex], fracFrame);
+
+ atcore_float3 lT = gfsdk_getTranslation(root);
+
+ if (zup)
+ lT.z = 0;
+ else
+ lT.y = 0;
+
+ gfsdk_makeIdentity(root);
+ gfsdk_setTranslation(root, -1.0f * lT);
+ }
+ }
+
+ // interpolate skinning matrix
+ for (int i = 0; i < numBones; i++)
+ {
+ atcore_float4x4 bone;
+
+ int index = m_pMappedBoneId[i];
+ if (index >= 0)
+ bone = gfsdk_lerp(pBoneStart[index], pBoneEnd[index], fracFrame);
+ else
+ gfsdk_makeIdentity(bone);
+
+ atcore_float4x4 pose = m_pPoseMatrices[i];
+
+ m_pBoneMatrices[i] = bone;
+ m_pSkinMatrices[i] = gfsdk_inverse(pose) * bone * root;
+ m_pSkinDQs[i] = gfsdk_makeDQ(m_pSkinMatrices[i]);
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void MeshDesc::Allocate(NvUInt32 numVertices, NvUInt32 numTriangles)
+{
+ Release();
+
+ m_NumTriangles = numTriangles;
+ m_NumVertices = numVertices;
+
+ m_pVertices = new atcore_float3[numVertices];
+
+ m_pVertexNormals = new atcore_float3[numTriangles * 3];
+ m_pFaceNormals = new atcore_float3[numTriangles * 3];
+
+ m_pTangents = new atcore_float3[numTriangles * 3];
+
+ m_pIndices = new NvUInt32[numTriangles * 3];
+ m_pTexCoords = new atcore_float2[numTriangles * 3];
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void MeshDesc::Release()
+{
+ if (m_pVertices)
+ delete []m_pVertices;
+ if (m_pVertexNormals)
+ delete []m_pVertexNormals;
+ if (m_pFaceNormals)
+ delete []m_pFaceNormals;
+ if (m_pTangents)
+ delete []m_pTangents;
+
+ if (m_pIndices)
+ delete []m_pIndices;
+ if (m_pTexCoords)
+ delete []m_pTexCoords;
+
+ m_NumTriangles = 0;
+ m_NumVertices = 0;
+
+ m_pVertices = nullptr;
+ m_pVertexNormals = nullptr;
+ m_pFaceNormals = nullptr;
+ m_pTangents = nullptr;
+
+ m_pIndices = nullptr;
+ m_pTexCoords = nullptr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void MeshDesc::UpdateNormal(bool updateVertexNormal)
+{
+ atcore_float3* vertexNormal = new atcore_float3[m_NumVertices];
+ memset(vertexNormal, 0, sizeof(atcore_float3) * m_NumVertices);
+
+ for (int i = 0; i < m_NumTriangles; i++)
+ {
+ atcore_float3 faceNormal;
+
+ int fidx = i*3;
+ int id0 = m_pIndices[fidx++];
+ int id1 = m_pIndices[fidx++];
+ int id2 = m_pIndices[fidx++];
+
+ atcore_float3 p0 = m_pVertices[id0];
+ atcore_float3 p1 = m_pVertices[id1];
+ atcore_float3 p2 = m_pVertices[id2];
+ atcore_float3 p01 = p1 - p0;
+ atcore_float3 p02 = p2 - p0;
+
+ faceNormal.x = p01.y * p02.z - p01.z * p02.y;
+ faceNormal.y = p01.z * p02.x - p01.x * p02.z;
+ faceNormal.z = p01.x * p02.y - p01.y * p02.x;
+
+ gfsdk_normalize(faceNormal);
+
+ m_pFaceNormals[i * 3 + 0] = faceNormal;
+ m_pFaceNormals[i * 3 + 1] = faceNormal;
+ m_pFaceNormals[i * 3 + 2] = faceNormal;
+
+ vertexNormal[id0] += faceNormal;
+ vertexNormal[id1] += faceNormal;
+ vertexNormal[id2] += faceNormal;
+ }
+
+ if (updateVertexNormal)
+ {
+ for (int i = 0; i < m_NumVertices; ++i)
+ gfsdk_normalize(vertexNormal[i]);
+
+ for (int i = 0; i < m_NumTriangles; i++)
+ {
+ int fidx = i*3;
+ int id0 = m_pIndices[fidx++];
+ int id1 = m_pIndices[fidx++];
+ int id2 = m_pIndices[fidx++];
+
+ for (int k = 0; k < 3; k++)
+ {
+ int fidx = i*3 + k;
+ int vidx = m_pIndices[fidx];
+ m_pVertexNormals[fidx] = vertexNormal[vidx];
+ }
+ }
+ }
+
+ delete []vertexNormal;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SkinData::Allocate(NvUInt32 numBones, NvUInt32 numVertices)
+{
+ Release();
+
+ m_boneData.Allocate(numBones);
+
+ m_pBoneIndices = new atcore_float4[numVertices];
+ m_pBoneWeights = new atcore_float4[numVertices];
+
+ memset(m_pBoneIndices, 0, sizeof(atcore_float4) * numVertices);
+ memset(m_pBoneWeights, 0, sizeof(atcore_float4) * numVertices);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SkinData::Release()
+{
+ // clear memory
+ if (m_pBoneIndices)
+ delete []m_pBoneIndices;
+ if (m_pBoneWeights)
+ delete []m_pBoneWeights;
+
+ m_pBoneIndices = 0;
+ m_pBoneWeights = 0;
+
+ m_boneData.Release();
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Anim/AnimUtil.h b/NvBlast/tools/ArtistTools/source/CoreLib/Anim/AnimUtil.h
new file mode 100644
index 0000000..8de718c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Anim/AnimUtil.h
@@ -0,0 +1,217 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#pragma once
+
+#include "MathUtil.h"
+#include <string.h>
+
+//#include <Nv/Blast/NvHairSdk.h>
+
+////////////////////////////////////////////////////////////////////////////////////////
+// cache for animated bone data
+struct CORELIB_EXPORT AnimationCache
+{
+ NvUInt32 m_numBones;
+ NvChar* m_pBoneNames;
+
+ NvInt32 m_frameStart;
+ NvInt32 m_frameEnd;
+ NvUInt32 m_numFrames;
+
+ atcore_float4x4* m_pBoneMatrices;
+
+ AnimationCache() :
+ m_numBones(0),
+ m_frameStart(0),
+ m_frameEnd(0),
+ m_numFrames(0),
+ m_pBoneMatrices(nullptr),
+ m_pBoneNames(nullptr)
+ {
+ }
+
+ bool isValid() const {
+ return (m_numBones > 0) && (m_numFrames > 0) && (m_pBoneMatrices != 0);
+ }
+
+ void Allocate();
+ void Release();
+ void Initialize(int numBones, NvInt32 frameStart, NvInt32 frameEnd);
+
+ bool GetInterpolationInfo(float frameTime, int& indexStart, int& indexEnd, float &fracFrame);
+
+ const atcore_float4x4* GetNodeMatrices(int index) const { return m_pBoneMatrices + index * m_numBones; }
+ atcore_float4x4* GetNodeMatrices(int index) { return m_pBoneMatrices + index * m_numBones; }
+ /*
+ const char* GetBoneName(int index) const
+ {
+ return m_pBoneNames + index * NV_HAIR_MAX_STRING;
+ }
+
+ void SetBoneName(int index, const char* boneName)
+ {
+ char* str = m_pBoneNames + index * NV_HAIR_MAX_STRING;
+ strcpy_s(str, NV_HAIR_MAX_STRING, boneName);
+ }
+ */
+ int FindBone(const char *boneName) const;
+ bool FindBoneMapping( int numBones, const NvChar* boneNames, int* mappedBoneId) const;
+
+ ~AnimationCache();
+};
+
+////////////////////////////////////////////////////////////////////////////////////////
+// bone matrices at each frame
+////////////////////////////////////////////////////////////////////////////////////////
+struct CORELIB_EXPORT BoneData
+{
+ NvUInt32 m_numBones;
+ NvChar* m_pBoneNames;
+
+ atcore_float4x4* m_pPoseMatrices; // rest pose for each bone
+ atcore_float4x4* m_pBoneMatrices; // updated bone matrix
+ atcore_float4x4* m_pSkinMatrices; // interpolated skinning matrix for current frame
+ atcore_dualquaternion* m_pSkinDQs; // dual quats
+
+ AnimationCache* m_pAnimationCache;
+ int* m_pMappedBoneId;
+ int m_nodeId;
+
+public:
+ BoneData() :
+ m_numBones(0),
+ m_pBoneNames(nullptr),
+ m_pPoseMatrices(nullptr),
+ m_pBoneMatrices(nullptr),
+ m_pSkinMatrices(nullptr),
+ m_pSkinDQs(nullptr),
+ m_pAnimationCache(nullptr),
+ m_pMappedBoneId(nullptr),
+ m_nodeId(-1)
+ {}
+
+ void Allocate(NvUInt32 numBones);
+ void Release();
+ /*
+ const char* getBoneName(int index)
+ {
+ return m_pBoneNames + index * NV_HAIR_MAX_STRING;
+ }
+
+ void setBoneName(int index, const char* boneName)
+ {
+ char* str = m_pBoneNames + index * NV_HAIR_MAX_STRING;
+ strcpy_s(str, NV_HAIR_MAX_STRING, boneName);
+ }
+ */
+ void InitializeAnimationCache(AnimationCache* pGlobalCache, const char* nodeName);
+ bool Update(float frameTime, const char* rootBoneName, bool bindPose, bool zup);
+
+};
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Skinning data
+struct CORELIB_EXPORT SkinData
+{
+ BoneData m_boneData;
+
+ atcore_float4* m_pBoneIndices;
+ atcore_float4* m_pBoneWeights;
+
+public:
+ SkinData() :
+ m_pBoneIndices(nullptr),
+ m_pBoneWeights(nullptr)
+ {}
+
+ void Allocate(NvUInt32 numBones, NvUInt32 numVertices);
+ void Release();
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+struct CORELIB_EXPORT MeshDesc
+{
+ NvUInt32 m_NumVertices;
+ NvUInt32 m_NumTriangles;
+
+ atcore_float3* m_pVertices;
+ atcore_float3* m_pVertexNormals;
+ atcore_float3* m_pFaceNormals;
+ atcore_float3* m_pTangents;
+
+ NvUInt32* m_pIndices;
+ atcore_float2* m_pTexCoords;
+
+public:
+ MeshDesc() :
+ m_NumVertices(0),
+ m_NumTriangles(0),
+
+ m_pVertices(nullptr),
+ m_pVertexNormals(nullptr),
+ m_pFaceNormals(nullptr),
+ m_pTangents(nullptr),
+
+ m_pIndices(nullptr),
+ m_pTexCoords(nullptr)
+ {}
+
+ void Allocate(NvUInt32 numVertices, NvUInt32 numTriangles);
+ void Release();
+
+ void UpdateNormal(bool updateVertexNormal = false);
+};
+
+////////////////////////////////////////////////////////////////////////////////////////
+#define MATERIAL_NAME_SIZE 128
+
+struct CORELIB_EXPORT MeshMaterial
+{
+ NvChar m_name[MATERIAL_NAME_SIZE];
+
+ atcore_float3 m_ambientColor;
+ float m_ambientFactor;
+
+ atcore_float3 m_diffuseColor;
+ float m_diffuseFactor;
+
+ float m_specularFactor;
+ float m_shininess;
+
+ NvChar m_diffuseTexture[MATERIAL_NAME_SIZE];
+ NvChar m_specularTexture[MATERIAL_NAME_SIZE];
+ NvChar m_bumpTexture[MATERIAL_NAME_SIZE];
+ NvChar m_normalTexture[MATERIAL_NAME_SIZE];
+ NvChar m_transparentTexture[MATERIAL_NAME_SIZE];
+
+public:
+ MeshMaterial()
+ {}
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Anim/FbxUtil.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Anim/FbxUtil.cpp
new file mode 100644
index 0000000..97ba7d8
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Anim/FbxUtil.cpp
@@ -0,0 +1,1023 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// This file contains wrapper functions to make hair lib easy to setup and use
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#include "fbxsdk.h"
+#include <vector>
+#include <string>
+
+#include "FbxUtil.h"
+#include "MathUtil.h"
+
+//#include <Nv/Blast/NvHairSdk.h>
+
+// local functions used only in this file
+namespace {
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Get the geometry offset to a node. It is never inherited by the children.
+ FbxAMatrix GetGeometry(FbxNode* pNode)
+ {
+ const FbxVector4 lT = pNode->GetGeometricTranslation(FbxNode::eSourcePivot);
+ const FbxVector4 lR = pNode->GetGeometricRotation(FbxNode::eSourcePivot);
+ const FbxVector4 lS = pNode->GetGeometricScaling(FbxNode::eSourcePivot);
+
+ return FbxAMatrix(lT, lR, lS);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ void convertFromFbxMatrix(atcore_float4x4& transform, FbxAMatrix& tmatrix)
+ {
+ float* data = (float*)&transform;
+
+ // update skinning matrix
+ for (int row = 0; row < 4; row++)
+ for (int col = 0; col < 4; col++)
+ {
+ data[ row * 4 + col] = float(tmatrix.Get(row,col));
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ bool checkMesh(FbxNode* pNode)
+ {
+ FbxMesh* pMesh = pNode->GetMesh();
+ if (!pMesh)
+ return false;
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ bool checkSkinned(FbxNode* pNode)
+ {
+ FbxGeometry* pFbxGeometry = pNode->GetGeometry();
+ if (!pFbxGeometry)
+ return false;
+
+ FbxSkin* pFbxSkin = (FbxSkin*)pFbxGeometry->GetDeformer(0, FbxDeformer::eSkin);
+ if (!pFbxSkin)
+ return false;
+
+ return true;
+ }
+}
+
+namespace
+{
+ FbxManager* s_FbxManager = nullptr;
+ FbxScene* s_FbxScene = nullptr;
+
+
+ /////////////////////////////////////////////////////////////////////////////
+ // find node by name
+ FbxNode*
+ FindNodeByName(FbxScene* scene, const char* nodeName)
+ {
+ if (!scene)
+ return 0;
+
+ if (!nodeName)
+ return 0;
+
+ for (int i = 0; i < scene->GetNodeCount(); i++)
+ {
+ FbxNode* node = scene->GetNode(i);
+ const char* name = node->GetName();
+ if (!strcmp(nodeName, name))
+ return node;
+ }
+ return 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool
+FbxUtil::Release(void)
+{
+ if (s_FbxScene)
+ {
+ s_FbxScene->Destroy();
+ s_FbxScene = nullptr;
+ }
+
+ if (s_FbxManager)
+ {
+ s_FbxManager->Destroy();
+ s_FbxManager = nullptr;
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool FbxUtil::Initialize(const char* fbxFileName, float sceneUnit)
+{
+ if (fbxFileName)
+ {
+ FbxImporter* s_FbxImporter = nullptr;
+
+ if (!s_FbxManager)
+ s_FbxManager = FbxManager::Create();
+
+ if (!s_FbxImporter)
+ s_FbxImporter = FbxImporter::Create(s_FbxManager, "");
+
+ if (!s_FbxScene)
+ s_FbxScene = FbxScene::Create(s_FbxManager, "");
+
+ if (!s_FbxImporter->Initialize(fbxFileName, -1))
+ return false;
+
+ if (!s_FbxImporter->Import(s_FbxScene))
+ return false;
+
+ FbxGlobalSettings& settings = s_FbxScene->GetGlobalSettings();
+
+ FbxSystemUnit fbxUnit = settings.GetSystemUnit();
+
+ if ((sceneUnit > 0.0f) && (sceneUnit != fbxUnit.GetScaleFactor()))
+ {
+ FbxSystemUnit convertUnit(sceneUnit);
+ convertUnit.ConvertScene(s_FbxScene);
+ }
+
+ s_FbxImporter->Destroy();
+
+ // get time info
+ FbxTimeSpan timespan;
+ settings.GetTimelineDefaultTimeSpan(timespan);
+
+ FbxTime startTime = timespan.GetStart();
+ FbxTime endTime = timespan.GetStop();
+
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool FbxUtil::GetGlobalSettings(float* pStartFrame, float* pEndFrame, float *pFps, int *upAxis, char* rootBoneName)
+{
+ return false;
+
+ /*
+ if ( !s_FbxScene)
+ return false;
+
+ FbxGlobalSettings& settings = s_FbxScene->GetGlobalSettings();
+
+ FbxTimeSpan timespan;
+ settings.GetTimelineDefaultTimeSpan(timespan);
+
+ FbxTime startTime = timespan.GetStart();
+ FbxTime endTime = timespan.GetStop();
+
+ if (pStartFrame)
+ *pStartFrame = (float)startTime.GetFrameCount();
+
+ if (pEndFrame)
+ *pEndFrame = (float)endTime.GetFrameCount();
+
+ if (pFps)
+ *pFps = (float)endTime.GetFrameRate(FbxTime::GetGlobalTimeMode());
+
+ if (upAxis)
+ {
+ int upSign = 0;
+ FbxAxisSystem axisSystem = settings.GetAxisSystem();
+ FbxAxisSystem::EUpVector upVector = axisSystem.GetUpVector(upSign);
+
+ enum FbxAxisSystem::ECoordSystem coordSystem = axisSystem.GetCoorSystem();
+
+ switch (upVector)
+ {
+ case FbxAxisSystem::eXAxis: *upAxis = 0; break;
+ case FbxAxisSystem::eYAxis: *upAxis = 1; break;
+ case FbxAxisSystem::eZAxis: *upAxis = 2; break;
+ }
+ }
+
+ if (rootBoneName)
+ {
+ FbxNode* pRoot = s_FbxScene->GetRootNode();
+ if (pRoot)
+ {
+ strncpy(rootBoneName, pRoot->GetName(), NV_HAIR_MAX_STRING);
+ }
+ else
+ strcpy(rootBoneName, "");
+ }
+
+ return true;
+ */
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+bool
+FbxUtil::InitializeAnimationCache(AnimationCache& animCache)
+{
+ return false;
+
+ /*
+ if (!s_FbxScene)
+ return false;
+
+ float startFrame, endFrame, fps;
+ FbxUtil::GetGlobalSettings(&startFrame, &endFrame, &fps);
+
+ int numNodes = s_FbxScene->GetNodeCount();
+
+ ////////////////////////////////////////////
+ animCache.Initialize(numNodes, (NvInt32)startFrame, (NvInt32)endFrame);
+
+ for (int i = 0; i < numNodes; i++)
+ {
+ FbxNode* node = s_FbxScene->GetNode(i);
+ const char* nodeName = node->GetName();
+ animCache.SetBoneName(i, nodeName);
+ }
+
+ ////////////////////////////////////////////
+ for (NvInt frame = animCache.m_frameStart; frame <= animCache.m_frameEnd; frame++)
+ {
+ FbxTime lTime;
+ lTime.SetSecondDouble( frame / fps);
+
+ int index = frame - animCache.m_frameStart;
+ atcore_float4x4 *pNodeMatrices = animCache.GetNodeMatrices(index);
+
+ for (int i = 0; i < numNodes; i++)
+ {
+ FbxNode* node = s_FbxScene->GetNode(i);
+ FbxAMatrix nodeMatrix = node->EvaluateGlobalTransform(lTime);
+ convertFromFbxMatrix(pNodeMatrices[i], nodeMatrix);
+ }
+ }
+
+ return true;
+ */
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+static FbxSkin* GetFbxSkin( FbxNode* pFbxNode )
+{
+ if (!pFbxNode)
+ return 0;
+
+ FbxMesh* pFbxMesh = pFbxNode->GetMesh();
+ if (!pFbxMesh)
+ return 0;
+
+ FbxGeometry* pFbxGeometry = pFbxNode->GetGeometry();
+ if (!pFbxGeometry)
+ return 0;
+
+ int deformerCount = pFbxGeometry->GetDeformerCount(FbxDeformer::eSkin);
+
+ FbxSkin *pFbxSkin = 0;
+ if (deformerCount > 0)
+ pFbxSkin = (FbxSkin*)pFbxGeometry->GetDeformer(0, FbxDeformer::eSkin);
+
+ return pFbxSkin;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+static int GetNumMeshPoints( FbxNode* pFbxNode)
+{
+ if (!pFbxNode)
+ return 0;
+
+ FbxMesh* pFbxMesh = pFbxNode->GetMesh();
+ if (!pFbxMesh)
+ return 0;
+
+ return pFbxMesh->GetControlPointsCount();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+static bool GetBoneData(FbxSkin *pFbxSkin, FbxNode* pFbxNode, NvChar* pBoneNames, atcore_float4x4 *pBindPoses)
+{
+ return false;
+
+ /*
+ if (!pFbxSkin || !pFbxNode)
+ return false;
+
+ int numBones = (int)pFbxSkin->GetClusterCount();
+
+ for (int i = 0; i < numBones; i++)
+ {
+ FbxCluster* pFbxCluster = pFbxSkin->GetCluster(i);
+
+ FbxNode* pLink = pFbxCluster->GetLink();
+
+ // copy bone names
+ const char* boneName = pLink->GetName();
+ char* str = pBoneNames + i * NV_HAIR_MAX_STRING;
+ strcpy_s(str, NV_HAIR_MAX_STRING, boneName);
+
+ // write pose matrix
+ {
+ FbxAMatrix lReferenceGlobalInitPosition;
+ pFbxCluster->GetTransformMatrix(lReferenceGlobalInitPosition);
+
+ FbxAMatrix lReferenceGeometry = GetGeometry(pFbxNode);
+ lReferenceGlobalInitPosition *= lReferenceGeometry;
+
+ FbxAMatrix lClusterGlobalInitPosition;
+ pFbxCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
+
+ FbxAMatrix lClusterMatrix = lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;
+ convertFromFbxMatrix(pBindPoses[i], lClusterMatrix.Inverse());
+ }
+ }
+ return true;
+ */
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+static bool GetSkinningWeights(FbxSkin* pFbxSkin, atcore_float4* boneIndices, atcore_float4* boneWeights, int numPoints)
+{
+ int numClusters = (int)pFbxSkin->GetClusterCount();
+ if (numClusters == 0)
+ return false;
+
+ // copy skinning weights and indices
+ int* pIndexCounts = new int[numPoints];
+ memset(pIndexCounts, 0, sizeof(int) * numPoints);
+
+ for (int i = 0; i < numClusters; i++)
+ {
+ if (!pFbxSkin) continue;
+
+ FbxCluster* pFbxCluster = pFbxSkin->GetCluster(i);
+
+ if (!pFbxCluster) continue;
+
+ int cpCount = pFbxCluster->GetControlPointIndicesCount();
+ int* pPointIndices = pFbxCluster->GetControlPointIndices();
+ double* pWeights = pFbxCluster->GetControlPointWeights();
+
+ for (int j = 0; j < cpCount; j++)
+ {
+ if (pWeights[j] == 0.0f)
+ continue;
+
+ int pointIndex = pPointIndices[j];
+ int& cnt = pIndexCounts[pointIndex];
+
+ float* pBoneIndex = (float*)&boneIndices[pointIndex];
+ float* pBoneWeights = (float*)&boneWeights[pointIndex];
+
+ if (cnt < 4)
+ {
+ pBoneIndex[cnt] = float(i);
+ pBoneWeights[cnt] = float(pWeights[j]);
+ cnt++;
+ }
+ else // over 4, so we just bind to largest weights
+ {
+ float minWeight = (float)pWeights[j];
+ int minIndex = -1;
+ for (int b = 0; b < 4; b++)
+ {
+ float w = pBoneWeights[b];
+
+ if (w < minWeight)
+ {
+ minWeight = w;
+ minIndex = b;
+ }
+ }
+
+ if (minIndex >= 0)
+ {
+ pBoneIndex[minIndex] = float(i);
+ pBoneWeights[minIndex] = float(pWeights[j]);
+ }
+
+ cnt++;
+ }
+ }
+ }
+
+ for (int i = 0; i < numPoints; i++)
+ {
+ float* pBoneWeights = (float*)&boneWeights[i];
+
+ float weightsum = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ weightsum += pBoneWeights[i];
+ }
+
+ if (weightsum == 0)
+ continue;
+
+ for (int i = 0; i < 4; i++)
+ pBoneWeights[i] /= weightsum;
+ }
+
+ if (pIndexCounts) delete []pIndexCounts;
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+bool FbxUtil::InitializeSkinData( const char* meshName, SkinData& skinData)
+{
+ return false;
+
+ /*
+ FbxNode* pFbxNode = FindNodeByName(s_FbxScene, meshName);
+ if (!pFbxNode)
+ return false;
+
+ FbxSkin* pFbxSkin = GetFbxSkin(pFbxNode);
+ int numPoints = GetNumMeshPoints(pFbxNode);
+
+ BoneData& boneData = skinData.m_boneData;
+
+ if (pFbxSkin)
+ {
+ int numBones = (int)pFbxSkin->GetClusterCount();
+ skinData.Allocate(numBones, numPoints);
+
+ // get bone data (bind pose, bone names, ..)
+ GetBoneData(pFbxSkin, pFbxNode, boneData.m_pBoneNames, boneData.m_pPoseMatrices);
+
+ // get skinning weights
+ atcore_float4* boneIndices = skinData.m_pBoneIndices;
+ atcore_float4* boneWeights = skinData.m_pBoneWeights;
+
+ GetSkinningWeights(pFbxSkin, boneIndices, boneWeights, numPoints);
+ }
+ else // no skinning, use model matrix
+ {
+ int numBones = 1;
+
+ skinData.Allocate(numBones, numPoints);
+
+ // copy bone name
+ const char* boneName = pFbxNode->GetName();
+ boneData.setBoneName(0, boneName);
+
+ // make pose matrix
+ gfsdk_makeIdentity(boneData.m_pPoseMatrices[0]);
+
+ // all the vertices map to the model matrix
+ atcore_float4* boneIndices = skinData.m_pBoneIndices;
+ atcore_float4* boneWeights = skinData.m_pBoneWeights;
+
+ for (int i = 0; i < numPoints; i++)
+ {
+ boneIndices[i] = gfsdk_makeFloat4(0, 0, 0, 0);
+ boneWeights[i] = gfsdk_makeFloat4(1, 0, 0, 0);
+ }
+ }
+
+ return true;
+ */
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool FbxUtil::GetMeshInfo(int* numMeshes, char** meshNames, char** skinned)
+{
+ int cnt = 0;
+
+ for (int i = 0; i < s_FbxScene->GetNodeCount(); i++)
+ {
+ FbxNode* pNode = s_FbxScene->GetNode(i);
+ if (checkMesh(pNode))
+ cnt++;
+ }
+
+ char *pNameBuffer = new char[cnt * 128];
+ char *pSkinnedBuffer = new char[cnt];
+
+ cnt = 0;
+ for (int i = 0; i < s_FbxScene->GetNodeCount(); i++)
+ {
+ FbxNode* pNode = s_FbxScene->GetNode(i);
+
+ if (!checkMesh(pNode))
+ continue;
+
+ strcpy(pNameBuffer + cnt * 128, pNode->GetName());
+
+ pSkinnedBuffer[cnt] = checkSkinned(pNode);
+
+ cnt++;
+ }
+
+ *numMeshes = cnt;
+ if (skinned)
+ {
+ *skinned = pSkinnedBuffer;
+ }
+ else
+ delete []pSkinnedBuffer;
+
+ *meshNames = pNameBuffer;
+
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool FbxUtil::GetMeshMaterials( const NvChar* meshName, int *numMaterials, MeshMaterial** materials)
+{
+ if (!s_FbxScene)
+ return false;
+
+ FbxNode* pNode = FindNodeByName(s_FbxScene, meshName);
+ if (!pNode)
+ return false;
+
+ int numMats = pNode->GetMaterialCount();
+
+ *materials = new MeshMaterial[numMats];
+
+ int matCnt = 0;
+
+ for (int i = 0; i < numMats; i++)
+ {
+ FbxSurfaceMaterial *mat = pNode->GetMaterial(i);
+ if (!mat) continue;
+ if (mat->GetUserDataPtr()) continue;
+
+ MeshMaterial& material = (*materials)[matCnt];
+
+ strcpy(material.m_name, mat->GetName());
+ strcpy(material.m_diffuseTexture, "");
+ strcpy(material.m_bumpTexture, "");
+ strcpy(material.m_transparentTexture, "");
+ strcpy(material.m_normalTexture, "");
+
+ (atcore_float3&)material.m_ambientColor = gfsdk_makeFloat3(1.0f, 1.0f, 1.0f);
+ (atcore_float3&)material.m_diffuseColor = gfsdk_makeFloat3(1.0f, 1.0f, 1.0f);
+
+ FbxProperty prop;
+ FbxProperty fact;
+ FbxDouble3 d3;
+
+ // get ambient
+ {
+ fact = mat->FindProperty(FbxSurfaceMaterial::sAmbientFactor);
+ material.m_ambientFactor = fact.IsValid() ? (float)fact.Get<FbxDouble>() : 0.1f;
+
+ prop = mat->FindProperty(FbxSurfaceMaterial::sAmbient);
+ if (prop.IsValid())
+ {
+ FbxDouble3 d3 = prop.Get<FbxDouble3>();
+ material.m_ambientColor = gfsdk_makeFloat3((float)d3[0], (float)d3[1], (float)d3[2]);
+ }
+ }
+
+ // get specular
+ {
+ fact = mat->FindProperty(FbxSurfaceMaterial::sSpecularFactor);
+ material.m_specularFactor = fact.IsValid() ? (float)fact.Get<FbxDouble>() : 0.1f;
+
+ fact = mat->FindProperty(FbxSurfaceMaterial::sShininess);
+ material.m_shininess = fact.IsValid() ? (float)fact.Get<FbxDouble>() : 20.0f;
+ }
+
+ // get diffuse
+ {
+ fact = mat->FindProperty(FbxSurfaceMaterial::sDiffuseFactor);
+ material.m_diffuseFactor = fact.IsValid() ? (float)fact.Get<FbxDouble>() : 0.5f;
+
+ prop = mat->FindProperty(FbxSurfaceMaterial::sDiffuse);
+ if (prop.IsValid())
+ {
+ FbxDouble3 d3 = prop.Get<FbxDouble3>();
+ material.m_diffuseColor = gfsdk_makeFloat3((float)d3[0], (float)d3[1], (float)d3[2]);
+
+ const FbxFileTexture* tex = prop.GetSrcObject<FbxFileTexture>();
+ if (tex)
+ strcpy(material.m_diffuseTexture, tex->GetFileName());
+ }
+ }
+
+ // get normal map
+ {
+ prop = mat->FindProperty(FbxSurfaceMaterial::sNormalMap);
+ if (prop.IsValid())
+ {
+ const FbxFileTexture* tex = prop.GetSrcObject<FbxFileTexture>();
+ if (tex)
+ strcpy(material.m_normalTexture, tex->GetFileName());
+ }
+ }
+
+ matCnt++;
+ }
+
+ *numMaterials = matCnt;
+
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool FbxUtil::CreateMeshDescriptor(const char* meshName, MeshDesc &desc)
+{
+ if (!s_FbxScene)
+ return false;
+
+ FbxNode* pNode = FindNodeByName(s_FbxScene, meshName);
+ if (!pNode)
+ return false;
+
+ // read growth mesh data
+ FbxMesh* pMesh = pNode->GetMesh();
+ if (!pMesh)
+ return false;
+
+ int cpCount = pMesh->GetControlPointsCount();
+
+ int triCount = 0;
+ for (int i = 0; i < pMesh->GetPolygonCount(); i++)
+ {
+ int psize = pMesh->GetPolygonSize(i);
+ triCount += (psize - 2);
+ }
+
+ // allocate buffers
+ desc.Allocate(cpCount, triCount);
+
+ // read positions
+ FbxVector4* points = pMesh->GetControlPoints();
+ for (int i = 0; i < desc.m_NumVertices; i++)
+ desc.m_pVertices[i] = gfsdk_makeFloat3(float(points[i].mData[0]), float(points[i].mData[1]), float(points[i].mData[2]));
+
+ memset(desc.m_pTexCoords, 0, sizeof(atcore_float2) * desc.m_NumTriangles * 3);
+
+ // read uvs
+ FbxLayerElementUV* leUV = pMesh->GetLayer(0)->GetUVs();
+
+ FbxGeometryElementNormal *lNormals = pMesh->GetElementNormal();
+ FbxGeometryElementTangent* lTangents = pMesh->GetElementTangent();
+
+ int tcnt = 0;
+ int vertexBase = 0;
+ for (int i = 0; i < pMesh->GetPolygonCount(); i++)
+ {
+ int vcnt = pMesh->GetPolygonSize(i);
+ for (int j = 0; j < (vcnt-2); j++)
+ {
+ int pIndex[3] = { 0, j+1, j+2 };
+
+ // get polygon index
+ for (int p = 0; p < 3; ++p)
+ desc.m_pIndices[tcnt*3+p] = pMesh->GetPolygonVertex(i, pIndex[p]);
+
+ // get face normal
+ if (lNormals)
+ {
+ FbxLayerElement::EMappingMode mode = lNormals->GetMappingMode();
+
+ for (int p = 0; p < 3; ++p)
+ {
+ int vertexId = vertexBase + pIndex[p];
+ int normalId = vertexId;
+ if (mode == FbxGeometryElement::eByPolygonVertex)
+ {
+ if (lNormals->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
+ normalId = lNormals->GetIndexArray().GetAt(vertexId);
+ }
+ else if (mode == FbxGeometryElement::eByControlPoint)
+ normalId = pMesh->GetPolygonVertex(i, pIndex[p]);
+
+ const FbxVector4 &n = lNormals->GetDirectArray().GetAt(normalId);
+ desc.m_pVertexNormals[tcnt*3+p] = gfsdk_makeFloat3((float)n[0], (float)n[1], (float)n[2]);
+ }
+ }
+
+ // get face normal
+ if (lTangents)
+ {
+ FbxLayerElement::EMappingMode mode = lTangents->GetMappingMode();
+
+ for (int p = 0; p < 3; ++p)
+ {
+ int vertexId = vertexBase + pIndex[p];
+ int tangentId = vertexId;
+ if (mode == FbxGeometryElement::eByPolygonVertex)
+ {
+ if (lTangents->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
+ tangentId = lTangents->GetIndexArray().GetAt(vertexId);
+ }
+ else if (mode == FbxGeometryElement::eByControlPoint)
+ tangentId = pMesh->GetPolygonVertex(i, pIndex[p]);
+
+ const FbxVector4 &n = lTangents->GetDirectArray().GetAt(tangentId);
+ desc.m_pTangents[tcnt*3+p] = gfsdk_makeFloat3((float)n[0], (float)n[1], (float)n[2]);
+ }
+ }
+
+ if (leUV)
+ {
+ int i0 = pMesh->GetTextureUVIndex(i, 0);
+ int i1 = pMesh->GetTextureUVIndex(i, j+1);
+ int i2 = pMesh->GetTextureUVIndex(i, j+2);
+
+ FbxVector2 texCoord0 = leUV->GetDirectArray().GetAt(i0);
+ FbxVector2 texCoord1 = leUV->GetDirectArray().GetAt(i1);
+ FbxVector2 texCoord2 = leUV->GetDirectArray().GetAt(i2);
+
+ desc.m_pTexCoords[tcnt*3+0] = gfsdk_makeFloat2(1.0f * float(texCoord0[0]), 1.0f - float(texCoord0[1]));
+ desc.m_pTexCoords[tcnt*3+1] = gfsdk_makeFloat2(1.0f * float(texCoord1[0]), 1.0f - float(texCoord1[1]));
+ desc.m_pTexCoords[tcnt*3+2] = gfsdk_makeFloat2(1.0f * float(texCoord2[0]), 1.0f - float(texCoord2[1]));
+ }
+
+ tcnt++;
+ }
+ vertexBase += vcnt;
+ }
+
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+bool FbxUtil::CreateHairFromFbx(const char* guideName, const char* growthMeshName, NvHair::AssetDescriptor& hairAsset)
+{
+ if (!s_FbxScene)
+ return false;
+
+ // read growth mesh data
+ MeshDesc meshDesc;
+ if (false == FbxUtil::CreateMeshDescriptor(growthMeshName, meshDesc))
+ return false;
+
+ FbxNode* pHairNode = FindNodeByName(s_FbxScene, guideName);
+ if (!pHairNode)
+ return false;
+
+ FbxNode* pMeshNode = FindNodeByName(s_FbxScene, growthMeshName);
+ if (!pMeshNode)
+ return false;
+
+ FbxSkin* pFbxSkin = GetFbxSkin(pMeshNode);
+ int numBones = 1;
+
+ if (pFbxSkin)
+ numBones = (int)pFbxSkin->GetClusterCount();
+
+ // get skin data from mesh
+ int numPoints = meshDesc.m_NumVertices;
+
+ atcore_float4* pMeshBoneIndices = new atcore_float4[numPoints];
+ atcore_float4* pMeshBoneWeights = new atcore_float4[numPoints];
+
+ GetSkinningWeights(pFbxSkin, pMeshBoneIndices, pMeshBoneWeights, numPoints);
+
+ // create raw hair array
+ FbxLine* pLine = pHairNode->GetLine();
+ if (!pLine)
+ return false;
+
+ int cpCount = pLine->GetControlPointsCount();
+ int curveCount = pLine->GetEndPointCount();
+
+ atcore_float3* pVertices = new atcore_float3[cpCount];
+ NvUInt32* pEndIndices = new NvUInt32[curveCount];
+
+ FbxVector4* pFbxPoints = pLine->GetControlPoints();
+ FbxArray<int>* pFbxEndIndices = pLine->GetEndPointArray();
+
+ for (int i = 0; i < cpCount; i++)
+ pVertices[i] = gfsdk_makeFloat3(float(pFbxPoints[i][0]), float(pFbxPoints[i][1]), float(pFbxPoints[i][2]));
+
+ for (int i = 0; i < curveCount; i++)
+ pEndIndices[i] = (*pFbxEndIndices)[i];
+
+ // check against closest growth mesh points
+ const float distThreshold = 25.0;
+
+ int numValidHairs = 0;
+ int numValidHairVertices = 0;
+
+ int* pMeshToHairMap = new int[meshDesc.m_NumVertices];
+ int* pHairToMeshMap = new int[curveCount];
+ int* pHairToHairMap = new int[curveCount];
+ float* pMinDistances = new float[meshDesc.m_NumVertices];
+ atcore_float3* pRootVertices = new atcore_float3[curveCount];
+ atcore_float3* pTriangleCenters = new atcore_float3[meshDesc.m_NumTriangles];
+
+ // initialize triangle centers
+ for (int i = 0; i < meshDesc.m_NumTriangles; i++)
+ {
+ NvUInt32 v0 = meshDesc.m_pIndices[i*3 + 0];
+ NvUInt32 v1 = meshDesc.m_pIndices[i * 3 + 1];
+ NvUInt32 v2 = meshDesc.m_pIndices[i * 3 + 2];
+
+ atcore_float3 p0 = meshDesc.m_pVertices[v0];
+ atcore_float3 p1 = meshDesc.m_pVertices[v1];
+ atcore_float3 p2 = meshDesc.m_pVertices[v2];
+
+ pTriangleCenters[i] = 1.0f / 3.0f * (p0 + p1 + p2);
+ }
+
+ // initialize mesh to hair map
+ for (int i = 0; i < meshDesc.m_NumVertices; i++)
+ {
+ pMeshToHairMap[i] = -1;
+ pMinDistances[i] = FLT_MAX;
+ }
+
+ // copy root vertices of input hairs
+
+ for (int i = 0; i < curveCount; i++)
+ {
+ int root = (i == 0) ? 0 : pEndIndices[i-1]+1;
+ pRootVertices[i] = pVertices[root];
+ pHairToMeshMap[i] = -1;
+ }
+
+ // for each input hair curve, find the closest mesh vertex
+ for (int i = 0; i < curveCount; i++)
+ {
+ atcore_float3 hp = pRootVertices[i];
+
+ float minDist = FLT_MAX;
+ int closestTriangle = -1;
+ for (int j = 0; j < meshDesc.m_NumTriangles; j++)
+ {
+ atcore_float3 c = pTriangleCenters[j];
+
+ float distSquared = gfsdk_lengthSquared(hp - c);
+ if (distSquared < minDist)
+ {
+ minDist = distSquared;
+ closestTriangle = j;
+ }
+ }
+
+ if (closestTriangle >= 0)
+ {
+ for (int k = 0; k < 3; k++)
+ {
+ NvUInt32 v = meshDesc.m_pIndices[closestTriangle * 3 + k];
+ atcore_float3 p = meshDesc.m_pVertices[v];
+
+ float distSquared = gfsdk_lengthSquared(hp - p);
+ if (distSquared < pMinDistances[v])
+ {
+ pMinDistances[v] = distSquared;
+ pMeshToHairMap[v] = i;
+ }
+ }
+ }
+ }
+
+ // prepare mapping from new hair set to mesh and old hairs
+ for (int i = 0; i < meshDesc.m_NumVertices; i++)
+ {
+ int closestHair = pMeshToHairMap[i];
+ if (closestHair < 0)
+ continue;
+
+ pHairToMeshMap[numValidHairs] = i;
+ pHairToHairMap[numValidHairs] = closestHair;
+ pMeshToHairMap[i] = numValidHairs; // update hair with new hair index
+
+ int root = (closestHair == 0) ? 0 : pEndIndices[closestHair-1]+1;
+ int tip = pEndIndices[closestHair];
+
+ numValidHairVertices += (tip - root + 1);
+ numValidHairs++;
+ }
+
+ // allocate new hairs
+ hairAsset.m_numGuideHairs = numValidHairs;
+ hairAsset.m_numVertices = numValidHairVertices;
+
+ hairAsset.m_boneIndices = new atcore_float4[hairAsset.m_numGuideHairs];
+ hairAsset.m_boneWeights = new atcore_float4[hairAsset.m_numGuideHairs];
+
+ hairAsset.m_vertices = new atcore_float3[hairAsset.m_numVertices];
+ hairAsset.m_endIndices = new NvUInt32[hairAsset.m_numGuideHairs];
+ hairAsset.m_faceIndices = new NvUInt32[meshDesc.m_NumTriangles * 3];
+ hairAsset.m_faceUvs = new atcore_float2[meshDesc.m_NumTriangles * 3];
+
+ hairAsset.m_numBones = numBones;
+ hairAsset.m_boneNames = new NvChar[NV_HAIR_MAX_STRING * hairAsset.m_numBones];
+ hairAsset.m_bindPoses = new atcore_float4x4[hairAsset.m_numBones];
+ hairAsset.m_boneParents = new NvInt32[hairAsset.m_numBones];
+
+ if (pFbxSkin)
+ GetBoneData(pFbxSkin, pMeshNode, hairAsset.m_boneNames, hairAsset.m_bindPoses);
+ else
+ {
+ strcpy(hairAsset.m_boneNames, "Root");
+ gfsdk_makeIdentity(hairAsset.m_bindPoses[0]);
+ hairAsset.m_boneParents[0] = -1;
+ }
+
+ // copy vertex data
+ int vertexCnt = 0;
+
+ for (int i = 0; i < hairAsset.m_numGuideHairs; i++)
+ {
+ int oldHair = pHairToHairMap[i];
+
+ int oldRoot = (oldHair == 0) ? 0 : pEndIndices[oldHair-1]+1;
+ int oldTip = pEndIndices[oldHair];
+
+ int offset = oldTip - oldRoot;
+
+ int newRoot = vertexCnt;
+ int newTip = vertexCnt + offset;
+
+ vertexCnt += (offset + 1);
+
+ hairAsset.m_endIndices[i] = newTip;
+
+ int meshVertex = pHairToMeshMap[i];
+ atcore_float3 meshRoot = meshDesc.m_pVertices[meshVertex];
+ atcore_float3 hairRoot = pVertices[oldRoot];
+
+ atcore_float3 rootOffset = meshRoot - hairRoot;
+
+ for (int j = 0; j <= offset; j++)
+ hairAsset.m_vertices[newRoot + j] = pVertices[oldRoot + j] + rootOffset;
+
+ hairAsset.m_boneIndices[i] = gfsdk_makeFloat4(0,0,0,0);
+ hairAsset.m_boneWeights[i] = gfsdk_makeFloat4(1,0,0,0);
+
+ if (pFbxSkin)
+ {
+ hairAsset.m_boneIndices[i] = pMeshBoneIndices[meshVertex];
+ hairAsset.m_boneWeights[i] = pMeshBoneWeights[meshVertex];
+ }
+ }
+
+ // copy face indices and texture uvs
+ int faceCnt = 0;
+ for (int i = 0; i < meshDesc.m_NumTriangles; i++)
+ {
+ NvUInt32 i0 = meshDesc.m_pIndices[i * 3 + 0];
+ NvUInt32 i1 = meshDesc.m_pIndices[i * 3 + 1];
+ NvUInt32 i2 = meshDesc.m_pIndices[i * 3 + 2];
+
+ int h0 = pMeshToHairMap[i0];
+ int h1 = pMeshToHairMap[i1];
+ int h2 = pMeshToHairMap[i2];
+
+ if ((h0 < 0) || (h1 < 0) || (h2 < 0))
+ continue; // invalid face
+
+ hairAsset.m_faceIndices[ faceCnt * 3 + 0] = h0;
+ hairAsset.m_faceIndices[ faceCnt * 3 + 1] = h1;
+ hairAsset.m_faceIndices[ faceCnt * 3 + 2] = h2;
+
+ hairAsset.m_faceUvs[ faceCnt * 3 + 0 ] = meshDesc.m_pTexCoords[i * 3 + 0];
+ hairAsset.m_faceUvs[ faceCnt * 3 + 1 ] = meshDesc.m_pTexCoords[i * 3 + 1];
+ hairAsset.m_faceUvs[ faceCnt * 3 + 2 ] = meshDesc.m_pTexCoords[i * 3 + 2];
+
+ faceCnt++;
+ }
+
+ hairAsset.m_numFaces = faceCnt;
+
+ delete []pMeshBoneIndices;
+ delete []pMeshBoneWeights;
+
+ delete []pMeshToHairMap;
+ delete []pHairToMeshMap;
+ delete []pHairToHairMap;
+
+ return true;
+}
+*/
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Anim/FbxUtil.h b/NvBlast/tools/ArtistTools/source/CoreLib/Anim/FbxUtil.h
new file mode 100644
index 0000000..26e61a9
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Anim/FbxUtil.h
@@ -0,0 +1,64 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#pragma once
+
+#include "AnimUtil.h"
+
+//#include <Nv/Blast/NvHairSdk.h>
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Helper for fbx file load
+class CORELIB_EXPORT FbxUtil
+{
+public:
+
+ /// initialize fbx loader.
+ static bool Initialize(const nvidia::Char* fbxFileName, nvidia::Float sceneUnit = 0.0f);
+ static bool Release(void);
+
+ static bool InitializeAnimationCache(AnimationCache& cache);
+
+ /// Get global frame range and fps information from fbx.
+ static bool GetGlobalSettings(nvidia::Float32* pStarfFrame = 0, nvidia::Float32* pEndFrame = 0, nvidia::Float32 *pFps = 0, int* upAxis = 0, char* rootBoneName = 0);
+
+ /// get skinning data from the mesh node
+ static bool InitializeSkinData( const nvidia::Char* meshName, SkinData& pSkinningDataToUpdate);
+
+ /// create mesh descriptor from fbx mesh node
+ static bool CreateMeshDescriptor(const nvidia::Char* meshName, MeshDesc &meshDesc);
+
+ /// get all the renderable meshes from the fbx scene
+ static bool GetMeshInfo(int* numMeshes, char** meshNames, char** skinned = 0);
+
+ /// get mesh material info from fbx scene
+ static bool GetMeshMaterials(const nvidia::Char* meshName, int *numMaterials, MeshMaterial** materials);
+
+ /// get hair directly from fbx
+// static bool CreateHairFromFbx(const char* guideName, const char* growthMeshName, NvHair::AssetDescriptor &hairAsset);
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Backdoor/backdoor.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Backdoor/backdoor.cpp
new file mode 100644
index 0000000..222debd
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Backdoor/backdoor.cpp
@@ -0,0 +1,263 @@
+#include "backdoor.h"
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include <Windows.h>
+#include "Nv.h"
+
+namespace BACKDOOR
+{
+
+ struct Header
+ {
+ int mCount;
+ int mType;
+ };
+
+#define MAX_BACKDOOR_PACKET 1024 // maximum size of a send/receive packet
+#define HEADER_SIZE (sizeof(Header))
+#define DATA_SIZE (MAX_BACKDOOR_PACKET - HEADER_SIZE)
+#define STRING_SIZE (DATA_SIZE - 1)
+#define MAX_ARGS 32
+#pragma warning(disable:4996)
+
+ // Chagne this helper class to use the memory mapped IO API relevant to your system.
+ // This implementation uses the Windows API for a memory mapped shared file system.
+ class MemoryMappedFile
+ {
+ public:
+
+ MemoryMappedFile(const char *mappingObject,unsigned int mapSize);
+ ~MemoryMappedFile(void);
+ void * getBaseAddress(void);
+ private:
+ class MemoryMappedFileImpl *mImpl;
+ };
+
+
+ class MemoryMappedFileImpl
+ {
+ public:
+ HANDLE mMapFile;
+ void * mHeader;
+ };
+
+ MemoryMappedFile::MemoryMappedFile(const char *mappingObject,unsigned int mapSize)
+ {
+ mImpl = (MemoryMappedFileImpl *)::malloc(sizeof(MemoryMappedFileImpl));
+ mImpl->mHeader = NV_NULL;
+ mImpl->mMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS,FALSE,mappingObject);
+ if ( mImpl->mMapFile == NV_NULL )
+ {
+ mImpl->mMapFile = CreateFileMappingA(
+ INVALID_HANDLE_VALUE, // use paging file
+ NV_NULL, // default security
+ PAGE_READWRITE, // read/write access
+ 0, // maximum object size (high-order DWORD)
+ mapSize, // maximum object size (low-order DWORD)
+ mappingObject);
+ }
+ if ( mImpl->mMapFile )
+ {
+ mImpl->mHeader = MapViewOfFile(mImpl->mMapFile,FILE_MAP_ALL_ACCESS,0,0,mapSize);
+ }
+
+ }
+
+ MemoryMappedFile::~MemoryMappedFile(void)
+ {
+
+ if ( mImpl->mHeader )
+ {
+ UnmapViewOfFile(mImpl->mHeader);
+ if ( mImpl->mMapFile )
+ {
+ CloseHandle(mImpl->mMapFile);
+ }
+ }
+
+ ::free(mImpl);
+ }
+
+ void * MemoryMappedFile::getBaseAddress(void)
+ {
+ return mImpl->mHeader;
+ }
+
+
+
+class _Backdoor : public Backdoor
+{
+ MemoryMappedFile *mReceiveFile;
+ MemoryMappedFile *mSendFile;
+ const char *mArgv[MAX_ARGS];
+ char mBuffer[MAX_BACKDOOR_PACKET];
+
+ int mSendCount;
+ int mReceiveCount;
+
+public:
+ _Backdoor(const char *sendName, // The name of the shared memory file to act as the 'sender' stream.
+ const char *receiveName) // The name of the shared memory file to act as the 'receive' message stream.
+ {
+ mSendCount = 0; // This is a semaphore used to signal when a new message has been sent.
+ mReceiveCount = 0; // This is a semaphore used to detect if a new message has been received.
+ mReceiveFile = new MemoryMappedFile(receiveName,MAX_BACKDOOR_PACKET); // Open the receive stream file
+ mSendFile = new MemoryMappedFile(sendName,MAX_BACKDOOR_PACKET); // Open the send stream file
+ }
+
+ virtual ~_Backdoor(void)
+ {
+ delete mReceiveFile; // Close the receive stream file
+ delete mSendFile; // Close the send stream file.
+ }
+
+ virtual void send(const char *fmt,...)
+ {
+ char wbuff[DATA_SIZE];
+ wbuff[STRING_SIZE] = 0;
+ _vsnprintf(wbuff,STRING_SIZE, fmt, (char *)(&fmt+1));
+
+ mSendCount++; // Increment the send counter.
+ size_t len = strlen(wbuff);
+
+ if ( len < STRING_SIZE && mSendFile )
+ {
+ char *baseAddress = (char *)mSendFile->getBaseAddress(); // get the base address of the shared memory
+ int *dest = (int *)baseAddress;
+
+ baseAddress+=sizeof(Header);
+
+ memcpy(baseAddress,wbuff,len+1); // First copy the message.
+ *dest = mSendCount; // Now revised the send count semaphore so the other process knows there is a new message to processs.
+ }
+ }
+
+ virtual const char **getInput(int &argc)
+ {
+ const char **ret = NV_NULL;
+ argc = 0;
+
+ if ( mReceiveFile )
+ {
+ const char *baseAddress = (const char *)mReceiveFile->getBaseAddress();
+ const int *source = (const int *)baseAddress;
+ baseAddress+=sizeof(Header);
+ if ( *source != mReceiveCount )
+ {
+ mReceiveCount = *source;
+ memcpy(mBuffer,baseAddress,DATA_SIZE);
+
+ char *scan = mBuffer;
+ while ( *scan == 32 ) scan++; // skip leading spaces
+ if ( *scan ) // if not EOS
+ {
+ argc = 1;
+ mArgv[0] = scan; // set the first argument
+
+ while ( *scan && argc < MAX_ARGS) // while still data and we haven't exceeded the maximum argument count.
+ {
+ while ( *scan && *scan != 32 ) scan++; // scan forward to the next space
+ if ( *scan == 32 ) // if we hit a space
+ {
+ *scan = 0; // null-terminate the argument
+ scan++; // skip to the next character
+ while ( *scan == 32 ) scan++; // skip any leading spaces
+ if ( *scan ) // if there is still a valid non-space character process that as the next argument
+ {
+ mArgv[argc] = scan;
+ argc++;
+ }
+ }
+ }
+ ret = mArgv;
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ bool sendData(char* ptr, size_t size, int dataType)
+ {
+ if ( size > DATA_SIZE || !mSendFile )
+ return false;
+
+ mSendCount++; // Increment the send counter.
+
+ char *baseAddress = (char *)mSendFile->getBaseAddress(); // get the base address of the shared memory
+
+ Header* header = (Header*)baseAddress;
+
+ header->mCount = mSendCount;
+ header->mType = dataType;
+
+ baseAddress+=sizeof(Header);
+ memcpy(baseAddress,ptr, size);
+
+ return true;
+ }
+
+ bool receiveData(char* ptr, size_t size, int dataType)
+ {
+ if ( size > DATA_SIZE || !mReceiveFile )
+ return false;
+
+ const char *baseAddress = (const char *)mReceiveFile->getBaseAddress();
+ const int *source = (const int *)baseAddress;
+
+ Header* header = (Header*)baseAddress;
+ if (header->mType != dataType)
+ return false;
+
+ baseAddress+=sizeof(Header);
+
+ if ( *source != mReceiveCount )
+ {
+ mReceiveCount = *source;
+ memcpy(ptr, baseAddress, size);
+ }
+
+ return true;
+ }
+
+ bool checkMessage(const char* msg)
+ {
+ if (!mReceiveFile)
+ return false;
+
+ const char *baseAddress = (const char *)mReceiveFile->getBaseAddress();
+ const int *source = (const int *)baseAddress;
+
+ if (*source == mReceiveCount)
+ return false;
+
+ if ( *source != mReceiveCount )
+ {
+ baseAddress+=sizeof(Header);
+
+ return (!strcmp(baseAddress, msg));
+ }
+
+ return false;
+ }
+
+ virtual void release(void)
+ {
+ delete this;
+ }
+
+
+};
+
+}; // end of namespace
+
+using namespace BACKDOOR;
+
+
+Backdoor * createBackdoor(const char *sendName,const char *receiveName)
+{
+ _Backdoor *ret = new _Backdoor(sendName,receiveName);
+ return static_cast< Backdoor *>(ret);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Backdoor/backdoor.h b/NvBlast/tools/ArtistTools/source/CoreLib/Backdoor/backdoor.h
new file mode 100644
index 0000000..a8ea1ac
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Backdoor/backdoor.h
@@ -0,0 +1,52 @@
+#ifndef BACKDOOR_H
+
+#define BACKDOOR_H
+
+// This is a tiny helper class that let's you easily perform communication using shared file memory between
+// two processes on the same machine. It is built to comple on Windows; but relatively minor changes
+// are necesary to make it work on other platforms; just change the memory mapped IO calls.
+//
+// This same technique would work as well if you simply opened a file on disk; though shared memory is much
+// faster.
+//
+// This is not meant to be some kind of sophisticated inter-process communciations class. Instead it's just
+// used for the very basic use case where you need to easily send simple 'commands' between two proceses.
+//
+// This code snippet comes with a console application which can be used to send commands to another process
+// and display received messaegs from that other process.
+//
+// Simply launch this console app with a command line argument indicating whether it is considered the 'server'
+// or the 'client'. You can test it by launching it twice; once as server and once as client and then send
+// chat messages back and forth.
+//
+// Written by John W. Ratcliff on February 10, 2013 and released into the public domain.
+//
+
+class Backdoor
+{
+public:
+
+ virtual void send(const char *str,...) = 0; // This sends a 'command' to the other process. Uses the printf style format for convenience.
+
+ // This method consumes an inomcing command from the other process and parses it into an argc/argv format.
+ virtual const char **getInput(int &argc) = 0;
+
+ virtual bool sendData(char* ptr, size_t size, int dataType) = 0;
+
+ virtual bool receiveData(char* ptr, size_t size, int dataType) = 0;
+
+ virtual bool checkMessage(const char* msg) = 0;
+
+ // This method releases the Backdoor interface class.
+ virtual void release(void) = 0;
+protected:
+ virtual ~Backdoor(void)
+ {
+ }
+};
+
+Backdoor * createBackdoor(const char *sendName,const char *receiveName);
+
+
+#endif
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/CoreLib.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/CoreLib.cpp
new file mode 100644
index 0000000..b94b1d9
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/CoreLib.cpp
@@ -0,0 +1,1460 @@
+#include <QtWidgets/QApplication>
+#include <QtCore/QTimer>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+#include <QtWidgets/QMessageBox>
+#include <QtCore/QFileInfo>
+
+#include "Nv.h"
+
+#include "AppMainWindow.h"
+#include "D3DWidget.h"
+#include "SimpleScene.h"
+#include "Automate.h"
+#include "Settings.h"
+#include "RenderInterface.h"
+#include "GlobalSettings.h"
+
+#ifndef NV_ARTISTTOOLS
+#include "FurCharacter.h"
+#include "PluginBlast.h"
+#endif // NV_ARTISTTOOLS
+
+#include "RenderPlugin.h"
+
+void SetupStyles()
+{
+ //QFile styleFile( ":/AppMainWindow/ThemeDefault.qss" );
+ QString appPath = QCoreApplication::applicationDirPath();
+ QString themeFilePath = appPath + "/ArtistToolsTheme.qss";
+ QFile styleFile;
+ if (QFile::exists(themeFilePath))
+ {
+ styleFile.setFileName(themeFilePath);
+ }
+ else
+ {
+ styleFile.setFileName(":/AppMainWindow/ThemeDark.qss");
+ }
+ styleFile.open(QFile::ReadOnly);
+
+ QString styleSheet(styleFile.readAll());
+ QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
+ qApp->setStyleSheet(styleSheet);
+}
+
+int ShowErrorMsg(int errorCode)
+{
+ const char* errorMsg = 0;
+ switch (errorCode)
+ {
+ case 1:
+ errorMsg = "Fail to create GPU device and context. "
+ "Please make sure you are using an independant GPU and choose '3D App - Game Development' in the Global Settings page in its Control Panel.";
+ break;
+ case 2:
+ errorMsg = "Fail to initialize all the shared shaders, resources, etc. "
+ "Please make sure you are using an independant GPU and choose '3D App - Game Development' in the Global Settings page in its Control Panel.";
+ break;
+ case 3:
+ errorMsg = "Fail to create render window, target, swap chains, etc. "
+ "Please make sure you are using an independant GPU and choose '3D App - Game Development' in the Global Settings page in its Control Panel.";
+ break;
+ case 4:
+ // Unable to load/start the dll.
+ errorMsg = "Unable to load and/or start the Blast dll. "
+ "Please make sure the appropriate hairworks dll is the same directory as the viewer executable.";
+ break;
+ default:
+ errorMsg = "We need define one error message!";
+ }
+ QMessageBox messageBox;
+ messageBox.information(0, "Error", errorMsg);
+ return errorCode;
+}
+
+extern void CreateAppMainWindow();
+extern void ReleaseAppMainWindow();
+
+int RunApp(QApplication& app)
+{
+ CreateAppMainWindow();
+
+ // resolution
+ int windowWidth = 0;
+ int windowHeight = 0;
+ std::string resolution = AppSettings::Inst().GetOptionValue("User/Resolution")->Value.Enum;
+ int width, height;
+ sscanf(resolution.c_str(), "%dx%d", &windowWidth, &windowHeight);
+
+ // aa sample count
+ int sampleCount = 8;
+ if (stricmp(AppSettings::Inst().GetOptionValue("User/AA")->Value.Enum, "2X") == 0)
+ {
+ sampleCount = 2;
+ }
+ else if (stricmp(AppSettings::Inst().GetOptionValue("User/AA")->Value.Enum, "4X") == 0)
+ {
+ sampleCount = 4;
+ }
+ else if (stricmp(AppSettings::Inst().GetOptionValue("User/AA")->Value.Enum, "8X") == 0)
+ {
+ sampleCount = 8;
+ }
+ else if (stricmp(AppSettings::Inst().GetOptionValue("User/AA")->Value.Enum, "Off") == 0)
+ {
+ sampleCount = 1;
+ }
+
+ // device id
+ int deviceID = (AppSettings::Inst().GetOptionValue("User/Device")->Value.Int);
+ if (deviceID < 0 || deviceID > 3)
+ {
+ deviceID = -1; // when -1 to choose a good GPU
+ }
+
+ // backdoor connection mode
+ int backdoor = 0;
+ if (stricmp(AppSettings::Inst().GetOptionValue("User/Backdoor")->Value.String, "master") == 0)
+ {
+ backdoor = 1;
+ }
+ else if (stricmp(AppSettings::Inst().GetOptionValue("User/Backdoor")->Value.String, "slave") == 0)
+ {
+ backdoor = 2;
+ }
+
+ AppMainWindow::setConnectionMode(backdoor);
+
+ SimpleScene::Inst();
+#ifdef NV_ARTISTTOOLS
+ CoreLib::Inst()->SimpleScene_SimpleScene();
+#endif // NV_ARTISTTOOLS
+ // initialize main window
+ // HAIR-285 Viewer - new command line to start Viewer in full screen
+ AppMainWindow::Inst().InitUI();
+ if (windowWidth == 0)
+ AppMainWindow::Inst().showFullScreen();
+ else if (windowWidth<0)
+ AppMainWindow::Inst().showMaximized();
+ else
+ AppMainWindow::Inst().resize(windowWidth, windowHeight);
+
+ D3DWidget* d3dWidget = AppMainWindow::Inst().GetRenderWidget();
+
+ HWND hWidget = (HWND)d3dWidget->winId();
+
+ // create GPU device and context
+ if (false == RenderInterface::InitDevice(deviceID))
+ return ShowErrorMsg(1);
+
+ // initialize all the shared shaders, resources, etc
+ if (false == RenderInterface::Initialize())
+ return ShowErrorMsg(2);
+
+ // create render window, target, swap chains, etc.
+ if (false == RenderInterface::CreateRenderWindow(hWidget, sampleCount))
+ return ShowErrorMsg(3);
+
+ SimpleScene* scene = SimpleScene::Inst();
+ if (false == scene->Initialize(hWidget, backdoor))
+ return ShowErrorMsg(4);
+
+ GlobalSettings::Inst().setRenderFps(60);
+
+ GlobalSettings::GetFrameTimer().start();
+
+ QObject::connect(&GlobalSettings::GetFrameTimer(), SIGNAL(timeout()), d3dWidget, SLOT(Timeout()));
+ QObject::connect(&app, SIGNAL(aboutToQuit()), d3dWidget, SLOT(Shutdown()));
+
+ SetupStyles();
+
+ AppMainWindow::Inst().show();
+ AppMainWindow::Inst().update();
+
+ std::string title = "";
+
+#ifdef NV_ARTISTTOOLS
+ title = "ArtistTools";
+#else
+ title = "Blast Viewer";
+#endif // NV_ARTISTTOOLS
+
+#ifdef _WIN64
+ title.append(" x64");
+#endif
+
+#ifdef _DEBUG
+ title.append(" (Debug)");
+#else
+#endif
+
+ std::string strApi = RenderPlugin::Instance()->GetRenderApi();
+ title.append(" ");
+ title.append(strApi);
+
+ switch (backdoor)
+ {
+ case 1:
+ title.append(" (Master Mode)");
+ break;
+ case 2:
+ title.append(" (Slave Mode)");
+ break;
+ }
+
+ AppMainWindow::Inst().setWindowTitle(title.c_str());
+
+ OptionValue* option = AppSettings::Inst().GetOptionValue("User/HideUI");
+ if (option)
+ {
+ if (option->Value.Bool == OA_TRUE)
+ {
+ AppMainWindow::Inst().shortcut_expert();
+ }
+ }
+
+#ifndef NV_ARTISTTOOLS
+ option = AppSettings::Inst().GetOptionValue("User/FurAssetPath");
+ if (option && option->Value.String && strlen(option->Value.String))
+ {
+ const char* path = option->Value.String;
+ QFileInfo fi(path);
+ QByteArray dir = QDir::toNativeSeparators(fi.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fi.fileName().toLocal8Bit();
+ scene->GetFurCharacter().LoadHairAsset(dir, file);
+ }
+#else
+ CoreLib::Inst()->CoreLib_RunApp();
+#endif // NV_ARTISTTOOLS
+
+ option = AppSettings::Inst().GetOptionValue("User/ProjectPath");
+ if (option && option->Value.String && strlen(option->Value.String))
+ {
+ const char* path = option->Value.String;
+ QFileInfo fi(path);
+ QByteArray dir = QDir::toNativeSeparators(fi.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fi.fileName().toLocal8Bit();
+ scene->LoadProject(dir, file);
+ }
+ option = AppSettings::Inst().GetOptionValue("User/Play");
+ if (option)
+ {
+ if (option->Value.Bool == OA_TRUE)
+ {
+ AppMainWindow::Inst().shortcut_pause();
+ }
+ }
+
+ int ret = app.exec();
+ // release GUI before releasing QApplication (and QWindowsContext) to avoid crash.
+ // e.g. GWDCC-415 Blast Viewer crashes when quit after clicked any main menu.
+ ReleaseAppMainWindow();
+ return ret;
+}
+
+static void ShowUsage()
+{
+ char message[] = {
+ "FurViewer Command-line Options:\n\n"
+ "Usage: FurViewer.[win64|win32].exe [file] [options]...\n\n"
+ "[file]: \n"
+ "\t: File to load. .furproj, .apx or .apb are supported.\n\t ex) media/HairBall/Hairball.furproj\n\n"
+ "[options]:\n"
+ "-size <width>x<height>\n\t: Window resolution\t ex) -size 1024x768\n"
+ "-aa <1|2|4|8>\n\t: MSAA anti-aliasing options. 1 for off.\t ex) -aa 4 or -aa 1\n"
+ "-backdoor <master|slave>\n\t: Backdoor options\n"
+ "-device <0|1|2|3>\n\t: Which GPU to use\n"
+ "-noui \n\t: Set this option to hide UI\n"
+ "-play \n\t: Play the default animation if it has\n"
+ "-fullscreen \n\t: Start the application in full screen\n"
+ "-maxscreen \n\t: Start the application in max sized screen\n"
+ "-demoMode playlistname.plist \n\t: Start the application and demo the projects in a fur playlist stored in media/playlists folder.\n"
+ };
+ QMessageBox messageBox;
+ messageBox.information(0, "Usage", message);
+}
+
+bool ParseCommandLineOptions(int argc, char* argv[])
+{
+ AppSettings& settings = AppSettings::Inst();
+
+ for (int idx = 1; idx < argc; ++idx)
+ {
+ if (!stricmp(argv[idx], "-size"))
+ {
+ if ((idx + 1) < argc)
+ {
+ oaValue value;
+ value.Enum = argv[idx + 1];
+ settings.SetOptionValue("User/Resolution", OA_TYPE_ENUM, &value);
+ idx++; // Skip next option
+ }
+ }
+ else if (!stricmp(argv[idx], "-fullscreen"))
+ {
+ // HAIR-285 Viewer - new command line to start Viewer in full screen
+ oaValue value;
+ value.Enum = "0x0";
+ settings.SetOptionValue("User/Resolution", OA_TYPE_ENUM, &value);;
+ }
+ else if (!stricmp(argv[idx], "-maxscreen"))
+ {
+ // HAIR-285 Viewer - new command line to start Viewer in full screen
+ oaValue value;
+ value.Enum = "-1x0";
+ settings.SetOptionValue("User/Resolution", OA_TYPE_ENUM, &value);;
+ }
+ else if (!stricmp(argv[idx], "-backdoor"))
+ {
+ if ((idx + 1) < argc)
+ {
+ oaValue value;
+ bool isValid = true;
+ if (!strcmp(argv[idx + 1], "master"))
+ value.String = "master";
+ else if (!strcmp(argv[idx + 1], "slave"))
+ value.String = "slave";
+ else
+ isValid = false;
+
+ if (isValid)
+ settings.SetOptionValue("User/Backdoor", OA_TYPE_STRING, &value);
+ idx++; // Skip next option
+ }
+ }
+ else if (!stricmp(argv[idx], "-aa"))
+ {
+ if ((idx + 1) < argc)
+ {
+ oaValue value;
+ bool isValid = true;
+ if (!strcmp(argv[idx + 1], "1"))
+ value.Enum = "Off";
+ else if (!strcmp(argv[idx + 1], "2"))
+ value.Enum = "2X";
+ else if (!strcmp(argv[idx + 1], "4"))
+ value.Enum = "4X";
+ else if (!strcmp(argv[idx + 1], "8"))
+ value.Enum = "8X";
+ else
+ isValid = false;
+ if (isValid)
+ settings.SetOptionValue("User/AA", OA_TYPE_ENUM, &value);
+ idx++; // Skip next option
+ }
+ }
+ else if (!stricmp(argv[idx], "-device"))
+ {
+ if ((idx + 1) < argc)
+ {
+ oaValue value;
+ bool isValid = true;
+ if (!strcmp(argv[idx + 1], "0"))
+ value.Int = 0;
+ else if (!strcmp(argv[idx + 1], "1"))
+ value.Int = 1;
+ else if (!strcmp(argv[idx + 1], "2"))
+ value.Int = 2;
+ else if (!strcmp(argv[idx + 1], "3"))
+ value.Int = 3;
+ else
+ isValid = false;
+ if (isValid)
+ settings.SetOptionValue("User/Device", OA_TYPE_INT, &value);
+ idx++; // Skip next option
+ }
+ }
+ else if (!stricmp(argv[idx], "-noui"))
+ {
+ oaValue value;
+ value.Bool = OA_TRUE;
+ settings.SetOptionValue("User/HideUI", OA_TYPE_BOOL, &value);
+ }
+ else if (!stricmp(argv[idx], "-perf"))
+ {
+ oaValue value;
+ value.Bool = OA_TRUE;
+ settings.SetOptionValue("User/PerfMode", OA_TYPE_BOOL, &value);
+ }
+ else if (!stricmp(argv[idx], "-play"))
+ {
+ oaValue value;
+ value.Bool = OA_TRUE;
+ settings.SetOptionValue("User/Play", OA_TYPE_BOOL, &value);
+ }
+ else if (!stricmp(argv[idx], "-install"))
+ {
+ // Install mode
+ // Just ignore here
+ }
+ else if (!stricmp(argv[idx], "-openautomate"))
+ {
+ // OpenAutomate mode
+ // Just ignore here
+ idx++; // Skip next option
+ }
+ else if (!stricmp(argv[idx], "-demoMode"))
+ {
+ //QMessageBox messageBox;
+ //messageBox.information(0, "debug", argv[idx]);
+ idx++; // check next arg
+ if (idx < argc)
+ {
+ bool isValid = false;
+ char* extension = strrchr(argv[idx], '.');
+ if (extension)
+ {
+ if (!_stricmp(extension, ".plist"))
+ {
+ oaValue value;
+ value.String = argv[idx];
+ settings.SetOptionValue("User/FurDemoPlaylist", OA_TYPE_STRING, &value);
+ isValid = true;
+ }
+ }
+ }
+ }
+ else // Try to load the file
+ {
+ bool isValid = false;
+ char* extension = strrchr(argv[idx], '.');
+ if (extension)
+ {
+ if (!_stricmp(extension, ".furproj"))
+ {
+ oaValue value;
+ value.String = argv[idx];
+ settings.SetOptionValue("User/ProjectPath", OA_TYPE_STRING, &value);
+ isValid = true;
+ }
+ else if (!_stricmp(extension, ".apx") || !_stricmp(extension, ".apb"))
+ {
+ oaValue value;
+ value.String = argv[idx];
+ settings.SetOptionValue("User/FurAssetPath", OA_TYPE_STRING, &value);
+ isValid = true;
+ }
+ }
+ if (!isValid)
+ {
+ // Invalid option
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+typedef RenderPlugin*(*Func)(void);
+
+void GetRenderPlugins(QApplication& app, std::vector<std::string>& render_plugins)
+{
+ HMODULE module = NULL;
+ Func CreateFunc = NULL;
+ RenderPlugin* Plugin = NULL;
+
+ QDir pluginsDir(app.applicationDirPath());
+ foreach(QString fileName, pluginsDir.entryList(QDir::Files)) {
+#ifdef NV_ARTISTTOOLS
+ if (!fileName.startsWith("Render"))
+#else
+ if (!fileName.startsWith("FurRender"))
+#endif
+ {
+ continue;
+ }
+
+#ifdef _WIN64
+#ifdef _DEBUG
+ if (!fileName.endsWith(".win64.d.dll"))
+ {
+ continue;
+ }
+#else
+ if (!fileName.endsWith(".win64.dll"))
+ {
+ continue;
+ }
+#endif
+#else
+#ifdef _DEBUG
+ if (!fileName.endsWith(".win32.d.dll"))
+ {
+ continue;
+ }
+#else
+ if (!fileName.endsWith(".win32.dll"))
+ {
+ continue;
+ }
+#endif
+#endif
+
+ QByteArray tmp = pluginsDir.absoluteFilePath(fileName).toUtf8();
+ const char* pName = tmp.data();
+ module = LoadLibraryA(pName);
+ if (NULL == module)
+ continue;
+
+ CreateFunc = (Func)GetProcAddress(module, "CreateRenderPlugin");
+ if (NULL == CreateFunc)
+ continue;
+
+ Plugin = CreateFunc();
+ if (NULL != Plugin)
+ {
+ std::string name = Plugin->GetRenderApi();
+ render_plugins.push_back(name);
+ delete Plugin;
+ Plugin = NULL;
+ }
+ }
+}
+
+
+#include "RenderPlugin.h"
+#include "CoreLib.h"
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#define LINE 10
+
+#ifndef NV_ARTISTTOOLS
+int CoreLib::CoreMain(int argc, char *argv[])
+#else
+int CoreLib::CoreMain(int argc, char *argv[], bool withPlugin)
+#endif
+{
+#ifdef OPEN_CONSOLE
+ AllocConsole();
+ freopen("CONOUT$", "w", stdout);
+ freopen("CONOUT$", "w", stderr);
+#endif
+
+ QApplication a(argc, argv);
+
+ AppSettings::Inst().InitOptions();
+
+ if (!ParseCommandLineOptions(argc, argv))
+ {
+ // Invalid option. Show the usage and quit
+ ShowUsage();
+ return 0;
+ }
+#if (0) // Install mode for OpenAutomate is not tested yet
+ bool isAutomateInstallMode = GetAutomateInstallModeOption(argc, argv);
+ if (isAutomateInstallMode)
+ {
+ if (AutomateInstallApp())
+ {
+ QMessageBox messageBox;
+ messageBox.information(0, "Info", "Install succeeded");
+ }
+ else
+ {
+ QMessageBox messageBox;
+ messageBox.information(0, "Info", "Install failed. Did you run with admin privilege?");
+ }
+ return 0;
+ }
+#endif
+ std::string openAutomateOptions = GetAutomateOption(argc, argv);
+ if (!openAutomateOptions.empty())
+ {
+ AutomateInit(openAutomateOptions.c_str());
+ }
+
+ std::vector<std::string> render_plugins;
+ std::vector<std::string>::iterator it;
+
+ FILE *pf;
+ if ((_access("RenderPlugin.txt", 0)) == -1)
+ {
+ GetRenderPlugins(a, render_plugins);
+
+ if (render_plugins.size() > 1)
+ {
+ pf = fopen("RenderPlugin.txt", "a");
+ for (it = render_plugins.begin(); it != render_plugins.end(); it++)
+ {
+ fprintf(pf, "%s\n", (*it).c_str());
+ }
+ fclose(pf);
+ }
+ }
+ else
+ {
+ pf = fopen("RenderPlugin.txt", "r");
+ char buf[LINE];
+ while (1) {
+ memset(buf, 0, LINE);
+ if (fscanf(pf, "%s", buf) == -1)
+ break;
+ render_plugins.push_back(buf);
+ }
+ fclose(pf);
+ }
+
+ RenderPlugin::Load(render_plugins);
+
+ std::string strApi = RenderPlugin::Instance()->GetRenderApi();
+ if ("" == strApi)
+ {
+ return -1;
+ }
+
+#ifdef NV_ARTISTTOOLS
+ if (withPlugin)
+ {
+ LoadPlugins(a);
+ }
+#else
+ bool loaded = PluginBlast::Create(strApi);
+ if (!loaded)
+ {
+ return -1;
+ }
+#endif
+
+ return RunApp(a);
+}
+
+CoreLib::CoreLib()
+{
+
+}
+
+CoreLib::~CoreLib()
+{
+
+}
+
+CoreLib* CoreLib::Inst()
+{
+ static CoreLib coreLib;
+ return &coreLib;
+}
+
+#ifdef NV_ARTISTTOOLS
+#include <QtWidgets/QApplication>
+#include <QtCore/QTimer>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+#include <QtWidgets/QMessageBox>
+#include <QtCore/QFileInfo>
+
+#include "Nv.h"
+
+#include "AppMainWindow.h"
+#include "D3DWidget.h"
+#include "SimpleScene.h"
+#include "Automate.h"
+#include "Settings.h"
+#include "RenderInterface.h"
+#include "Light.h"
+
+#include <QtCore/QPluginLoader>
+void CoreLib::LoadPlugins(QApplication& app)
+{
+ QDir pluginsDir(app.applicationDirPath());
+ foreach(QString fileName, pluginsDir.entryList(QDir::Files)) {
+ if (!fileName.startsWith("Plugin"))
+ {
+ continue;
+ }
+
+#ifdef _WIN64
+#ifdef _DEBUG
+ if (!fileName.endsWith(".win64.d.dll"))
+ {
+ continue;
+ }
+#else
+ if (!fileName.endsWith(".win64.dll"))
+ {
+ continue;
+ }
+#endif
+#else
+#ifdef _DEBUG
+ if (!fileName.endsWith(".win32.d.dll"))
+ {
+ continue;
+ }
+#else
+ if (!fileName.endsWith(".win32.dll"))
+ {
+ continue;
+ }
+#endif
+#endif
+
+ PluginInterface* pInterface;
+ QByteArray tmp = pluginsDir.absoluteFilePath(fileName).toUtf8();
+ const char* pName = tmp.data();
+ QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
+ QObject *plugin = pluginLoader.instance();
+ if (plugin) {
+ pInterface = qobject_cast<PluginInterface *>(plugin);
+ if (pInterface)
+ {
+ std::string strApi = RenderPlugin::Instance()->GetRenderApi();
+ bool loaded = pInterface->LoadRenderPlugin(strApi);
+ if (!loaded)
+ {
+ continue;
+ }
+
+ QString name = pInterface->GetPluginName();
+ m_PluginInterfaces[name] = pInterface;
+ }
+ }
+ else
+ {
+ QMessageBox::critical(nullptr, "", pluginLoader.errorString());
+ }
+ }
+}
+
+PluginInterface* CoreLib::GetPluginInterface(QString name)
+{
+ PluginInterface* pPluginInterface = 0;
+ std::map<QString, PluginInterface*>::iterator it;
+ it = m_PluginInterfaces.find(name);
+ if (it != m_PluginInterfaces.end())
+ {
+ pPluginInterface = it->second;
+ }
+ return pPluginInterface;
+}
+
+bool CoreLib::GetBoneNames(std::vector<std::string>& BoneNames)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->GetBoneNames(BoneNames))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::CoreLib_RunApp()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->CoreLib_RunApp())
+ break;
+ }
+
+ return true;
+}
+
+bool CoreLib::MainToolbar_updateValues()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->MainToolbar_updateValues())
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::CurveEditor_updateValues(int _paramId, float* _values)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->CurveEditor_updateValues(_paramId, _values))
+ break;
+ }
+ return true;
+}
+bool CoreLib::CurveEditor_onUpdateValues(int _paramId, float* _values)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->CurveEditor_onUpdateValues(_paramId, _values))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::DisplayMeshesPanel_updateValues()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->DisplayMeshesPanel_updateValues())
+ break;
+ }
+ return true;
+}
+bool CoreLib::DisplayMeshesPanel_EmitToggleSignal(unsigned int id, bool visible)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->DisplayMeshesPanel_EmitToggleSignal(id, visible))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::Camera_LoadParameters(void* ptr, Camera* pCamera)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->Camera_LoadParameters(ptr, pCamera))
+ break;
+ }
+ return true;
+}
+bool CoreLib::Camera_SaveParameters(void* ptr, Camera* pCamera)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->Camera_SaveParameters(ptr, pCamera))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::Light_loadParameters(NvParameterized::Handle& handle, Light* pLight)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->Light_loadParameters(handle, pLight))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::Light_saveParameters(NvParameterized::Handle& handle, Light* pLight)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->Light_saveParameters(handle, pLight))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::Gamepad_ToggleSimulation()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->Gamepad_ToggleSimulation())
+ break;
+ }
+ return true;
+}
+bool CoreLib::Gamepad_LoadSamples(QString fn)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->Gamepad_LoadSamples(fn))
+ break;
+ }
+ return true;
+}
+bool CoreLib::Gamepad_ResetScene()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->Gamepad_ResetScene())
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::Gamepad_StartAnimation()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->Gamepad_StartAnimation())
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::GamepadHandler_ShowHair()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->GamepadHandler_ShowHair())
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::GamepadHandler_SpinWindStrength(float windStrength)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->GamepadHandler_SpinWindStrength(windStrength))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::Gamepad_ResetAnimation()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->Gamepad_ResetAnimation())
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::Gamepad_PlayPauseAnimation()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->Gamepad_PlayPauseAnimation())
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::SimpleScene_SimpleScene()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_SimpleScene())
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_Initialize(int backdoor)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_Initialize(backdoor))
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_Shutdown()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_Shutdown())
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_Clear()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_Clear())
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_Draw_DX12()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_Draw_DX12())
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_Draw_DX11()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_Draw_DX11())
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_FitCamera(atcore_float3& center, atcore_float3& extents)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_FitCamera(center, extents))
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_DrawGround()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_DrawGround())
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_DrawWind()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_DrawWind())
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_DrawAxis()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_DrawAxis())
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_LoadSceneFromFbx(const char* dir, const char* fbxName)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_LoadSceneFromFbx(dir, fbxName))
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_LoadProject(const char* dir, const char* file)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_LoadProject(dir, file))
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_SaveProject(const char* dir, const char* file)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_SaveProject(dir, file))
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_LoadParameters(NvParameterized::Interface* iface)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_LoadParameters(iface))
+ break;
+ }
+ return true;
+}
+bool CoreLib::SimpleScene_SaveParameters(NvParameterized::Interface* iface)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_SaveParameters(iface))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::SimpleScene_LoadCameraBookmarks(NvParameterized::Interface* iface)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_LoadCameraBookmarks(iface))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::SimpleScene_SaveCameraBookmarks(NvParameterized::Interface* iface)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->SimpleScene_SaveCameraBookmarks(iface))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::D3DWidget_resizeEvent(QResizeEvent* e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_resizeEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_paintEvent(QPaintEvent* e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_paintEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_mousePressEvent(QMouseEvent* e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_mousePressEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_mouseReleaseEvent(QMouseEvent* e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_mouseReleaseEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_mouseMoveEvent(QMouseEvent* e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_mouseMoveEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_wheelEvent(QWheelEvent * e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_wheelEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_keyPressEvent(QKeyEvent* e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_keyPressEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_keyReleaseEvent(QKeyEvent* e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_keyReleaseEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_dragEnterEvent(QDragEnterEvent *e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_dragEnterEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_dragMoveEvent(QDragMoveEvent *e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_dragMoveEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_dragLeaveEvent(QDragLeaveEvent *e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_dragLeaveEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_dropEvent(QDropEvent *e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_dropEvent(e))
+ break;
+ }
+ return true;
+}
+bool CoreLib::D3DWidget_contextMenuEvent(QContextMenuEvent *e)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3DWidget_contextMenuEvent(e))
+ break;
+ }
+ return true;
+}
+
+#ifdef NV_ARTISTTOOLS
+bool CoreLib::D3D11Shaders_InitializeShadersD3D11(std::map<int, D3D11RenderShader*>& ShaderMap)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->D3D11Shaders_InitializeShadersD3D11(ShaderMap))
+ break;
+ }
+ return true;
+}
+#endif // NV_ARTISTTOOLS
+
+bool CoreLib::AppMainWindow_AppMainWindow()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_AppMainWindow())
+ break;
+ }
+ return true;
+}
+bool CoreLib::AppMainWindow_InitMenuItems(QMenuBar* pMenuBar)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_InitMenuItems(pMenuBar))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_InitMainTab(QWidget *displayScrollAreaContents, QVBoxLayout *displayScrollAreaLayout, int idx)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_InitMainTab(displayScrollAreaContents, displayScrollAreaLayout, idx))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_InitPluginTab(QTabWidget* pTabWidget)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_InitPluginTab(pTabWidget))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_InitUI()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_InitUI())
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_updateUI()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_updateUI())
+ break;
+ }
+ return true;
+}
+bool CoreLib::AppMainWindow_updatePluginUI()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_updatePluginUI())
+ break;
+ }
+ return true;
+}
+bool CoreLib::AppMainWindow_processDragAndDrop(QString fname)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_processDragAndDrop(fname))
+ break;
+ }
+ return true;
+}
+bool CoreLib::AppMainWindow_closeEvent(QCloseEvent *event)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_closeEvent(event))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_menu_about()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_menu_about())
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_menu_opendoc()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_menu_opendoc())
+ break;
+ }
+ return true;
+}
+#if USE_CURVE_EDITOR
+bool CoreLib::AppMainWindow_UpdateCurveEditor()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_UpdateCurveEditor())
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_ShowCurveEditor(int paramId)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_ShowCurveEditor(paramId))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_onCurveAttributeChanged(attribute))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_onColorAttributeChanged(attribute))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_onReloadColorAttributeTexture(attribute, reloadColorTex, selectedCtrlPntIndex))
+ break;
+ }
+ return true;
+}
+#endif
+bool CoreLib::AppMainWindow_InitToolbar(QWidget *pQWidget, QVBoxLayout* pLayout)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_InitToolbar(pQWidget, pLayout))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_shortcut_expert(bool mode)
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_shortcut_expert(mode))
+ break;
+ }
+ return true;
+}
+
+bool CoreLib::AppMainWindow_updateMainToolbar()
+{
+ std::map<QString, PluginInterface*>::iterator it;
+ for (it = m_PluginInterfaces.begin(); it != m_PluginInterfaces.end(); it++)
+ {
+ if (!(it->second)->AppMainWindow_updateMainToolbar())
+ break;
+ }
+ return true;
+}
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/CoreLib.h b/NvBlast/tools/ArtistTools/source/CoreLib/CoreLib.h
new file mode 100644
index 0000000..3d86bcf
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/CoreLib.h
@@ -0,0 +1,121 @@
+#ifndef CORELIB_H
+#define CORELIB_H
+
+#include "corelib_global.h"
+#include "PluginInterface.h"
+#include "NvParameterized.h"
+#if USE_CURVE_EDITOR
+#include <Attribute.h>
+#endif
+
+class QCloseEvent;
+class Camera;
+class Light;
+namespace NvParameterized
+{
+ class Interface;
+ class Handle;
+}
+class D3D11RenderShader;
+
+class CORELIB_EXPORT CoreLib
+{
+public:
+ CoreLib();
+ ~CoreLib();
+
+ static CoreLib* Inst();
+#ifndef NV_ARTISTTOOLS
+ int CoreMain(int argc, char *argv[]);
+#else
+ int CoreMain(int argc, char *argv[], bool withPlugin = true);
+
+ bool CoreLib_RunApp();
+ void LoadPlugins(QApplication& app);
+ PluginInterface* GetPluginInterface(QString name);
+
+ bool GetBoneNames(std::vector<std::string>& BoneNames);
+ bool MainToolbar_updateValues();
+
+ bool CurveEditor_updateValues(int _paramId, float* _values);
+ bool CurveEditor_onUpdateValues(int _paramId, float* _values);
+
+ bool DisplayMeshesPanel_updateValues();
+ bool DisplayMeshesPanel_EmitToggleSignal(unsigned int id, bool visible);
+
+ bool Camera_LoadParameters(void* ptr, Camera* pCamera);
+ bool Camera_SaveParameters(void* ptr, Camera* pCamera);
+ bool Light_loadParameters(NvParameterized::Handle& handle, Light* pLight);
+ bool Light_saveParameters(NvParameterized::Handle& handle, Light* pLight);
+
+ bool Gamepad_ToggleSimulation();
+ bool Gamepad_LoadSamples(QString fn);
+ bool Gamepad_ResetScene();
+ bool Gamepad_StartAnimation();
+ bool GamepadHandler_ShowHair();
+ bool GamepadHandler_SpinWindStrength(float windStrength);
+ bool Gamepad_ResetAnimation();
+ bool Gamepad_PlayPauseAnimation();
+
+ bool SimpleScene_SimpleScene();
+ bool SimpleScene_Initialize(int backdoor);
+ bool SimpleScene_Shutdown();
+ bool SimpleScene_Clear();
+ bool SimpleScene_Draw_DX12();
+ bool SimpleScene_Draw_DX11();
+ bool SimpleScene_FitCamera(atcore_float3& center, atcore_float3& extents);
+ bool SimpleScene_DrawGround();
+ bool SimpleScene_DrawWind();
+ bool SimpleScene_DrawAxis();
+ bool SimpleScene_LoadSceneFromFbx(const char* dir, const char* fbxName);
+ bool SimpleScene_LoadProject(const char* dir, const char* file);
+ bool SimpleScene_SaveProject(const char* dir, const char* file);
+ bool SimpleScene_LoadParameters(NvParameterized::Interface* iface);
+ bool SimpleScene_SaveParameters(NvParameterized::Interface* iface);
+ bool SimpleScene_LoadCameraBookmarks(NvParameterized::Interface* iface);
+ bool SimpleScene_SaveCameraBookmarks(NvParameterized::Interface* iface);
+
+ bool D3DWidget_resizeEvent(QResizeEvent* e);
+ bool D3DWidget_paintEvent(QPaintEvent* e);
+ bool D3DWidget_mousePressEvent(QMouseEvent* e);
+ bool D3DWidget_mouseReleaseEvent(QMouseEvent* e);
+ bool D3DWidget_mouseMoveEvent(QMouseEvent* e);
+ bool D3DWidget_wheelEvent(QWheelEvent * e);
+ bool D3DWidget_keyPressEvent(QKeyEvent* e);
+ bool D3DWidget_keyReleaseEvent(QKeyEvent* e);
+ bool D3DWidget_dragEnterEvent(QDragEnterEvent *e);
+ bool D3DWidget_dragMoveEvent(QDragMoveEvent *e);
+ bool D3DWidget_dragLeaveEvent(QDragLeaveEvent *e);
+ bool D3DWidget_dropEvent(QDropEvent *e);
+ bool D3DWidget_contextMenuEvent(QContextMenuEvent *e);
+
+ bool D3D11Shaders_InitializeShadersD3D11(std::map<int, D3D11RenderShader*>& ShaderMap);
+
+ bool AppMainWindow_AppMainWindow();
+ bool AppMainWindow_InitMenuItems(QMenuBar* pMenuBar);
+ bool AppMainWindow_InitMainTab(QWidget *displayScrollAreaContents, QVBoxLayout *displayScrollAreaLayout, int idx);
+ bool AppMainWindow_InitPluginTab(QTabWidget* pTabWidget);
+ bool AppMainWindow_InitUI();
+ bool AppMainWindow_updateUI();
+ bool AppMainWindow_updatePluginUI();
+ bool AppMainWindow_processDragAndDrop(QString fname);
+ bool AppMainWindow_closeEvent(QCloseEvent *event);
+ bool AppMainWindow_InitToolbar(QWidget *pQWidget, QVBoxLayout* pLayout);
+ bool AppMainWindow_shortcut_expert(bool mode);
+ bool AppMainWindow_updateMainToolbar();
+
+ bool AppMainWindow_menu_about();
+ bool AppMainWindow_menu_opendoc();
+#if USE_CURVE_EDITOR
+ bool AppMainWindow_UpdateCurveEditor();
+ bool AppMainWindow_ShowCurveEditor(int paramId);
+ bool AppMainWindow_onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute);
+ bool AppMainWindow_onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute);
+ bool AppMainWindow_onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex);
+#endif
+private:
+ std::map<QString, PluginInterface*> m_PluginInterfaces;
+#endif // NV_ARTISTTOOLS
+};
+
+#endif // CORELIB_H
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Parameters/FoundationHolder.h b/NvBlast/tools/ArtistTools/source/CoreLib/Parameters/FoundationHolder.h
new file mode 100644
index 0000000..5ec7868
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Parameters/FoundationHolder.h
@@ -0,0 +1,138 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "NvErrorCallback.h"
+#include "NsGlobals.h"
+#include "NsVersionNumber.h"
+
+class DefaultErrorCallback : public nvidia::NvErrorCallback
+{
+public:
+ DefaultErrorCallback(void)
+ {
+ }
+
+ virtual void reportError(nvidia::NvErrorCode::Enum code, const char* message, const char* file, int line)
+ {
+ NV_UNUSED(code);
+ printf("PhysX: %s : %s : %d\r\n", message, file, line);
+ }
+private:
+};
+
+class DefaultAllocator : public nvidia::NvAllocatorCallback
+{
+public:
+ DefaultAllocator(void)
+ {
+ }
+
+ ~DefaultAllocator(void)
+ {
+ }
+
+ virtual void* allocate(size_t size, const char* typeName, const char* filename, int line)
+ {
+ NV_UNUSED(typeName);
+ NV_UNUSED(filename);
+ NV_UNUSED(line);
+ void *ret = ::_aligned_malloc(size, 16);
+ return ret;
+ }
+
+ virtual void deallocate(void* ptr)
+ {
+ ::_aligned_free(ptr);
+ }
+private:
+};
+
+
+#if 0
+class FoundationHolder
+{
+ NvFoundation* mFoundation;
+ FoundationHolder()
+ :mFoundation(nullptr)
+ {
+ }
+
+ ~FoundationHolder()
+ {
+ if (mFoundation)
+ {
+ // to-do
+ // we should release foundation. but Hair SDK could release it first.
+ //mFoundation->release();
+ mFoundation = nullptr;
+ }
+ }
+
+public:
+
+ static NvFoundation* GetFoundation()
+ {
+ static FoundationHolder fh;
+ if (fh.mFoundation == nullptr)
+ {
+ static DefaultAllocator sDefaultAllocator;
+ static DefaultErrorCallback sDefaultErrorCallback;
+ fh.mFoundation = NvCreateFoundation(NV_FOUNDATION_VERSION, sDefaultAllocator, sDefaultErrorCallback);
+ assert(fh.mFoundation != nullptr);
+ }
+ return fh.mFoundation;
+ }
+};
+
+#else
+
+class FoundationHolder
+{
+ bool m_isInitialized;
+ public:
+ static void GetFoundation()
+ {
+ static FoundationHolder s_holder;
+ if (!s_holder.m_isInitialized)
+ {
+ static DefaultAllocator sDefaultAllocator;
+ static DefaultErrorCallback sDefaultErrorCallback;
+ nvidia::shdfnd::initializeSharedFoundation(NV_FOUNDATION_VERSION, sDefaultAllocator, sDefaultErrorCallback);
+
+ s_holder.m_isInitialized = true;
+ }
+ }
+ ~FoundationHolder()
+ {
+ //nvidia::terminateSharedFoundation();
+ }
+};
+
+#endif
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/PluginInterface.h b/NvBlast/tools/ArtistTools/source/CoreLib/PluginInterface.h
new file mode 100644
index 0000000..aae8da8
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/PluginInterface.h
@@ -0,0 +1,137 @@
+#ifndef BlastInterface_H
+#define BlastInterface_H
+
+#include <QtCore/QString>
+#include <QtCore/QObject>
+#if USE_CURVE_EDITOR
+#include <Attribute.h>
+#endif
+#include <Nv/NvBlastCommon.h>
+class QMenuBar;
+class QHBoxLayout;
+class QVBoxLayout;
+class QTabWidget;
+
+class Camera;
+class Light;
+enum RenderApi;
+namespace NvParameterized
+{
+ class Interface;
+ class Handle;
+}
+class D3D11RenderShader;
+class QCloseEvent;
+#define NV_AT_UNUSED
+
+class QResizeEvent;
+class QPaintEvent;
+class QMouseEvent;
+class QWheelEvent;
+class QKeyEvent;
+class QDragEnterEvent;
+class QDragMoveEvent;
+class QDragLeaveEvent;
+class QDropEvent;
+class QContextMenuEvent;
+
+class PluginInterface
+{
+public:
+ virtual ~PluginInterface() {}
+
+ virtual QString GetPluginName() = 0;
+
+ virtual bool CoreLib_RunApp() = 0;
+
+ virtual bool LoadRenderPlugin(std::string api) = 0;
+
+ virtual bool GetBoneNames(std::vector<std::string>& BoneNames) = 0;
+
+ NV_AT_UNUSED virtual bool MainToolbar_updateValues() = 0;
+
+ NV_AT_UNUSED virtual bool CurveEditor_updateValues(int _paramId, float* _values) = 0;
+ NV_AT_UNUSED virtual bool CurveEditor_onUpdateValues(int _paramId, float* _values) = 0;
+
+ virtual bool DisplayMeshesPanel_updateValues() = 0;
+ virtual bool DisplayMeshesPanel_EmitToggleSignal(unsigned int id, bool visible) = 0;
+
+ virtual bool Camera_LoadParameters(void* ptr, Camera* pCamera) = 0;
+ virtual bool Camera_SaveParameters(void * ptr, Camera* pCamera) = 0;
+
+ virtual bool Gamepad_ToggleSimulation() = 0;
+ virtual bool Gamepad_ResetScene() = 0;
+ NV_AT_UNUSED virtual bool Gamepad_LoadSamples(QString fn) = 0;
+ virtual bool Gamepad_StartAnimation() = 0;
+ virtual bool GamepadHandler_ShowHair() = 0;
+ virtual bool GamepadHandler_SpinWindStrength(float windStrength) = 0;
+ virtual bool Gamepad_ResetAnimation() = 0;
+ virtual bool Gamepad_PlayPauseAnimation() = 0;
+
+ virtual bool Light_loadParameters(NvParameterized::Handle& handle, Light* pLight) = 0;
+ virtual bool Light_saveParameters(NvParameterized::Handle& handle, Light* pLight) = 0;
+
+ virtual bool SimpleScene_SimpleScene() = 0;
+ virtual bool SimpleScene_Initialize(int backdoor) = 0;
+ virtual bool SimpleScene_Shutdown() = 0;
+ virtual bool SimpleScene_Clear() = 0;
+ virtual bool SimpleScene_Draw_DX12() = 0;
+ virtual bool SimpleScene_Draw_DX11() = 0;
+ virtual bool SimpleScene_FitCamera(atcore_float3& center, atcore_float3& extents) = 0;
+ virtual bool SimpleScene_LoadSceneFromFbx(const char* dir, const char* fbxName) = 0;
+ virtual bool SimpleScene_LoadProject(const char* dir, const char* file) = 0;
+ virtual bool SimpleScene_SaveProject(const char* dir, const char* file) = 0;
+ virtual bool SimpleScene_LoadParameters(NvParameterized::Interface* iface) = 0;
+ virtual bool SimpleScene_SaveParameters(NvParameterized::Interface* iface) = 0;
+ virtual bool SimpleScene_LoadCameraBookmarks(NvParameterized::Interface* iface) = 0;
+ virtual bool SimpleScene_SaveCameraBookmarks(NvParameterized::Interface* iface) = 0;
+ NV_AT_UNUSED virtual bool SimpleScene_DrawGround() = 0;
+ NV_AT_UNUSED virtual bool SimpleScene_DrawWind() = 0;
+ NV_AT_UNUSED virtual bool SimpleScene_DrawAxis() = 0;
+
+ virtual bool D3DWidget_resizeEvent(QResizeEvent* e) = 0;
+ virtual bool D3DWidget_paintEvent(QPaintEvent* e) = 0;
+ virtual bool D3DWidget_mousePressEvent(QMouseEvent* e) = 0;
+ virtual bool D3DWidget_mouseReleaseEvent(QMouseEvent* e) = 0;
+ virtual bool D3DWidget_mouseMoveEvent(QMouseEvent* e) = 0;
+ virtual bool D3DWidget_wheelEvent(QWheelEvent * e) = 0;
+ virtual bool D3DWidget_keyPressEvent(QKeyEvent* e) = 0;
+ virtual bool D3DWidget_keyReleaseEvent(QKeyEvent* e) = 0;
+ virtual bool D3DWidget_dragEnterEvent(QDragEnterEvent *e) = 0;
+ virtual bool D3DWidget_dragMoveEvent(QDragMoveEvent *e) = 0;
+ virtual bool D3DWidget_dragLeaveEvent(QDragLeaveEvent *e) = 0;
+ virtual bool D3DWidget_dropEvent(QDropEvent *e) = 0;
+ virtual bool D3DWidget_contextMenuEvent(QContextMenuEvent *e) = 0;
+
+ virtual bool D3D11Shaders_InitializeShadersD3D11(std::map<int, D3D11RenderShader*>& ShaderMap) = 0;
+
+ virtual bool AppMainWindow_AppMainWindow() = 0;
+ virtual bool AppMainWindow_InitMenuItems(QMenuBar* pMenuBar) = 0;
+ virtual bool AppMainWindow_InitMainTab(QWidget *displayScrollAreaContents, QVBoxLayout *displayScrollAreaLayout, int idx) = 0;
+ virtual bool AppMainWindow_InitPluginTab(QTabWidget* pTabWidget) = 0;
+ virtual bool AppMainWindow_InitUI() = 0;
+ virtual bool AppMainWindow_updateUI() = 0;
+ virtual bool AppMainWindow_updatePluginUI() = 0;
+ NV_AT_UNUSED virtual bool AppMainWindow_processDragAndDrop(QString fname) = 0;
+ virtual bool AppMainWindow_closeEvent(QCloseEvent *event) = 0;
+ virtual bool AppMainWindow_InitToolbar(QWidget *pQWidget, QVBoxLayout* pLayout) = 0;
+ virtual bool AppMainWindow_shortcut_expert(bool mode) = 0;
+ virtual bool AppMainWindow_updateMainToolbar() = 0;
+
+ virtual bool AppMainWindow_menu_about() = 0;
+ virtual bool AppMainWindow_menu_opendoc() = 0;
+#if USE_CURVE_EDITOR
+ virtual bool AppMainWindow_UpdateCurveEditor() = 0;
+ virtual bool AppMainWindow_ShowCurveEditor(int paramId) = 0;
+ virtual bool AppMainWindow_onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute) = 0;
+ virtual bool AppMainWindow_onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute) = 0;
+ virtual bool AppMainWindow_onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex) = 0;
+#endif
+};
+
+QT_BEGIN_NAMESPACE
+#define PluginInterface_iid "com.nvidia.PluginInterface"
+Q_DECLARE_INTERFACE(PluginInterface, PluginInterface_iid)
+QT_END_NAMESPACE
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Buffer.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Buffer.cpp
new file mode 100644
index 0000000..4e261f1
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Buffer.cpp
@@ -0,0 +1,31 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D11Buffer.h"
+
+// shared path
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Buffer.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Buffer.h
new file mode 100644
index 0000000..d9d9730
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Buffer.h
@@ -0,0 +1,65 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "RenderResources.h"
+
+#include "d3d11.h"
+
+// GPU resources for texture
+struct GPUBufferD3D11 : public GPUBufferResource
+{
+ ID3D11Buffer* m_pD3D11Resource;
+
+public:
+ static GPUBufferResource* Create(ID3D11Buffer* pResource) {
+ GPUBufferD3D11* pBuffer = new GPUBufferD3D11;
+ pBuffer->m_pD3D11Resource = pResource;
+ return pBuffer;
+ }
+
+ static ID3D11Buffer* GetResource(GPUBufferResource* pBuffer)
+ {
+ GPUBufferD3D11* pD3D11Buffer = dynamic_cast<GPUBufferD3D11*>(pBuffer);
+ if (!pD3D11Buffer)
+ return 0;
+ return pD3D11Buffer->m_pD3D11Resource;
+ }
+
+ ~GPUBufferD3D11()
+ {
+ Release();
+ }
+
+ void Release()
+ {
+ SAFE_RELEASE(m_pD3D11Resource);
+ }
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11GPUProfiler.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11GPUProfiler.cpp
new file mode 100644
index 0000000..060a0cb
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11GPUProfiler.cpp
@@ -0,0 +1,138 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D11GPUProfiler.h"
+
+#include "D3D11RenderInterface.h"
+
+///////////////////////////////////////////////////////////////
+// factory function to create D3D11 GPU profiler
+/*
+GPUProfiler* GPUProfiler::CreateD3D11()
+{
+ GPUProfiler* pProfiler = new D3D11GPUProfiler;
+ pProfiler->Initialize();
+ return pProfiler;
+}
+*/
+///////////////////////////////////////////////////////////////
+D3D11GPUProfiler::~D3D11GPUProfiler()
+{
+ Release();
+}
+
+///////////////////////////////////////////////////////////////
+void D3D11GPUProfiler::Initialize()
+{
+ ID3D11Device *pDevice = RenderInterfaceD3D11::GetDevice();
+
+ m_pContext = RenderInterfaceD3D11::GetDeviceContext();
+
+ D3D11_QUERY_DESC desc;
+ memset(&desc, 0, sizeof(D3D11_QUERY_DESC));
+ desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
+ desc.MiscFlags = 0;
+
+ pDevice->CreateQuery(&desc, &m_pQueryDisjoint);
+
+ desc.Query = D3D11_QUERY_TIMESTAMP;
+
+ for (int i = 0; i < MAX_QUERY_COUNT; i++)
+ {
+ pDevice->CreateQuery(&desc, &m_pQueryStart[i]);
+ pDevice->CreateQuery(&desc, &m_pQueryEnd[i]);
+ }
+ m_enable = true;
+}
+
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(x) { if (x) x->Release(); x = 0; }
+#endif
+
+///////////////////////////////////////////////////////////////
+void D3D11GPUProfiler::Release()
+{
+ for (int i = 0; i < MAX_QUERY_COUNT; i++)
+ {
+ SAFE_RELEASE(m_pQueryStart[i]);
+ SAFE_RELEASE(m_pQueryEnd[i]);
+ }
+
+ SAFE_RELEASE(m_pQueryDisjoint);
+}
+
+///////////////////////////////////////////////////////////////
+void D3D11GPUProfiler::StartProfile(int id)
+{
+ if (!m_enable) return;
+
+ ID3D11Query* pQuery = m_pQueryStart[id];
+ m_pContext->End(pQuery);
+}
+
+///////////////////////////////////////////////////////////////
+void D3D11GPUProfiler::EndProfile(int id)
+{
+ if (!m_enable) return;
+
+ ID3D11Query* pQuery = m_pQueryEnd[id];
+ m_pContext->End(pQuery);
+}
+
+///////////////////////////////////////////////////////////////
+void D3D11GPUProfiler::StartFrame()
+{
+ if (!m_enable) return;
+
+ m_pContext->Begin(m_pQueryDisjoint);
+}
+
+///////////////////////////////////////////////////////////////
+void D3D11GPUProfiler::EndFrame()
+{
+ if (!m_enable) return;
+
+ m_pContext->End(m_pQueryDisjoint);
+
+ while(m_pContext->GetData(m_pQueryDisjoint, &m_disjointData, sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT), 0) != S_OK);
+}
+
+///////////////////////////////////////////////////////////////
+float D3D11GPUProfiler::GetProfileData(int id)
+{
+ if (!m_enable)
+ return 0.0f;
+
+ UINT64 startTime = 0;
+ while(m_pContext->GetData(m_pQueryStart[id], &startTime, sizeof(UINT64), 0) != S_OK);
+
+ UINT64 endTime = 0;
+ while(m_pContext->GetData(m_pQueryEnd[id], &endTime, sizeof(UINT64), 0) != S_OK);
+
+ float frequency = static_cast<float>(m_disjointData.Frequency);
+ return (endTime - startTime) / frequency * 1000.0f;
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11GPUProfiler.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11GPUProfiler.h
new file mode 100644
index 0000000..4c5b32f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11GPUProfiler.h
@@ -0,0 +1,56 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "d3d11.h"
+
+#include "GPUProfiler.h"
+
+#define MAX_QUERY_COUNT 64
+struct D3D11GPUProfiler : public GPUProfiler
+{
+public:
+ ~D3D11GPUProfiler();
+
+ void Initialize();
+ void Release();
+ void StartProfile(int id);
+ void EndProfile(int id);
+ void StartFrame();
+ void EndFrame();
+ float GetProfileData(int id);
+
+protected:
+ ID3D11Query* m_pQueryDisjoint;
+ ID3D11Query* m_pQueryStart[MAX_QUERY_COUNT];
+ ID3D11Query* m_pQueryEnd[MAX_QUERY_COUNT];
+ D3D11_QUERY_DATA_TIMESTAMP_DISJOINT m_disjointData;
+ ID3D11DeviceContext* m_pContext;
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderInterface.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderInterface.cpp
new file mode 100644
index 0000000..71d1b7d
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderInterface.cpp
@@ -0,0 +1,890 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D11RenderInterface.h"
+
+#include "D3D11TextureResource.h"
+#include "D3D11Shaders.h"
+#include "D3D11Buffer.h"
+#include "Nv.h"
+#ifdef USE_11ON12_WRAPPER
+#include "D3D11on12Wrapper.h"
+#endif // USE_11ON12_WRAPPER
+namespace RenderInterfaceD3D11
+{
+ using namespace RenderInterface;
+
+ ID3D11SamplerState* m_pSamplerStates[SAMPLER_TYPE_END];
+ ID3D11BlendState* m_pBlendStates[BLEND_STATE_END];
+ ID3D11DepthStencilState* m_pDepthStencilStates[DEPTH_STENCIL_STATE_END];
+ ID3D11RasterizerState* m_pRasterizerStates[RASTERIZER_STATE_END];
+
+#ifdef USE_11ON12_WRAPPER
+#else
+ ID3D11DeviceContext* g_d3dDeviceContext = 0;
+ ID3D11Device* g_d3dDevice = 0;
+ IDXGIFactory1* g_pDXGIFactory1 = 0;
+ IDXGIDevice* g_dxgiDevice = 0;
+ IDXGIAdapter * g_pAdapter = 0;
+#endif // USE_11ON12_WRAPPER
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+ID3D11DeviceContext* GetDeviceContext()
+{
+#ifdef USE_11ON12_WRAPPER
+ return D3D11on12Wrapper::GetDeviceContext();
+#else
+ return g_d3dDeviceContext;
+#endif // USE_11ON12_WRAPPER
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+ID3D11Device* GetDevice()
+{
+#ifdef USE_11ON12_WRAPPER
+ return D3D11on12Wrapper::GetDevice11();
+#else
+ return g_d3dDevice;
+#endif // USE_11ON12_WRAPPER
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+IDXGIFactory1* GetDXGIFactory()
+{
+#ifdef USE_11ON12_WRAPPER
+ return D3D11on12Wrapper::GetDXGIFactory();
+#else
+ return g_pDXGIFactory1;
+#endif // USE_11ON12_WRAPPER
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+IDXGIDevice* GetDXGIDevice()
+{
+#ifdef USE_11ON12_WRAPPER
+ return nullptr;
+#else
+ return g_dxgiDevice;
+#endif // USE_11ON12_WRAPPER
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+IDXGIAdapter* GetAdapter()
+{
+#ifdef USE_11ON12_WRAPPER
+ return D3D11on12Wrapper::GetAdapter();
+#else
+ return g_pAdapter;
+#endif // USE_11ON12_WRAPPER
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool IsNvDeviceID(UINT id)
+{
+ return id == 0x10DE;
+}
+
+IDXGIAdapter* FindAdapter(IDXGIFactory* IDXGIFactory_0001, const WCHAR* targetName, bool& isNv)
+{
+ IDXGIAdapter* targetAdapter = nullptr;
+ std::vector<IDXGIAdapter*> adapters;
+ // check current adapter first. EnumAdapters could fail on some device
+ IDXGIAdapter* pAdapter = nullptr;
+ ID3D11Device* pD3dDevice = nullptr;
+ ID3D11DeviceContext* pD3dDeviceContext = nullptr;
+ DWORD createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG;
+ D3D_FEATURE_LEVEL fl;
+ // This following code is the robust way to get all possible feature levels while handling DirectX 11.0 systems:
+ // please read https://blogs.msdn.microsoft.com/chuckw/2014/02/05/anatomy-of-direct3d-11-create-device/
+ D3D_FEATURE_LEVEL lvl[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0,
+ D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 };
+ HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
+ createDeviceFlags, lvl, _countof(lvl),
+ D3D11_SDK_VERSION, &pD3dDevice, &fl, &pD3dDeviceContext);
+ if (pD3dDevice)
+ {
+ IDXGIDevice* dxgiDevice = nullptr;
+ hr = pD3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
+ if (SUCCEEDED(hr))
+ {
+ hr = dxgiDevice->GetAdapter(&pAdapter);
+ if (pAdapter)
+ {
+ adapters.push_back(pAdapter);
+ }
+ SAFE_RELEASE(dxgiDevice);
+ }
+ SAFE_RELEASE(pD3dDeviceContext);
+ SAFE_RELEASE(pD3dDevice);
+ }
+
+ // Enum Adapters
+ unsigned int adapterNo = 0;
+ HRESULT hres = S_OK;
+ while (SUCCEEDED(hres = IDXGIFactory_0001->EnumAdapters(adapterNo, (IDXGIAdapter**)&pAdapter)))
+ {
+ adapters.push_back(pAdapter);
+ adapterNo++;
+ }
+ if (wcslen(targetName) != 0)
+ {
+ // find the adapter with specified name
+ for (int i = 0; i < adapters.size(); ++i)
+ {
+ IDXGIAdapter* pAdapter = adapters[i];
+ DXGI_ADAPTER_DESC aDesc;
+ pAdapter->GetDesc(&aDesc);
+ std::wstring aName = aDesc.Description;
+ if (aName.find(targetName) != std::string::npos)
+ {
+ targetAdapter = pAdapter;
+ isNv = IsNvDeviceID(aDesc.VendorId);
+ }
+ }
+ }
+ else
+ {
+ // no name specified, find one NV adapter
+ for (int i = 0; i < adapters.size(); ++i)
+ {
+ IDXGIAdapter* pAdapter = adapters[i];
+ DXGI_ADAPTER_DESC aDesc;
+ pAdapter->GetDesc(&aDesc);
+ std::wstring aName = aDesc.Description;
+ if (IsNvDeviceID(aDesc.VendorId))
+ {
+ targetAdapter = pAdapter;
+ isNv = true;
+ }
+ }
+ }
+ if (targetAdapter == nullptr)
+ targetAdapter = adapters[0];
+ for (int i = 0; i < adapters.size(); ++i)
+ {
+ IDXGIAdapter* pAdapter = adapters[i];
+ if(pAdapter != targetAdapter)
+ {
+ pAdapter->Release();
+ }
+ }
+
+ return targetAdapter;
+}
+
+HRESULT UseGoodGPUDevice()
+{
+#ifdef USE_11ON12_WRAPPER
+ return S_OK;
+#else
+ // create factory
+ if (g_pDXGIFactory1 == NV_NULL)
+ {
+ HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&g_pDXGIFactory1));
+ if (FAILED(hr))
+ return hr;
+ }
+
+ DWORD createDeviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED; // 0; // I changed only this line.
+#ifdef _DEBUG
+ createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+ bool bNVAdapter = false;
+ WCHAR* pwName = L"";
+ g_pAdapter = FindAdapter(g_pDXGIFactory1, pwName, bNVAdapter);
+
+#ifdef _DEBUG
+ DXGI_ADAPTER_DESC adapterDesc;
+ g_pAdapter->GetDesc(&adapterDesc);
+ std::wstring adapterName = adapterDesc.Description;
+#endif
+
+ D3D_FEATURE_LEVEL fl;
+ HRESULT hr = D3D11CreateDevice(g_pAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
+ createDeviceFlags, 0, 0,
+ D3D11_SDK_VERSION, &g_d3dDevice, &fl, &g_d3dDeviceContext);
+
+ if(g_d3dDevice)
+ {
+ IDXGIDevice* dxgiDevice = nullptr;
+ hr = g_d3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
+ if (SUCCEEDED(hr))
+ {
+ g_dxgiDevice = dxgiDevice;
+ return hr;
+ }
+ else
+ {
+ SAFE_RELEASE(g_d3dDevice);
+ SAFE_RELEASE(g_pAdapter);
+ SAFE_RELEASE(g_pDXGIFactory1);
+ }
+ }
+ return hr;
+#endif // USE_11ON12_WRAPPER
+}
+
+bool InitDevice(int deviceID)
+{
+#ifdef USE_11ON12_WRAPPER
+ D3D11on12Wrapper::InitDevice();
+#else
+ if (deviceID == -1)
+ {
+ HRESULT hResult = UseGoodGPUDevice();
+ if (FAILED(hResult))
+ return false;
+
+ return true;
+ }
+
+ D3D_FEATURE_LEVEL featureLvl;
+
+ // create factory
+ if (g_pDXGIFactory1 == NV_NULL)
+ {
+ HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&g_pDXGIFactory1));
+ if (FAILED(hr))
+ return false;
+ }
+
+ // create adapter for selected device
+ if (g_pAdapter == NV_NULL)
+ {
+ HRESULT hr = g_pDXGIFactory1->EnumAdapters(deviceID, &g_pAdapter);
+ if (FAILED(hr))
+ return false;
+ }
+
+ UINT deviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED;
+#ifdef _DEBUG
+ deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+ // create device
+ HRESULT hResult = D3D11CreateDevice(
+ g_pAdapter,
+ D3D_DRIVER_TYPE_UNKNOWN, //D3D_DRIVER_TYPE_HARDWARE,
+ 0,
+ deviceFlags,
+ NV_NULL,
+ 0,
+ D3D11_SDK_VERSION,
+ &g_d3dDevice,
+ &featureLvl,
+ &g_d3dDeviceContext);
+
+ if(FAILED(hResult))
+ return false;
+#endif // USE_11ON12_WRAPPER
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool Initialize()
+{
+ if (!GetDevice() || !GetDeviceContext())
+ return false;
+
+ D3D11_COMPARISON_FUNC depthFunc = D3D11_COMPARISON_LESS;
+
+ InitializeShadersD3D11();
+ InitializeRenderStates();
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void Shutdown()
+{
+ DestroyShadersD3D11();
+ ClearRenderStates();
+
+ // release d3d resources
+ IDXGIFactory1* pDxgiFactory = GetDXGIFactory();
+ SAFE_RELEASE(pDxgiFactory);
+
+ IDXGIAdapter* pAdapter = GetAdapter();
+ SAFE_RELEASE(pAdapter);
+
+ IDXGIDevice* pDXGIDevice = GetDXGIDevice();
+ SAFE_RELEASE(pDXGIDevice);
+
+ ID3D11DeviceContext* pContext = GetDeviceContext();
+ SAFE_RELEASE(pContext);
+
+ ID3D11Device* pDevice = GetDevice();
+#if defined(DEBUG) || defined(_DEBUG)
+ // output d3d leak
+ ID3D11Debug *d3dDebug;
+ HRESULT hr = pDevice->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<void**>(&d3dDebug));
+ if (SUCCEEDED(hr))
+ {
+ hr = d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
+ }
+ if (d3dDebug != nullptr)
+ d3dDebug->Release();
+#endif
+
+ SAFE_RELEASE(pDevice);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void InitializeRenderStates()
+{
+ ID3D11Device* pDevice = GetDevice();
+ if (!pDevice)
+ return;
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // alpha blending state descriptors
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ // alpha blending enabled
+ {
+ D3D11_BLEND_DESC desc;
+ desc.AlphaToCoverageEnable = false;
+ desc.IndependentBlendEnable = false;
+
+ D3D11_RENDER_TARGET_BLEND_DESC &rtDesc = desc.RenderTarget[0];
+ {
+ rtDesc.BlendEnable = true;
+ rtDesc.SrcBlend = D3D11_BLEND_SRC_ALPHA;
+ rtDesc.DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
+ rtDesc.BlendOp = D3D11_BLEND_OP_ADD;
+ rtDesc.SrcBlendAlpha = D3D11_BLEND_ZERO;
+ rtDesc.DestBlendAlpha = D3D11_BLEND_ONE;
+ rtDesc.BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ rtDesc.RenderTargetWriteMask = 0x0f;
+ }
+ pDevice->CreateBlendState(&desc, &m_pBlendStates[BLEND_STATE_ALPHA]);
+ }
+
+ // no alpha blending
+ {
+ D3D11_BLEND_DESC desc;
+ desc.AlphaToCoverageEnable = false;
+ desc.IndependentBlendEnable = false;
+
+ D3D11_RENDER_TARGET_BLEND_DESC &rtDesc = desc.RenderTarget[0];
+ {
+ rtDesc.BlendEnable = false;
+ rtDesc.SrcBlend = D3D11_BLEND_SRC_ALPHA;
+ rtDesc.DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
+ rtDesc.BlendOp = D3D11_BLEND_OP_ADD;
+ rtDesc.SrcBlendAlpha = D3D11_BLEND_ZERO;
+ rtDesc.DestBlendAlpha = D3D11_BLEND_ONE;
+ rtDesc.BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ rtDesc.RenderTargetWriteMask = 0x0f;
+ }
+ pDevice->CreateBlendState(&desc, &m_pBlendStates[BLEND_STATE_NONE]);
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // depth and stencil
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ D3D11_DEPTH_STENCIL_DESC depthTestDesc;
+ {
+ depthTestDesc.DepthEnable = true;
+ depthTestDesc.DepthFunc = D3D11_COMPARISON_LESS;
+ depthTestDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ depthTestDesc.StencilEnable = false;
+ depthTestDesc.StencilReadMask = 0xff;
+ depthTestDesc.StencilWriteMask = 0xff;
+ }
+
+ pDevice->CreateDepthStencilState(&depthTestDesc, &m_pDepthStencilStates[DEPTH_STENCIL_DEPTH_TEST]);
+
+ D3D11_DEPTH_STENCIL_DESC depthNone;
+ {
+ depthNone.DepthEnable = false;
+ depthNone.DepthFunc = D3D11_COMPARISON_LESS;
+ depthNone.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
+ depthNone.StencilEnable = false;
+ depthNone.StencilReadMask = 0xff;
+ depthNone.StencilWriteMask = 0xff;
+ }
+
+ pDevice->CreateDepthStencilState(&depthNone, &m_pDepthStencilStates[DEPTH_STENCIL_DEPTH_NONE]);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // rasterizer
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ D3D11_RASTERIZER_DESC rsDesc;
+
+ // solid cull front
+ {
+ rsDesc.FillMode = D3D11_FILL_SOLID;
+ rsDesc.CullMode = D3D11_CULL_FRONT;
+ rsDesc.AntialiasedLineEnable = false;
+ rsDesc.MultisampleEnable = true;
+ rsDesc.FrontCounterClockwise = true;
+ rsDesc.DepthBias = 10;
+ rsDesc.DepthBiasClamp = 0;
+ rsDesc.SlopeScaledDepthBias = 0;
+ rsDesc.DepthClipEnable = true;
+ rsDesc.ScissorEnable = 0;
+
+ pDevice->CreateRasterizerState(&rsDesc, &m_pRasterizerStates[RASTERIZER_STATE_FILL_CULL_FRONT]);
+ };
+
+ // solid cull back
+ {
+ rsDesc.FillMode = D3D11_FILL_SOLID;
+ rsDesc.CullMode = D3D11_CULL_BACK;
+ rsDesc.AntialiasedLineEnable = false;
+ rsDesc.MultisampleEnable = true;
+ rsDesc.FrontCounterClockwise = true;
+ rsDesc.DepthBias = 10;
+ rsDesc.DepthBiasClamp = 0;
+ rsDesc.SlopeScaledDepthBias = 0;
+ rsDesc.DepthClipEnable = true;
+ rsDesc.ScissorEnable = 0;
+
+ pDevice->CreateRasterizerState(&rsDesc, &m_pRasterizerStates[RASTERIZER_STATE_FILL_CULL_BACK]);
+ }
+
+ // solid cull none
+ {
+ rsDesc.FillMode = D3D11_FILL_SOLID;
+ rsDesc.CullMode = D3D11_CULL_NONE;
+ rsDesc.AntialiasedLineEnable = false;
+ rsDesc.MultisampleEnable = true;
+ rsDesc.FrontCounterClockwise = true;
+ rsDesc.DepthBias = 10;
+ rsDesc.DepthBiasClamp = 0;
+ rsDesc.SlopeScaledDepthBias = 0;
+ rsDesc.DepthClipEnable = true;
+ rsDesc.ScissorEnable = 0;
+
+ pDevice->CreateRasterizerState(&rsDesc, &m_pRasterizerStates[RASTERIZER_STATE_FILL_CULL_NONE]);
+
+ }
+
+ // wireframe cull none
+ {
+ rsDesc.FillMode = D3D11_FILL_WIREFRAME;
+ rsDesc.CullMode = D3D11_CULL_NONE;
+ rsDesc.AntialiasedLineEnable = false;
+ rsDesc.MultisampleEnable = true;
+ rsDesc.FrontCounterClockwise = 0;
+ rsDesc.DepthBias = 0;
+ rsDesc.DepthBiasClamp = 0;
+ rsDesc.SlopeScaledDepthBias = 0;
+ rsDesc.DepthClipEnable = true;
+ rsDesc.ScissorEnable = 0;
+ };
+
+ pDevice->CreateRasterizerState(&rsDesc, &m_pRasterizerStates[RASTERIZER_STATE_WIRE]);
+
+ // samplers
+
+ D3D11_SAMPLER_DESC linearSamplerDesc[1] = {
+ D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT,
+ D3D11_TEXTURE_ADDRESS_WRAP,
+ D3D11_TEXTURE_ADDRESS_WRAP,
+ D3D11_TEXTURE_ADDRESS_WRAP,
+ 0.0, 0, D3D11_COMPARISON_NEVER, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, D3D11_FLOAT32_MAX,
+ };
+ pDevice->CreateSamplerState(linearSamplerDesc, &m_pSamplerStates[SAMPLER_TYPE_LINEAR]);
+
+ // create point clamp sampler for PCF sampling for hair
+ D3D11_SAMPLER_DESC pointClampSamplerDesc[1] = {
+ D3D11_FILTER_MIN_MAG_MIP_POINT,
+ D3D11_TEXTURE_ADDRESS_CLAMP,
+ D3D11_TEXTURE_ADDRESS_CLAMP,
+ D3D11_TEXTURE_ADDRESS_CLAMP,
+ 0.0, 0, D3D11_COMPARISON_NEVER,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, D3D11_FLOAT32_MAX,
+ };
+ pDevice->CreateSamplerState(pointClampSamplerDesc, &m_pSamplerStates[SAMPLER_TYPE_POINTCLAMP]);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void ClearRenderStates()
+{
+ for (int i = 0; i < RASTERIZER_STATE_END; i++)
+ SAFE_RELEASE(m_pRasterizerStates[i]);
+
+ for (int i = 0; i < DEPTH_STENCIL_STATE_END; i++)
+ SAFE_RELEASE(m_pDepthStencilStates[i]);
+
+ for (int i = 0; i < SAMPLER_TYPE_END; i++)
+ SAFE_RELEASE(m_pSamplerStates[i]);
+
+ for (int i = 0; i < BLEND_STATE_END; i++)
+ SAFE_RELEASE(m_pBlendStates[i]);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void BindVertexShaderResources( int startSlot, int numSRVs, ID3D11ShaderResourceView** ppSRVs)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->VSSetShaderResources( startSlot, numSRVs, ppSRVs);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void BindPixelShaderResources( int startSlot, int numSRVs, ID3D11ShaderResourceView** ppSRVs)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->PSSetShaderResources( startSlot, numSRVs, ppSRVs);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void BindVertexShaderResources( int startSlot, int numSRVs, GPUShaderResource** ppSRVs)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ for (int i = startSlot; i < (startSlot + numSRVs); i++)
+ {
+ ID3D11ShaderResourceView* pSRV = D3D11TextureResource::GetResource(ppSRVs[i]);
+ pDeviceContext->VSSetShaderResources( i, 1, &pSRV);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void BindPixelShaderResources( int startSlot, int numSRVs, GPUShaderResource** ppSRVs)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ for (int i = startSlot; i < (startSlot + numSRVs); i++)
+ {
+ ID3D11ShaderResourceView* pSRV = D3D11TextureResource::GetResource(ppSRVs[i]);
+ pDeviceContext->PSSetShaderResources( i, 1, &pSRV);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void ClearPixelShaderResources( int startSlot, int numSRVs)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ // clean up
+ ID3D11ShaderResourceView* ppSRVNull[128];
+ memset(&ppSRVNull, 0, sizeof(ID3D11ShaderResourceView*)*128);
+
+ pDeviceContext->PSSetShaderResources( startSlot, numSRVs, ppSRVNull);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void ClearVertexShaderResources( int startSlot, int numSRVs)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ // clean up
+ ID3D11ShaderResourceView* ppSRVNull[128];
+ memset(&ppSRVNull, 0, sizeof(ID3D11ShaderResourceView*)*128);
+
+ pDeviceContext->VSSetShaderResources( startSlot, numSRVs, ppSRVNull);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void ClearInputLayout()
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->IASetInputLayout(nullptr);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void SetPrimitiveTopologyTriangleStrip()
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void SetPrimitiveTopologyTriangleList()
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void SetPrimitiveTopologyLineList()
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINELIST );
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void SetVertexBuffer(GPUBufferResource* pBuffer, UINT stride, UINT offset)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ ID3D11Buffer* pD3D11Buffer = GPUBufferD3D11::GetResource(pBuffer);
+ if (!pD3D11Buffer)
+ return;
+
+ pDeviceContext->IASetVertexBuffers( 0, 1, &pD3D11Buffer, &stride, &offset );
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void ApplySampler(int slot, RenderInterface::SAMPLER_TYPE st)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->PSSetSamplers(slot, 1, &m_pSamplerStates[st] );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyDepthStencilState(DEPTH_STENCIL_STATE state)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->OMSetDepthStencilState(m_pDepthStencilStates[state], 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyRasterizerState(RASTERIZER_STATE state)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->RSSetState(m_pRasterizerStates[state]);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyBlendState(BLEND_STATE st)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ float zerov[] = {0,0,0,0};
+
+ pDeviceContext->OMSetBlendState(m_pBlendStates[st], zerov, 0xffffffff);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void SetViewport(const RenderInterface::Viewport& vp)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ D3D11_VIEWPORT d3dViewport;
+
+ d3dViewport.TopLeftX = vp.TopLeftX;
+ d3dViewport.TopLeftY = vp.TopLeftY;
+
+ d3dViewport.Width = vp.Width;
+ d3dViewport.Height = vp.Height;
+
+ d3dViewport.MinDepth = vp.MinDepth;
+ d3dViewport.MaxDepth = vp.MaxDepth;
+
+ pDeviceContext->RSSetViewports(1, &d3dViewport);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void GetViewport(RenderInterface::Viewport& vp)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ UINT numViewports = 1;
+ D3D11_VIEWPORT d3dViewport;
+ pDeviceContext->RSGetViewports(&numViewports, &d3dViewport);
+
+ vp.TopLeftX = d3dViewport.TopLeftX;
+ vp.TopLeftY = d3dViewport.TopLeftY;
+
+ vp.Width = d3dViewport.Width;
+ vp.Height = d3dViewport.Height;
+
+ vp.MinDepth = d3dViewport.MinDepth;
+ vp.MaxDepth = d3dViewport.MaxDepth;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void Draw(unsigned int vertexCount, unsigned int startCount)
+{
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->Draw(vertexCount, startCount);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// gpu buffer management
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+ID3D11Buffer* CreateD3D11Buffer(
+ D3D11_USAGE Usage, UINT ByteWidth, UINT StructureByteStride,
+ UINT BindFlags, UINT MiscFlags,
+ UINT CPUAccessFlags, void *pSysMem)
+{
+ ID3D11Device* pDevice = RenderInterfaceD3D11::GetDevice();
+ if (!pDevice)
+ return 0;
+
+ D3D11_BUFFER_DESC desc;
+
+ desc.Usage = Usage;
+ desc.ByteWidth = ByteWidth;
+ desc.StructureByteStride = StructureByteStride;
+ desc.BindFlags = BindFlags;
+ desc.MiscFlags = MiscFlags;
+ desc.CPUAccessFlags = CPUAccessFlags;
+
+ D3D11_SUBRESOURCE_DATA InitData;
+
+ InitData.pSysMem = pSysMem;
+ InitData.SysMemPitch = 0;
+ InitData.SysMemSlicePitch = 0;
+
+ ID3D11Buffer* pBuffer = 0;
+
+ HRESULT hr = pSysMem ? pDevice->CreateBuffer( &desc, &InitData, &pBuffer)
+ : pDevice->CreateBuffer( &desc, 0, &pBuffer);
+
+ if( FAILED(hr) )
+ return 0;
+
+ return pBuffer;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+ID3D11ShaderResourceView*
+CreateD3D11ShaderResourceView(
+ ID3D11Buffer* pBuffer,
+ DXGI_FORMAT Format,
+ D3D11_SRV_DIMENSION ViewDimension,
+ UINT NumElements,
+ UINT FirstElement = 0
+ )
+{
+ ID3D11Device* pDevice = RenderInterfaceD3D11::GetDevice();
+ if (!pDevice)
+ return 0;
+
+ ID3D11ShaderResourceView* pSRV = 0;
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+ {
+ desc.Format = Format;
+ desc.ViewDimension = ViewDimension;
+ desc.Buffer.FirstElement = FirstElement;
+ desc.Buffer.NumElements = NumElements;
+ }
+
+ pDevice->CreateShaderResourceView( pBuffer, &desc, &pSRV);
+
+ return pSRV;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+GPUBufferResource* CreateVertexBuffer(
+ unsigned int ByteWidth, void* pSysMem)
+{
+ ID3D11Buffer* pD3D11Buffer = CreateD3D11Buffer(D3D11_USAGE_DEFAULT,
+ ByteWidth, 0, D3D11_BIND_VERTEX_BUFFER, 0, 0, pSysMem);
+
+ return GPUBufferD3D11::Create(pD3D11Buffer);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+GPUShaderResource* CreateShaderResource( unsigned int stride, unsigned int numElements, void* pSysMem)
+{
+ unsigned int byteWidth = numElements * stride;
+
+ ID3D11Buffer* pBuffer = CreateD3D11Buffer(
+ D3D11_USAGE_DEFAULT, byteWidth, 0,
+ D3D11_BIND_SHADER_RESOURCE, 0, 0, pSysMem);
+
+ // create SRV for bone indices
+ ID3D11ShaderResourceView* pSRV = CreateD3D11ShaderResourceView(
+ pBuffer,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ D3D11_SRV_DIMENSION_BUFFER,
+ numElements);
+
+ SAFE_RELEASE(pBuffer); // dec ref count as this is not explicitly used later
+
+ return D3D11TextureResource::Create(pSRV);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// create read only shader resource buffer
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+void CopyToDevice(
+ GPUBufferResource *pDevicePtr, void* pSysMem, unsigned int ByteWidth)
+{
+ ID3D11Buffer* pBuffer = GPUBufferD3D11::GetResource(pDevicePtr);
+ if (!pBuffer)
+ return;
+
+ ID3D11DeviceContext* pDeviceContext = GetDeviceContext();
+ if (!pDeviceContext)
+ return;
+
+ pDeviceContext->UpdateSubresource(pBuffer, 0, NV_NULL, pSysMem, ByteWidth, 0);
+}
+
+} // end namespace
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderInterface.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderInterface.h
new file mode 100644
index 0000000..e5f3c02
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderInterface.h
@@ -0,0 +1,90 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "d3d11.h"
+
+#include "RenderInterface.h"
+
+#include "RenderPlugin.h"
+
+#ifdef NV_ARTISTTOOLS
+enum HAIR_SHADER_TYPE
+{
+ SHADER_TYPE_HAIR_SHADER_DEFAULT = RenderInterface::SHADER_TYPE_SIMPLE_COLOR + 1,
+ SHADER_TYPE_HAIR_SHADER_SHADOW,
+};
+#endif
+
+// abstract interface to D3D calls
+namespace RenderInterfaceD3D11
+{
+ CORERENDER_EXPORT bool InitDevice(int deviceID);
+ CORERENDER_EXPORT bool Initialize();
+ CORERENDER_EXPORT void Shutdown();
+
+ CORERENDER_EXPORT ID3D11DeviceContext* GetDeviceContext();
+ CORERENDER_EXPORT ID3D11Device* GetDevice();
+ IDXGIFactory1* GetDXGIFactory();
+ IDXGIAdapter* GetAdapter();
+
+ CORERENDER_EXPORT void InitializeRenderStates();
+ CORERENDER_EXPORT void ClearRenderStates();
+
+ CORERENDER_EXPORT void ApplySampler(int slot, RenderInterface::SAMPLER_TYPE st);
+ CORERENDER_EXPORT void ApplyDepthStencilState(RenderInterface::DEPTH_STENCIL_STATE st);
+ CORERENDER_EXPORT void ApplyRasterizerState(RenderInterface::RASTERIZER_STATE st);
+ CORERENDER_EXPORT void ApplyBlendState(RenderInterface::BLEND_STATE st);
+
+ CORERENDER_EXPORT void GetViewport(RenderInterface::Viewport& vp);
+ CORERENDER_EXPORT void SetViewport(const RenderInterface::Viewport& vp);
+
+ CORERENDER_EXPORT void BindVertexShaderResources( int startSlot, int numSRVs, GPUShaderResource** ppSRVs);
+ CORERENDER_EXPORT void BindPixelShaderResources( int startSlot, int numSRVs, GPUShaderResource** ppSRVs);
+
+ CORERENDER_EXPORT void ClearVertexShaderResources( int startSlot, int numSRVs);
+ CORERENDER_EXPORT void ClearPixelShaderResources( int startSlot, int numSRVs);
+
+ CORERENDER_EXPORT GPUBufferResource* CreateVertexBuffer( unsigned int ByteWidth, void* pSysMem);
+ CORERENDER_EXPORT GPUShaderResource* CreateShaderResource( unsigned int stride, unsigned int numElements, void* pSysMem );
+
+ CORERENDER_EXPORT void CopyToDevice(GPUBufferResource *pDevicePtr, void* pSysMem, unsigned int ByteWidth);
+
+ CORERENDER_EXPORT void ClearInputLayout();
+
+ CORERENDER_EXPORT void SetVertexBuffer(GPUBufferResource* pBuffer, UINT stride, UINT offset = 0);
+
+ CORERENDER_EXPORT void SetPrimitiveTopologyTriangleStrip();
+ CORERENDER_EXPORT void SetPrimitiveTopologyTriangleList();
+ CORERENDER_EXPORT void SetPrimitiveTopologyLineList();
+
+
+ CORERENDER_EXPORT void Draw(unsigned int vertexCount, unsigned int startCount = 0);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderShader.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderShader.cpp
new file mode 100644
index 0000000..3a4d27e
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderShader.cpp
@@ -0,0 +1,256 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#include "D3D11RenderShader.h"
+
+#include "D3D11RenderInterface.h"
+#include "D3D11Wrapper.h"
+#include "Nv.h"
+
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(x) { if (x) x->Release(); }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+D3D11RenderShader::D3D11RenderShader() :
+ m_pVertexShader(0),
+ m_pPixelShader(0),
+ m_pInputLayout(0)
+{
+ for (int i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_HW_SLOT_COUNT; i++)
+ {
+ m_pParamBuffers[i] = nullptr;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+D3D11RenderShader::~D3D11RenderShader()
+{
+ SAFE_RELEASE(m_pVertexShader);
+ SAFE_RELEASE(m_pPixelShader);
+ SAFE_RELEASE(m_pInputLayout);
+
+ for (int i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_HW_SLOT_COUNT; i++)
+ SAFE_RELEASE(m_pParamBuffers[i]);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+D3D11RenderShader* D3D11RenderShader::Create(
+ const char *name,
+ void* pVSBlob, size_t vsBlobSize,
+ void* pPSBlob, size_t psBlobSize,
+ UINT cbufferSize0, UINT cbufferSize1,
+ D3D11_INPUT_ELEMENT_DESC* pElemDesc, UINT numElements)
+{
+ D3D11RenderShader* pShader = new D3D11RenderShader;
+
+ pShader->CreateVSFromBlob(pVSBlob, vsBlobSize, pElemDesc, numElements);
+ pShader->CreatePSFromBlob(pPSBlob, psBlobSize);
+
+ if (cbufferSize0 > 0)
+ {
+ pShader->CreateParamBuffer(cbufferSize0, 0);
+ SET_D3D_DEBUG_NAME(pShader->getParamBuffer(0), name);
+ }
+
+ if (cbufferSize1 > 0)
+ {
+ pShader->CreateParamBuffer(cbufferSize1, 1);
+ SET_D3D_DEBUG_NAME(pShader->getParamBuffer(1), name);
+ }
+
+ if (pShader->getVertexShader())
+ SET_D3D_DEBUG_NAME(pShader->getVertexShader(), name);
+
+ if (pShader->getPixelShader())
+ SET_D3D_DEBUG_NAME(pShader->getPixelShader(), name);
+
+ if (pShader->getInputLayout())
+ SET_D3D_DEBUG_NAME(pShader->getInputLayout(), name);
+
+ return pShader;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool D3D11RenderShader::CreateVSFromBlob(
+ void* pBlob, size_t blobSize,
+ D3D11_INPUT_ELEMENT_DESC *desc, int elemCount)
+{
+ ID3D11Device *pDevice = RenderInterfaceD3D11::GetDevice();
+ if (!pDevice)
+ return false;
+
+ if (!pBlob || (blobSize == 0))
+ return false;
+
+ SAFE_RELEASE(m_pVertexShader);
+ SAFE_RELEASE(m_pInputLayout);
+
+ HRESULT res = pDevice->CreateVertexShader(pBlob, blobSize, NV_NULL, &m_pVertexShader);
+
+ if(FAILED(res)) return false;
+
+ if (desc)
+ {
+ res = pDevice->CreateInputLayout(desc, elemCount,
+ pBlob, blobSize, &m_pInputLayout);
+
+ if(FAILED(res)) return false;
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool D3D11RenderShader::CreatePSFromBlob(void* pBlob, size_t blobSize)
+{
+ ID3D11Device* pDevice = RenderInterfaceD3D11::GetDevice();
+ if (!pDevice)
+ return false;
+
+ if (!pBlob || (blobSize == 0))
+ return false;
+
+ SAFE_RELEASE(m_pPixelShader);
+
+ HRESULT res = pDevice->CreatePixelShader(pBlob, blobSize, NV_NULL, &m_pPixelShader);
+
+ if (FAILED(res))
+ return false;
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D11RenderShader::SetConstantBuffer()
+{
+ ID3D11DeviceContext* pContext = RenderInterfaceD3D11::GetDeviceContext();
+
+ //for (int i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_HW_SLOT_COUNT; i++)
+ for (int i = 0; i < 2; i++)
+ {
+ pContext->PSSetConstantBuffers(i, 1, &m_pParamBuffers[i]);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D11RenderShader::MakeCurrent()
+{
+ ID3D11DeviceContext* pContext = RenderInterfaceD3D11::GetDeviceContext();
+
+ if (m_pInputLayout)
+ pContext->IASetInputLayout(m_pInputLayout);
+ else
+ pContext->IASetInputLayout(NV_NULL);
+
+
+ if (m_pVertexShader)
+ {
+ pContext->VSSetShader( m_pVertexShader, NV_NULL, 0);
+ if (m_pParamBuffers[0])
+ pContext->VSSetConstantBuffers(0, 1, &m_pParamBuffers[0]);
+ }
+
+ if (m_pPixelShader)
+ {
+ pContext->PSSetShader( m_pPixelShader, NV_NULL, 0);
+ if (m_pParamBuffers[0])
+ pContext->PSSetConstantBuffers(0, 1, &m_pParamBuffers[0]);
+ if (m_pParamBuffers[1])
+ pContext->PSSetConstantBuffers(1, 1, &m_pParamBuffers[1]);
+ }
+
+ pContext->GSSetShader( 0, 0, 0);
+ pContext->DSSetShader( 0, 0, 0);
+ pContext->HSSetShader( 0, 0, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D11RenderShader::Disable()
+{
+ ID3D11DeviceContext* pContext = RenderInterfaceD3D11::GetDeviceContext();
+
+ pContext->IASetInputLayout(NV_NULL);
+
+ pContext->VSSetShader( 0, NV_NULL, 0);
+ pContext->PSSetShader( 0, NV_NULL, 0);
+ pContext->GSSetShader( 0, 0, 0);
+ pContext->DSSetShader( 0, 0, 0);
+ pContext->HSSetShader( 0, 0, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool D3D11RenderShader::CreateParamBuffer( UINT sizeBuffer, UINT slot )
+{
+ ID3D11Device* pDevice = RenderInterfaceD3D11::GetDevice();
+ if (!pDevice)
+ return false;
+
+ SAFE_RELEASE(m_pParamBuffers[slot]);
+
+ D3D11_BUFFER_DESC Desc;
+ {
+ Desc.Usage = D3D11_USAGE_DYNAMIC;
+ Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ Desc.MiscFlags = 0;
+ Desc.ByteWidth = sizeBuffer;
+ }
+
+ HRESULT hr = pDevice->CreateBuffer( &Desc, NV_NULL, &m_pParamBuffers[slot] );
+ if( FAILED(hr) )
+ false;
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void* D3D11RenderShader::MapParam(UINT slot)
+{
+ ID3D11DeviceContext* pContext = RenderInterfaceD3D11::GetDeviceContext();
+
+ if (!m_pParamBuffers[slot] || !pContext)
+ return 0;
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT hr = pContext->Map(m_pParamBuffers[slot], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+
+ if ( FAILED(hr))
+ return 0;
+
+ return mappedResource.pData;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D11RenderShader::UnmapParam( UINT slot )
+{
+ ID3D11DeviceContext* pContext = RenderInterfaceD3D11::GetDeviceContext();
+
+ if (pContext && m_pParamBuffers[slot])
+ pContext->Unmap( m_pParamBuffers[slot], 0);
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderShader.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderShader.h
new file mode 100644
index 0000000..1aad045
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RenderShader.h
@@ -0,0 +1,72 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include <d3d11.h>
+#include "RenderPlugin.h"
+
+class CORERENDER_EXPORT D3D11RenderShader
+{
+public:
+ D3D11RenderShader();
+ ~D3D11RenderShader();
+
+ static D3D11RenderShader* Create(
+ const char *name,
+ void* pVSBlob, size_t vsBlobSize,
+ void* pPSBlob, size_t psBlobSize,
+ UINT cbufferSize0 = 0, UINT cbufferSize1 = 0,
+ D3D11_INPUT_ELEMENT_DESC* pElemDesc = 0, UINT numElements = 0);
+
+ void MakeCurrent();
+ void Disable();
+ void SetConstantBuffer();
+
+ void* MapParam(UINT slot = 0);
+ void UnmapParam(UINT slot = 0);
+
+ ID3D11VertexShader* getVertexShader() { return m_pVertexShader; }
+ ID3D11PixelShader* getPixelShader() { return m_pPixelShader; }
+ ID3D11InputLayout* getInputLayout() { return m_pInputLayout; }
+ ID3D11Buffer* getParamBuffer(UINT slot = 0) { return m_pParamBuffers[slot]; }
+
+protected:
+ bool CreateVSFromBlob(void* pBlob, size_t blobSize,
+ D3D11_INPUT_ELEMENT_DESC *desc, int elemCount);
+ bool CreatePSFromBlob(void* pBlob, size_t blobSize);
+ bool CreateParamBuffer(UINT sizeBuffer, UINT slot = 0);
+
+private:
+
+ ID3D11VertexShader* m_pVertexShader;
+ ID3D11PixelShader* m_pPixelShader;
+ ID3D11InputLayout* m_pInputLayout;
+ ID3D11Buffer* m_pParamBuffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_HW_SLOT_COUNT];
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RendererWindow.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RendererWindow.cpp
new file mode 100644
index 0000000..1274ed5
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RendererWindow.cpp
@@ -0,0 +1,319 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D11RendererWindow.h"
+
+#include "windows.h"
+
+#include "DXUT.h"
+#include "DXUTgui.h"
+#include "sdkmisc.h"
+
+#include "D3D11RenderInterface.h"
+#include "Nv.h"
+#ifdef USE_11ON12_WRAPPER
+#include "D3D11on12Wrapper.h"
+#endif // USE_11ON12_WRAPPER
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(x) { if (x) x->Release(); x = 0; }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+D3D11RenderWindow::D3D11RenderWindow() :
+ m_sampleCount(8)
+ , m_sampleQuality(0)
+#ifdef USE_11ON12_WRAPPER
+#else
+ , m_pDXGISwapChain(NV_NULL)
+ , m_pD3D11BackBuffer(NV_NULL)
+ , m_pD3D11DepthBuffer(NV_NULL)
+ , m_pD3D11RenderTargetView(NV_NULL)
+ , m_pD3D11DepthStencilView(NV_NULL)
+#endif // USE_11ON12_WRAPPER
+{
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+D3D11RenderWindow::~D3D11RenderWindow()
+{
+ Free();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool D3D11RenderWindow::Create( HWND hWnd, unsigned int nSamples )
+{
+#ifdef USE_11ON12_WRAPPER
+#else
+ if (m_pD3D11BackBuffer != NV_NULL || m_pD3D11RenderTargetView != NV_NULL)
+ Free();
+#endif // USE_11ON12_WRAPPER
+
+ ID3D11Device *pDevice = RenderInterfaceD3D11::GetDevice();
+ if (!pDevice)
+ return false;
+
+ ID3D11DeviceContext* pDeviceContext = RenderInterfaceD3D11::GetDeviceContext();
+ if (!pDeviceContext)
+ return false;
+
+ if(nSamples > D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT)
+ nSamples = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
+
+ m_sampleCount = nSamples;
+ m_sampleQuality = 0;
+ if(nSamples > 1)
+ {
+ pDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, nSamples, &m_sampleQuality);
+ assert(m_sampleQuality > 0);
+ m_sampleQuality--;
+ }
+
+ RECT rc;
+ GetClientRect((HWND)hWnd, &rc);
+ int wBuf = rc.right - rc.left;
+ int hBuf = rc.bottom- rc.top;
+
+#ifdef USE_11ON12_WRAPPER
+ D3D11on12Wrapper::InitSwapchain(wBuf, hBuf, hWnd);
+#else
+ DXGI_SWAP_CHAIN_DESC swapChainDesc;
+ {
+ memset(&swapChainDesc, 0, sizeof(DXGI_SWAP_CHAIN_DESC));
+ swapChainDesc.BufferDesc.Width = wBuf;
+ swapChainDesc.BufferDesc.Height= hBuf;
+ swapChainDesc.BufferDesc.Format= DXGI_FORMAT_R8G8B8A8_UNORM;
+ swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
+ swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
+ swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+ swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+ swapChainDesc.OutputWindow = (HWND)hWnd;
+ swapChainDesc.SampleDesc.Count = m_sampleCount;
+ swapChainDesc.SampleDesc.Quality = m_sampleQuality;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+ swapChainDesc.Windowed = true;
+ }
+
+ // Create the swap chain
+ IDXGIFactory1* pDXGIFactory = RenderInterfaceD3D11::GetDXGIFactory();
+ HRESULT res = pDXGIFactory->CreateSwapChain(pDevice, &swapChainDesc, &m_pDXGISwapChain);
+ if (FAILED(res)) return false;
+#endif // USE_11ON12_WRAPPER
+
+ // create DXUT text rendering class
+ m_pDialogResourceManager = new CDXUTDialogResourceManager;
+ m_pDialogResourceManager->OnD3D11CreateDevice(pDevice, pDeviceContext);
+ m_pTextHelper = new CDXUTTextHelper( pDevice, pDeviceContext, m_pDialogResourceManager, 15 );
+
+ CreateRenderTarget();
+ Resize(wBuf, hBuf);
+ return true;// SUCCEEDED(res);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D11RenderWindow::Free()
+{
+ FreeBuffer();
+
+ SAFE_DELETE(m_pTextHelper);
+
+#ifdef USE_11ON12_WRAPPER
+#else
+ SAFE_RELEASE(m_pDXGISwapChain);
+#endif // USE_11ON12_WRAPPER
+
+ if (m_pDialogResourceManager)
+ {
+ m_pDialogResourceManager->OnD3D11DestroyDevice();
+ SAFE_DELETE(m_pDialogResourceManager);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D11RenderWindow::FreeBuffer()
+{
+#ifdef USE_11ON12_WRAPPER
+#else
+ SAFE_RELEASE(m_pD3D11RenderTargetView);
+ SAFE_RELEASE(m_pD3D11BackBuffer);
+ SAFE_RELEASE(m_pD3D11DepthStencilView);
+ SAFE_RELEASE(m_pD3D11DepthBuffer);
+#endif // USE_11ON12_WRAPPER
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D11RenderWindow::Present()
+{
+#ifdef USE_11ON12_WRAPPER
+ D3D11on12Wrapper::EndScene();
+#else
+ assert(m_pDXGISwapChain);
+
+ if(m_pDXGISwapChain)
+ {
+ //m_pDXGISwapChain->Present(1, 0); // present in vsync
+ m_pDXGISwapChain->Present(0, 0); // present in vsync off
+ }
+#endif // USE_11ON12_WRAPPER
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D11RenderWindow::Clear(float r, float g, float b)
+{
+#ifdef USE_11ON12_WRAPPER
+ D3D11on12Wrapper::BeginScene();
+ D3D11on12Wrapper::ClearScene(r, g, b);
+#else
+ const float clearColor[4] = {r, g, b, 1.0f};
+
+ ID3D11DeviceContext* pD3DContext = RenderInterfaceD3D11::GetDeviceContext();
+ pD3DContext->ClearRenderTargetView(m_pD3D11RenderTargetView, clearColor);
+ pD3DContext->ClearDepthStencilView(m_pD3D11DepthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);
+#endif // USE_11ON12_WRAPPER
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool D3D11RenderWindow::Resize(int w, int h)
+{
+ assert(w > 0 && h > 0);
+ DXGI_SWAP_CHAIN_DESC swapChainDesc;
+ HRESULT res0 = m_pDXGISwapChain->GetDesc(&swapChainDesc);
+ if (w == (LONG)swapChainDesc.BufferDesc.Width &&
+ h == (LONG)swapChainDesc.BufferDesc.Height)
+ return true;
+
+#ifdef USE_11ON12_WRAPPER
+#else
+ //ID3D11DeviceContext* pD3DContext = RenderInterfaceD3D11::GetDeviceContext();
+ //ID3D11RenderTargetView *nullRTV = NULL;
+ //pD3DContext->OMSetRenderTargets(1, &nullRTV, NULL);
+ FreeBuffer();
+ swapChainDesc.BufferDesc.Width = w;
+ swapChainDesc.BufferDesc.Height = h;
+ //HRESULT res = m_pDXGISwapChain->ResizeBuffers(1, w, h, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
+ HRESULT res = m_pDXGISwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.BufferDesc.Width,
+ swapChainDesc.BufferDesc.Height, swapChainDesc.BufferDesc.Format,
+ swapChainDesc.Flags);
+ assert(SUCCEEDED(res));
+#endif
+ return CreateRenderTarget();
+}
+
+bool D3D11RenderWindow::CreateRenderTarget()
+{
+#ifdef USE_11ON12_WRAPPER
+ D3D11on12Wrapper::ResizeScene(w, h);
+#else
+ ID3D11Device* pDevice = RenderInterfaceD3D11::GetDevice();
+ // Retrieve the 2D back buffer
+ HRESULT res = m_pDXGISwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&m_pD3D11BackBuffer);
+ assert(SUCCEEDED(res));
+
+ D3D11_TEXTURE2D_DESC descTex2D;
+ m_pD3D11BackBuffer->GetDesc(&descTex2D);
+
+ // Create the render target view
+ D3D11_RENDER_TARGET_VIEW_DESC descRenderTargetView;
+ {
+ memset(&descRenderTargetView, 0, sizeof(D3D11_RENDER_TARGET_VIEW_DESC));
+ descRenderTargetView.Format = descTex2D.Format;
+ descRenderTargetView.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; // -MS dimension to support MSAA
+ descRenderTargetView.Texture2D.MipSlice = 0;
+ }
+
+ res = pDevice->CreateRenderTargetView(m_pD3D11BackBuffer, &descRenderTargetView, &m_pD3D11RenderTargetView);
+
+ assert(SUCCEEDED(res));
+
+ DXGI_SWAP_CHAIN_DESC swapChainDesc;
+ HRESULT res0 = m_pDXGISwapChain->GetDesc(&swapChainDesc);
+ // Create the depth/stencil buffer and view
+ D3D11_TEXTURE2D_DESC depthStencilDesc;
+
+ depthStencilDesc.Width = swapChainDesc.BufferDesc.Width;
+ depthStencilDesc.Height = swapChainDesc.BufferDesc.Height;
+ depthStencilDesc.MipLevels = 1;
+ depthStencilDesc.ArraySize = 1;
+ depthStencilDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
+ depthStencilDesc.SampleDesc.Count = m_sampleCount;
+ depthStencilDesc.SampleDesc.Quality = m_sampleQuality;
+ depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
+ depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
+ depthStencilDesc.CPUAccessFlags = 0;
+ depthStencilDesc.MiscFlags = 0;
+
+ res = pDevice->CreateTexture2D(&depthStencilDesc, 0, &m_pD3D11DepthBuffer);
+ assert(SUCCEEDED(res));
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC descDepthStencilView;
+ memset(&descDepthStencilView, 0, sizeof(D3D11_DEPTH_STENCIL_VIEW_DESC));
+ descDepthStencilView.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ descDepthStencilView.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; // -MS dimension to support MSAA
+ descDepthStencilView.Texture2D.MipSlice = 0;
+
+ res = pDevice->CreateDepthStencilView(m_pD3D11DepthBuffer, &descDepthStencilView, &m_pD3D11DepthStencilView);
+ assert(SUCCEEDED(res));
+
+ m_Width = swapChainDesc.BufferDesc.Width;
+ m_Height= swapChainDesc.BufferDesc.Height;
+
+ /////////////////////////////////////////
+ if (m_pDialogResourceManager)
+ {
+ DXGI_SURFACE_DESC backbufferDesc;
+ backbufferDesc.Width = descTex2D.Width;
+ backbufferDesc.Height = descTex2D.Height;
+ backbufferDesc.Format = descTex2D.Format;
+ backbufferDesc.SampleDesc = descTex2D.SampleDesc;
+
+ m_pDialogResourceManager->OnD3D11ResizedSwapChain(pDevice, &backbufferDesc);
+ }
+
+ // assume always the current render window, bind to render context immediately
+ ID3D11DeviceContext* pD3DContext = RenderInterfaceD3D11::GetDeviceContext();
+ pD3DContext->OMSetRenderTargets(1, &m_pD3D11RenderTargetView, m_pD3D11DepthStencilView);
+
+ // set the viewport transform
+ D3D11_VIEWPORT vp;
+ {
+ vp.TopLeftX = 0;
+ vp.TopLeftY = 0;
+ vp.Width = (float)m_Width;
+ vp.Height = (float)m_Height;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ }
+ pD3DContext->RSSetViewports(1, &vp);
+#endif // USE_11ON12_WRAPPER
+
+ return true;
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RendererWindow.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RendererWindow.h
new file mode 100644
index 0000000..88d5c8f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11RendererWindow.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <d3d11.h>
+
+// DXUT stuffs for text rendering
+class CDXUTDialogResourceManager;
+class CDXUTTextHelper;
+
+struct D3D11RenderWindow
+{
+public:
+ D3D11RenderWindow();
+ ~D3D11RenderWindow();
+
+ bool Create(HWND hWnd, unsigned int nSamples = 1);
+ bool Resize(int w, int h);
+ void Present();
+ void Clear(float r, float g, float b);
+ bool CreateRenderTarget();
+
+ // sample desc
+ UINT m_sampleCount;
+ UINT m_sampleQuality;
+#ifdef USE_11ON12_WRAPPER
+#else
+ int m_Height, m_Width;
+
+ IDXGISwapChain* m_pDXGISwapChain;
+ ID3D11Texture2D* m_pD3D11BackBuffer;
+ ID3D11Texture2D* m_pD3D11DepthBuffer;
+ ID3D11RenderTargetView* m_pD3D11RenderTargetView;
+ ID3D11DepthStencilView* m_pD3D11DepthStencilView;
+#endif // USE_11ON12_WRAPPER
+
+ CDXUTDialogResourceManager* m_pDialogResourceManager;
+ CDXUTTextHelper* m_pTextHelper;
+
+private:
+ void Free();
+ void FreeBuffer();
+
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Shaders.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Shaders.cpp
new file mode 100644
index 0000000..eba1184
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Shaders.cpp
@@ -0,0 +1,225 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D11Shaders.h"
+
+#include "MeshShaderParam.h"
+#include "LightShaderParam.h"
+
+//#include <Nv/Blast/NvHairSdk.h>
+#include "D3D11RenderShader.h"
+
+using namespace RenderInterface;
+
+/////////////////////////////////////////////////////////////////////////////////////
+// Common shader settings
+//static D3D11RenderShader* g_pShaders[SHADER_TYPE_END];
+static std::map<int, D3D11RenderShader*> g_pShaders;
+/*
+namespace BodyShaderBlobs
+{
+ #include "Shaders/BodyShader_VS.h"
+ #include "Shaders/BodyShader_PS.h"
+}
+
+namespace BodyShadowBlobs
+{
+ #include "Shaders/BodyShadow_VS.h"
+ #include "Shaders/BodyShadow_PS.h"
+}
+
+namespace ScreenQuadBlobs
+{
+ #include "Shaders/ScreenQuad_VS.h"
+ #include "Shaders/ScreenQuad_PS.h"
+}
+
+namespace ScreenQuadColorBlobs
+{
+ #include "Shaders/ScreenQuadColor_VS.h"
+ #include "Shaders/ScreenQuadColor_PS.h"
+}
+
+namespace VisualizeShadowBlobs
+{
+ #include "Shaders/VisualizeShadow_VS.h"
+ #include "Shaders/VisualizeShadow_PS.h"
+}
+
+namespace ColorBlobs
+{
+ #include "Shaders/Color_VS.h"
+ #include "Shaders/Color_PS.h"
+}
+
+#ifndef NV_ARTISTTOOLS
+namespace BlastShaderBlobs
+{
+#include "Shaders/BlastShader_PS.h"
+}
+
+namespace BlastShadowBlobs
+{
+#include "Shaders/BlastShadow_PS.h"
+}
+#endif // NV_ARTISTTOOLS
+*/
+//////////////////////////////////////////////////////////////////////////
+bool InitializeShadersD3D11()
+{
+ /*
+ D3D11_INPUT_ELEMENT_DESC layoutBodyRender[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "VERTEX_NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "FACE_NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 36, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 48, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "VERTEX_ID", 0, DXGI_FORMAT_R32_FLOAT, 0, 56, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+
+ UINT numElements = sizeof(layoutBodyRender)/sizeof(D3D11_INPUT_ELEMENT_DESC);
+
+ g_pShaders[SHADER_TYPE_MESH_RENDERING] = D3D11RenderShader::Create( "MeshRenderShader",
+ (void*)BodyShaderBlobs::g_vs_main, sizeof(BodyShaderBlobs::g_vs_main),
+ (void*)BodyShaderBlobs::g_ps_main, sizeof(BodyShaderBlobs::g_ps_main),
+ sizeof(MeshShaderParam), 0,
+ &layoutBodyRender[0], numElements);
+
+ g_pShaders[SHADER_TYPE_MESH_SHADOW] = D3D11RenderShader::Create( "MeshShadowShader",
+ (void*)BodyShadowBlobs::g_vs_main, sizeof(BodyShadowBlobs::g_vs_main),
+ (void*)BodyShadowBlobs::g_ps_main, sizeof(BodyShadowBlobs::g_ps_main),
+ sizeof(MeshShadowShaderParam), 0,
+ &layoutBodyRender[0], numElements);
+
+ g_pShaders[SHADER_TYPE_SCREEN_QUAD] = D3D11RenderShader::Create( "ScreenQuadShader",
+ (void*)ScreenQuadBlobs::g_vs_main, sizeof(ScreenQuadBlobs::g_vs_main),
+ (void*)ScreenQuadBlobs::g_ps_main, sizeof(ScreenQuadBlobs::g_ps_main));
+
+ g_pShaders[SHADER_TYPE_SCREEN_QUAD_COLOR] = D3D11RenderShader::Create( "ScreenQuadColorShader",
+ (void*)ScreenQuadColorBlobs::g_vs_main, sizeof(ScreenQuadColorBlobs::g_vs_main),
+ (void*)ScreenQuadColorBlobs::g_ps_main, sizeof(ScreenQuadColorBlobs::g_ps_main));
+
+ g_pShaders[SHADER_TYPE_VISUALIZE_SHADOW] = D3D11RenderShader::Create( "VisualizeShadowShader",
+ (void*)VisualizeShadowBlobs::g_vs_main, sizeof(VisualizeShadowBlobs::g_vs_main),
+ (void*)VisualizeShadowBlobs::g_ps_main, sizeof(VisualizeShadowBlobs::g_ps_main),
+ sizeof(ShadowVizParam));
+
+ D3D11_INPUT_ELEMENT_DESC layout_Position_And_Color[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+ UINT numElements2 = sizeof(layout_Position_And_Color)/sizeof(D3D11_INPUT_ELEMENT_DESC);
+
+ g_pShaders[SHADER_TYPE_SIMPLE_COLOR] = D3D11RenderShader::Create( "Color",
+ (void*)ColorBlobs::g_vs_main, sizeof(ColorBlobs::g_vs_main),
+ (void*)ColorBlobs::g_ps_main, sizeof(ColorBlobs::g_ps_main),
+ sizeof(SimpleShaderParam), 0,
+ &layout_Position_And_Color[0], numElements2);
+
+#ifndef NV_ARTISTTOOLS
+ g_pShaders[SHADER_TYPE_HAIR_SHADER_DEFAULT] = D3D11RenderShader::Create(
+ "hairShaderDefault", 0, 0,
+ (void*)BlastShaderBlobs::g_ps_main, sizeof(BlastShaderBlobs::g_ps_main),
+ sizeof(NvHair::ShaderConstantBuffer),
+ sizeof(LightShaderParam)
+ );
+
+ g_pShaders[SHADER_TYPE_HAIR_SHADER_SHADOW] = D3D11RenderShader::Create(
+ "hairShadow", 0, 0,
+ (void*)BlastShadowBlobs::g_ps_main, sizeof(BlastShadowBlobs::g_ps_main),
+ sizeof(NvHair::ShaderConstantBuffer),
+ 0);
+#else
+ CoreLib::Inst()->D3D11Shaders_InitializeShadersD3D11(g_pShaders);
+#endif // NV_ARTISTTOOLS
+ */
+ return true;
+}
+
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(x) { if (x) x->Release(); x = 0; }
+#endif
+
+#ifndef SAFE_DELETE
+#define SAFE_DELETE(x) { if (x) delete x; x = 0; }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+void DestroyShadersD3D11()
+{
+ for (int i = 0; i < g_pShaders.size(); i++)
+ {
+ D3D11RenderShader*& pShader = g_pShaders[i];
+ if (pShader)
+ {
+ delete pShader;
+ pShader = 0;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+D3D11RenderShader* GetShaderD3D11(SHADER_TYPE st)
+{
+ return g_pShaders[st];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyShaderD3D11(SHADER_TYPE st)
+{
+ D3D11RenderShader* pD3D11Shader = GetShaderD3D11(st);
+ if (!pD3D11Shader)
+ return;
+
+ pD3D11Shader->MakeCurrent();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void DisableShaderD3D11(RenderInterface::SHADER_TYPE st)
+{
+ D3D11RenderShader* pD3D11Shader = GetShaderD3D11(st);
+ if (!pD3D11Shader)
+ return;
+
+ pD3D11Shader->Disable();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void CopyShaderParamD3D11(SHADER_TYPE st, void* pSysMem, unsigned int bytes, unsigned int slot)
+{
+ D3D11RenderShader* pD3D11Shader = GetShaderD3D11(st);
+ if (!pD3D11Shader)
+ return;
+
+ void* mappedParam = pD3D11Shader->MapParam(slot);
+
+ memcpy(mappedParam, pSysMem, bytes);
+
+ pD3D11Shader->UnmapParam(slot);
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Shaders.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Shaders.h
new file mode 100644
index 0000000..b1d4929
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Shaders.h
@@ -0,0 +1,43 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "RenderInterface.h"
+
+#include "RenderPlugin.h"
+
+///////////////////////////////////////////////////////////////////
+// default shaders
+///////////////////////////////////////////////////////////////////
+CORERENDER_EXPORT bool InitializeShadersD3D11();
+CORERENDER_EXPORT void DestroyShadersD3D11();
+
+CORERENDER_EXPORT void ApplyShaderD3D11(RenderInterface::SHADER_TYPE st);
+CORERENDER_EXPORT void DisableShaderD3D11(RenderInterface::SHADER_TYPE st);
+CORERENDER_EXPORT void CopyShaderParamD3D11(RenderInterface::SHADER_TYPE st, void* pSysMem, unsigned int bytes, unsigned int slot = 0);
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11ShadowMap.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11ShadowMap.cpp
new file mode 100644
index 0000000..90e30b2
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11ShadowMap.cpp
@@ -0,0 +1,208 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D11ShadowMap.h"
+
+#include "RenderResources.h"
+
+#include "D3D11RenderInterface.h"
+#include "D3D11TextureResource.h"
+
+namespace
+{
+//////////////////////////////////////////////////////////////////////////////////////////////////
+D3D11_TEXTURE2D_DESC CreateD3D11TextureDesc(
+ DXGI_FORMAT Format, UINT Width, UINT Height,
+ UINT BindFlags, UINT SampleCount = 1, D3D11_USAGE Usage = D3D11_USAGE_DEFAULT, UINT CPUAccessFlags = 0,
+ UINT MiscFlags = 0, UINT ArraySize = 1, UINT MipLevels = 1)
+{
+
+ D3D11_TEXTURE2D_DESC desc;
+
+ desc.Format = Format;
+ desc.Width = Width;
+ desc.Height = Height;
+
+ desc.ArraySize = ArraySize;
+ desc.MiscFlags = MiscFlags;
+ desc.MipLevels = MipLevels;
+
+ desc.SampleDesc.Count = SampleCount;
+ desc.SampleDesc.Quality = 0;
+ desc.BindFlags = BindFlags;
+ desc.Usage = Usage;
+ desc.CPUAccessFlags = CPUAccessFlags;
+
+ return desc;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+D3D11_DEPTH_STENCIL_VIEW_DESC CreateD3D11DSVDesc(
+ DXGI_FORMAT Format, D3D11_DSV_DIMENSION ViewDimension,
+ UINT Flags = 0, UINT MipSlice = 0)
+{
+ D3D11_DEPTH_STENCIL_VIEW_DESC desc;
+
+ desc.Format = Format;
+ desc.ViewDimension = ViewDimension;
+ desc.Flags = Flags;
+ desc.Texture2D.MipSlice = MipSlice;
+
+ return desc;
+}
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+D3D11ShadowMap::D3D11ShadowMap(int resolution)
+{
+ m_pShadowTexture = nullptr;
+ m_pShadowRTV = nullptr;
+ m_pShadowSRV = nullptr;
+
+ m_pDepthTexture = nullptr;
+ m_pDepthDSV = nullptr;
+
+ ID3D11Device* pd3dDevice = RenderInterfaceD3D11::GetDevice();
+ if (!pd3dDevice)
+ return;
+
+ {
+ m_viewport.Width = float(resolution);
+ m_viewport.Height = float(resolution);
+ m_viewport.MinDepth = 0;
+ m_viewport.MaxDepth = 1;
+ m_viewport.TopLeftX = 0;
+ m_viewport.TopLeftY = 0;
+ }
+
+ HRESULT hr;
+
+ // create shadow render target
+ {
+ D3D11_TEXTURE2D_DESC texDesc = CreateD3D11TextureDesc(
+ DXGI_FORMAT_R32_FLOAT, UINT(m_viewport.Width), UINT(m_viewport.Height),
+ D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
+
+ hr = pd3dDevice->CreateTexture2D( &texDesc, NULL, &m_pShadowTexture );
+ hr = pd3dDevice->CreateShaderResourceView( m_pShadowTexture, NULL, &m_pShadowSRV );
+ hr = pd3dDevice->CreateRenderTargetView(m_pShadowTexture, NULL, &m_pShadowRTV);
+
+ m_shadowResource.m_pD3D11Resource = m_pShadowSRV;
+ }
+
+ // create shadow depth stencil
+ {
+ D3D11_TEXTURE2D_DESC texDesc = CreateD3D11TextureDesc(
+ DXGI_FORMAT_R32_TYPELESS, UINT(m_viewport.Width), UINT(m_viewport.Height),
+ D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE);
+
+ hr = pd3dDevice->CreateTexture2D( &texDesc, NULL, &m_pDepthTexture );
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = CreateD3D11DSVDesc(
+ DXGI_FORMAT_D32_FLOAT, D3D11_DSV_DIMENSION_TEXTURE2D);
+
+ hr = pd3dDevice->CreateDepthStencilView(m_pDepthTexture, &dsvDesc, &m_pDepthDSV);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+D3D11ShadowMap::~D3D11ShadowMap()
+{
+ Release();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void D3D11ShadowMap::Release()
+{
+ SAFE_RELEASE(m_pShadowTexture);
+ SAFE_RELEASE(m_pShadowRTV);
+ SAFE_RELEASE(m_pShadowSRV);
+ SAFE_RELEASE(m_pDepthTexture);
+ SAFE_RELEASE(m_pDepthDSV);
+
+ m_shadowResource.m_pD3D11Resource = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+GPUShaderResource* D3D11ShadowMap::GetShadowSRV()
+{
+ return &m_shadowResource;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool D3D11ShadowMap::isValid()
+{
+ return m_pShadowTexture && m_pShadowRTV && m_pShadowSRV && m_pDepthTexture && m_pDepthDSV;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void D3D11ShadowMap::BeginRendering(float clearDepth)
+{
+ if (!isValid())
+ return;
+
+ ID3D11DeviceContext* pd3dContext = RenderInterfaceD3D11::GetDeviceContext();
+ if (!pd3dContext)
+ return;
+
+ pd3dContext->OMGetRenderTargets(1, &m_pPreviousRTV, &m_pPreviousDSV);
+ m_numPreviousViewports = 1;
+ pd3dContext->RSGetViewports(&m_numPreviousViewports, m_previousViewport);
+
+ pd3dContext->OMSetRenderTargets( 1, &m_pShadowRTV, m_pDepthDSV);
+ pd3dContext->RSSetViewports(1, &m_viewport);
+
+ float ClearColor[4] = { clearDepth, clearDepth, clearDepth, clearDepth};
+
+ pd3dContext->ClearRenderTargetView( m_pShadowRTV, ClearColor );
+ pd3dContext->ClearDepthStencilView( m_pDepthDSV, D3D11_CLEAR_DEPTH, 1.0, 0 );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void D3D11ShadowMap::EndRendering()
+{
+ if (!isValid())
+ return;
+
+ ID3D11DeviceContext* pd3dContext = RenderInterfaceD3D11::GetDeviceContext();
+ if (!pd3dContext)
+ return;
+
+ pd3dContext->OMSetRenderTargets(0, NULL, NULL);
+
+ if (m_pPreviousRTV)
+ {
+ pd3dContext->OMSetRenderTargets(1, &m_pPreviousRTV, m_pPreviousDSV);
+ m_pPreviousRTV->Release();
+ if (m_pPreviousDSV) m_pPreviousDSV->Release();
+ }
+
+ if (m_numPreviousViewports)
+ pd3dContext->RSSetViewports(m_numPreviousViewports, m_previousViewport);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11ShadowMap.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11ShadowMap.h
new file mode 100644
index 0000000..fc9fe79
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11ShadowMap.h
@@ -0,0 +1,72 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "ShadowMap.h"
+
+#include "d3d11.h"
+#include "D3D11TextureResource.h"
+
+class GPUShaderResource;
+class D3D11TextureResource;
+
+struct D3D11ShadowMap : public ShadowMap
+{
+ D3D11_VIEWPORT m_viewport;
+
+ ID3D11Texture2D* m_pShadowTexture;
+ ID3D11RenderTargetView* m_pShadowRTV;
+ ID3D11ShaderResourceView* m_pShadowSRV;
+
+ ID3D11Texture2D* m_pDepthTexture;
+ ID3D11DepthStencilView* m_pDepthDSV;
+ ID3D11ShaderResourceView* m_pDepthSRV;
+
+ D3D11TextureResource m_shadowResource;
+
+public:
+ D3D11ShadowMap(int resolution );
+ ~D3D11ShadowMap();
+
+ void Release();
+ void BeginRendering(float clearDepth);
+ void EndRendering();
+
+ GPUShaderResource* GetShadowSRV();
+
+protected:
+
+ bool isValid();
+
+ ID3D11RenderTargetView* m_pPreviousRTV;
+ ID3D11DepthStencilView* m_pPreviousDSV;
+ UINT m_numPreviousViewports;
+ D3D11_VIEWPORT m_previousViewport[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11TextureResource.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11TextureResource.cpp
new file mode 100644
index 0000000..2a8f7ee
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11TextureResource.cpp
@@ -0,0 +1,29 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D11TextureResource.h"
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11TextureResource.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11TextureResource.h
new file mode 100644
index 0000000..91d6539
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11TextureResource.h
@@ -0,0 +1,64 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "RenderResources.h"
+
+#include "d3d11.h"
+
+// GPU resources for texture
+struct D3D11TextureResource : public GPUShaderResource
+{
+ ID3D11ShaderResourceView* m_pD3D11Resource;
+
+public:
+ static GPUShaderResource* Create(ID3D11ShaderResourceView* pResource) {
+ D3D11TextureResource* pBuffer = new D3D11TextureResource;
+ pBuffer->m_pD3D11Resource = pResource;
+ return pBuffer;
+ }
+
+ static ID3D11ShaderResourceView* GetResource(GPUShaderResource* pBuffer)
+ {
+ D3D11TextureResource* pD3D11Buffer = dynamic_cast<D3D11TextureResource*>(pBuffer);
+ if (!pD3D11Buffer)
+ return 0;
+ return pD3D11Buffer->m_pD3D11Resource;
+ }
+
+ ~D3D11TextureResource()
+ {
+ }
+
+ void Release()
+ {
+ SAFE_RELEASE(m_pD3D11Resource);
+ }
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Util.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Util.cpp
new file mode 100644
index 0000000..b13c8e3
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Util.cpp
@@ -0,0 +1,333 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D11Util.h"
+
+#include "D3D11Shaders.h"
+#include "D3D11RenderShader.h"
+
+#include "D3DX10tex.h"
+#include "D3DX11tex.h"
+
+#include "D3D11Wrapper.h"
+#include "DXUT.h"
+#include "DXUTgui.h"
+#include "sdkmisc.h"
+#include "D3D11RendererWindow.h"
+#include "SimpleRenderable.h"
+//#include "MeshShaderParam.h"
+#include "D3D11RenderInterface.h"
+#include "D3D11TextureResource.h"
+
+namespace D3D11Util
+{
+ using namespace RenderInterface;
+
+ // D3D hook to render window
+ D3D11RenderWindow* g_pRenderWindow = 0;
+
+///////////////////////////////////////////////////////////////////////////////
+#include "../../../../../../external/stb_image/stb_image.c"
+
+GPUShaderResource*
+CreateTextureSRV(const char* texturename)
+{
+ ID3D11Device* pDevice = RenderInterfaceD3D11::GetDevice();
+ if (!pDevice)
+ return 0;
+
+ D3DX11_IMAGE_LOAD_INFO texLoadInfo;
+
+ texLoadInfo.MipLevels = 8;
+ texLoadInfo.MipFilter = D3DX10_FILTER_TRIANGLE;
+ texLoadInfo.Filter = D3DX10_FILTER_TRIANGLE;
+
+ ID3D11Resource *pRes = 0;
+
+ HRESULT hr;
+ D3DX11CreateTextureFromFileA(pDevice, texturename, &texLoadInfo, NULL, &pRes, &hr);
+
+ ID3D11Texture2D* texture = NULL;
+
+ if (!pRes)
+ {
+ // Try stb_image for .TGA
+ int width = 0;
+ int height = 0;
+ int numComponents = 0;
+ unsigned char *pSTBIRes = stbi_load(texturename, &width, &height, &numComponents, 4);
+
+ if (!pSTBIRes)
+ return 0;
+
+ const int requestedMipLevels = texLoadInfo.MipLevels;
+
+ D3D11_SUBRESOURCE_DATA* initData = new D3D11_SUBRESOURCE_DATA[requestedMipLevels];
+ ZeroMemory(initData, sizeof(D3D11_SUBRESOURCE_DATA)*requestedMipLevels);
+
+ struct Pixel
+ {
+ unsigned char rgba[4];
+ };
+
+ // prepare target buffer just large enough to include all the mip levels
+ Pixel* targets = new Pixel[width*height*2];
+
+ // copy the first mip level
+ memcpy(targets, pSTBIRes, width*height*4);
+
+ // now it's OK to delete the original
+ if (pSTBIRes)
+ stbi_image_free(pSTBIRes);
+
+ // current mip level width and height
+ int mipWidth = width;
+ int mipHeight = height;
+
+ // actual mip levels
+ int mipLevels = 0;
+
+ // current data
+ Pixel* source = targets;
+ Pixel* target = nullptr;
+
+ for (int idx = 0; idx < requestedMipLevels; ++idx)
+ {
+ // set initData
+ initData[idx].pSysMem = source;
+ initData[idx].SysMemPitch = mipWidth*4;
+ mipLevels++;
+
+ // skip generating mip for 1x1
+ if ((mipWidth == 1) && (mipHeight == 1))
+ break;
+
+ // skip generating mip for the last level
+ if (idx == (requestedMipLevels-1))
+ break;
+
+ // buffer for the next mip level
+ target = &source[mipWidth*mipHeight];
+
+ const int prevWidth = mipWidth; // previous mip's width
+
+ // generate the next mip level
+ mipWidth = max(1, mipWidth >> 1);
+ mipHeight = max(1, mipHeight >> 1);
+
+ Pixel samples[4];
+
+ for (int y = 0; y < mipHeight; ++y)
+ {
+ for (int x = 0; x < mipWidth; ++x)
+ {
+ const int px = x*2; // x in previous mip
+ const int py = y*2; // y in previous mip
+
+ samples[0] = source[py*prevWidth + px]; // left top
+ samples[1] = source[py*prevWidth + px+1]; // right top
+ samples[2] = source[(py+1)*prevWidth + px]; // left bottom
+ samples[3] = source[(py+1)*prevWidth + px+1]; // right bottom
+
+ // for each component
+ for (int comp = 0; comp < 4; ++comp)
+ {
+ // do the linear box filter for lower mip level
+ target[y*mipWidth + x].rgba[comp] = (samples[0].rgba[comp] + samples[1].rgba[comp] + samples[2].rgba[comp] + samples[3].rgba[comp])/4;
+ }
+ }
+ }
+
+ // update source
+ source = target;
+ }
+
+ D3D11_TEXTURE2D_DESC desc;
+ ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
+ desc.ArraySize = 1;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.Height = height;
+ desc.Width = width;
+ desc.MipLevels = mipLevels;
+ desc.MiscFlags = 0;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+
+ HRESULT ret = pDevice->CreateTexture2D(&desc, initData, &texture);
+
+ delete initData;
+ delete targets;
+
+ if (ret != S_OK)
+ return 0;
+ }
+ else
+ {
+ pRes->QueryInterface(__uuidof( ID3D11Texture2D ), (LPVOID*)&texture);
+ }
+
+ D3D11_TEXTURE2D_DESC desc;
+ texture->GetDesc( &desc );
+
+ ID3D11ShaderResourceView* pTextureSRV = 0;
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+ ZeroMemory( &SRVDesc, sizeof(SRVDesc) );
+ SRVDesc.Format = desc.Format;
+ SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ SRVDesc.Texture2D.MostDetailedMip = 0;
+ SRVDesc.Texture2D.MipLevels = desc.MipLevels;
+ pDevice->CreateShaderResourceView(texture, &SRVDesc, &pTextureSRV);
+
+ if (texture) texture->Release();
+
+ if (pRes)
+ pRes->Release();
+
+ return D3D11TextureResource::Create(pTextureSRV);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+bool GetDeviceInfoString(wchar_t *str)
+{
+ IDXGIAdapter* pAdapter = RenderInterfaceD3D11::GetAdapter();
+ if (!pAdapter)
+ return false;
+
+ auto adapterDescription = DXGI_ADAPTER_DESC();
+ pAdapter->GetDesc(&adapterDescription);
+
+ WCHAR* pDescStr = adapterDescription.Description;
+ float memInGB = float(adapterDescription.DedicatedVideoMemory) / 1e9f;
+ swprintf_s(str, 1000, L"%s(%.1fGb)\n", pDescStr, memInGB);
+
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Render window interafce
+/////////////////////////////////////////////////////////////////////////////////////////
+bool CreateRenderWindow(HWND hWnd, int nSamples)
+{
+ SAFE_DELETE(g_pRenderWindow);
+
+ g_pRenderWindow = new D3D11RenderWindow;
+ return g_pRenderWindow->Create(hWnd, nSamples);
+}
+
+D3DHandles& GetDeviceHandles(D3DHandles& deviceHandles)
+{
+ deviceHandles.pAdapter = RenderInterfaceD3D11::GetAdapter();
+ deviceHandles.pFactory = RenderInterfaceD3D11::GetDXGIFactory();
+ deviceHandles.pDevice = RenderInterfaceD3D11::GetDevice();
+ deviceHandles.pDeviceContext = RenderInterfaceD3D11::GetDeviceContext();
+
+ deviceHandles.pDXGISwapChain = g_pRenderWindow->m_pDXGISwapChain;
+ deviceHandles.pD3D11BackBuffer = g_pRenderWindow->m_pD3D11BackBuffer;
+ deviceHandles.pD3D11RenderTargetView = g_pRenderWindow->m_pD3D11RenderTargetView;
+ deviceHandles.pD3D11DepthBuffer = g_pRenderWindow->m_pD3D11DepthBuffer;
+ deviceHandles.pD3D11DepthStencilView = g_pRenderWindow->m_pD3D11DepthStencilView;
+ return deviceHandles;
+}
+
+void DestroyRenderWindow()
+{
+ SAFE_DELETE(g_pRenderWindow);
+}
+
+bool ResizeRenderWindow(int w, int h)
+{
+ if (!g_pRenderWindow)
+ return false;
+
+ return g_pRenderWindow->Resize(w,h);
+}
+
+void PresentRenderWindow()
+{
+ if (!g_pRenderWindow)
+ return;
+
+ g_pRenderWindow->Present();
+}
+
+void ClearRenderWindow(float r, float g, float b)
+{
+ if (!g_pRenderWindow)
+ return;
+
+ g_pRenderWindow->Clear(r,g,b);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Text draw helper functions (using DXUT)
+/////////////////////////////////////////////////////////////////////////////////////////
+void TxtHelperBegin()
+{
+ if (!g_pRenderWindow || !g_pRenderWindow->m_pTextHelper)
+ return;
+
+ g_pRenderWindow->m_pTextHelper->Begin();
+}
+
+void TxtHelperEnd()
+{
+ if (!g_pRenderWindow || !g_pRenderWindow->m_pTextHelper)
+ return;
+
+ g_pRenderWindow->m_pTextHelper->End();
+}
+
+void TxtHelperSetInsertionPos(int x, int y)
+{
+ if (!g_pRenderWindow || !g_pRenderWindow->m_pTextHelper)
+ return;
+
+ g_pRenderWindow->m_pTextHelper->SetInsertionPos(x, y);
+}
+
+void TxtHelperSetForegroundColor(float r, float g, float b, float a)
+{
+ if (!g_pRenderWindow || !g_pRenderWindow->m_pTextHelper)
+ return;
+
+ g_pRenderWindow->m_pTextHelper->SetForegroundColor(DirectX::XMFLOAT4(r,g,b,a));
+}
+
+void TxtHelperDrawTextLine(wchar_t* str)
+{
+ if (!g_pRenderWindow || !g_pRenderWindow->m_pTextHelper)
+ return;
+
+ g_pRenderWindow->m_pTextHelper->DrawTextLine(str);
+}
+
+} // end namespace \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Util.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Util.h
new file mode 100644
index 0000000..8a9176e
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Util.h
@@ -0,0 +1,69 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "d3d11.h"
+
+#include "RenderPlugin.h"
+
+class GPUShaderResource;
+class IDXGISwapChain;
+
+namespace D3D11Util
+{
+ ///////////////////////////////////////////////////////////////////
+ // render window management
+ ///////////////////////////////////////////////////////////////////
+ D3DHandles& GetDeviceHandles(D3DHandles& deviceHandles);
+ bool CreateRenderWindow(HWND hWnd, int nSamples);
+ void DestroyRenderWindow();
+ bool ResizeRenderWindow(int w, int h);
+ void PresentRenderWindow();
+ void ClearRenderWindow(float r, float g, float b);
+
+ ///////////////////////////////////////////////////////////////////
+ // background textures
+ bool LoadBackgroundTexture(const char* filePath);
+ void RenderBackgroundTexture();
+ void ClearBackgroundTexture();
+ GPUShaderResource* CreateTextureSRV(const char* texturename);
+
+ ///////////////////////////////////////////////////////////////////
+ CORERENDER_EXPORT bool GetDeviceInfoString(wchar_t *str);
+
+ ///////////////////////////////////////////////////////////////////
+ // text helpers
+ CORERENDER_EXPORT void TxtHelperBegin();
+ CORERENDER_EXPORT void TxtHelperEnd();
+ CORERENDER_EXPORT void TxtHelperSetInsertionPos(int x, int y);
+ CORERENDER_EXPORT void TxtHelperSetForegroundColor(float r, float g, float b, float a = 1.0f);
+ CORERENDER_EXPORT void TxtHelperDrawTextLine(wchar_t* str);
+
+
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Wrapper.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Wrapper.cpp
new file mode 100644
index 0000000..5a117f1
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Wrapper.cpp
@@ -0,0 +1,33 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D11Wrapper.h"
+
+namespace D3DWrapper
+{
+
+} // end namespace \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Wrapper.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Wrapper.h
new file mode 100644
index 0000000..0d752d8
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/D3D11Wrapper.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "d3d11.h"
+
+namespace D3DWrapper
+{
+ inline void SetDebugName(ID3D11DeviceChild* pResource, const char *name)
+ {
+ if (pResource) pResource->SetPrivateData( WKPDID_D3DDebugObjectName, strlen(name), name);
+ }
+}
+
+#define SET_D3D_DEBUG_NAME(x, name) D3DWrapper::SetDebugName(x, name);
+#define SET_D3D_DEBUG_NAME_VAR(x) D3DWrapper::SetDebugName(x, #x);
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/RenderPluginDx11.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/RenderPluginDx11.cpp
new file mode 100644
index 0000000..93d3fdf
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/RenderPluginDx11.cpp
@@ -0,0 +1,315 @@
+#include "RenderPluginDx11.h"
+
+#include "D3D11RenderInterface.h"
+#include "D3D11Util.h"
+#include "D3D11Shaders.h"
+#include "D3D11GPUProfiler.h"
+#include "D3D11ShadowMap.h"
+
+RenderPlugin* CreateRenderPlugin(void)
+{
+ return new RenderPluginDx11;
+}
+
+RenderPluginDx11::RenderPluginDx11()
+{
+ m_RenderApi = "Dx11";
+}
+
+RenderPluginDx11::~RenderPluginDx11()
+{
+}
+
+// interface
+bool RenderPluginDx11::InitDevice(int deviceID)
+{
+ return RenderInterfaceD3D11::InitDevice(deviceID);
+}
+
+bool RenderPluginDx11::Initialize()
+{
+ return RenderInterfaceD3D11::Initialize();
+}
+
+void RenderPluginDx11::Shutdown()
+{
+ D3D11Util::DestroyRenderWindow();
+ RenderInterfaceD3D11::Shutdown();
+}
+
+void RenderPluginDx11::CopyToDevice(GPUBufferResource *pDevicePtr,
+ void* pSysMem, unsigned int ByteWidth)
+{
+ RenderInterfaceD3D11::CopyToDevice(pDevicePtr, pSysMem, ByteWidth);
+}
+
+void RenderPluginDx11::ApplyDepthStencilState(DEPTH_STENCIL_STATE state)
+{
+ RenderInterfaceD3D11::ApplyDepthStencilState(state);
+}
+
+void RenderPluginDx11::ApplyRasterizerState(RASTERIZER_STATE state)
+{
+ RenderInterfaceD3D11::ApplyRasterizerState(state);
+}
+
+void RenderPluginDx11::ApplySampler(int slot, SAMPLER_TYPE state)
+{
+ RenderInterfaceD3D11::ApplySampler(slot, state);
+}
+
+void RenderPluginDx11::ApplyBlendState(BLEND_STATE state)
+{
+ RenderInterfaceD3D11::ApplyBlendState(state);
+}
+
+void RenderPluginDx11::GetViewport(Viewport& vp)
+{
+ RenderInterfaceD3D11::GetViewport(vp);
+}
+
+void RenderPluginDx11::SetViewport(const Viewport& vp)
+{
+ RenderInterfaceD3D11::SetViewport(vp);
+}
+
+void RenderPluginDx11::BindVertexShaderResources(int startSlot,
+ int numSRVs, GPUShaderResource** ppSRVs)
+{
+ RenderInterfaceD3D11::BindVertexShaderResources(startSlot, numSRVs, ppSRVs);
+}
+
+void RenderPluginDx11::BindPixelShaderResources(int startSlot,
+ int numSRVs, GPUShaderResource** ppSRVs)
+{
+ RenderInterfaceD3D11::BindPixelShaderResources(startSlot, numSRVs, ppSRVs);
+}
+
+void RenderPluginDx11::ClearVertexShaderResources(int startSlot, int numSRVs)
+{
+ RenderInterfaceD3D11::ClearVertexShaderResources(startSlot, numSRVs);
+}
+
+void RenderPluginDx11::ClearPixelShaderResources(int startSlot, int numSRVs)
+{
+ RenderInterfaceD3D11::ClearPixelShaderResources(startSlot, numSRVs);
+}
+
+void RenderPluginDx11::ClearInputLayout()
+{
+ RenderInterfaceD3D11::ClearInputLayout();
+}
+
+void RenderPluginDx11::SetVertexBuffer(GPUBufferResource* pBuffer, UINT stride, UINT offset)
+{
+ RenderInterfaceD3D11::SetVertexBuffer(pBuffer, stride, offset);
+}
+
+void RenderPluginDx11::SetPrimitiveTopologyTriangleStrip()
+{
+ RenderInterfaceD3D11::SetPrimitiveTopologyTriangleStrip();
+}
+
+void RenderPluginDx11::SetPrimitiveTopologyTriangleList()
+{
+ RenderInterfaceD3D11::SetPrimitiveTopologyTriangleList();
+}
+
+void RenderPluginDx11::SetPrimitiveTopologyLineList()
+{
+ RenderInterfaceD3D11::SetPrimitiveTopologyLineList();
+}
+
+void RenderPluginDx11::Draw(unsigned int vertexCount, unsigned int startCount)
+{
+ RenderInterfaceD3D11::Draw(vertexCount, startCount);
+}
+
+GPUBufferResource* RenderPluginDx11::CreateVertexBuffer(unsigned int ByteWidth, void* pSysMem)
+{
+ return RenderInterfaceD3D11::CreateVertexBuffer(ByteWidth, pSysMem);
+}
+
+GPUShaderResource* RenderPluginDx11::CreateShaderResource(unsigned int stride,
+ unsigned int numElements, void* pSysMem, NVHairReadOnlyBuffer* pReadOnlyBuffer)
+{
+ return RenderInterfaceD3D11::CreateShaderResource(stride, numElements, pSysMem);
+}
+
+void RenderPluginDx11::ApplyForShadow(int ForShadow)
+{
+}
+
+void RenderPluginDx11::SwitchToDX11()
+{
+}
+
+void RenderPluginDx11::FlushDX11()
+{
+}
+
+void RenderPluginDx11::FlushDX12()
+{
+}
+
+void RenderPluginDx11::ApplyPrimitiveTopologyLine()
+{
+}
+
+void RenderPluginDx11::ApplyPrimitiveTopologyTriangle()
+{
+}
+
+void RenderPluginDx11::SubmitGpuWork()
+{
+}
+
+void RenderPluginDx11::WaitForGpu()
+{
+}
+
+// util
+bool RenderPluginDx11::CreateRenderWindow(HWND hWnd, int nSamples)
+{
+ return D3D11Util::CreateRenderWindow(hWnd, nSamples);
+}
+
+bool RenderPluginDx11::ResizeRenderWindow(int w, int h)
+{
+ return D3D11Util::ResizeRenderWindow(w, h);
+}
+
+void RenderPluginDx11::PresentRenderWindow()
+{
+ D3D11Util::PresentRenderWindow();
+}
+
+void RenderPluginDx11::ClearRenderWindow(float r, float g, float b)
+{
+ D3D11Util::ClearRenderWindow(r, g, b);
+}
+
+bool RenderPluginDx11::GetDeviceInfoString(wchar_t *str)
+{
+ return D3D11Util::GetDeviceInfoString(str);
+}
+
+GPUShaderResource* RenderPluginDx11::CreateTextureSRV(const char* texturename)
+{
+ return D3D11Util::CreateTextureSRV(texturename);
+}
+
+void RenderPluginDx11::TxtHelperBegin()
+{
+ D3D11Util::TxtHelperBegin();
+}
+
+void RenderPluginDx11::TxtHelperEnd()
+{
+ D3D11Util::TxtHelperEnd();
+}
+
+void RenderPluginDx11::TxtHelperSetInsertionPos(int x, int y)
+{
+ D3D11Util::TxtHelperSetInsertionPos(x, y);
+}
+
+void RenderPluginDx11::TxtHelperSetForegroundColor(float r, float g, float b, float a)
+{
+ D3D11Util::TxtHelperSetForegroundColor(r, g, b, a);
+}
+
+void RenderPluginDx11::TxtHelperDrawTextLine(wchar_t* str)
+{
+ D3D11Util::TxtHelperDrawTextLine(str);
+}
+
+// shader
+bool RenderPluginDx11::InitializeShaders()
+{
+ return InitializeShadersD3D11();
+}
+
+void RenderPluginDx11::DestroyShaders()
+{
+ DestroyShadersD3D11();
+}
+
+void RenderPluginDx11::ApplyShader(SHADER_TYPE st)
+{
+ ApplyShaderD3D11(st);
+}
+
+void RenderPluginDx11::DisableShader(SHADER_TYPE st)
+{
+ DisableShaderD3D11(st);
+}
+
+void RenderPluginDx11::BindShaderResources(SHADER_TYPE st, int numSRVs, GPUShaderResource** ppSRVs)
+{
+}
+
+void RenderPluginDx11::CopyShaderParam(SHADER_TYPE st,
+ void* pSysMem, unsigned int bytes, unsigned int slot)
+{
+ CopyShaderParamD3D11(st, pSysMem, bytes, slot);
+}
+
+// GPUProfiler
+GPUProfiler* RenderPluginDx11::CreateGPUProfiler()
+{
+ GPUProfiler* pProfiler = new D3D11GPUProfiler;
+ pProfiler->Initialize();
+ return pProfiler;
+}
+
+// ShadowMap
+ShadowMap* RenderPluginDx11::CreateShadowMap(int resolution)
+{
+ return new D3D11ShadowMap(resolution);
+}
+
+// D3D12RenderContext
+void RenderPluginDx11::PreRender()
+{
+}
+
+void RenderPluginDx11::PostRender()
+{
+}
+
+// GPUMeshResources
+
+#include "MeshData.h"
+#include "AnimUtil.h"
+
+GPUMeshResources* RenderPluginDx11::GPUMeshResourcesCreate(MeshData* pMeshData, const SkinData& skinData)
+{
+ GPUMeshResources* resources = new GPUMeshResources;
+
+ int numIndices = pMeshData->m_NumIndices;
+ int numVertices = pMeshData->m_NumVertices;
+
+ resources->m_pVertexBuffer = CreateVertexBuffer(
+ sizeof(MeshData::MeshVertex) * numIndices, pMeshData->m_pMeshVertices);
+
+ resources->m_pBoneIndicesSRV = CreateShaderResource(
+ sizeof(atcore_float4), numVertices, skinData.m_pBoneIndices);
+
+ resources->m_pBoneWeightsSRV = CreateShaderResource(
+ sizeof(atcore_float4), numVertices, skinData.m_pBoneWeights);
+
+ return resources;
+}
+
+void RenderPluginDx11::GPUMeshResourcesRelease(GPUMeshResources* pResource)
+{
+ SAFE_RELEASE(pResource->m_pVertexBuffer);
+ SAFE_RELEASE(pResource->m_pBoneIndicesSRV);
+ SAFE_RELEASE(pResource->m_pBoneWeightsSRV);
+}
+
+D3DHandles& RenderPluginDx11::GetDeviceHandles(D3DHandles& deviceHandles)
+{
+ return D3D11Util::GetDeviceHandles(deviceHandles);
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/RenderPluginDx11.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/RenderPluginDx11.h
new file mode 100644
index 0000000..a43eb94
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D11/RenderPluginDx11.h
@@ -0,0 +1,83 @@
+#pragma once
+
+#include "RenderPlugin.h"
+
+extern "C" CORERENDER_EXPORT RenderPlugin* CreateRenderPlugin(void);
+
+class CORERENDER_EXPORT RenderPluginDx11 : public RenderPlugin
+{
+public:
+ RenderPluginDx11();
+ ~RenderPluginDx11();
+
+ // interface
+ virtual bool InitDevice(int deviceID);
+ virtual bool Initialize();
+ virtual void Shutdown();
+ virtual void CopyToDevice(GPUBufferResource *pDevicePtr, void* pSysMem, unsigned int ByteWidth);
+ virtual void ApplyDepthStencilState(DEPTH_STENCIL_STATE state);
+ virtual void ApplyRasterizerState(RASTERIZER_STATE state);
+ virtual void ApplySampler(int slot, SAMPLER_TYPE st);
+ virtual void ApplyBlendState(BLEND_STATE st);
+ virtual void GetViewport(Viewport& vp);
+ virtual void SetViewport(const Viewport& vp);
+ virtual void BindVertexShaderResources(int startSlot, int numSRVs, GPUShaderResource** ppSRVs);
+ virtual void BindPixelShaderResources(int startSlot, int numSRVs, GPUShaderResource** ppSRVs);
+ virtual void ClearVertexShaderResources(int startSlot, int numSRVs);
+ virtual void ClearPixelShaderResources(int startSlot, int numSRVs);
+ virtual void ClearInputLayout();
+ virtual void SetVertexBuffer(GPUBufferResource* pBuffer, UINT stride, UINT offset = 0);
+ virtual void SetPrimitiveTopologyTriangleStrip();
+ virtual void SetPrimitiveTopologyTriangleList();
+ virtual void SetPrimitiveTopologyLineList();
+ virtual void Draw(unsigned int vertexCount, unsigned int startCount = 0);
+ virtual GPUBufferResource* CreateVertexBuffer(unsigned int ByteWidth, void* pSysMem = 0);
+ virtual GPUShaderResource* CreateShaderResource(unsigned int stride, unsigned int numElements, void* pSysMem, NVHairReadOnlyBuffer* pReadOnlyBuffer = NULL);
+ virtual void ApplyForShadow(int ForShadow);
+ virtual void SwitchToDX11();
+ virtual void FlushDX11();
+ virtual void FlushDX12();
+ virtual void ApplyPrimitiveTopologyLine();
+ virtual void ApplyPrimitiveTopologyTriangle();
+ virtual void SubmitGpuWork();
+ virtual void WaitForGpu();
+
+ // util
+ virtual bool CreateRenderWindow(HWND hWnd, int nSamples);
+ virtual bool ResizeRenderWindow(int w, int h);
+ virtual void PresentRenderWindow();
+ virtual void ClearRenderWindow(float r, float g, float b);
+ virtual bool GetDeviceInfoString(wchar_t *str);
+ virtual GPUShaderResource* CreateTextureSRV(const char* texturename);
+ virtual void TxtHelperBegin();
+ virtual void TxtHelperEnd();
+ virtual void TxtHelperSetInsertionPos(int x, int y);
+ virtual void TxtHelperSetForegroundColor(float r, float g, float b, float a = 1.0f);
+ virtual void TxtHelperDrawTextLine(wchar_t* str);
+
+ // shader
+ virtual bool InitializeShaders();
+ virtual void DestroyShaders();
+ virtual void ApplyShader(SHADER_TYPE st);
+ virtual void DisableShader(SHADER_TYPE st);
+ virtual void BindShaderResources(SHADER_TYPE st, int numSRVs, GPUShaderResource** ppSRVs);
+ virtual void CopyShaderParam(SHADER_TYPE st, void* pSysMem, unsigned int bytes, unsigned int slot = 0);
+
+ // GPUProfiler
+ virtual GPUProfiler* CreateGPUProfiler();
+
+ // ShadowMap
+ virtual ShadowMap* CreateShadowMap(int resolution);
+
+ // D3D12RenderContext
+ virtual void PreRender();
+ virtual void PostRender();
+
+ // GPUMeshResources
+ virtual GPUMeshResources* GPUMeshResourcesCreate(MeshData* pMeshData, const SkinData& skinData);
+ virtual void GPUMeshResourcesRelease(GPUMeshResources* pResource);
+
+ // Get devices related
+ virtual D3DHandles& GetDeviceHandles(D3DHandles& deviceHandles);
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Buffer.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Buffer.cpp
new file mode 100644
index 0000000..0421792
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Buffer.cpp
@@ -0,0 +1,31 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D12Buffer.h"
+
+// shared path
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Buffer.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Buffer.h
new file mode 100644
index 0000000..ccf636b
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Buffer.h
@@ -0,0 +1,81 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "RenderResources.h"
+
+#include <d3d12.h>
+
+// GPU resources for texture
+struct GPUBufferD3D12 : public GPUBufferResource
+{
+ ID3D12Resource* m_pBuffer;
+ UINT m_pBufferSize;
+
+ D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView;
+
+public:
+ static GPUBufferResource* Create(ID3D12Resource* pResource, int nSize) {
+ GPUBufferD3D12* pBuffer = new GPUBufferD3D12;
+ pBuffer->m_pBuffer = pResource;
+ pBuffer->m_pBufferSize = nSize;
+ return pBuffer;
+ }
+
+ static ID3D12Resource* GetResource(GPUBufferResource* pBuffer)
+ {
+ GPUBufferD3D12* pD3D12Buffer = dynamic_cast<GPUBufferD3D12*>(pBuffer);
+ if (!pD3D12Buffer)
+ return 0;
+ return pD3D12Buffer->m_pBuffer;
+ }
+
+ static D3D12_VERTEX_BUFFER_VIEW* GetVertexView(GPUBufferResource* pBuffer)
+ {
+ GPUBufferD3D12* pD3D12Buffer = dynamic_cast<GPUBufferD3D12*>(pBuffer);
+ if (!pD3D12Buffer)
+ return 0;
+
+ pD3D12Buffer->m_vertexBufferView.BufferLocation = pD3D12Buffer->m_pBuffer->GetGPUVirtualAddress();
+ pD3D12Buffer->m_vertexBufferView.StrideInBytes = 0;
+ pD3D12Buffer->m_vertexBufferView.SizeInBytes = pD3D12Buffer->m_pBufferSize;
+ return &pD3D12Buffer->m_vertexBufferView;
+ }
+
+ ~GPUBufferD3D12()
+ {
+ Release();
+ }
+
+ void Release()
+ {
+ SAFE_RELEASE(m_pBuffer);
+ }
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12GPUProfiler.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12GPUProfiler.cpp
new file mode 100644
index 0000000..b434c3c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12GPUProfiler.cpp
@@ -0,0 +1,222 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D12GPUProfiler.h"
+
+#include "D3D12RenderInterface.h"
+#include "D3D12RenderContext.h"
+///////////////////////////////////////////////////////////////
+// factory function to create D3D12 GPU profiler
+/*
+GPUProfiler* GPUProfiler::CreateD3D12()
+{
+ GPUProfiler* pProfiler = new D3D12GPUProfiler;
+ pProfiler->Initialize();
+ return pProfiler;
+}
+*/
+
+///////////////////////////////////////////////////////////////
+D3D12GPUProfiler::~D3D12GPUProfiler()
+{
+ Release();
+}
+
+///////////////////////////////////////////////////////////////
+void D3D12GPUProfiler::Initialize()
+{
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+
+ /*
+ ID3D12Device* pDevice12 = pContext->GetDevice();
+
+ D3D12_QUERY_HEAP_DESC queryHeapDesc = {};
+ queryHeapDesc.Count = MAX_QUERY_COUNT * 2;
+ queryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP;
+ ThrowIfFailed(pDevice12->CreateQueryHeap(&queryHeapDesc, IID_PPV_ARGS(&query_heap)));
+
+ D3D12_HEAP_PROPERTIES heap_prop;
+ heap_prop.Type = D3D12_HEAP_TYPE_DEFAULT;
+ heap_prop.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heap_prop.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heap_prop.CreationNodeMask = 0;
+ heap_prop.VisibleNodeMask = 0;
+
+ D3D12_RESOURCE_DESC res_desc;
+ res_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ res_desc.Alignment = 0;
+ res_desc.Width = sizeof(UINT64) * 2;
+ res_desc.Height = 1;
+ res_desc.DepthOrArraySize = 1;
+ res_desc.MipLevels = 1;
+ res_desc.Format = DXGI_FORMAT_UNKNOWN;
+ res_desc.SampleDesc.Count = 1;
+ res_desc.SampleDesc.Quality = 0;
+ res_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ res_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ ThrowIfFailed(pDevice12->CreateCommittedResource(&heap_prop, D3D12_HEAP_FLAG_NONE,
+ &res_desc, D3D12_RESOURCE_STATE_COMMON, nullptr,
+ IID_ID3D12Resource, reinterpret_cast<void**>(&query_result)));
+
+ heap_prop.Type = D3D12_HEAP_TYPE_READBACK;
+ ThrowIfFailed(pDevice12->CreateCommittedResource(&heap_prop, D3D12_HEAP_FLAG_NONE,
+ &res_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr,
+ IID_ID3D12Resource, reinterpret_cast<void**>(&query_result_readback)));
+ */
+
+ m_pContext = pContext->GetDeviceContext();
+
+ D3D11_QUERY_DESC desc;
+ memset(&desc, 0, sizeof(D3D11_QUERY_DESC));
+ desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
+ desc.MiscFlags = 0;
+
+ ID3D11Device* pDevice = pContext->GetDevice11();
+ pDevice->CreateQuery(&desc, &m_pQueryDisjoint);
+
+ desc.Query = D3D11_QUERY_TIMESTAMP;
+
+ for (int i = 0; i < MAX_QUERY_COUNT; i++)
+ {
+ pDevice->CreateQuery(&desc, &m_pQueryStart[i]);
+ pDevice->CreateQuery(&desc, &m_pQueryEnd[i]);
+ }
+ m_enable = true;
+}
+
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(x) { if (x) x->Release(); x = 0; }
+#endif
+
+///////////////////////////////////////////////////////////////
+void D3D12GPUProfiler::Release()
+{
+ for (int i = 0; i < MAX_QUERY_COUNT; i++)
+ {
+ SAFE_RELEASE(m_pQueryStart[i]);
+ SAFE_RELEASE(m_pQueryEnd[i]);
+ }
+
+ SAFE_RELEASE(m_pQueryDisjoint);
+}
+
+///////////////////////////////////////////////////////////////
+void D3D12GPUProfiler::StartProfile(int id)
+{
+ if (!m_enable) return;
+
+ /*
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ ID3D12GraphicsCommandList* pCommandList = pContext->GetGraphicsCommandList();
+ pCommandList->EndQuery(query_heap, D3D12_QUERY_TYPE_TIMESTAMP, id * 2);
+ */
+
+ ID3D11Query* pQuery = m_pQueryStart[id];
+ m_pContext->End(pQuery);
+}
+
+///////////////////////////////////////////////////////////////
+void D3D12GPUProfiler::EndProfile(int id)
+{
+ if (!m_enable) return;
+
+ /*
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ ID3D12GraphicsCommandList* pCommandList = pContext->GetGraphicsCommandList();
+ pCommandList->EndQuery(query_heap, D3D12_QUERY_TYPE_TIMESTAMP, id * 2 + 1);
+ */
+
+ ID3D11Query* pQuery = m_pQueryEnd[id];
+ m_pContext->End(pQuery);
+}
+
+///////////////////////////////////////////////////////////////
+void D3D12GPUProfiler::StartFrame()
+{
+ if (!m_enable) return;
+
+ m_pContext->Begin(m_pQueryDisjoint);
+}
+
+///////////////////////////////////////////////////////////////
+void D3D12GPUProfiler::EndFrame()
+{
+ if (!m_enable) return;
+
+ m_pContext->End(m_pQueryDisjoint);
+
+ while(m_pContext->GetData(m_pQueryDisjoint, &m_disjointData, sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT), 0) != S_OK);
+}
+
+///////////////////////////////////////////////////////////////
+float D3D12GPUProfiler::GetProfileData(int id)
+{
+ if (!m_enable)
+ return 0.0f;
+
+ /*
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ ID3D12GraphicsCommandList* pCommandList = pContext->GetGraphicsCommandList();
+
+ UINT64 times[2];
+ D3D12_RESOURCE_BARRIER barrier;
+ barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrier.Transition.pResource = query_result;
+ barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COMMON;
+ barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
+ barrier.Transition.Subresource = 0;
+ pCommandList->ResourceBarrier(1, &barrier);
+
+ pCommandList->ResolveQueryData(query_heap, D3D12_QUERY_TYPE_TIMESTAMP, id * 2, 2, query_result, 0);
+
+ barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
+ barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
+ pCommandList->ResourceBarrier(1, &barrier);
+
+ pCommandList->CopyResource(query_result_readback, query_result);
+
+ barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
+ barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON;
+ pCommandList->ResourceBarrier(1, &barrier);
+
+ void* pData;
+ ThrowIfFailed(query_result_readback->Map(0, 0, &pData));
+ memcpy(times, pData, sizeof(UINT64) * 2);
+ query_result_readback->Unmap(0, 0);
+ */
+
+ UINT64 startTime = 0;
+ while(m_pContext->GetData(m_pQueryStart[id], &startTime, sizeof(UINT64), 0) != S_OK);
+
+ UINT64 endTime = 0;
+ while(m_pContext->GetData(m_pQueryEnd[id], &endTime, sizeof(UINT64), 0) != S_OK);
+
+ float frequency = static_cast<float>(m_disjointData.Frequency);
+ return (endTime - startTime) / frequency * 1000.0f;
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12GPUProfiler.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12GPUProfiler.h
new file mode 100644
index 0000000..721b8a9
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12GPUProfiler.h
@@ -0,0 +1,63 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include <d3d11.h>
+/*
+#include <d3d12.h>
+*/
+#include "GPUProfiler.h"
+
+#define MAX_QUERY_COUNT 64
+struct D3D12GPUProfiler : public GPUProfiler
+{
+public:
+ ~D3D12GPUProfiler();
+
+ void Initialize();
+ void Release();
+ void StartProfile(int id);
+ void EndProfile(int id);
+ void StartFrame();
+ void EndFrame();
+ float GetProfileData(int id);
+
+protected:
+ ID3D11Query* m_pQueryDisjoint;
+ ID3D11Query* m_pQueryStart[MAX_QUERY_COUNT];
+ ID3D11Query* m_pQueryEnd[MAX_QUERY_COUNT];
+ D3D11_QUERY_DATA_TIMESTAMP_DISJOINT m_disjointData;
+ ID3D11DeviceContext* m_pContext;
+ /*
+ ID3D12QueryHeap* query_heap;
+ ID3D12Resource* query_result;
+ ID3D12Resource* query_result_readback;
+ */
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderContext.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderContext.cpp
new file mode 100644
index 0000000..8202139
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderContext.cpp
@@ -0,0 +1,564 @@
+#include "D3D12RenderContext.h"
+
+const int nBufferCount = 2;
+//const int nBufferCount = 5;
+
+int nRenderTargetIndex = 1;
+//int nRenderTargetIndex = 4;
+
+D3D12RenderContext::D3D12RenderContext()
+{
+ m_sampleCount = 1;
+}
+
+D3D12RenderContext::~D3D12RenderContext()
+{
+}
+
+D3D12RenderContext* D3D12RenderContext::Instance()
+{
+ static D3D12RenderContext ri;
+ return &ri;
+}
+
+void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter)
+{
+ IDXGIAdapter1* pAdapter = nullptr;
+ *ppAdapter = nullptr;
+
+ for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, &pAdapter); ++adapterIndex)
+ {
+ DXGI_ADAPTER_DESC1 desc;
+ pAdapter->GetDesc1(&desc);
+
+ if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
+ {
+ // Don't select the Basic Render Driver adapter.
+ // If you want a software adapter, pass in "/warp" on the command line.
+ continue;
+ }
+
+ // Check to see if the adapter supports Direct3D 12, but don't create the
+ // actual device yet.
+ if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
+ {
+ break;
+ }
+ }
+
+ *ppAdapter = pAdapter;
+}
+
+void D3D12RenderContext::InitDevice()
+{
+ UINT d3d11DeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+#if defined(_DEBUG)
+ // Enable the D3D11 debug layer.
+ d3d11DeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+ // Enable the D3D12 debug layer.
+ {
+ ComPtr<ID3D12Debug> debugController;
+ if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
+ {
+ debugController->EnableDebugLayer();
+ }
+ }
+#endif
+
+ ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&m_factory)));
+
+ GetHardwareAdapter(m_factory.Get(), &m_adapter);
+
+ auto adapterDescription = DXGI_ADAPTER_DESC();
+ m_adapter->GetDesc(&adapterDescription);
+
+ D3D12CreateDevice(m_adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
+ if (nullptr == m_device)
+ {
+ ComPtr<IDXGIAdapter> warpAdapter;
+ ThrowIfFailed(m_factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)));
+ ThrowIfFailed(D3D12CreateDevice(warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device)));
+ }
+
+ // Describe and create the command queue.
+ D3D12_COMMAND_QUEUE_DESC queueDesc = {};
+ queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
+ queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+
+ ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)));
+
+ ThrowIfFailed(D3D11On12CreateDevice(
+ m_device.Get(),
+ d3d11DeviceFlags, nullptr, 0,
+ reinterpret_cast<IUnknown**>(m_commandQueue.GetAddressOf()), 1, 0,
+ &m_d3d11Device,
+ &m_d3d11DeviceContext,
+ nullptr ));
+
+ ThrowIfFailed(m_d3d11Device.As(&m_d3d11On12Device));
+}
+
+void D3D12RenderContext::InitSwapchain(int nWidth, int nHeight, HWND hWnd)
+{
+ // Describe and create the swap chain.
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
+ swapChainDesc.BufferCount = nBufferCount;
+ swapChainDesc.BufferDesc.Width = nWidth;
+ swapChainDesc.BufferDesc.Height = nHeight;
+ swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ swapChainDesc.OutputWindow = hWnd;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.Windowed = TRUE;
+
+ ComPtr<IDXGISwapChain> swapChain;
+ ThrowIfFailed(m_factory->CreateSwapChain(
+ m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it.
+ &swapChainDesc,
+ &swapChain
+ ));
+
+ ThrowIfFailed(swapChain.As(&m_swapChain));
+
+ // This sample does not support fullscreen transitions.
+ // ThrowIfFailed(m_factory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER));
+
+ m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
+
+ ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator)));
+
+ // Create the command list.
+ ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator.Get(), nullptr, IID_PPV_ARGS(&m_commandList)));
+
+ m_pCurrentRenderTarget = new D3D12RenderTarget(0, nBufferCount);
+ m_pCurrentRenderTarget->OnCreate(nWidth, nHeight);
+ m_pCurrentRenderTarget->SetClearColor(0.5, 0.5, 0.5);
+ m_RenderTargetMap[0] = m_pCurrentRenderTarget;
+
+ m_pD3D11RenderTargetView = new ID3D11RenderTargetView*[nBufferCount];
+ m_wrappedBackBuffers = new ID3D11Resource*[nBufferCount];
+ for (int n = 0; n < nBufferCount; n++)
+ {
+ m_pD3D11RenderTargetView[n] = nullptr;
+ m_wrappedBackBuffers[n] = nullptr;
+ }
+
+ PostCreate();
+}
+
+#ifndef Safe_Release
+#define Safe_Release(p) { if (p) { p->Release(); (p) = nullptr; } }
+#endif // !Safe_Delete
+
+void D3D12RenderContext::ResizeSwapchain(int width, int height)
+{
+ D3D12RenderTarget* rt = m_RenderTargetMap[0];
+
+ for (int n = 0; n < nBufferCount; n++)
+ {
+ Safe_Release(m_pD3D11RenderTargetView[n]);
+ Safe_Release(m_wrappedBackBuffers[n]);
+ }
+ m_d3d11DeviceContext->Flush();
+
+ rt->OnDestroy();
+
+ ThrowIfFailed(m_swapChain->ResizeBuffers(nBufferCount, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
+
+ m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
+
+ rt->OnResize(width, height);
+
+ for (int n = 0; n < nBufferCount; n++)
+ {
+ ID3D11On12Device* pDevice11On12 = GetDevice11On12();
+
+ D3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET };
+ ThrowIfFailed(pDevice11On12->CreateWrappedResource(
+ rt->GetTexture(n, false),
+ &d3d11Flags,
+ D3D12_RESOURCE_STATE_RENDER_TARGET,
+ D3D12_RESOURCE_STATE_PRESENT,
+ IID_PPV_ARGS(&m_wrappedBackBuffers[n])));
+
+ ThrowIfFailed(m_d3d11Device->CreateRenderTargetView(m_wrappedBackBuffers[n],
+ NULL, &m_pD3D11RenderTargetView[n]));
+ }
+}
+
+void D3D12RenderContext::PostCreate()
+{
+ m_srvUavHeap.Init(m_device.Get(), 256, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
+
+ {
+ ThrowIfFailed(m_commandList->Close());
+ ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
+ m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
+ }
+
+ {
+ ThrowIfFailed(m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)));
+ m_fenceValue = 1;
+
+ // Create an event handle to use for frame synchronization.
+ m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ if (m_fenceEvent == nullptr)
+ {
+ ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
+ }
+
+ WaitForGpu();
+ }
+}
+
+void D3D12RenderContext::OnDestroy()
+{
+ WaitForGpu();
+ if (nullptr != m_fenceEvent)
+ {
+ CloseHandle(m_fenceEvent);
+ m_fenceEvent = nullptr;
+ }
+
+#if 0
+ ID3D12DebugDevice* debugInterface;
+ if (SUCCEEDED(m_device.Get()->QueryInterface(&debugInterface)))
+ {
+ debugInterface->ReportLiveDeviceObjects(D3D12_RLDO_DETAIL | D3D12_RLDO_IGNORE_INTERNAL);
+ debugInterface->Release();
+ }
+#endif // 0
+}
+
+void D3D12RenderContext::PreRender()
+{
+ ThrowIfFailed(m_commandAllocator->Reset());
+ ThrowIfFailed(m_commandList->Reset(m_commandAllocator.Get(), nullptr));
+}
+
+void D3D12RenderContext::PostRender()
+{
+ ThrowIfFailed(m_commandList->Close());
+ ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
+ m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
+
+ OnGpuWorkSubmitted(m_commandQueue.Get());
+
+ WaitForGpu();
+}
+
+void D3D12RenderContext::SubmitGpuWork()
+{
+ ThrowIfFailed(m_commandList->Close());
+ ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
+ m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
+
+ ThrowIfFailed(m_commandList->Reset(m_commandAllocator.Get(), nullptr));
+
+ OnGpuWorkSubmitted(m_commandQueue.Get());
+}
+
+
+void D3D12RenderContext::Flush()
+{
+ m_pCurrentRenderTarget->PostRender();
+ PostRender();
+ PreRender();
+ m_pCurrentRenderTarget->PreRender();
+}
+
+void D3D12RenderContext::Present()
+{
+ ThrowIfFailed(m_swapChain->Present(1, 0));
+ //ThrowIfFailed(m_swapChain->Present(0, 0));
+ m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
+
+ //OnGpuWorkSubmitted(m_commandQueue.Get(), true);
+ //WaitForGpu();
+}
+
+int D3D12RenderContext::AllocRenderTargetIndex()
+{
+ return nRenderTargetIndex++;
+}
+
+
+void D3D12RenderContext::AddGpuInterface(GpuInterface* gpuIntf)
+{
+ m_gpuInterfaces.push_back(gpuIntf);
+}
+
+
+void D3D12RenderContext::OnGpuWorkSubmitted(ID3D12CommandQueue* queue)
+{
+ std::vector<GpuInterface*>::const_iterator cur = m_gpuInterfaces.begin();
+ std::vector<GpuInterface*>::const_iterator end = m_gpuInterfaces.end();
+
+ for (; cur != end; cur++)
+ {
+ (*cur)->onGpuWorkSubmitted(queue);
+ }
+}
+
+void D3D12RenderContext::UpdateGpuWorkCompleted()
+{
+ std::vector<GpuInterface*>::const_iterator cur = m_gpuInterfaces.begin();
+ std::vector<GpuInterface*>::const_iterator end = m_gpuInterfaces.end();
+
+ for (; cur != end; cur++)
+ {
+ (*cur)->updateGpuWorkCompleted();
+ }
+}
+
+D3D12RenderTarget* D3D12RenderContext::CreateRenderTarget(int renderTargetIndex, int nWidth, int nHeight)
+{
+ D3D12RenderTarget* pRenderTarget = new D3D12RenderTarget(renderTargetIndex);
+ pRenderTarget->OnCreate(nWidth, nHeight);
+ m_RenderTargetMap[renderTargetIndex] = pRenderTarget;
+ return pRenderTarget;
+}
+
+ID3D12Resource* D3D12RenderContext::GetTexture(int renderTargetIndex, int index)
+{
+ D3D12RenderTarget* pRenderTarget = m_RenderTargetMap[renderTargetIndex];
+ ID3D12Resource* pTexture = pRenderTarget->GetTexture(index);
+ return pTexture;
+}
+
+void D3D12RenderContext::SetViewport(D3D12_VIEWPORT& vp)
+{
+ m_pCurrentRenderTarget->m_viewport = vp;
+ m_commandList->RSSetViewports(1, &vp);
+}
+
+void D3D12RenderContext::GetViewport(D3D12_VIEWPORT& vp)
+{
+ vp = m_pCurrentRenderTarget->m_viewport;
+}
+
+D3D12_RESOURCE_DESC D3D12RenderContext::GetBackBufferDesc()
+{
+ D3D12RenderTarget* pRenderTarget = m_RenderTargetMap[0];
+ ID3D12Resource* pResource = pRenderTarget->GetTexture();
+ return pResource->GetDesc();
+}
+
+void D3D12RenderContext::SwitchToDX11()
+{
+ ReleaseRenderTarget();
+ PostRender();
+
+ if (nullptr == m_wrappedBackBuffers[m_frameIndex])
+ {
+ return;
+ }
+
+ m_d3d11On12Device->AcquireWrappedResources(&m_wrappedBackBuffers[m_frameIndex], 1);
+
+ m_d3d11DeviceContext->OMSetRenderTargets(1, &m_pD3D11RenderTargetView[m_frameIndex], nullptr);
+ D3D12RenderTarget* pRenderTarget = m_RenderTargetMap[0];
+ D3D11_VIEWPORT vp;
+ {
+ vp.TopLeftX = 0;
+ vp.TopLeftY = 0;
+ vp.Width = (float)pRenderTarget->m_viewport.Width;
+ vp.Height = (float)pRenderTarget->m_viewport.Height;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ }
+ m_d3d11DeviceContext->RSSetViewports(1, &vp);
+}
+
+void D3D12RenderContext::FlushDX11()
+{
+ if (nullptr == m_wrappedBackBuffers[m_frameIndex])
+ {
+ return;
+ }
+
+ m_d3d11On12Device->ReleaseWrappedResources(&m_wrappedBackBuffers[m_frameIndex], 1);
+ m_d3d11DeviceContext->Flush();
+}
+
+ID3D12Resource* D3D12RenderContext::GetDepthStencilResource()
+{
+ D3D12RenderTarget* pRenderTarget = m_RenderTargetMap[0];
+ return pRenderTarget->GetDepthStencilResource();
+}
+
+D3D12_CPU_DESCRIPTOR_HANDLE D3D12RenderContext::GetRenderTargetViewHandle()
+{
+ D3D12RenderTarget* pRenderTarget = m_RenderTargetMap[0];
+ return pRenderTarget->GetRenderTargetViewHandle();
+}
+
+D3D12_CPU_DESCRIPTOR_HANDLE D3D12RenderContext::GetDepthStencilViewHandle()
+{
+ D3D12RenderTarget* pRenderTarget = m_RenderTargetMap[0];
+ return pRenderTarget->GetDepthStencilViewHandle();
+}
+
+void D3D12RenderContext::AcquireRenderTarget(bool doClear, int renderTargetIndex)
+{
+ m_pCurrentRenderTarget = m_RenderTargetMap[renderTargetIndex];
+ m_pCurrentRenderTarget->PreRender(doClear);
+}
+
+void D3D12RenderContext::ReleaseRenderTarget(int renderTargetIndex)
+{
+ D3D12RenderTarget* pRenderTarget = m_RenderTargetMap[renderTargetIndex];
+ pRenderTarget->PostRender();
+}
+
+void D3D12RenderContext::SetClearColor(int renderTargetIndex, float r, float g, float b, float a, float depth, float stencil)
+{
+ D3D12RenderTarget* pRenderTarget = m_RenderTargetMap[renderTargetIndex];
+ pRenderTarget->SetClearColor(r, g, b, a, depth, stencil);
+}
+
+void D3D12RenderContext::WaitForGpu()
+{
+ const UINT64 fence = m_fenceValue;
+ ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), fence));
+ m_fenceValue++;
+
+ // Wait until the previous frame is finished.
+ if (m_fence->GetCompletedValue() < fence)
+ {
+ ThrowIfFailed(m_fence->SetEventOnCompletion(fence, m_fenceEvent));
+ WaitForSingleObject(m_fenceEvent, INFINITE);
+ }
+}
+
+void D3D12RenderContext::InitBuffer(NVHairReadOnlyBuffer& buffer)
+{
+ buffer.Init(&m_srvUavHeap);
+}
+
+void D3D12RenderContext::DestroyBuffer(NVHairReadOnlyBuffer& buffer)
+{
+ buffer.Release();
+}
+
+CD3DX12_CPU_DESCRIPTOR_HANDLE D3D12RenderContext::NVHairINT_CreateD3D12ReadOnlyBuffer(
+ UINT stride,
+ UINT numElements,
+ NVHairReadOnlyBuffer* pReadOnlyBuffer,
+ void* pSysMem)
+{
+ ID3D12Device* pd3dDevice = m_device.Get();
+ ID3D12GraphicsCommandList* pCommandList = m_commandList.Get();
+
+ UINT bufferSize = numElements * stride;
+
+ HRESULT hr;
+ hr = pd3dDevice->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
+ D3D12_HEAP_FLAG_NONE,
+ &CD3DX12_RESOURCE_DESC::Buffer(bufferSize),
+ D3D12_RESOURCE_STATE_COPY_DEST,
+ nullptr,
+ IID_PPV_ARGS(pReadOnlyBuffer->m_pBuffer.ReleaseAndGetAddressOf()));
+
+ hr = pd3dDevice->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
+ D3D12_HEAP_FLAG_NONE,
+ &CD3DX12_RESOURCE_DESC::Buffer(bufferSize),
+ D3D12_RESOURCE_STATE_GENERIC_READ,
+ nullptr,
+ IID_PPV_ARGS(pReadOnlyBuffer->m_pBufferUpload.ReleaseAndGetAddressOf()));
+
+ D3D12_SUBRESOURCE_DATA data = {};
+ data.pData = reinterpret_cast<UINT8*>(pSysMem);
+ data.RowPitch = bufferSize;
+ data.SlicePitch = data.RowPitch;
+
+ PreRender();
+ UpdateSubresources<1>(pCommandList, pReadOnlyBuffer->m_pBuffer.Get(), pReadOnlyBuffer->m_pBufferUpload.Get(), 0, 0, 1, &data);
+ pCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(pReadOnlyBuffer->m_pBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE));
+ PostRender();
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(pReadOnlyBuffer->m_pSrvUavHeap->m_pHeap.Get()->GetCPUDescriptorHandleForHeapStart(), pReadOnlyBuffer->m_srvIndex, pReadOnlyBuffer->m_pSrvUavHeap->m_sizeDescriptor);
+ D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
+ srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+ srvDesc.Format = DXGI_FORMAT_UNKNOWN;
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
+ srvDesc.Buffer.FirstElement = 0;
+ srvDesc.Buffer.NumElements = numElements;
+ srvDesc.Buffer.StructureByteStride = stride;
+ srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
+ pd3dDevice->CreateShaderResourceView(pReadOnlyBuffer->m_pBuffer.Get(), &srvDesc, srvHandle);
+
+ return srvHandle;
+}
+
+CD3DX12_CPU_DESCRIPTOR_HANDLE D3D12RenderContext::NVHairINT_CreateD3D12Texture(ID3D12Resource* pTexture, int& nIndexInHeap)
+{
+ CD3DX12_CPU_DESCRIPTOR_HANDLE handle = {};
+
+ if (!pTexture)
+ return handle;
+
+ ID3D12Device* pDevice = m_device.Get();
+ if (!pDevice)
+ return handle;
+
+ nIndexInHeap = m_srvUavHeap.allocate();
+ if(nIndexInHeap == -1)
+ return handle;
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(m_srvUavHeap.m_pHeap.Get()->GetCPUDescriptorHandleForHeapStart(),
+ nIndexInHeap, m_srvUavHeap.m_sizeDescriptor);
+
+ D3D12_RESOURCE_DESC desc = pTexture->GetDesc();
+
+ D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
+ srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+ srvDesc.Format = desc.Format;
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MipLevels = 1;
+
+ pDevice->CreateShaderResourceView(pTexture, &srvDesc, srvHandle);
+
+ return srvHandle;
+}
+
+void D3D12RenderContext::NVHairINT_DestroyD3D12Texture(int& nIndexInHeap)
+{
+ if (nIndexInHeap != -1)
+ {
+ m_srvUavHeap.deallocate(nIndexInHeap);
+ }
+}
+
+void D3D12RenderContext::SetSampleCount(int nSampleCount)
+{
+ m_sampleCount = 1;
+
+ if (nSampleCount > D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT)
+ nSampleCount = D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT;
+
+ if (nSampleCount > 1)
+ {
+ D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS qualityLevels;
+ qualityLevels.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ qualityLevels.Flags = D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE;
+ qualityLevels.NumQualityLevels = 0;
+ qualityLevels.SampleCount = nSampleCount;
+
+ ID3D12Device *pDevice = GetDevice();
+ pDevice->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &qualityLevels, sizeof(qualityLevels));
+
+ if (qualityLevels.NumQualityLevels > 0)
+ {
+ m_sampleCount = qualityLevels.SampleCount;
+ }
+ }
+}
+
+int D3D12RenderContext::GetSampleCount()
+{
+ return m_sampleCount;
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderContext.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderContext.h
new file mode 100644
index 0000000..2e0b393
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderContext.h
@@ -0,0 +1,254 @@
+#pragma once
+
+#include "D3D12RenderTarget.h"
+#include "RenderPlugin.h"
+
+#include "d3dx12.h"
+#include <wrl.h>
+using namespace Microsoft::WRL;
+
+struct NVHairHeap
+{
+ ComPtr<ID3D12DescriptorHeap> m_pHeap;
+ UINT m_sizeHeap;
+ UINT m_currentIndex;
+ UINT m_sizeDescriptor;
+ std::vector<UINT> m_availableIndexes;
+
+ void Init(ID3D12Device* pd3dDevice, UINT size, D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags)
+ {
+ HRESULT hr;
+
+ D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
+ srvHeapDesc.NumDescriptors = size;
+ srvHeapDesc.Flags = flags;
+ srvHeapDesc.Type = type;
+ hr = pd3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(m_pHeap.ReleaseAndGetAddressOf()));
+
+ if (SUCCEEDED(hr))
+ {
+ m_sizeHeap = size;
+ m_sizeDescriptor = pd3dDevice->GetDescriptorHandleIncrementSize(type);
+ }
+ else
+ {
+ m_sizeHeap = 0;
+ m_sizeDescriptor = 0;
+ }
+ m_currentIndex = 0;
+ m_availableIndexes.clear();
+ }
+
+ UINT allocate()
+ {
+ int availables = m_availableIndexes.size();
+ if (availables > 0)
+ {
+ UINT index = m_availableIndexes[availables - 1];
+ m_availableIndexes.pop_back();
+ return index;
+ }
+ UINT index = m_currentIndex++;
+ if (m_sizeHeap > m_currentIndex)
+ return index;
+ return (UINT)-1;
+ }
+
+ void deallocate(UINT availableIndex)
+ {
+ m_availableIndexes.push_back(availableIndex);
+ }
+
+ void Release()
+ {
+ if (m_pHeap) m_pHeap = nullptr;
+ m_sizeHeap = 0;
+ m_currentIndex = 0;
+ m_sizeDescriptor = 0;
+ m_availableIndexes.clear();
+ }
+};
+
+struct NVHairVertexBuffer
+{
+ ComPtr<ID3D12Resource> m_pBuffer;
+ ComPtr<ID3D12Resource> m_pBufferUpload;
+ D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView;
+ NVHairHeap* m_pSrvUavHeap;
+ UINT m_uavIndex;
+
+ void Init(NVHairHeap* pHeap)
+ {
+ m_pBuffer = nullptr;
+ m_pBufferUpload = nullptr;
+ memset(&m_vertexBufferView, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW));
+ m_pSrvUavHeap = pHeap;
+
+ m_uavIndex = m_pSrvUavHeap->allocate();
+ }
+
+ D3D12_CPU_DESCRIPTOR_HANDLE getUavCpuHandle()
+ {
+ CD3DX12_CPU_DESCRIPTOR_HANDLE uavHandle(m_pSrvUavHeap->m_pHeap.Get()->GetCPUDescriptorHandleForHeapStart(), m_uavIndex, m_pSrvUavHeap->m_sizeDescriptor);
+ return uavHandle;
+ }
+
+ void Release()
+ {
+ if (m_pBuffer) m_pBuffer = nullptr;
+ if (m_pBufferUpload) m_pBufferUpload = nullptr;
+ memset(&m_vertexBufferView, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW));
+ if (m_pSrvUavHeap) m_pSrvUavHeap = nullptr;
+ m_uavIndex = (UINT)-1;
+ }
+};
+
+struct NVHairReadOnlyBuffer
+{
+ ComPtr<ID3D12Resource> m_pBuffer;
+ ComPtr<ID3D12Resource> m_pBufferUpload;
+ NVHairHeap* m_pSrvUavHeap;
+ UINT m_srvIndex;
+
+ void Init(NVHairHeap* pHeap)
+ {
+ m_pBuffer = nullptr;
+ m_pBufferUpload = nullptr;
+ m_pSrvUavHeap = pHeap;
+
+ m_srvIndex = m_pSrvUavHeap->allocate();
+ }
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE getSrvCpuHandle()
+ {
+ CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(m_pSrvUavHeap->m_pHeap.Get()->GetCPUDescriptorHandleForHeapStart(), m_srvIndex, m_pSrvUavHeap->m_sizeDescriptor);
+ return srvHandle;
+ }
+
+ void Release()
+ {
+ m_pSrvUavHeap->deallocate(m_srvIndex);
+
+ if (m_pBuffer) m_pBuffer = nullptr;
+ if (m_pBufferUpload) m_pBufferUpload = nullptr;
+ if (m_pSrvUavHeap) m_pSrvUavHeap = nullptr;
+ m_srvIndex = (UINT)-1;
+ }
+};
+
+class CORERENDER_EXPORT D3D12RenderContext
+{
+public:
+ ~D3D12RenderContext();
+ static D3D12RenderContext* Instance();
+
+ class GpuInterface
+ {
+ public:
+ virtual void onGpuWorkSubmitted(ID3D12CommandQueue* queue) = 0;
+ virtual void updateGpuWorkCompleted() = 0;
+ virtual ~GpuInterface() {}
+ };
+
+ typedef void (*GpuWorkSubmitFunc)(ID3D12CommandQueue* queue, void* data);
+ typedef void (*GpuUpdateCompletedFunc)(void* data);
+
+ void InitDevice();
+ void InitSwapchain(int width, int height, HWND hWnd);
+ void ResizeSwapchain(int width, int height);
+ void PostCreate();
+
+ void OnDestroy();
+
+ void PreRender();
+ void PostRender();
+ void Flush();
+
+ void SubmitGpuWork();
+ void WaitForGpu();
+
+ void UpdateGpuWorkCompleted();
+
+ void Present();
+
+ int AllocRenderTargetIndex();
+ D3D12RenderTarget* CreateRenderTarget(int renderTargetIndex, int nWidth, int nHeight);
+ void SetClearColor(int renderTargetIndex, float r, float g, float b, float a = 1.0, float depth = 1.0, float stencil = 0.0);
+ void AcquireRenderTarget(bool doClear = false, int renderTargetIndex = 0);
+ void ReleaseRenderTarget(int renderTargetIndex = 0);
+ ID3D12Resource* GetTexture(int renderTargetIndex, int index = 0);
+ void SetViewport(D3D12_VIEWPORT& vp);
+ void GetViewport(D3D12_VIEWPORT& vp);
+
+ ID3D12Device* GetDevice() { return m_device.Get(); }
+ ID3D12GraphicsCommandList* GetGraphicsCommandList() { return m_commandList.Get(); }
+ ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); }
+
+ IDXGISwapChain3* GetSwapChain() { return m_swapChain.Get(); }
+ UINT GetFrameIndex() { return m_frameIndex; }
+
+ ID3D11Device* GetDevice11() { return m_d3d11Device.Get(); }
+ ID3D11On12Device* GetDevice11On12() { return m_d3d11On12Device.Get(); }
+ ID3D11DeviceContext* GetDeviceContext() { return m_d3d11DeviceContext.Get(); }
+
+ D3D12_RESOURCE_DESC GetBackBufferDesc();
+ void SwitchToDX11();
+ void FlushDX11();
+
+ ID3D12Resource* GetDepthStencilResource();
+ D3D12_CPU_DESCRIPTOR_HANDLE GetRenderTargetViewHandle();
+ D3D12_CPU_DESCRIPTOR_HANDLE GetDepthStencilViewHandle();
+
+ void InitBuffer(NVHairReadOnlyBuffer& buffer);
+ void DestroyBuffer(NVHairReadOnlyBuffer& buffer);
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE NVHairINT_CreateD3D12ReadOnlyBuffer(
+ UINT stride,
+ UINT numElements,
+ NVHairReadOnlyBuffer* pReadOnlyBuffer,
+ void* pSysMem);
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE NVHairINT_CreateD3D12Texture(ID3D12Resource* pTexture, int& nIndexInHeap);
+ void NVHairINT_DestroyD3D12Texture(int& nIndexInHeap);
+
+ void SetSampleCount(int nSampleCount);
+ int GetSampleCount();
+
+ void AddGpuInterface(GpuInterface* intf);
+
+private:
+ void OnGpuWorkSubmitted(ID3D12CommandQueue* queue);
+
+ D3D12RenderContext();
+
+ ComPtr<IDXGIFactory4> m_factory;
+ ComPtr<IDXGIAdapter1> m_adapter;
+
+ ComPtr<ID3D12Device> m_device;
+ ComPtr<ID3D12CommandQueue> m_commandQueue;
+ ComPtr<ID3D12CommandAllocator> m_commandAllocator;
+ ComPtr<ID3D12GraphicsCommandList> m_commandList;
+ ComPtr<IDXGISwapChain3> m_swapChain;
+
+ ComPtr<ID3D11Device> m_d3d11Device;
+ ComPtr<ID3D11On12Device> m_d3d11On12Device;
+ ComPtr<ID3D11DeviceContext> m_d3d11DeviceContext;
+ ID3D11Resource** m_wrappedBackBuffers;
+ ID3D11RenderTargetView** m_pD3D11RenderTargetView;
+
+ UINT m_frameIndex;
+ HANDLE m_fenceEvent;
+ ComPtr<ID3D12Fence> m_fence;
+ UINT64 m_fenceValue;
+
+ D3D12RenderTarget* m_pCurrentRenderTarget;
+ map<int, D3D12RenderTarget*> m_RenderTargetMap;
+
+ std::vector<GpuInterface*> m_gpuInterfaces;
+
+ NVHairHeap m_srvUavHeap;
+
+ // sample desc
+ UINT m_sampleCount;
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderInterface.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderInterface.cpp
new file mode 100644
index 0000000..2346683
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderInterface.cpp
@@ -0,0 +1,467 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D12RenderInterface.h"
+
+#include "D3D12TextureResource.h"
+#include "D3D12Shaders.h"
+#include "D3D12Buffer.h"
+
+#include "D3D12RenderContext.h"
+
+namespace RenderInterfaceD3D12
+{
+ using namespace RenderInterface;
+
+ D3D12_BLEND_DESC m_BlendStates[BLEND_STATE_END];
+ D3D12_DEPTH_STENCIL_DESC m_DepthStencilStates[DEPTH_STENCIL_STATE_END];
+ D3D12_RASTERIZER_DESC m_RasterizerStates[RASTERIZER_STATE_END];
+
+ D3D12RenderContext *pRenderContext = D3D12RenderContext::Instance();
+
+ SHADER_TYPE m_ShaderType;
+ RenderShaderStateKey m_ShaderStateKey;
+
+ map<RenderShaderStateKey, RenderShaderState*> m_RenderShaderStates;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool InitDevice(int deviceID)
+{
+ pRenderContext->InitDevice();
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool Initialize()
+{
+ if (!pRenderContext)
+ return false;
+
+ InitializeShadersD3D12();
+ InitializeRenderStates();
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void Shutdown()
+{
+ DestroyShadersD3D12();
+}
+
+RenderShaderState* GetShaderState()
+{
+ RenderShaderState* pShaderState = nullptr;
+ map<RenderShaderStateKey, RenderShaderState*>::iterator it = m_RenderShaderStates.find(m_ShaderStateKey);
+ if (it != m_RenderShaderStates.end())
+ {
+ pShaderState = it->second;
+ }
+ else
+ {
+ pShaderState = new RenderShaderState;
+ pShaderState->BlendState = m_BlendStates[m_ShaderStateKey.BlendState];
+ pShaderState->DepthStencilState = m_DepthStencilStates[m_ShaderStateKey.DepthStencilState];
+ pShaderState->RasterizerState = m_RasterizerStates[m_ShaderStateKey.RasterizerState];
+ pShaderState->PrimitiveTopologyType = m_ShaderStateKey.PrimitiveTopologyType;
+ if (m_ShaderStateKey.ForShadow)
+ {
+ pShaderState->RTVFormat = DXGI_FORMAT_R32_FLOAT;
+ pShaderState->DSVFormat = DXGI_FORMAT_D32_FLOAT;
+ }
+ else
+ {
+ pShaderState->RTVFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+ pShaderState->DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ pShaderState->SampleCount = D3D12RenderContext::Instance()->GetSampleCount();
+ }
+
+ m_RenderShaderStates[m_ShaderStateKey] = pShaderState;
+ }
+ return pShaderState;
+}
+//////////////////////////////////////////////////////////////////////////////////////
+void InitializeRenderStates()
+{
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // alpha blending state descriptors
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ // alpha blending enabled
+ {
+ D3D12_BLEND_DESC desc = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
+ desc.AlphaToCoverageEnable = false;
+ desc.IndependentBlendEnable = false;
+
+ D3D12_RENDER_TARGET_BLEND_DESC &rtDesc = desc.RenderTarget[0];
+ {
+ rtDesc.BlendEnable = true;
+ rtDesc.SrcBlend = D3D12_BLEND_SRC_ALPHA;
+ rtDesc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
+ rtDesc.BlendOp = D3D12_BLEND_OP_ADD;
+ rtDesc.SrcBlendAlpha = D3D12_BLEND_ZERO;
+ rtDesc.DestBlendAlpha = D3D12_BLEND_ONE;
+ rtDesc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
+ rtDesc.RenderTargetWriteMask = 0x0f;
+ }
+ m_BlendStates[BLEND_STATE_ALPHA] = desc;
+ }
+
+ // no alpha blending
+ {
+ D3D12_BLEND_DESC desc = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
+ desc.AlphaToCoverageEnable = false;
+ desc.IndependentBlendEnable = false;
+
+ D3D12_RENDER_TARGET_BLEND_DESC &rtDesc = desc.RenderTarget[0];
+ {
+ rtDesc.BlendEnable = false;
+ rtDesc.SrcBlend = D3D12_BLEND_SRC_ALPHA;
+ rtDesc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
+ rtDesc.BlendOp = D3D12_BLEND_OP_ADD;
+ rtDesc.SrcBlendAlpha = D3D12_BLEND_ZERO;
+ rtDesc.DestBlendAlpha = D3D12_BLEND_ONE;
+ rtDesc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
+ rtDesc.RenderTargetWriteMask = 0x0f;
+ }
+ m_BlendStates[BLEND_STATE_NONE] = desc;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // depth and stencil
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ D3D12_DEPTH_STENCIL_DESC depthTestDesc = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
+ {
+ depthTestDesc.DepthEnable = true;
+ depthTestDesc.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
+ depthTestDesc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
+ depthTestDesc.StencilEnable = false;
+ depthTestDesc.StencilReadMask = 0xff;
+ depthTestDesc.StencilWriteMask = 0xff;
+ }
+
+ m_DepthStencilStates[DEPTH_STENCIL_DEPTH_TEST] = depthTestDesc;
+
+ D3D12_DEPTH_STENCIL_DESC depthNone = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
+ {
+ depthNone.DepthEnable = false;
+ depthNone.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
+ depthNone.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
+ depthNone.StencilEnable = false;
+ depthNone.StencilReadMask = 0xff;
+ depthNone.StencilWriteMask = 0xff;
+ }
+
+ m_DepthStencilStates[DEPTH_STENCIL_DEPTH_NONE] = depthNone;
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // rasterizer
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ D3D12_RASTERIZER_DESC rsDesc = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
+
+ // solid cull front
+ {
+ rsDesc.FillMode = D3D12_FILL_MODE_SOLID;
+ rsDesc.CullMode = D3D12_CULL_MODE_FRONT;
+ rsDesc.AntialiasedLineEnable = false;
+ rsDesc.MultisampleEnable = true;
+ rsDesc.FrontCounterClockwise = true;
+ rsDesc.DepthBias = 10;
+ rsDesc.DepthBiasClamp = 0;
+ rsDesc.SlopeScaledDepthBias = 0;
+ rsDesc.DepthClipEnable = true;
+ rsDesc.ForcedSampleCount = 0;
+
+ m_RasterizerStates[RASTERIZER_STATE_FILL_CULL_FRONT] = rsDesc;
+ };
+
+ // solid cull back
+ {
+ rsDesc.FillMode = D3D12_FILL_MODE_SOLID;
+ rsDesc.CullMode = D3D12_CULL_MODE_BACK;
+ rsDesc.AntialiasedLineEnable = false;
+ rsDesc.MultisampleEnable = true;
+ rsDesc.FrontCounterClockwise = true;
+ rsDesc.DepthBias = 10;
+ rsDesc.DepthBiasClamp = 0;
+ rsDesc.SlopeScaledDepthBias = 0;
+ rsDesc.DepthClipEnable = true;
+ rsDesc.ForcedSampleCount = 0;
+
+ m_RasterizerStates[RASTERIZER_STATE_FILL_CULL_BACK] = rsDesc;
+ }
+
+ // solid cull none
+ {
+ rsDesc.FillMode = D3D12_FILL_MODE_SOLID;
+ rsDesc.CullMode = D3D12_CULL_MODE_NONE;
+ rsDesc.AntialiasedLineEnable = false;
+ rsDesc.MultisampleEnable = true;
+ rsDesc.FrontCounterClockwise = true;
+ rsDesc.DepthBias = 10;
+ rsDesc.DepthBiasClamp = 0;
+ rsDesc.SlopeScaledDepthBias = 0;
+ rsDesc.DepthClipEnable = true;
+ rsDesc.ForcedSampleCount = 0;
+
+ m_RasterizerStates[RASTERIZER_STATE_FILL_CULL_NONE] = rsDesc;
+ }
+
+ // wireframe cull none
+ {
+ rsDesc.FillMode = D3D12_FILL_MODE_WIREFRAME;
+ rsDesc.CullMode = D3D12_CULL_MODE_NONE;
+ rsDesc.AntialiasedLineEnable = false;
+ rsDesc.MultisampleEnable = true;
+ rsDesc.FrontCounterClockwise = 0;
+ rsDesc.DepthBias = 0;
+ rsDesc.DepthBiasClamp = 0;
+ rsDesc.SlopeScaledDepthBias = 0;
+ rsDesc.DepthClipEnable = true;
+ rsDesc.ForcedSampleCount = 0;
+ };
+
+ m_RasterizerStates[RASTERIZER_STATE_WIRE] = rsDesc;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void SetPrimitiveTopologyTriangleStrip()
+{
+ ID3D12GraphicsCommandList* pCommandList = pRenderContext->GetGraphicsCommandList();
+ pCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void SetPrimitiveTopologyTriangleList()
+{
+ ID3D12GraphicsCommandList* pCommandList = pRenderContext->GetGraphicsCommandList();
+ pCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void SetPrimitiveTopologyLineList()
+{
+ ID3D12GraphicsCommandList* pCommandList = pRenderContext->GetGraphicsCommandList();
+ pCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_LINELIST);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+void SetVertexBuffer(GPUBufferResource* pBuffer, UINT stride, UINT offset)
+{
+ D3D12_VERTEX_BUFFER_VIEW* vertexView = GPUBufferD3D12::GetVertexView(pBuffer);
+ if (!vertexView)
+ return;
+
+ vertexView->StrideInBytes = stride;
+ ID3D12GraphicsCommandList* m_commandList = pRenderContext->GetGraphicsCommandList();
+ m_commandList->IASetVertexBuffers(0, 1, vertexView);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyDepthStencilState(DEPTH_STENCIL_STATE state)
+{
+ m_ShaderStateKey.DepthStencilState = state;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyRasterizerState(RASTERIZER_STATE state)
+{
+ m_ShaderStateKey.RasterizerState = state;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyBlendState(BLEND_STATE state)
+{
+ m_ShaderStateKey.BlendState = state;
+}
+
+void ApplyPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType)
+{
+ m_ShaderStateKey.PrimitiveTopologyType = PrimitiveTopologyType;
+}
+
+void ApplyForShadow(int ForShadow)
+{
+ m_ShaderStateKey.ForShadow = ForShadow;
+}
+
+void SwitchToDX11()
+{
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ pContext->SwitchToDX11();
+}
+
+void FlushDX11()
+{
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ pContext->FlushDX11();
+}
+
+void FlushDX12()
+{
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ pContext->Flush();
+}
+
+void SubmitGpuWork()
+{
+ D3D12RenderContext::Instance()->SubmitGpuWork();
+}
+
+void WaitForGpu()
+{
+ D3D12RenderContext* context = D3D12RenderContext::Instance();
+ context->WaitForGpu();
+ context->UpdateGpuWorkCompleted();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void SetViewport(const RenderInterface::Viewport& vp)
+{
+ ID3D12GraphicsCommandList* pCommandList = pRenderContext->GetGraphicsCommandList();
+
+ D3D12_VIEWPORT d3dViewport;
+
+ d3dViewport.TopLeftX = vp.TopLeftX;
+ d3dViewport.TopLeftY = vp.TopLeftY;
+
+ d3dViewport.Width = vp.Width;
+ d3dViewport.Height = vp.Height;
+
+ d3dViewport.MinDepth = vp.MinDepth;
+ d3dViewport.MaxDepth = vp.MaxDepth;
+
+ pRenderContext->SetViewport(d3dViewport);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void GetViewport(RenderInterface::Viewport& vp)
+{
+ D3D12_VIEWPORT d3dViewport;
+ pRenderContext->GetViewport(d3dViewport);
+
+ vp.TopLeftX = d3dViewport.TopLeftX;
+ vp.TopLeftY = d3dViewport.TopLeftY;
+
+ vp.Width = d3dViewport.Width;
+ vp.Height = d3dViewport.Height;
+
+ vp.MinDepth = d3dViewport.MinDepth;
+ vp.MaxDepth = d3dViewport.MaxDepth;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void Draw(unsigned int vertexCount, unsigned int startCount)
+{
+ ID3D12GraphicsCommandList* pCommandList = pRenderContext->GetGraphicsCommandList();
+ pCommandList->DrawInstanced(vertexCount, 1, startCount, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+GPUBufferResource* CreateVertexBuffer(
+ unsigned int ByteWidth, void* pSysMem)
+{
+ ID3D12Device* pDevice = D3D12RenderContext::Instance()->GetDevice();
+ if (!pDevice)
+ return false;
+
+ ID3D12Resource* pBuffer = nullptr;
+ ThrowIfFailed(pDevice->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
+ D3D12_HEAP_FLAG_NONE,
+ &CD3DX12_RESOURCE_DESC::Buffer(ByteWidth),
+ D3D12_RESOURCE_STATE_GENERIC_READ,
+ nullptr,
+ IID_PPV_ARGS(&pBuffer)));
+ if (nullptr == pBuffer)
+ {
+ return false;
+ }
+
+ void* pData;
+ ThrowIfFailed(pBuffer->Map(0, nullptr, &pData));
+ memcpy(pData, pSysMem, ByteWidth);
+ pBuffer->Unmap(0, nullptr);
+
+ return GPUBufferD3D12::Create(pBuffer, ByteWidth);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+GPUShaderResource* CreateShaderResource(unsigned int stride,
+ unsigned int numElements, void* pSysMem, NVHairReadOnlyBuffer* pReadOnlyBuffer)
+{
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ if (!pContext)
+ return false;
+
+ ID3D12Device* pDevice = pContext->GetDevice();
+ ID3D12GraphicsCommandList* pCommandList = pContext->GetGraphicsCommandList();
+
+ pContext->NVHairINT_CreateD3D12ReadOnlyBuffer(stride, numElements, pReadOnlyBuffer, pSysMem);
+
+ int nIndexInHeap = -1;
+ return D3D12TextureResource::Create(pReadOnlyBuffer->m_pBuffer.Get(), pReadOnlyBuffer->getSrvCpuHandle(), nIndexInHeap);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// create read only shader resource buffer
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+void CopyToDevice(
+ GPUBufferResource *pGPUBuffer, void* pSysMem, unsigned int ByteWidth)
+{
+ ID3D12Resource* pBuffer = GPUBufferD3D12::GetResource(pGPUBuffer);
+ if (!pBuffer)
+ return;
+
+ void* pData;
+ ThrowIfFailed(pBuffer->Map(0, nullptr, &pData));
+ memcpy(pData, pSysMem, ByteWidth);
+ pBuffer->Unmap(0, nullptr);
+
+ /*
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ if (!pContext)
+ return;
+
+ ID3D12Device* pDevice = pContext->GetDevice();
+ ID3D12GraphicsCommandList* pCommandList = pContext->GetGraphicsCommandList();
+
+ D3D12_SUBRESOURCE_DATA data = {};
+ data.pData = reinterpret_cast<UINT8*>(pSysMem);
+ data.RowPitch = ByteWidth;
+ data.SlicePitch = data.RowPitch;
+
+ ID3D12Resource* m_pBufferUpload = GPUBufferD3D12::GetResourceUpload(pGPUBuffer, pDevice, ByteWidth);
+
+ UpdateSubresources<1>(pCommandList, pBuffer, m_pBufferUpload, 0, 0, 1, &data);
+ pCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(pBuffer,
+ D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE));
+ */
+}
+} // end namespace
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderInterface.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderInterface.h
new file mode 100644
index 0000000..8168936
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderInterface.h
@@ -0,0 +1,74 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+#include <d3d11.h>
+#include <d3d12.h>
+#include <dxgi1_4.h>
+#include "RenderInterface.h"
+#include "RenderPlugin.h"
+class RenderShaderState;
+// abstract interface to D3D calls
+namespace RenderInterfaceD3D12
+{
+ CORERENDER_EXPORT bool InitDevice(int deviceID);
+ CORERENDER_EXPORT bool Initialize();
+ CORERENDER_EXPORT void Shutdown();
+
+ RenderShaderState* GetShaderState();
+ void InitializeRenderStates();
+
+ CORERENDER_EXPORT void ApplyDepthStencilState(RenderInterface::DEPTH_STENCIL_STATE st);
+ CORERENDER_EXPORT void ApplyRasterizerState(RenderInterface::RASTERIZER_STATE st);
+ CORERENDER_EXPORT void ApplyBlendState(RenderInterface::BLEND_STATE st);
+ CORERENDER_EXPORT void ApplyPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType);
+ CORERENDER_EXPORT void ApplyForShadow(int ForShadow);
+ CORERENDER_EXPORT void SwitchToDX11();
+ CORERENDER_EXPORT void FlushDX11();
+ CORERENDER_EXPORT void FlushDX12();
+ CORERENDER_EXPORT void SubmitGpuWork();
+ CORERENDER_EXPORT void WaitForGpu();
+
+ CORERENDER_EXPORT void GetViewport(RenderInterface::Viewport& vp);
+ CORERENDER_EXPORT void SetViewport(const RenderInterface::Viewport& vp);
+
+ CORERENDER_EXPORT GPUBufferResource* CreateVertexBuffer( unsigned int ByteWidth, void* pSysMem);
+ CORERENDER_EXPORT GPUShaderResource* CreateShaderResource( unsigned int stride, unsigned int numElements, void* pSysMem, NVHairReadOnlyBuffer* pReadOnlyBuffer);
+
+ CORERENDER_EXPORT void CopyToDevice(GPUBufferResource *pDevicePtr, void* pSysMem, unsigned int ByteWidth);
+
+ CORERENDER_EXPORT void SetVertexBuffer(GPUBufferResource* pBuffer, UINT stride, UINT offset = 0);
+
+ CORERENDER_EXPORT void SetPrimitiveTopologyTriangleStrip();
+ CORERENDER_EXPORT void SetPrimitiveTopologyTriangleList();
+ CORERENDER_EXPORT void SetPrimitiveTopologyLineList();
+
+
+ CORERENDER_EXPORT void Draw(unsigned int vertexCount, unsigned int startCount = 0);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderShader.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderShader.cpp
new file mode 100644
index 0000000..f115349
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderShader.cpp
@@ -0,0 +1,384 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#include "D3D12RenderShader.h"
+
+#include "D3D12RenderInterface.h"
+#include "D3D12Wrapper.h"
+#include "D3D12RenderContext.h"
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(x) { if (x) x->Release(); }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+D3D12RenderShader::D3D12RenderShader()
+{
+ m_vertexShader = 0;
+ m_vertexShaderSize = 0;
+ m_pixelShader = 0;
+ m_pixelShaderSize = 0;
+
+ m_inputElementDescs = 0;
+ m_inputElementDescsNum = 0;
+
+ m_pRootSignature = 0;
+
+ m_scuHeap = 0;
+ m_scuDescriptorSize = 0;
+
+ m_samplerHeap = 0;
+ m_samplerDescriptorSize = 0;
+
+ m_PipelineStates.clear();
+
+ for (int i = 0; i < 2; i++)
+ {
+ m_ConstantBuffer[i] = nullptr;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+D3D12RenderShader::~D3D12RenderShader()
+{
+ for (int i = 0; i < 1; i++)
+ {
+ SAFE_RELEASE(m_ConstantBuffer[i]);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+D3D12RenderShader* D3D12RenderShader::Create(
+ const char *name,
+ void* vertexShader, size_t vertexShaderSize, void* pixelShader, size_t pixelShaderSize,
+ UINT cbufferSize0, UINT cbufferSize1,
+ D3D12_INPUT_ELEMENT_DESC* pElemDesc, UINT numElements,
+ int ShaderResourceNum, int UnorderedAccessNum, int SamplerNum)
+{
+ D3D12RenderContext* pAdapter = D3D12RenderContext::Instance();
+ ID3D12Device* m_device = pAdapter->GetDevice();
+
+ D3D12RenderShader* pShader = new D3D12RenderShader;
+
+ int sizeofuint = sizeof(UINT8);
+ pShader->m_vertexShaderSize = vertexShaderSize;
+ if (vertexShaderSize > 0)
+ {
+ pShader->m_vertexShader = new UINT8[vertexShaderSize / sizeofuint];
+ memcpy(pShader->m_vertexShader, vertexShader, vertexShaderSize);
+ }
+ pShader->m_pixelShaderSize = pixelShaderSize;
+ if (pixelShaderSize > 0)
+ {
+ pShader->m_pixelShader = new UINT8[pixelShaderSize / sizeofuint];
+ memcpy(pShader->m_pixelShader, pixelShader, pixelShaderSize);
+ }
+
+ pShader->m_inputElementDescsNum = numElements;
+ pShader->m_inputElementDescs = pElemDesc;
+
+ CD3DX12_DESCRIPTOR_RANGE ranges[3];
+ CD3DX12_ROOT_PARAMETER rootParameters[2];
+
+ int rangesindex = 0;
+ int rootParametersindex = 0;
+
+ if (ShaderResourceNum > 0)
+ {
+ ranges[rangesindex++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, ShaderResourceNum, 0);
+ }
+ int ConstantBufferNum = 0;
+ if (cbufferSize0 > 0)
+ {
+ ConstantBufferNum++;
+ }
+ if (cbufferSize1 > 0)
+ {
+ ConstantBufferNum++;
+ }
+ if (ConstantBufferNum > 0)
+ {
+ ranges[rangesindex++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, ConstantBufferNum, 0);
+ }
+ if (UnorderedAccessNum > 0)
+ {
+ ranges[rangesindex++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, UnorderedAccessNum, 0);
+ }
+ if (rangesindex > 0)
+ {
+ rootParameters[rootParametersindex++].InitAsDescriptorTable(rangesindex, &ranges[0], D3D12_SHADER_VISIBILITY_ALL);
+ }
+
+ if (SamplerNum > 0)
+ {
+ ranges[rangesindex].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, SamplerNum, 0);
+ rootParameters[rootParametersindex++].InitAsDescriptorTable(1, &ranges[rangesindex], D3D12_SHADER_VISIBILITY_ALL);
+ }
+
+ D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =
+ D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS;
+ CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
+ rootSignatureDesc.Init(rootParametersindex, rootParameters, 0, nullptr, rootSignatureFlags);
+
+ ComPtr<ID3DBlob> signature;
+ ComPtr<ID3DBlob> error;
+ ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
+ ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&pShader->m_pRootSignature)));
+
+ int numSCU = ShaderResourceNum + ConstantBufferNum + UnorderedAccessNum;
+ if (numSCU > 0)
+ {
+ D3D12_DESCRIPTOR_HEAP_DESC scuHeapDesc = {};
+ scuHeapDesc.NumDescriptors = numSCU;
+ scuHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+ scuHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+ ThrowIfFailed(m_device->CreateDescriptorHeap(&scuHeapDesc, IID_PPV_ARGS(&pShader->m_scuHeap)));
+ pShader->m_scuDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+
+ if (ConstantBufferNum > 0)
+ {
+ CD3DX12_CPU_DESCRIPTOR_HANDLE scuHandle(pShader->m_scuHeap->GetCPUDescriptorHandleForHeapStart(),
+ ShaderResourceNum, pShader->m_scuDescriptorSize);
+
+ if (cbufferSize0 > 0)
+ {
+ pShader->CreateParamBuffer(cbufferSize0, 0);
+
+ // Describe and create a constant buffer view.
+ D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
+ // CB size is required to be 256-byte aligned.
+ cbvDesc.SizeInBytes = (cbufferSize0 + 255) & ~255;
+ cbvDesc.BufferLocation = pShader->m_ConstantBuffer[0]->GetGPUVirtualAddress();
+ m_device->CreateConstantBufferView(&cbvDesc, scuHandle);
+ scuHandle.Offset(pShader->m_scuDescriptorSize);
+ }
+ if (cbufferSize1 > 0)
+ {
+ pShader->CreateParamBuffer(cbufferSize1, 1);
+
+ // Describe and create a constant buffer view.
+ D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
+ // CB size is required to be 256-byte aligned.
+ cbvDesc.SizeInBytes = (cbufferSize1 + 255) & ~255;
+ cbvDesc.BufferLocation = pShader->m_ConstantBuffer[1]->GetGPUVirtualAddress();
+ m_device->CreateConstantBufferView(&cbvDesc, scuHandle);
+ }
+ }
+ }
+
+ if (SamplerNum > 0)
+ {
+ D3D12_DESCRIPTOR_HEAP_DESC samplerHeapDesc = {};
+ samplerHeapDesc.NumDescriptors = SamplerNum;
+ samplerHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
+ samplerHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+ ThrowIfFailed(m_device->CreateDescriptorHeap(&samplerHeapDesc, IID_PPV_ARGS(&pShader->m_samplerHeap)));
+ pShader->m_samplerDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE samplerHandle(pShader->m_samplerHeap->GetCPUDescriptorHandleForHeapStart());
+
+ if(SamplerNum == 1)
+ {
+ D3D12_SAMPLER_DESC pointClampSamplerDesc[1] = {
+ D3D12_FILTER_MIN_MAG_MIP_POINT,
+ D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
+ D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
+ D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
+ 0.0, 0, D3D12_COMPARISON_FUNC_NEVER,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, D3D12_FLOAT32_MAX,
+ };
+ m_device->CreateSampler(pointClampSamplerDesc, samplerHandle);
+ }
+ else if(SamplerNum == 2)
+ {
+ D3D12_SAMPLER_DESC linearSamplerDesc[1] = {
+ D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT,
+ D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ D3D12_TEXTURE_ADDRESS_MODE_WRAP,
+ 0.0, 0, D3D12_COMPARISON_FUNC_NEVER, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, D3D12_FLOAT32_MAX,
+ };
+ m_device->CreateSampler(linearSamplerDesc, samplerHandle);
+ samplerHandle.Offset(pShader->m_samplerDescriptorSize);
+
+ D3D12_SAMPLER_DESC pointClampSamplerDesc[1] = {
+ D3D12_FILTER_MIN_MAG_MIP_POINT,
+ D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
+ D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
+ D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
+ 0.0, 0, D3D12_COMPARISON_FUNC_NEVER,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, D3D12_FLOAT32_MAX,
+ };
+ m_device->CreateSampler(pointClampSamplerDesc, samplerHandle);
+ }
+ }
+
+ return pShader;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D12RenderShader::SetConstantBuffer()
+{
+ return;
+}
+
+ID3D12PipelineState* D3D12RenderShader::GetPipelineState(RenderShaderState* pShaderState)
+{
+ ID3D12PipelineState* pPipelineState = nullptr;
+ map<RenderShaderState*, ID3D12PipelineState*>::iterator it = m_PipelineStates.find(pShaderState);
+ if (it == m_PipelineStates.end())
+ {
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
+ psoDesc.InputLayout = { m_inputElementDescs, m_inputElementDescsNum };
+ psoDesc.pRootSignature = m_pRootSignature;
+ psoDesc.VS = { reinterpret_cast<UINT8*>(m_vertexShader), m_vertexShaderSize };
+ psoDesc.PS = { reinterpret_cast<UINT8*>(m_pixelShader), m_pixelShaderSize };
+ psoDesc.BlendState = pShaderState->BlendState;
+ psoDesc.RasterizerState = pShaderState->RasterizerState;
+ psoDesc.DepthStencilState = pShaderState->DepthStencilState;
+ psoDesc.SampleMask = UINT_MAX;
+ psoDesc.PrimitiveTopologyType = pShaderState->PrimitiveTopologyType;
+ psoDesc.NumRenderTargets = 1;
+ psoDesc.RTVFormats[0] = pShaderState->RTVFormat;
+ psoDesc.DSVFormat = pShaderState->DSVFormat;
+ psoDesc.SampleDesc.Count = pShaderState->SampleCount;
+
+ ID3D12Device* pDevice = D3D12RenderContext::Instance()->GetDevice();
+ ThrowIfFailed(pDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pPipelineState)));
+
+ m_PipelineStates[pShaderState] = pPipelineState;
+ }
+ else
+ {
+ pPipelineState = it->second;
+ }
+ return pPipelineState;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D12RenderShader::MakeCurrent()
+{
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ ID3D12GraphicsCommandList* m_commandList = pContext->GetGraphicsCommandList();
+
+ RenderShaderState* pShaderState = RenderInterfaceD3D12::GetShaderState();
+ if (nullptr == pShaderState)
+ {
+ return;
+ }
+
+ ID3D12PipelineState* pPipelineState = GetPipelineState(pShaderState);
+
+ m_commandList->SetGraphicsRootSignature(m_pRootSignature);
+ m_commandList->SetPipelineState(pPipelineState);
+
+ vector<ID3D12DescriptorHeap*> heaps;
+ if (nullptr != m_scuHeap)
+ {
+ heaps.push_back(m_scuHeap);
+ }
+ if (nullptr != m_samplerHeap)
+ {
+ heaps.push_back(m_samplerHeap);
+ }
+ if (heaps.size() > 0)
+ {
+ m_commandList->SetDescriptorHeaps(heaps.size(), heaps.data());
+ }
+ int heapindex = 0;
+ if (nullptr != m_scuHeap)
+ {
+ m_commandList->SetGraphicsRootDescriptorTable(heapindex++, m_scuHeap->GetGPUDescriptorHandleForHeapStart());
+ }
+ if (nullptr != m_samplerHeap)
+ {
+ m_commandList->SetGraphicsRootDescriptorTable(heapindex++, m_samplerHeap->GetGPUDescriptorHandleForHeapStart());
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D12RenderShader::Disable()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool D3D12RenderShader::CreateParamBuffer( UINT sizeBuffer, UINT slot )
+{
+ ID3D12Device* pDevice = D3D12RenderContext::Instance()->GetDevice();
+ if (!pDevice)
+ return false;
+
+ SAFE_RELEASE(m_ConstantBuffer[slot]);
+
+ ThrowIfFailed(pDevice->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
+ D3D12_HEAP_FLAG_NONE,
+ &CD3DX12_RESOURCE_DESC::Buffer(sizeBuffer),
+ D3D12_RESOURCE_STATE_GENERIC_READ,
+ nullptr,
+ IID_PPV_ARGS(&m_ConstantBuffer[slot])));
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void* D3D12RenderShader::MapParam(UINT slot)
+{
+ if (!m_ConstantBuffer[slot])
+ return 0;
+
+ void* pData;
+ ThrowIfFailed(m_ConstantBuffer[slot]->Map(0, nullptr, &pData));
+ return pData;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D12RenderShader::UnmapParam( UINT slot )
+{
+ if (!m_ConstantBuffer[slot])
+ return;
+
+ m_ConstantBuffer[slot]->Unmap(0, nullptr);
+}
+
+void D3D12RenderShader::BindShaderResource(UINT slot, CD3DX12_CPU_DESCRIPTOR_HANDLE& handle)
+{
+ ID3D12Device* pDevice = D3D12RenderContext::Instance()->GetDevice();
+ if (!pDevice)
+ return;
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE destHandle(m_scuHeap->GetCPUDescriptorHandleForHeapStart(), slot, m_scuDescriptorSize);
+ if (handle.ptr != 0)
+ {
+ pDevice->CopyDescriptorsSimple(1, destHandle, handle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ }
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderShader.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderShader.h
new file mode 100644
index 0000000..d43783c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderShader.h
@@ -0,0 +1,85 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include <d3d11.h>
+#include <d3d12.h>
+
+#include "D3D12RenderTarget.h"
+
+class D3D12RenderShader
+{
+public:
+ D3D12RenderShader();
+ ~D3D12RenderShader();
+
+ static D3D12RenderShader* Create(
+ const char *name,
+ void* pVSBlob, size_t vsBlobSize,
+ void* pPSBlob, size_t psBlobSize,
+ UINT cbufferSize0 = 0, UINT cbufferSize1 = 0,
+ D3D12_INPUT_ELEMENT_DESC* pElemDesc = 0, UINT numElements = 0,
+ int ShaderResourceNum = 0, int UnorderedAccessNum = 0, int SamplerNum = 0);
+
+ void MakeCurrent();
+ void Disable();
+ void SetConstantBuffer();
+
+ void* MapParam(UINT slot = 0);
+ void UnmapParam(UINT slot = 0);
+
+ void BindShaderResource(UINT slot, CD3DX12_CPU_DESCRIPTOR_HANDLE& handle);
+
+protected:
+ bool CreateParamBuffer(UINT sizeBuffer, UINT slot = 0);
+
+private:
+ ID3D12PipelineState* GetPipelineState(RenderShaderState* pShaderState);
+
+ void* m_vertexShader;
+ SIZE_T m_vertexShaderSize;
+ void* m_pixelShader;
+ SIZE_T m_pixelShaderSize;
+
+ D3D12_INPUT_ELEMENT_DESC* m_inputElementDescs;
+ UINT m_inputElementDescsNum;
+
+ ID3D12RootSignature* m_pRootSignature;
+
+ ID3D12DescriptorHeap* m_scuHeap;
+ int m_scuDescriptorSize;
+
+ ID3D12Resource* m_ConstantBuffer[2];
+
+ ID3D12DescriptorHeap* m_samplerHeap;
+ int m_samplerDescriptorSize;
+
+ map<RenderShaderState*, ID3D12PipelineState*> m_PipelineStates;
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderTarget.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderTarget.cpp
new file mode 100644
index 0000000..301cad6
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderTarget.cpp
@@ -0,0 +1,371 @@
+#include "D3D12RenderTarget.h"
+#include "D3D12RenderContext.h"
+
+D3D12RenderTarget::D3D12RenderTarget(int renderTargetIndex, int nRenderTargetCount)
+{
+ m_RenderTargetIndex = renderTargetIndex;
+
+ m_RenderTargetCount = nRenderTargetCount;
+
+ m_BackBuffers = nullptr;
+ m_RenderTargets = nullptr;
+ m_DepthStencil = nullptr;
+
+ m_pRenderContext = D3D12RenderContext::Instance();
+
+ if (m_RenderTargetCount > 0)
+ {
+ m_BackBuffers = new ID3D12Resource*[m_RenderTargetCount];
+
+ for (int n = 0; n < m_RenderTargetCount; n++)
+ {
+ m_BackBuffers[n] = nullptr;
+ }
+
+ m_RenderTargets = new ID3D12Resource*[m_RenderTargetCount];
+
+ for (int n = 0; n < m_RenderTargetCount; n++)
+ {
+ m_RenderTargets[n] = nullptr;
+ }
+ }
+
+ if (renderTargetIndex == 0)
+ {
+ m_rtvClearValue.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ m_rtvClearValue.Color[0] = 0.0;
+ m_rtvClearValue.Color[1] = 0.0;
+ m_rtvClearValue.Color[2] = 0.0;
+ m_rtvClearValue.Color[3] = 1.0;
+ }
+ else
+ {
+ m_rtvClearValue.Format = DXGI_FORMAT_R32_FLOAT;
+ m_rtvClearValue.Color[0] = FLT_MAX;
+ m_rtvClearValue.Color[1] = FLT_MAX;
+ m_rtvClearValue.Color[2] = FLT_MAX;
+ m_rtvClearValue.Color[3] = FLT_MAX;
+ }
+
+ if (renderTargetIndex == 0)
+ {
+ m_dsvClearValue.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ }
+ else
+ {
+ m_dsvClearValue.Format = DXGI_FORMAT_D32_FLOAT;
+ }
+ m_dsvClearValue.DepthStencil.Depth = 1.0f;
+ m_dsvClearValue.DepthStencil.Stencil = 0;
+}
+
+D3D12RenderTarget::~D3D12RenderTarget()
+{
+ if (nullptr != m_BackBuffers)
+ {
+ delete[] m_BackBuffers;
+ m_BackBuffers = nullptr;
+ }
+
+ if (nullptr != m_RenderTargets)
+ {
+ delete[] m_RenderTargets;
+ m_RenderTargets = nullptr;
+ }
+}
+
+ID3D12Resource* D3D12RenderTarget::GetDepthStencilResource()
+{
+ return m_DepthStencil;
+}
+
+D3D12_CPU_DESCRIPTOR_HANDLE D3D12RenderTarget::GetRenderTargetViewHandle()
+{
+ CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
+ return rtvHandle;
+}
+
+D3D12_CPU_DESCRIPTOR_HANDLE D3D12RenderTarget::GetDepthStencilViewHandle()
+{
+ CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
+ return dsvHandle;
+}
+
+void D3D12RenderTarget::CreateResource(int nWidth, int nHeight)
+{
+ ID3D12Device* m_device = m_pRenderContext->GetDevice();
+ int nSampleCount = m_pRenderContext->GetSampleCount();
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
+
+ if (m_RenderTargetIndex == 0)
+ {
+ IDXGISwapChain3* m_swapChain = m_pRenderContext->GetSwapChain();
+
+ // Create a RTV for each frame.
+ for (int n = 0; n < m_RenderTargetCount; n++)
+ {
+ ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_BackBuffers[n])));
+
+ if (nSampleCount > 1)
+ {
+ // If we are multi-sampling - create a render target separate from the back buffer
+ CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT);
+ D3D12_RESOURCE_DESC desc = m_BackBuffers[n]->GetDesc();
+
+ desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ desc.SampleDesc.Count = nSampleCount;
+ desc.SampleDesc.Quality = 0;
+ desc.Alignment = 0;
+
+ ThrowIfFailed(m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_RENDER_TARGET,
+ &m_rtvClearValue, IID_PPV_ARGS(&m_RenderTargets[n])));
+ }
+ else
+ {
+ // The render targets and back buffers are the same thing
+ m_RenderTargets[n] = m_BackBuffers[n];
+ }
+
+ m_device->CreateRenderTargetView(m_RenderTargets[n], nullptr, rtvHandle);
+ rtvHandle.Offset(1, m_rtvDescriptorSize);
+ }
+
+ {
+ auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(m_dsvClearValue.Format,
+ nWidth, nHeight, 1, 1, nSampleCount, 0,
+ D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);
+
+ ThrowIfFailed(m_device->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), // No need to read/write by CPU
+ D3D12_HEAP_FLAG_NONE,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_DEPTH_WRITE,
+ &m_dsvClearValue,
+ IID_PPV_ARGS(&m_DepthStencil)));
+
+ D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
+ dsvDesc.ViewDimension = nSampleCount <= 1 ? D3D12_DSV_DIMENSION_TEXTURE2D : D3D12_DSV_DIMENSION_TEXTURE2DMS;
+ dsvDesc.Format = m_dsvClearValue.Format;
+ dsvDesc.Texture2D.MipSlice = 0;
+ dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
+ m_device->CreateDepthStencilView(m_DepthStencil, &dsvDesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
+ }
+ }
+ else
+ {
+ {
+ auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(m_rtvClearValue.Format,
+ nWidth, nHeight, 1, 1, 1, 0,
+ D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
+
+ D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
+ rtvDesc.Format = m_rtvClearValue.Format;
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = 0;
+ rtvDesc.Texture2D.PlaneSlice = 0;
+
+ for (int n = 0; n < m_RenderTargetCount; n++)
+ {
+ m_device->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
+ D3D12_HEAP_FLAG_NONE,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_RENDER_TARGET,
+ &m_rtvClearValue,
+ IID_PPV_ARGS(&m_RenderTargets[n]));
+ m_device->CreateRenderTargetView(m_RenderTargets[n], &rtvDesc, rtvHandle);
+ rtvHandle.Offset(1, m_rtvDescriptorSize);
+ }
+ }
+
+ {
+ auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(m_dsvClearValue.Format,
+ nWidth, nHeight, 1, 1, 1, 0,
+ D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);
+
+ m_device->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
+ D3D12_HEAP_FLAG_NONE,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_DEPTH_WRITE,
+ &m_dsvClearValue,
+ IID_PPV_ARGS(&m_DepthStencil));
+
+ D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
+ dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
+ dsvDesc.Format = m_dsvClearValue.Format;
+ dsvDesc.Texture2D.MipSlice = 0;
+ dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
+ m_device->CreateDepthStencilView(m_DepthStencil, &dsvDesc, m_dsvHeap.Get()->GetCPUDescriptorHandleForHeapStart());
+ }
+ }
+}
+
+void D3D12RenderTarget::OnCreate(int nWidth, int nHeight)
+{
+ ID3D12Device* m_device = m_pRenderContext->GetDevice();
+
+ // Create descriptor heaps.
+ {
+ // Describe and create a render target view (RTV) descriptor heap.
+ D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
+ rtvHeapDesc.NumDescriptors = m_RenderTargetCount;
+ rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
+ rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
+ ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap)));
+
+ m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
+
+ // Describe and create a render target view (RTV) descriptor heap.
+ D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
+ dsvHeapDesc.NumDescriptors = 1;
+ dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
+ dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
+ ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap)));
+
+ m_dsvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
+ }
+
+ OnResize(nWidth, nHeight);
+}
+
+void D3D12RenderTarget::OnResize(int nWidth, int nHeight)
+{
+ CreateResource(nWidth, nHeight);
+
+ // viewport and scissor rect
+ {
+ memset(&m_viewport, 0, sizeof(m_viewport));
+ m_viewport.Width = nWidth;
+ m_viewport.Height = nHeight;
+ m_viewport.MaxDepth = 1.0;
+
+ memset(&m_scissorRect, 0, sizeof(m_scissorRect));
+ m_scissorRect.right = nWidth;
+ m_scissorRect.bottom = nHeight;
+ }
+}
+
+void D3D12RenderTarget::OnDestroy()
+{
+ for (int n = 0; n < m_RenderTargetCount; n++)
+ {
+ Safe_Release(m_RenderTargets[n]);
+
+ if (m_pRenderContext->GetSampleCount() > 1)
+ {
+ Safe_Release(m_BackBuffers[n]);
+ }
+ }
+ Safe_Release(m_DepthStencil);
+}
+
+void D3D12RenderTarget::PreRender(bool doClear)
+{
+ ID3D12GraphicsCommandList* m_commandList = m_pRenderContext->GetGraphicsCommandList();
+ m_commandList->RSSetViewports(1, &m_viewport);
+ m_commandList->RSSetScissorRects(1, &m_scissorRect);
+
+ int numSamples = 1;
+ UINT m_frameIndex = 0;
+ D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ if (m_RenderTargetIndex == 0)
+ {
+ numSamples = m_pRenderContext->GetSampleCount();
+ m_frameIndex = m_pRenderContext->GetFrameIndex();
+ if (numSamples <= 1)
+ {
+ state = D3D12_RESOURCE_STATE_PRESENT;
+ }
+ else
+ {
+ state = D3D12_RESOURCE_STATE_RESOLVE_SOURCE;
+ }
+ }
+
+ ID3D12Resource* pRenderTarget = m_RenderTargets[m_frameIndex];
+
+ m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(pRenderTarget, state, D3D12_RESOURCE_STATE_RENDER_TARGET));
+
+ CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
+ CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
+ m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
+
+ if (doClear)
+ {
+ m_commandList->ClearRenderTargetView(rtvHandle, m_rtvClearValue.Color, 0, nullptr);
+ m_commandList->ClearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH,
+ m_dsvClearValue.DepthStencil.Depth, m_dsvClearValue.DepthStencil.Stencil, 0, nullptr);
+ }
+}
+
+void D3D12RenderTarget::PostRender()
+{
+ ID3D12GraphicsCommandList* m_commandList = m_pRenderContext->GetGraphicsCommandList();
+
+ int numSamples = 1;
+ UINT m_frameIndex = 0;
+ D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ if (m_RenderTargetIndex == 0)
+ {
+ numSamples = m_pRenderContext->GetSampleCount();
+ m_frameIndex = m_pRenderContext->GetFrameIndex();
+ state = D3D12_RESOURCE_STATE_PRESENT;
+ }
+
+ if (numSamples <= 1)
+ {
+ ID3D12Resource* renderTarget = m_RenderTargets[m_frameIndex];
+ CD3DX12_RESOURCE_BARRIER barrier(CD3DX12_RESOURCE_BARRIER::Transition(renderTarget, D3D12_RESOURCE_STATE_RENDER_TARGET, state));
+ m_commandList->ResourceBarrier(1, &barrier);
+ }
+ else
+ {
+ ID3D12Resource* backBuffer = m_BackBuffers[m_frameIndex];
+ ID3D12Resource* renderTarget = m_RenderTargets[m_frameIndex];
+
+ // Barriers to wait for the render target, and the backbuffer to be in correct state
+ {
+ D3D12_RESOURCE_BARRIER barriers[] =
+ {
+ CD3DX12_RESOURCE_BARRIER::Transition(renderTarget, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE),
+ CD3DX12_RESOURCE_BARRIER::Transition(backBuffer, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RESOLVE_DEST),
+ };
+ m_commandList->ResourceBarrier(2, barriers);
+ }
+ // Do the resolve...
+ m_commandList->ResolveSubresource(backBuffer, 0, renderTarget, 0, m_rtvClearValue.Format);
+ // Barrier until can present
+ {
+ CD3DX12_RESOURCE_BARRIER barrier(CD3DX12_RESOURCE_BARRIER::Transition(backBuffer, D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT));
+ m_commandList->ResourceBarrier(1, &barrier);
+ }
+ }
+}
+
+void D3D12RenderTarget::SetClearColor(float r, float g, float b, float a, float depth, float stencil)
+{
+ m_rtvClearValue.Color[0] = r;
+ m_rtvClearValue.Color[1] = g;
+ m_rtvClearValue.Color[2] = b;
+ m_rtvClearValue.Color[3] = a;
+
+ m_dsvClearValue.DepthStencil.Depth = depth;
+ m_dsvClearValue.DepthStencil.Stencil = stencil;
+}
+
+ID3D12Resource* D3D12RenderTarget::GetTexture(int nIndex, bool bRenderTarget)
+{
+ if (nIndex < 0 || nIndex > m_RenderTargetCount)
+ return nullptr;
+
+ if (bRenderTarget)
+ {
+ return m_RenderTargets[nIndex];
+ }
+ else
+ {
+ return m_BackBuffers[nIndex];
+ }
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderTarget.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderTarget.h
new file mode 100644
index 0000000..8ae0b7d
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RenderTarget.h
@@ -0,0 +1,110 @@
+#pragma once
+
+class D3D12RenderContext;
+
+#include "RenderInterface.h"
+using namespace RenderInterface;
+
+#include <d3d12.h>
+#include <d3d11on12.h>
+#include <dxgi1_4.h>
+#include <D3Dcompiler.h>
+#include <DirectXMath.h>
+#include "d3dx12.h"
+#include <string>
+#include <vector>
+#include <map>
+#include <wrl.h>
+#include <shellapi.h>
+using namespace std;
+using namespace DirectX;
+using namespace Microsoft::WRL;
+
+#ifndef Safe_Delete
+#define Safe_Delete(p) { if (p) { delete (p); (p) = nullptr; } }
+#endif // !Safe_Delete
+#ifndef Safe_Release
+#define Safe_Release(p) { if (p) { p->Release(); (p) = nullptr; } }
+#endif // !Safe_Delete
+
+inline void ThrowIfFailed(HRESULT hr)
+{
+ if (FAILED(hr))
+ {
+ throw;
+ }
+}
+
+typedef struct RenderShaderStateKey
+{
+ BLEND_STATE BlendState = BLEND_STATE_NONE;
+ RASTERIZER_STATE RasterizerState = RASTERIZER_STATE_FILL_CULL_NONE;
+ DEPTH_STENCIL_STATE DepthStencilState = DEPTH_STENCIL_DEPTH_TEST;
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ int ForShadow = 0;
+
+ bool operator <(const RenderShaderStateKey &other) const
+ {
+ int key = (((BlendState * 10 + RasterizerState) * 10 + DepthStencilState) * 10 + PrimitiveTopologyType) * 10 + ForShadow;
+ int otherkey = (((other.BlendState * 10 + other.RasterizerState) * 10 + other.DepthStencilState) * 10 + other.PrimitiveTopologyType) * 10 + other.ForShadow;
+ return key < otherkey;
+ }
+} RenderShaderStateKey;
+
+typedef struct RenderShaderState
+{
+ D3D12_BLEND_DESC BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
+ D3D12_RASTERIZER_DESC RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
+ D3D12_DEPTH_STENCIL_DESC DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ DXGI_FORMAT RTVFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+ DXGI_FORMAT DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ int SampleCount = 1;
+} RenderShaderState;
+
+class D3D12RenderTarget
+{
+public:
+ D3D12RenderTarget(int renderTargetIndex, int nRenderTargetCount = 1);
+ ~D3D12RenderTarget();
+
+ void OnCreate(int nWidth, int nHeight);
+ void OnResize(int nWidth, int nHeight);
+ void OnDestroy();
+
+ void PreRender(bool doClear = false);
+ void PostRender();
+
+ void SetClearColor(float r, float g, float b, float a = 1.0, float depth = 1.0, float stencil = 0.0);
+
+ ID3D12Resource* GetTexture(int nIndex = 0, bool bRenderTarget = true);
+
+ D3D12_VIEWPORT m_viewport;
+
+ ID3D12Resource* GetDepthStencilResource();
+ D3D12_CPU_DESCRIPTOR_HANDLE GetRenderTargetViewHandle();
+ D3D12_CPU_DESCRIPTOR_HANDLE GetDepthStencilViewHandle();
+
+private:
+ void CreateResource(int nWidth, int nHeight);
+
+ int m_RenderTargetIndex;
+ int m_RenderTargetCount;
+
+ ID3D12Resource** m_BackBuffers;
+ ID3D12Resource** m_RenderTargets;
+ ID3D12Resource* m_DepthStencil;
+
+ ComPtr<ID3D12DescriptorHeap> m_rtvHeap;
+ UINT m_rtvDescriptorSize;
+ ComPtr<ID3D12DescriptorHeap> m_dsvHeap;
+ UINT m_dsvDescriptorSize;
+
+ D3D12_RECT m_scissorRect;
+
+ D3D12RenderContext* m_pRenderContext;
+
+ D3D12_CLEAR_VALUE m_rtvClearValue;
+ D3D12_CLEAR_VALUE m_dsvClearValue;
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RendererWindow.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RendererWindow.cpp
new file mode 100644
index 0000000..b640ebd
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RendererWindow.cpp
@@ -0,0 +1,141 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D12RendererWindow.h"
+
+#include "DXUT.h"
+#include "DXUTgui.h"
+#include "sdkmisc.h"
+
+#include "D3D12RenderInterface.h"
+#include "D3D12RenderContext.h"
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(x) { if (x) x->Release(); x = 0; }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+D3D12RenderWindow::D3D12RenderWindow()
+{
+ m_pRenderContext = D3D12RenderContext::Instance();
+
+ m_pDialogResourceManager = 0;
+ m_pTextHelper = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+D3D12RenderWindow::~D3D12RenderWindow()
+{
+ Free();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool D3D12RenderWindow::Create( HWND hWnd, unsigned int nSamples )
+{
+ m_pRenderContext->SetSampleCount(nSamples);
+
+ RECT rc;
+ GetClientRect((HWND)hWnd, &rc);
+ int wBuf = rc.right - rc.left;
+ int hBuf = rc.bottom- rc.top;
+
+ ID3D11Device *pDevice = m_pRenderContext->GetDevice11();
+ ID3D11DeviceContext* pDeviceContext = m_pRenderContext->GetDeviceContext();
+ if (nullptr != pDevice && nullptr != pDeviceContext)
+ {
+ m_pDialogResourceManager = new CDXUTDialogResourceManager;
+ m_pDialogResourceManager->OnD3D11CreateDevice(pDevice, pDeviceContext);
+ m_pTextHelper = new CDXUTTextHelper(pDevice, pDeviceContext, m_pDialogResourceManager, 15);
+ }
+
+ m_pRenderContext->InitSwapchain(wBuf, hBuf, hWnd);
+ Resize(wBuf, hBuf);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D12RenderWindow::Free()
+{
+ FreeBuffer();
+
+ SAFE_DELETE(m_pTextHelper);
+
+ if (m_pDialogResourceManager)
+ {
+ m_pDialogResourceManager->OnD3D11DestroyDevice();
+ SAFE_DELETE(m_pDialogResourceManager);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D12RenderWindow::FreeBuffer()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D12RenderWindow::Present()
+{
+// m_pRenderContext->ReleaseRenderTarget();
+
+// m_pRenderContext->PostRender();
+
+ m_pRenderContext->Present();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void D3D12RenderWindow::Clear(float r, float g, float b)
+{
+ m_pRenderContext->PreRender();
+
+ m_pRenderContext->SetClearColor(0, r, g, b);
+ m_pRenderContext->AcquireRenderTarget(true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool D3D12RenderWindow::Resize( int w, int h )
+{
+ assert(w > 0 && h > 0);
+
+ m_pRenderContext->ResizeSwapchain(w, h);
+
+ if (m_pDialogResourceManager)
+ {
+ ID3D11Device *pDevice = m_pRenderContext->GetDevice11();
+ D3D12_RESOURCE_DESC descTex2D = m_pRenderContext->GetBackBufferDesc();
+
+ DXGI_SURFACE_DESC backbufferDesc;
+ backbufferDesc.Width = descTex2D.Width;
+ backbufferDesc.Height = descTex2D.Height;
+ backbufferDesc.Format = descTex2D.Format;
+ backbufferDesc.SampleDesc = descTex2D.SampleDesc;
+
+ m_pDialogResourceManager->OnD3D11ResizedSwapChain(pDevice, &backbufferDesc);
+ }
+
+ return true;
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RendererWindow.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RendererWindow.h
new file mode 100644
index 0000000..abd5d9b
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12RendererWindow.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <d3d12.h>
+class D3D12RenderContext;
+// DXUT stuffs for text rendering
+class CDXUTDialogResourceManager;
+class CDXUTTextHelper;
+
+struct D3D12RenderWindow
+{
+public:
+ D3D12RenderWindow();
+ ~D3D12RenderWindow();
+
+ bool Create(HWND hWnd, unsigned int nSamples = 1);
+ bool Resize(int w, int h);
+ void Present();
+ void Clear(float r, float g, float b);
+
+ CDXUTDialogResourceManager* m_pDialogResourceManager;
+ CDXUTTextHelper* m_pTextHelper;
+
+private:
+ void Free();
+ void FreeBuffer();
+
+ D3D12RenderContext* m_pRenderContext;
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Shaders.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Shaders.cpp
new file mode 100644
index 0000000..0c07409
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Shaders.cpp
@@ -0,0 +1,231 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D12Shaders.h"
+
+#include "MeshShaderParam.h"
+#include "LightShaderParam.h"
+
+//#include <Nv/Blast/NvHairSdk.h>
+#include "D3D12RenderShader.h"
+#include "D3D12RenderContext.h"
+#include "D3D12TextureResource.h"
+using namespace RenderInterface;
+
+D3D12_INPUT_ELEMENT_DESC layoutBodyRender[] =
+{
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "VERTEX_NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "FACE_NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 36, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 48, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "VERTEX_ID", 0, DXGI_FORMAT_R32_FLOAT, 0, 56, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+};
+
+D3D12_INPUT_ELEMENT_DESC layout_Position_And_Color[] =
+{
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+};
+
+/////////////////////////////////////////////////////////////////////////////////////
+// Common shader settings
+//static D3D12RenderShader* g_pShaders[SHADER_TYPE_END];
+static std::map<int, D3D12RenderShader*> g_pShaders;
+/*
+namespace BodyShaderBlobs
+{
+ #include "Shaders/BodyShader_VS.h"
+ #include "Shaders/BodyShader_PS.h"
+}
+
+namespace BodyShadowBlobs
+{
+ #include "Shaders/BodyShadow_VS.h"
+ #include "Shaders/BodyShadow_PS.h"
+}
+
+namespace ScreenQuadBlobs
+{
+ #include "Shaders/ScreenQuad_VS.h"
+ #include "Shaders/ScreenQuad_PS.h"
+}
+
+namespace ScreenQuadColorBlobs
+{
+ #include "Shaders/ScreenQuadColor_VS.h"
+ #include "Shaders/ScreenQuadColor_PS.h"
+}
+
+namespace VisualizeShadowBlobs
+{
+ #include "Shaders/VisualizeShadow_VS.h"
+ #include "Shaders/VisualizeShadow_PS.h"
+}
+
+namespace ColorBlobs
+{
+ #include "Shaders/Color_VS.h"
+ #include "Shaders/Color_PS.h"
+}
+*/
+//////////////////////////////////////////////////////////////////////////
+bool InitializeShadersD3D12()
+{
+ /*
+ UINT numElements = sizeof(layoutBodyRender) / sizeof(D3D11_INPUT_ELEMENT_DESC);
+
+ g_pShaders[SHADER_TYPE_MESH_RENDERING] = D3D12RenderShader::Create("MeshRenderShader",
+ (void*)BodyShaderBlobs::g_vs_main, sizeof(BodyShaderBlobs::g_vs_main),
+ (void*)BodyShaderBlobs::g_ps_main, sizeof(BodyShaderBlobs::g_ps_main),
+ sizeof(MeshShaderParam), 0,
+ &layoutBodyRender[0], numElements,
+ 10, 0, 2);
+
+ g_pShaders[SHADER_TYPE_MESH_SHADOW] = D3D12RenderShader::Create("MeshShadowShader",
+ (void*)BodyShadowBlobs::g_vs_main, sizeof(BodyShadowBlobs::g_vs_main),
+ (void*)BodyShadowBlobs::g_ps_main, sizeof(BodyShadowBlobs::g_ps_main),
+ sizeof(MeshShadowShaderParam), 0,
+ &layoutBodyRender[0], numElements,
+ 2);
+
+ g_pShaders[SHADER_TYPE_SCREEN_QUAD] = D3D12RenderShader::Create("ScreenQuadShader",
+ (void*)ScreenQuadBlobs::g_vs_main, sizeof(ScreenQuadBlobs::g_vs_main),
+ (void*)ScreenQuadBlobs::g_ps_main, sizeof(ScreenQuadBlobs::g_ps_main),
+ 0, 0,
+ 0, 0,
+ 1, 0, 1);
+
+ g_pShaders[SHADER_TYPE_SCREEN_QUAD_COLOR] = D3D12RenderShader::Create("ScreenQuadColorShader",
+ (void*)ScreenQuadColorBlobs::g_vs_main, sizeof(ScreenQuadColorBlobs::g_vs_main),
+ (void*)ScreenQuadColorBlobs::g_ps_main, sizeof(ScreenQuadColorBlobs::g_ps_main));
+
+ g_pShaders[SHADER_TYPE_VISUALIZE_SHADOW] = D3D12RenderShader::Create("VisualizeShadowShader",
+ (void*)VisualizeShadowBlobs::g_vs_main, sizeof(VisualizeShadowBlobs::g_vs_main),
+ (void*)VisualizeShadowBlobs::g_ps_main, sizeof(VisualizeShadowBlobs::g_ps_main),
+ sizeof(ShadowVizParam), 0,
+ 0, 0,
+ 1, 0, 1);
+
+ UINT numElements2 = sizeof(layout_Position_And_Color) / sizeof(D3D11_INPUT_ELEMENT_DESC);
+
+ g_pShaders[SHADER_TYPE_SIMPLE_COLOR] = D3D12RenderShader::Create("Color",
+ (void*)ColorBlobs::g_vs_main, sizeof(ColorBlobs::g_vs_main),
+ (void*)ColorBlobs::g_ps_main, sizeof(ColorBlobs::g_ps_main),
+ sizeof(SimpleShaderParam), 0,
+ &layout_Position_And_Color[0], numElements2);
+
+ g_pShaders[SHADER_TYPE_HAIR_SHADER_DEFAULT] = D3D12RenderShader::Create(
+ "hairShaderDefault", 0, 0,
+ (void*)BlastShaderBlobs::g_ps_main, sizeof(BlastShaderBlobs::g_ps_main),
+ sizeof(NvHair::ShaderConstantBuffer),
+ sizeof(LightShaderParam)
+ );
+
+ g_pShaders[SHADER_TYPE_HAIR_SHADER_SHADOW] = D3D12RenderShader::Create(
+ "hairShadow", 0, 0,
+ (void*)BlastShadowBlobs::g_ps_main, sizeof(BlastShadowBlobs::g_ps_main),
+ sizeof(NvHair::ShaderConstantBuffer),
+ 0);
+ */
+ return true;
+}
+
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(x) { if (x) x->Release(); x = 0; }
+#endif
+
+#ifndef SAFE_DELETE
+#define SAFE_DELETE(x) { if (x) delete x; x = 0; }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+void DestroyShadersD3D12()
+{
+ for (int i = 0; i < g_pShaders.size(); i++)
+ {
+ D3D12RenderShader*& pShader = g_pShaders[i];
+ if (pShader)
+ {
+ delete pShader;
+ pShader = 0;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+D3D12RenderShader* GetShaderD3D12(SHADER_TYPE st)
+{
+ return g_pShaders[st];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyShaderD3D12(SHADER_TYPE st)
+{
+ D3D12RenderShader* pD3D12Shader = GetShaderD3D12(st);
+ if (!pD3D12Shader)
+ return;
+
+ pD3D12Shader->MakeCurrent();
+}
+
+void BindShaderResourcesD3D12(SHADER_TYPE st, int numSRVs, GPUShaderResource** ppSRVs)
+{
+ D3D12RenderShader* pD3D12Shader = GetShaderD3D12(st);
+ if (!pD3D12Shader)
+ return;
+
+ for (int i = 0; i < numSRVs; i++)
+ {
+ CD3DX12_CPU_DESCRIPTOR_HANDLE handle = D3D12TextureResource::GetHandle(ppSRVs[i]);
+ pD3D12Shader->BindShaderResource(i, handle);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void DisableShaderD3D12(RenderInterface::SHADER_TYPE st)
+{
+ D3D12RenderShader* pD3D12Shader = GetShaderD3D12(st);
+ if (!pD3D12Shader)
+ return;
+
+ pD3D12Shader->Disable();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void CopyShaderParamD3D12(SHADER_TYPE st, void* pSysMem, unsigned int bytes, unsigned int slot)
+{
+ D3D12RenderShader* pD3D12Shader = GetShaderD3D12(st);
+ if (!pD3D12Shader)
+ return;
+
+ void* mappedParam = pD3D12Shader->MapParam(slot);
+
+ memcpy(mappedParam, pSysMem, bytes);
+
+ pD3D12Shader->UnmapParam(slot);
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Shaders.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Shaders.h
new file mode 100644
index 0000000..29b0e1b
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Shaders.h
@@ -0,0 +1,42 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "RenderInterface.h"
+#include "RenderPlugin.h"
+///////////////////////////////////////////////////////////////////
+// default shaders
+///////////////////////////////////////////////////////////////////
+CORERENDER_EXPORT bool InitializeShadersD3D12();
+CORERENDER_EXPORT void DestroyShadersD3D12();
+
+CORERENDER_EXPORT void ApplyShaderD3D12(RenderInterface::SHADER_TYPE st);
+CORERENDER_EXPORT void DisableShaderD3D12(RenderInterface::SHADER_TYPE st);
+CORERENDER_EXPORT void BindShaderResourcesD3D12(RenderInterface::SHADER_TYPE st, int numSRVs, GPUShaderResource** ppSRVs);
+CORERENDER_EXPORT void CopyShaderParamD3D12(RenderInterface::SHADER_TYPE st, void* pSysMem, unsigned int bytes, unsigned int slot = 0);
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12ShadowMap.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12ShadowMap.cpp
new file mode 100644
index 0000000..342c6f3
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12ShadowMap.cpp
@@ -0,0 +1,99 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D12ShadowMap.h"
+
+#include "RenderResources.h"
+
+#include "D3D12RenderInterface.h"
+#include "D3D12TextureResource.h"
+#include "D3D12RenderContext.h"
+
+//////////////////////////////////////////////////////////////////////////////
+D3D12ShadowMap::D3D12ShadowMap(int resolution)
+{
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ m_nIndex = pContext->AllocRenderTargetIndex();
+ m_pRenderTarget = pContext->CreateRenderTarget(m_nIndex, resolution, resolution);
+ ID3D12Resource* pTexture = pContext->GetTexture(m_nIndex);
+ int nIndexInHeap = -1;
+ CD3DX12_CPU_DESCRIPTOR_HANDLE handle = pContext->NVHairINT_CreateD3D12Texture(pTexture, nIndexInHeap);
+ m_ShadowResource.m_pResource = pTexture;
+ m_ShadowResource.m_Handle = handle;
+ m_ShadowResource.m_nIndexInHeap = nIndexInHeap;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+D3D12ShadowMap::~D3D12ShadowMap()
+{
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ pContext->NVHairINT_DestroyD3D12Texture(m_ShadowResource.m_nIndexInHeap);
+
+ Release();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void D3D12ShadowMap::Release()
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////
+GPUShaderResource* D3D12ShadowMap::GetShadowSRV()
+{
+ return &m_ShadowResource;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool D3D12ShadowMap::isValid()
+{
+ return m_pRenderTarget != nullptr;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void D3D12ShadowMap::BeginRendering(float clearDepth)
+{
+ if (!isValid())
+ return;
+
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ pContext->ReleaseRenderTarget();
+
+ pContext->AcquireRenderTarget(true, m_nIndex);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void D3D12ShadowMap::EndRendering()
+{
+ if (!isValid())
+ return;
+
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ pContext->ReleaseRenderTarget(m_nIndex);
+
+ pContext->AcquireRenderTarget();
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12ShadowMap.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12ShadowMap.h
new file mode 100644
index 0000000..dabf9a1
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12ShadowMap.h
@@ -0,0 +1,68 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "ShadowMap.h"
+
+#include <d3d11.h>
+#include <d3d12.h>
+#include "D3D12TextureResource.h"
+
+#include "DXUT.h" // DXUT header
+#include "d3dx12.h"
+
+#include "D3D12RenderTarget.h"
+
+using namespace Microsoft::WRL;
+
+class GPUShaderResource;
+class D3D12TextureResource;
+
+struct D3D12ShadowMap : public ShadowMap
+{
+ D3D12TextureResource m_ShadowResource;
+
+ D3D12RenderTarget* m_pRenderTarget;
+
+public:
+ D3D12ShadowMap(int resolution );
+ ~D3D12ShadowMap();
+
+ void Release();
+ void BeginRendering(float clearDepth);
+ void EndRendering();
+
+ GPUShaderResource* GetShadowSRV();
+
+protected:
+
+ bool isValid();
+ int m_nIndex;
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12TextureResource.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12TextureResource.cpp
new file mode 100644
index 0000000..0247895
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12TextureResource.cpp
@@ -0,0 +1,29 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D12TextureResource.h"
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12TextureResource.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12TextureResource.h
new file mode 100644
index 0000000..b6c7584
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12TextureResource.h
@@ -0,0 +1,89 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "RenderResources.h"
+
+#include "d3d12.h"
+#include "d3dx12.h"
+
+// GPU resources for texture
+struct D3D12TextureResource : public GPUShaderResource
+{
+ ID3D12Resource* m_pResource;
+ CD3DX12_CPU_DESCRIPTOR_HANDLE m_Handle;
+ int m_nIndexInHeap;
+
+public:
+ static GPUShaderResource* Create(
+ ID3D12Resource* pResource,
+ CD3DX12_CPU_DESCRIPTOR_HANDLE handle,
+ int nIndexInHeap) {
+ D3D12TextureResource* pBuffer = new D3D12TextureResource;
+ pBuffer->m_pResource = pResource;
+ pBuffer->m_Handle = handle;
+ pBuffer->m_nIndexInHeap = nIndexInHeap;
+ return pBuffer;
+ }
+
+ static ID3D12Resource* GetResource(GPUShaderResource* pBuffer)
+ {
+ D3D12TextureResource* pD3D12Buffer = dynamic_cast<D3D12TextureResource*>(pBuffer);
+ if (!pD3D12Buffer)
+ return 0;
+ return pD3D12Buffer->m_pResource;
+ }
+
+ static CD3DX12_CPU_DESCRIPTOR_HANDLE GetHandle(GPUShaderResource* pBuffer)
+ {
+ CD3DX12_CPU_DESCRIPTOR_HANDLE handle = {};
+ D3D12TextureResource* pD3D12Buffer = dynamic_cast<D3D12TextureResource*>(pBuffer);
+ if (pD3D12Buffer)
+ handle = pD3D12Buffer->m_Handle;
+ else
+ handle.ptr = 0;
+ return handle;
+ }
+
+ D3D12TextureResource()
+ {
+ m_pResource = 0;
+ }
+
+ void Release()
+ {
+ SAFE_RELEASE(m_pResource);
+ }
+
+ ~D3D12TextureResource()
+ {
+ Release();
+ }
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Util.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Util.cpp
new file mode 100644
index 0000000..695bb41
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Util.cpp
@@ -0,0 +1,386 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include <DirectXTex.h>
+#include "D3D12Util.h"
+
+#include "D3D12Shaders.h"
+#include "D3D12RenderShader.h"
+
+#include "D3DX10tex.h"
+#include "D3DX11tex.h"
+
+#include "D3D12Wrapper.h"
+#include "DXUT.h"
+#include "DXUTgui.h"
+#include "sdkmisc.h"
+#include "D3D12RendererWindow.h"
+#include "SimpleRenderable.h"
+//#include "MeshShaderParam.h"
+#include "D3D12RenderInterface.h"
+#include "D3D12TextureResource.h"
+#include "D3D12RenderContext.h"
+namespace D3D12Util
+{
+ using namespace RenderInterface;
+
+ // D3D hook to render window
+ D3D12RenderWindow* g_pRenderWindow = 0;
+
+///////////////////////////////////////////////////////////////////////////////
+GPUShaderResource*
+ CreateTextureSRV(const char* texturename)
+{
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ if (!pContext)
+ return 0;
+ ID3D12Device* pDevice = pContext->GetDevice();
+ if (!pDevice)
+ return 0;
+ ID3D12GraphicsCommandList* pCommandList = pContext->GetGraphicsCommandList();
+ if (!pCommandList)
+ return 0;
+
+ unsigned char *pSTBIRes = 0;
+ int width = 0;
+ int height = 0;
+
+ size_t nu = strlen(texturename);
+ size_t n = (size_t)MultiByteToWideChar(CP_ACP, 0, (const char *)texturename, (int)nu, NULL, 0);
+ wchar_t* pwstr = new wchar_t[n];
+ MultiByteToWideChar(CP_ACP, 0, (const char *)texturename, (int)nu, pwstr, (int)n);
+ pwstr[n] = 0;
+
+ TexMetadata texMetadata;
+ ScratchImage scratchImage;
+ HRESULT loaded = LoadFromTGAFile(pwstr, &texMetadata, scratchImage);
+
+ if (loaded != S_OK)
+ {
+ loaded = LoadFromWICFile(pwstr, TEX_FILTER_DEFAULT | WIC_FLAGS_ALL_FRAMES, &texMetadata, scratchImage);
+ }
+
+ if (loaded != S_OK)
+ {
+ loaded = LoadFromDDSFile(pwstr, DDS_FLAGS_NONE, &texMetadata, scratchImage);
+ }
+
+ if (loaded == S_OK)
+ {
+ pSTBIRes = scratchImage.GetPixels();
+ width = texMetadata.width;
+ height = texMetadata.height;
+ }
+
+ if (!pSTBIRes)
+ return 0;
+
+ int numMipMaps = 0;
+ {
+ int mipWidth = width;
+ int mipHeight = height;
+ while (mipWidth > 1 || mipHeight > 1)
+ {
+ numMipMaps++;
+ mipWidth >>= 1;
+ mipHeight >>= 1;
+
+ if ((mipWidth * sizeof(uint32_t)) < D3D12_TEXTURE_DATA_PITCH_ALIGNMENT)
+ break;
+ }
+ }
+
+ std::vector<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> layouts(numMipMaps);
+ std::vector<uint64_t> row_sizes_in_bytes(numMipMaps);
+ std::vector<uint32_t> num_rows(numMipMaps);
+
+ auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(
+ DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, (UINT16)numMipMaps, 1, 0, D3D12_RESOURCE_FLAG_NONE,
+ D3D12_TEXTURE_LAYOUT_UNKNOWN, 0);
+
+ uint64_t required_size = 0;
+ pDevice->GetCopyableFootprints(&resourceDesc, 0, numMipMaps, 0, &layouts[0], &num_rows[0], &row_sizes_in_bytes[0], &required_size);
+
+ HRESULT hr;
+ ID3D12Resource* mTextureUpload;
+ ID3D12Resource* mTexture;
+
+ hr = pDevice->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
+ D3D12_HEAP_FLAG_NONE,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_COPY_DEST,
+ nullptr,
+ IID_PPV_ARGS(&mTexture));
+ mTexture->SetName(L"Texture");
+ hr = pDevice->CreateCommittedResource(
+ &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
+ D3D12_HEAP_FLAG_NONE,
+ &CD3DX12_RESOURCE_DESC::Buffer(required_size),
+ D3D12_RESOURCE_STATE_GENERIC_READ,
+ nullptr,
+ IID_PPV_ARGS(&mTextureUpload));
+ mTextureUpload->SetName(L"TextureUpload");
+
+ const int requestedMipLevels = numMipMaps;
+ D3D12_SUBRESOURCE_DATA* initData = new D3D12_SUBRESOURCE_DATA[requestedMipLevels];
+ ZeroMemory(initData, sizeof(D3D12_SUBRESOURCE_DATA)*requestedMipLevels);
+
+ struct Pixel
+ {
+ unsigned char rgba[4];
+ };
+
+ // prepare target buffer just large enough to include all the mip levels
+ Pixel* targets = new Pixel[width*height * 2];
+
+ // copy the first mip level
+ memcpy(targets, pSTBIRes, width*height * 4);
+
+ // current mip level width and height
+ int mipWidth = width;
+ int mipHeight = height;
+
+ // actual mip levels
+ int mipLevels = 0;
+
+ // current data
+ Pixel* source = targets;
+ Pixel* target = nullptr;
+
+ for (int idx = 0; idx < requestedMipLevels; ++idx)
+ {
+ // set initData
+ initData[idx].pData = source;
+ initData[idx].RowPitch = mipWidth * 4;
+ mipLevels++;
+
+ // skip generating mip for 1x1
+ if ((mipWidth == 1) && (mipHeight == 1))
+ break;
+
+ // skip generating mip for the last level
+ if (idx == (requestedMipLevels - 1))
+ break;
+
+ // buffer for the next mip level
+ target = &source[mipWidth*mipHeight];
+
+ const int prevWidth = mipWidth; // previous mip's width
+
+ // generate the next mip level
+ mipWidth = max(1, mipWidth >> 1);
+ mipHeight = max(1, mipHeight >> 1);
+
+ Pixel samples[4];
+
+ for (int y = 0; y < mipHeight; ++y)
+ {
+ for (int x = 0; x < mipWidth; ++x)
+ {
+ const int px = x * 2; // x in previous mip
+ const int py = y * 2; // y in previous mip
+
+ samples[0] = source[py*prevWidth + px]; // left top
+ samples[1] = source[py*prevWidth + px + 1]; // right top
+ samples[2] = source[(py + 1)*prevWidth + px]; // left bottom
+ samples[3] = source[(py + 1)*prevWidth + px + 1]; // right bottom
+
+ // for each component
+ for (int comp = 0; comp < 4; ++comp)
+ {
+ // do the linear box filter for lower mip level
+ target[y*mipWidth + x].rgba[comp] = (samples[0].rgba[comp] + samples[1].rgba[comp] + samples[2].rgba[comp] + samples[3].rgba[comp]) / 4;
+ }
+ }
+ }
+
+ // update source
+ source = target;
+ }
+
+ uint8_t* p;
+ mTextureUpload->Map(0, nullptr, reinterpret_cast<void**>(&p));
+ for (uint32_t i = 0; i < numMipMaps; ++i)
+ {
+ memcpy(p + layouts[i].Offset, initData[i].pData, layouts[i].Footprint.RowPitch * num_rows[i]);
+ }
+ mTextureUpload->Unmap(0, nullptr);
+
+ for (uint32_t i = 0; i < numMipMaps; ++i)
+ {
+ D3D12_TEXTURE_COPY_LOCATION src;
+ src.pResource = mTextureUpload;
+ src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ src.PlacedFootprint = layouts[i];
+
+ D3D12_TEXTURE_COPY_LOCATION dst;
+ dst.pResource = mTexture;
+ dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ dst.SubresourceIndex = i;
+ pCommandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
+ }
+ pCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mTexture, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE));
+
+ delete initData;
+ delete targets;
+
+ int nIndexInHeap = -1;
+ CD3DX12_CPU_DESCRIPTOR_HANDLE handle = pContext->NVHairINT_CreateD3D12Texture(mTexture, nIndexInHeap);
+ return D3D12TextureResource::Create(mTexture, handle, nIndexInHeap);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+bool GetDeviceInfoString(wchar_t *str)
+{
+ ID3D11Device* pDevice = nullptr;// RenderInterfaceD3D12::GetDevice();
+ if (!pDevice)
+ return false;
+
+ {
+ IDXGIDevice1 *pDXGIDevice1 = NULL;
+ pDevice->QueryInterface(__uuidof(IDXGIDevice1), reinterpret_cast<void **>(&pDXGIDevice1));
+
+ IDXGIAdapter1 *pDXGIAdapter1 = NULL;
+ pDXGIDevice1->GetParent(__uuidof(IDXGIAdapter1), reinterpret_cast<void **>(&pDXGIAdapter1));
+
+ if (pDXGIAdapter1)
+ {
+ auto adapterDescription = DXGI_ADAPTER_DESC1();
+ pDXGIAdapter1->GetDesc1(&adapterDescription);
+
+ WCHAR* pDescStr = adapterDescription.Description;
+ float memInGB = float(adapterDescription.DedicatedVideoMemory) / 1e9f;
+ swprintf_s(str, 1000, L"%s(%.1fGb)\n", pDescStr, memInGB);
+ }
+ }
+
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Render window interafce
+/////////////////////////////////////////////////////////////////////////////////////////
+bool CreateRenderWindow(HWND hWnd, int nSamples)
+{
+ SAFE_DELETE(g_pRenderWindow);
+
+ g_pRenderWindow = new D3D12RenderWindow;
+ return g_pRenderWindow->Create(hWnd, nSamples);
+}
+
+D3DHandles& GetDeviceHandles(D3DHandles& deviceHandles)
+{
+ /*
+ deviceHandles.pAdapter = RenderInterfaceD3D11::GetAdapter();
+ deviceHandles.pFactory = RenderInterfaceD3D11::GetDXGIFactory();
+ deviceHandles.pDevice = RenderInterfaceD3D11::GetDevice();
+ deviceHandles.pDeviceContext = RenderInterfaceD3D11::GetDeviceContext();
+
+ deviceHandles.pDXGISwapChain = g_pRenderWindow->m_pDXGISwapChain;
+ deviceHandles.pD3D11BackBuffer = g_pRenderWindow->m_pD3D11BackBuffer;
+ deviceHandles.pD3D11RenderTargetView = g_pRenderWindow->m_pD3D11RenderTargetView;
+ deviceHandles.pD3D11DepthBuffer = g_pRenderWindow->m_pD3D11DepthBuffer;
+ deviceHandles.pD3D11DepthStencilView = g_pRenderWindow->m_pD3D11DepthStencilView;
+ */
+ return deviceHandles;
+}
+
+void DestroyRenderWindow()
+{
+ SAFE_DELETE(g_pRenderWindow);
+}
+
+bool ResizeRenderWindow(int w, int h)
+{
+ if (!g_pRenderWindow)
+ return false;
+
+ return g_pRenderWindow->Resize(w,h);
+}
+
+void PresentRenderWindow()
+{
+ if (!g_pRenderWindow)
+ return;
+
+ g_pRenderWindow->Present();
+}
+
+void ClearRenderWindow(float r, float g, float b)
+{
+ if (!g_pRenderWindow)
+ return;
+
+ g_pRenderWindow->Clear(r,g,b);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Text draw helper functions (using DXUT)
+/////////////////////////////////////////////////////////////////////////////////////////
+void TxtHelperBegin()
+{
+ if (!g_pRenderWindow || !g_pRenderWindow->m_pTextHelper)
+ return;
+
+ g_pRenderWindow->m_pTextHelper->Begin();
+}
+
+void TxtHelperEnd()
+{
+ if (!g_pRenderWindow || !g_pRenderWindow->m_pTextHelper)
+ return;
+
+ g_pRenderWindow->m_pTextHelper->End();
+}
+
+void TxtHelperSetInsertionPos(int x, int y)
+{
+ if (!g_pRenderWindow || !g_pRenderWindow->m_pTextHelper)
+ return;
+
+ g_pRenderWindow->m_pTextHelper->SetInsertionPos(x, y);
+}
+
+void TxtHelperSetForegroundColor(float r, float g, float b, float a)
+{
+ if (!g_pRenderWindow || !g_pRenderWindow->m_pTextHelper)
+ return;
+
+ g_pRenderWindow->m_pTextHelper->SetForegroundColor(DirectX::XMFLOAT4(r,g,b,a));
+}
+
+void TxtHelperDrawTextLine(wchar_t* str)
+{
+ if (!g_pRenderWindow || !g_pRenderWindow->m_pTextHelper)
+ return;
+
+ g_pRenderWindow->m_pTextHelper->DrawTextLine(str);
+}
+
+} // end namespace \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Util.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Util.h
new file mode 100644
index 0000000..f83b063
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Util.h
@@ -0,0 +1,68 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include <d3d12.h>
+
+#include "RenderPlugin.h"
+
+class GPUShaderResource;
+
+namespace D3D12Util
+{
+ ///////////////////////////////////////////////////////////////////
+ // render window management
+ ///////////////////////////////////////////////////////////////////
+ D3DHandles& GetDeviceHandles(D3DHandles& deviceHandles);
+ bool CreateRenderWindow(HWND hWnd, int nSamples);
+ void DestroyRenderWindow();
+ bool ResizeRenderWindow(int w, int h);
+ void PresentRenderWindow();
+ void ClearRenderWindow(float r, float g, float b);
+
+ ///////////////////////////////////////////////////////////////////
+ // background textures
+ bool LoadBackgroundTexture(const char* filePath);
+ void RenderBackgroundTexture();
+ void ClearBackgroundTexture();
+ GPUShaderResource* CreateTextureSRV(const char* texturename);
+
+ ///////////////////////////////////////////////////////////////////
+ bool GetDeviceInfoString(wchar_t *str);
+
+ ///////////////////////////////////////////////////////////////////
+ // text helpers
+ void TxtHelperBegin();
+ void TxtHelperEnd();
+ void TxtHelperSetInsertionPos(int x, int y);
+ void TxtHelperSetForegroundColor(float r, float g, float b, float a = 1.0f);
+ void TxtHelperDrawTextLine(wchar_t* str);
+
+
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Wrapper.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Wrapper.cpp
new file mode 100644
index 0000000..b534a36
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Wrapper.cpp
@@ -0,0 +1,33 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "D3D12Wrapper.h"
+
+namespace D3DWrapper
+{
+
+} // end namespace \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Wrapper.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Wrapper.h
new file mode 100644
index 0000000..dc81e34
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/D3D12Wrapper.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <d3d11.h>
+
+namespace D3DWrapper
+{
+ inline void SetDebugName(ID3D11DeviceChild* pResource, const char *name)
+ {
+ if (pResource) pResource->SetPrivateData( WKPDID_D3DDebugObjectName, strlen(name), name);
+ }
+}
+
+#define SET_D3D_DEBUG_NAME(x, name) D3DWrapper::SetDebugName(x, name);
+#define SET_D3D_DEBUG_NAME_VAR(x) D3DWrapper::SetDebugName(x, #x);
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/RenderPluginDx12.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/RenderPluginDx12.cpp
new file mode 100644
index 0000000..9945d7c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/RenderPluginDx12.cpp
@@ -0,0 +1,343 @@
+#include "RenderPluginDx12.h"
+
+#include "D3D12RenderInterface.h"
+#include "D3D12Util.h"
+#include "D3D12Shaders.h"
+#include "D3D12GPUProfiler.h"
+#include "D3D12ShadowMap.h"
+#include "D3D12RenderContext.h"
+
+RenderPlugin* CreateRenderPlugin(void)
+{
+ return new RenderPluginDx12;
+}
+
+RenderPluginDx12::RenderPluginDx12()
+{
+ m_RenderApi = "Dx12";
+}
+
+RenderPluginDx12::~RenderPluginDx12()
+{
+}
+
+// interface
+bool RenderPluginDx12::InitDevice(int deviceID)
+{
+ return RenderInterfaceD3D12::InitDevice(deviceID);
+}
+
+bool RenderPluginDx12::Initialize()
+{
+ return RenderInterfaceD3D12::Initialize();
+}
+
+void RenderPluginDx12::Shutdown()
+{
+ D3D12Util::DestroyRenderWindow();
+ RenderInterfaceD3D12::Shutdown();
+}
+
+void RenderPluginDx12::CopyToDevice(GPUBufferResource *pDevicePtr,
+ void* pSysMem, unsigned int ByteWidth)
+{
+ RenderInterfaceD3D12::CopyToDevice(pDevicePtr, pSysMem, ByteWidth);
+}
+
+void RenderPluginDx12::ApplyDepthStencilState(DEPTH_STENCIL_STATE state)
+{
+ RenderInterfaceD3D12::ApplyDepthStencilState(state);
+}
+
+void RenderPluginDx12::ApplyRasterizerState(RASTERIZER_STATE state)
+{
+ RenderInterfaceD3D12::ApplyRasterizerState(state);
+}
+
+void RenderPluginDx12::ApplySampler(int slot, SAMPLER_TYPE state)
+{
+}
+
+void RenderPluginDx12::ApplyBlendState(BLEND_STATE state)
+{
+ RenderInterfaceD3D12::ApplyBlendState(state);
+}
+
+void RenderPluginDx12::GetViewport(Viewport& vp)
+{
+ RenderInterfaceD3D12::GetViewport(vp);
+}
+
+void RenderPluginDx12::SetViewport(const Viewport& vp)
+{
+ RenderInterfaceD3D12::SetViewport(vp);
+}
+
+void RenderPluginDx12::BindVertexShaderResources(int startSlot,
+ int numSRVs, GPUShaderResource** ppSRVs)
+{
+}
+
+void RenderPluginDx12::BindPixelShaderResources(int startSlot,
+ int numSRVs, GPUShaderResource** ppSRVs)
+{
+}
+
+void RenderPluginDx12::ClearVertexShaderResources(int startSlot, int numSRVs)
+{
+}
+
+void RenderPluginDx12::ClearPixelShaderResources(int startSlot, int numSRVs)
+{
+}
+
+void RenderPluginDx12::ClearInputLayout()
+{
+}
+
+void RenderPluginDx12::SetVertexBuffer(GPUBufferResource* pBuffer, UINT stride, UINT offset)
+{
+ RenderInterfaceD3D12::SetVertexBuffer(pBuffer, stride, offset);
+}
+
+void RenderPluginDx12::SetPrimitiveTopologyTriangleStrip()
+{
+ RenderInterfaceD3D12::SetPrimitiveTopologyTriangleStrip();
+}
+
+void RenderPluginDx12::SetPrimitiveTopologyTriangleList()
+{
+ RenderInterfaceD3D12::SetPrimitiveTopologyTriangleList();
+}
+
+void RenderPluginDx12::SetPrimitiveTopologyLineList()
+{
+ RenderInterfaceD3D12::SetPrimitiveTopologyLineList();
+}
+
+void RenderPluginDx12::Draw(unsigned int vertexCount, unsigned int startCount)
+{
+ RenderInterfaceD3D12::Draw(vertexCount, startCount);
+}
+
+GPUBufferResource* RenderPluginDx12::CreateVertexBuffer(unsigned int ByteWidth, void* pSysMem)
+{
+ return RenderInterfaceD3D12::CreateVertexBuffer(ByteWidth, pSysMem);
+}
+
+GPUShaderResource* RenderPluginDx12::CreateShaderResource(unsigned int stride,
+ unsigned int numElements, void* pSysMem, NVHairReadOnlyBuffer* pReadOnlyBuffer)
+{
+ return RenderInterfaceD3D12::CreateShaderResource(stride, numElements, pSysMem, pReadOnlyBuffer);
+}
+
+void RenderPluginDx12::ApplyForShadow(int ForShadow)
+{
+ RenderInterfaceD3D12::ApplyForShadow(ForShadow);
+}
+
+void RenderPluginDx12::SwitchToDX11()
+{
+ RenderInterfaceD3D12::SwitchToDX11();
+}
+
+void RenderPluginDx12::FlushDX11()
+{
+ RenderInterfaceD3D12::FlushDX11();
+}
+
+void RenderPluginDx12::FlushDX12()
+{
+ RenderInterfaceD3D12::FlushDX12();
+}
+
+void RenderPluginDx12::ApplyPrimitiveTopologyLine()
+{
+ RenderInterfaceD3D12::ApplyPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE);
+}
+
+void RenderPluginDx12::ApplyPrimitiveTopologyTriangle()
+{
+ RenderInterfaceD3D12::ApplyPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);
+}
+
+void RenderPluginDx12::SubmitGpuWork()
+{
+ RenderInterfaceD3D12::SubmitGpuWork();
+}
+
+void RenderPluginDx12::WaitForGpu()
+{
+ RenderInterfaceD3D12::WaitForGpu();
+}
+
+// util
+bool RenderPluginDx12::CreateRenderWindow(HWND hWnd, int nSamples)
+{
+ return D3D12Util::CreateRenderWindow(hWnd, nSamples);
+}
+
+bool RenderPluginDx12::ResizeRenderWindow(int w, int h)
+{
+ return D3D12Util::ResizeRenderWindow(w, h);
+}
+
+void RenderPluginDx12::PresentRenderWindow()
+{
+ D3D12Util::PresentRenderWindow();
+}
+
+void RenderPluginDx12::ClearRenderWindow(float r, float g, float b)
+{
+ D3D12Util::ClearRenderWindow(r, g, b);
+}
+
+bool RenderPluginDx12::GetDeviceInfoString(wchar_t *str)
+{
+ return D3D12Util::GetDeviceInfoString(str);
+}
+
+GPUShaderResource* RenderPluginDx12::CreateTextureSRV(const char* texturename)
+{
+ return D3D12Util::CreateTextureSRV(texturename);
+}
+
+void RenderPluginDx12::TxtHelperBegin()
+{
+ D3D12Util::TxtHelperBegin();
+}
+
+void RenderPluginDx12::TxtHelperEnd()
+{
+ D3D12Util::TxtHelperEnd();
+}
+
+void RenderPluginDx12::TxtHelperSetInsertionPos(int x, int y)
+{
+ D3D12Util::TxtHelperSetInsertionPos(x, y);
+}
+
+void RenderPluginDx12::TxtHelperSetForegroundColor(float r, float g, float b, float a)
+{
+ D3D12Util::TxtHelperSetForegroundColor(r, g, b, a);
+}
+
+void RenderPluginDx12::TxtHelperDrawTextLine(wchar_t* str)
+{
+ D3D12Util::TxtHelperDrawTextLine(str);
+}
+
+// shader
+bool RenderPluginDx12::InitializeShaders()
+{
+ return InitializeShadersD3D12();
+}
+
+void RenderPluginDx12::DestroyShaders()
+{
+ DestroyShadersD3D12();
+}
+
+void RenderPluginDx12::ApplyShader(SHADER_TYPE st)
+{
+ ApplyShaderD3D12(st);
+}
+
+void RenderPluginDx12::DisableShader(SHADER_TYPE st)
+{
+ DisableShaderD3D12(st);
+}
+
+void RenderPluginDx12::BindShaderResources(SHADER_TYPE st, int numSRVs, GPUShaderResource** ppSRVs)
+{
+ BindShaderResourcesD3D12(st, numSRVs, ppSRVs);
+}
+
+void RenderPluginDx12::CopyShaderParam(SHADER_TYPE st,
+ void* pSysMem, unsigned int bytes, unsigned int slot)
+{
+ CopyShaderParamD3D12(st, pSysMem, bytes, slot);
+}
+
+// GPUProfiler
+GPUProfiler* RenderPluginDx12::CreateGPUProfiler()
+{
+ GPUProfiler* pProfiler = new D3D12GPUProfiler;
+ pProfiler->Initialize();
+ return pProfiler;
+}
+
+// ShadowMap
+ShadowMap* RenderPluginDx12::CreateShadowMap(int resolution)
+{
+ return new D3D12ShadowMap(resolution);
+}
+
+// D3D12RenderContext
+void RenderPluginDx12::PreRender()
+{
+ D3D12RenderContext::Instance()->PreRender();
+}
+
+void RenderPluginDx12::PostRender()
+{
+ D3D12RenderContext::Instance()->PostRender();
+}
+
+// GPUMeshResources
+#include "MeshData.h"
+#include "AnimUtil.h"
+
+class GPUMeshResourcesDx12 : public GPUMeshResources
+{
+public:
+ NVHairReadOnlyBuffer m_BoneIndicesBuffer;
+ NVHairReadOnlyBuffer m_BoneWeightsBuffer;
+};
+
+GPUMeshResources* RenderPluginDx12::GPUMeshResourcesCreate(MeshData* pMeshData, const SkinData& skinData)
+{
+ GPUMeshResources* resources = new GPUMeshResourcesDx12;
+
+ int numIndices = pMeshData->m_NumIndices;
+ int numVertices = pMeshData->m_NumVertices;
+
+ resources->m_pVertexBuffer = CreateVertexBuffer(
+ sizeof(MeshData::MeshVertex) * numIndices, pMeshData->m_pMeshVertices);
+
+ GPUMeshResourcesDx12* resourceDx12 = (GPUMeshResourcesDx12*)resources;
+ if (NULL != resourceDx12)
+ {
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ pContext->InitBuffer(resourceDx12->m_BoneIndicesBuffer);
+ pContext->InitBuffer(resourceDx12->m_BoneWeightsBuffer);
+ resources->m_pBoneIndicesSRV = CreateShaderResource(
+ sizeof(atcore_float4), numVertices, skinData.m_pBoneIndices, &resourceDx12->m_BoneIndicesBuffer);
+ resources->m_pBoneWeightsSRV = CreateShaderResource(
+ sizeof(atcore_float4), numVertices, skinData.m_pBoneWeights, &resourceDx12->m_BoneWeightsBuffer);
+ }
+
+ return resources;
+}
+
+void RenderPluginDx12::GPUMeshResourcesRelease(GPUMeshResources* pResource)
+{
+ SAFE_RELEASE(pResource->m_pVertexBuffer);
+ SAFE_RELEASE(pResource->m_pBoneIndicesSRV);
+ SAFE_RELEASE(pResource->m_pBoneWeightsSRV);
+
+ GPUMeshResourcesDx12* pResourceDx12 = (GPUMeshResourcesDx12*)pResource;
+ if (NULL == pResourceDx12)
+ {
+ return;
+ }
+
+ D3D12RenderContext* pContext = D3D12RenderContext::Instance();
+ pContext->DestroyBuffer(pResourceDx12->m_BoneIndicesBuffer);
+ pContext->DestroyBuffer(pResourceDx12->m_BoneWeightsBuffer);
+}
+
+D3DHandles& RenderPluginDx12::GetDeviceHandles(D3DHandles& deviceHandles)
+{
+ return D3D12Util::GetDeviceHandles(deviceHandles);
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/RenderPluginDx12.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/RenderPluginDx12.h
new file mode 100644
index 0000000..a88dfbf
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/D3D12/RenderPluginDx12.h
@@ -0,0 +1,83 @@
+#pragma once
+
+#include "RenderPlugin.h"
+
+extern "C" CORERENDER_EXPORT RenderPlugin* CreateRenderPlugin(void);
+
+class CORERENDER_EXPORT RenderPluginDx12 : public RenderPlugin
+{
+public:
+ RenderPluginDx12();
+ ~RenderPluginDx12();
+
+ // interface
+ virtual bool InitDevice(int deviceID);
+ virtual bool Initialize();
+ virtual void Shutdown();
+ virtual void CopyToDevice(GPUBufferResource *pDevicePtr, void* pSysMem, unsigned int ByteWidth);
+ virtual void ApplyDepthStencilState(DEPTH_STENCIL_STATE state);
+ virtual void ApplyRasterizerState(RASTERIZER_STATE state);
+ virtual void ApplySampler(int slot, SAMPLER_TYPE st);
+ virtual void ApplyBlendState(BLEND_STATE st);
+ virtual void GetViewport(Viewport& vp);
+ virtual void SetViewport(const Viewport& vp);
+ virtual void BindVertexShaderResources(int startSlot, int numSRVs, GPUShaderResource** ppSRVs);
+ virtual void BindPixelShaderResources(int startSlot, int numSRVs, GPUShaderResource** ppSRVs);
+ virtual void ClearVertexShaderResources(int startSlot, int numSRVs);
+ virtual void ClearPixelShaderResources(int startSlot, int numSRVs);
+ virtual void ClearInputLayout();
+ virtual void SetVertexBuffer(GPUBufferResource* pBuffer, UINT stride, UINT offset = 0);
+ virtual void SetPrimitiveTopologyTriangleStrip();
+ virtual void SetPrimitiveTopologyTriangleList();
+ virtual void SetPrimitiveTopologyLineList();
+ virtual void Draw(unsigned int vertexCount, unsigned int startCount = 0);
+ virtual GPUBufferResource* CreateVertexBuffer(unsigned int ByteWidth, void* pSysMem = 0);
+ virtual GPUShaderResource* CreateShaderResource(unsigned int stride, unsigned int numElements, void* pSysMem, NVHairReadOnlyBuffer* pReadOnlyBuffer = NULL);
+ virtual void ApplyForShadow(int ForShadow);
+ virtual void SwitchToDX11();
+ virtual void FlushDX11();
+ virtual void FlushDX12();
+ virtual void ApplyPrimitiveTopologyLine();
+ virtual void ApplyPrimitiveTopologyTriangle();
+ virtual void SubmitGpuWork();
+ virtual void WaitForGpu();
+
+ // util
+ virtual bool CreateRenderWindow(HWND hWnd, int nSamples);
+ virtual bool ResizeRenderWindow(int w, int h);
+ virtual void PresentRenderWindow();
+ virtual void ClearRenderWindow(float r, float g, float b);
+ virtual bool GetDeviceInfoString(wchar_t *str);
+ virtual GPUShaderResource* CreateTextureSRV(const char* texturename);
+ virtual void TxtHelperBegin();
+ virtual void TxtHelperEnd();
+ virtual void TxtHelperSetInsertionPos(int x, int y);
+ virtual void TxtHelperSetForegroundColor(float r, float g, float b, float a = 1.0f);
+ virtual void TxtHelperDrawTextLine(wchar_t* str);
+
+ // shader
+ virtual bool InitializeShaders();
+ virtual void DestroyShaders();
+ virtual void ApplyShader(SHADER_TYPE st);
+ virtual void DisableShader(SHADER_TYPE st);
+ virtual void BindShaderResources(SHADER_TYPE st, int numSRVs, GPUShaderResource** ppSRVs);
+ virtual void CopyShaderParam(SHADER_TYPE st, void* pSysMem, unsigned int bytes, unsigned int slot = 0);
+
+ // GPUProfiler
+ virtual GPUProfiler* CreateGPUProfiler();
+
+ // ShadowMap
+ virtual ShadowMap* CreateShadowMap(int resolution);
+
+ // D3D12RenderContext
+ virtual void PreRender();
+ virtual void PostRender();
+
+ // GPUMeshResources
+ virtual GPUMeshResources* GPUMeshResourcesCreate(MeshData* pMeshData, const SkinData& skinData);
+ virtual void GPUMeshResourcesRelease(GPUMeshResources* pResource);
+
+ // Get devices related
+ virtual D3DHandles& GetDeviceHandles(D3DHandles& deviceHandles);
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/GPUProfiler.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/GPUProfiler.cpp
new file mode 100644
index 0000000..08a3497
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/GPUProfiler.cpp
@@ -0,0 +1,87 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "GPUProfiler.h"
+
+#include "RenderPlugin.h"
+
+#ifndef SAFE_DELETE
+#define SAFE_DELETE(x) {if(x){delete x; x=nullptr;}}
+#endif
+
+GPUProfiler* g_pGPUProfiler = 0;
+
+void GPUProfiler_Initialize()
+{
+ g_pGPUProfiler = RenderPlugin::Instance()->CreateGPUProfiler();
+}
+
+void GPUProfiler_Shutdown()
+{
+ SAFE_DELETE(g_pGPUProfiler);
+}
+
+void GPUProfiler_Enable(bool b)
+{
+ if (g_pGPUProfiler)
+ g_pGPUProfiler->Enable(b);
+}
+
+void GPUProfiler_StartFrame()
+{
+ if (g_pGPUProfiler)
+ g_pGPUProfiler->StartFrame();
+}
+
+void GPUProfiler_EndFrame()
+{
+ if (g_pGPUProfiler)
+ g_pGPUProfiler->EndFrame();
+}
+
+void GPUProfiler_StartProfile(int id)
+{
+ if (g_pGPUProfiler)
+ g_pGPUProfiler->StartProfile(id);
+}
+
+void GPUProfiler_EndProfile(int id)
+{
+ if (g_pGPUProfiler)
+ g_pGPUProfiler->EndProfile(id);
+}
+
+float GPUProfiler_GetProfileData(int id)
+{
+ if (!g_pGPUProfiler)
+ return 0;
+
+ return g_pGPUProfiler->GetProfileData(id);
+}
+
+
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/GPUProfiler.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/GPUProfiler.h
new file mode 100644
index 0000000..65bb602
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/GPUProfiler.h
@@ -0,0 +1,61 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "corelib_global.h"
+
+struct CORELIB_EXPORT GPUProfiler
+{
+ bool m_enable;
+
+public:
+ // define base class virtual destructor to make sure child classes call destructor right.
+ virtual ~GPUProfiler() {}
+
+ void Enable(bool b) { m_enable = b; }
+
+ virtual void Initialize() = 0;
+ virtual void Release() = 0;
+ virtual void StartFrame() = 0;
+ virtual void EndFrame() = 0;
+ virtual void StartProfile(int id) = 0;
+ virtual void EndProfile(int id) = 0;
+ virtual float GetProfileData(int id) = 0;
+};
+
+// helper functions
+CORELIB_EXPORT void GPUProfiler_Initialize();
+CORELIB_EXPORT void GPUProfiler_Enable(bool);
+CORELIB_EXPORT void GPUProfiler_Shutdown();
+CORELIB_EXPORT void GPUProfiler_StartFrame();
+CORELIB_EXPORT void GPUProfiler_EndFrame();
+CORELIB_EXPORT void GPUProfiler_StartProfile(int id);
+CORELIB_EXPORT void GPUProfiler_EndProfile(int id);
+CORELIB_EXPORT float GPUProfiler_GetProfileData(int id);
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/BoneGeometryData.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/BoneGeometryData.h
new file mode 100644
index 0000000..4a6ea37
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/BoneGeometryData.h
@@ -0,0 +1,305 @@
+const int num_faces = 100;
+
+// pos.xyz, uv.uv, normal.xyz
+float vertices[100*3*8] = {
+0.250000, -0.951057, -0.181636, 0.000000, 0.900000, 0.277578, -0.881468, -0.382053,
+0.095491, -0.951057, -0.293893, 0.100000, 0.900000, 0.277578, -0.881468, -0.382053,
+0.181636, -0.809017, -0.559017, 0.100000, 0.800000, 0.277578, -0.881468, -0.382053,
+0.095491, -0.951057, -0.293893, 0.100000, 0.900000, -0.000000, -0.881468, -0.472244,
+-0.095492, -0.951057, -0.293893, 0.200000, 0.900000, -0.000000, -0.881468, -0.472244,
+-0.181636, -0.809017, -0.559017, 0.200000, 0.800000, -0.000000, -0.881468, -0.472244,
+-0.095492, -0.951057, -0.293893, 0.200000, 0.900000, -0.277578, -0.881468, -0.382053,
+-0.250000, -0.951057, -0.181636, 0.300000, 0.900000, -0.277578, -0.881468, -0.382053,
+-0.475528, -0.809017, -0.345491, 0.300000, 0.800000, -0.277578, -0.881468, -0.382053,
+-0.250000, -0.951057, -0.181636, 0.300000, 0.900000, -0.449130, -0.881468, -0.145931,
+-0.309017, -0.951057, 0.000000, 0.400000, 0.900000, -0.449130, -0.881468, -0.145931,
+-0.587785, -0.809017, 0.000000, 0.400000, 0.800000, -0.449130, -0.881468, -0.145931,
+-0.309017, -0.951057, 0.000000, 0.400000, 0.900000, -0.449130, -0.881468, 0.145931,
+-0.250000, -0.951057, 0.181636, 0.500000, 0.900000, -0.449130, -0.881468, 0.145931,
+-0.475528, -0.809017, 0.345492, 0.500000, 0.800000, -0.449130, -0.881468, 0.145931,
+-0.250000, -0.951057, 0.181636, 0.500000, 0.900000, -0.277578, -0.881468, 0.382053,
+-0.095491, -0.951057, 0.293893, 0.600000, 0.900000, -0.277578, -0.881468, 0.382053,
+-0.181636, -0.809017, 0.559017, 0.600000, 0.800000, -0.277578, -0.881468, 0.382053,
+-0.095491, -0.951057, 0.293893, 0.600000, 0.900000, 0.000000, -0.881468, 0.472244,
+0.095492, -0.951057, 0.293893, 0.700000, 0.900000, 0.000000, -0.881468, 0.472244,
+0.181636, -0.809017, 0.559017, 0.700000, 0.800000, 0.000000, -0.881468, 0.472244,
+0.095492, -0.951057, 0.293893, 0.700000, 0.900000, 0.277578, -0.881468, 0.382053,
+0.250000, -0.951057, 0.181636, 0.800000, 0.900000, 0.277578, -0.881468, 0.382053,
+0.475528, -0.809017, 0.345491, 0.800000, 0.800000, 0.277578, -0.881468, 0.382053,
+0.250000, -0.951057, 0.181636, 0.800000, 0.900000, 0.449130, -0.881468, 0.145931,
+0.309017, -0.951057, 0.000000, 0.900000, 0.900000, 0.449130, -0.881468, 0.145931,
+0.587785, -0.809017, 0.000000, 0.900000, 0.800000, 0.449131, -0.881468, 0.145931,
+0.309017, -0.951057, 0.000000, 0.900000, 0.900000, 0.449131, -0.881468, -0.145931,
+0.250000, -0.951057, -0.181636, 1.000000, 0.900000, 0.449131, -0.881468, -0.145931,
+0.475528, -0.809017, -0.345492, 1.000000, 0.800000, 0.449131, -0.881468, -0.145931,
+0.475528, -0.809017, -0.345492, 0.000000, 0.800000, 0.425919, -0.689152, -0.586227,
+0.181636, -0.809017, -0.559017, 0.100000, 0.800000, 0.425919, -0.689152, -0.586227,
+0.250000, -0.587785, -0.769421, 0.100000, 0.700000, 0.425919, -0.689152, -0.586227,
+0.181636, -0.809017, -0.559017, 0.100000, 0.800000, -0.000000, -0.689152, -0.724617,
+-0.181636, -0.809017, -0.559017, 0.200000, 0.800000, -0.000000, -0.689152, -0.724617,
+-0.250000, -0.587785, -0.769421, 0.200000, 0.700000, -0.000000, -0.689152, -0.724617,
+-0.181636, -0.809017, -0.559017, 0.200000, 0.800000, -0.425919, -0.689152, -0.586228,
+-0.475528, -0.809017, -0.345491, 0.300000, 0.800000, -0.425919, -0.689152, -0.586228,
+-0.654509, -0.587785, -0.475528, 0.300000, 0.700000, -0.425919, -0.689152, -0.586228,
+-0.475528, -0.809017, -0.345491, 0.300000, 0.800000, -0.689152, -0.689152, -0.223919,
+-0.587785, -0.809017, 0.000000, 0.400000, 0.800000, -0.689152, -0.689152, -0.223919,
+-0.809017, -0.587785, 0.000000, 0.400000, 0.700000, -0.689152, -0.689152, -0.223919,
+-0.587785, -0.809017, 0.000000, 0.400000, 0.800000, -0.689152, -0.689152, 0.223919,
+-0.475528, -0.809017, 0.345492, 0.500000, 0.800000, -0.689152, -0.689152, 0.223919,
+-0.654509, -0.587785, 0.475528, 0.500000, 0.700000, -0.689152, -0.689152, 0.223919,
+-0.475528, -0.809017, 0.345492, 0.500000, 0.800000, -0.425919, -0.689152, 0.586228,
+-0.181636, -0.809017, 0.559017, 0.600000, 0.800000, -0.425919, -0.689152, 0.586228,
+-0.250000, -0.587785, 0.769421, 0.600000, 0.700000, -0.425919, -0.689152, 0.586228,
+-0.181636, -0.809017, 0.559017, 0.600000, 0.800000, 0.000000, -0.689152, 0.724617,
+0.181636, -0.809017, 0.559017, 0.700000, 0.800000, 0.000000, -0.689152, 0.724617,
+0.250000, -0.587785, 0.769421, 0.700000, 0.700000, 0.000000, -0.689152, 0.724617,
+0.181636, -0.809017, 0.559017, 0.700000, 0.800000, 0.425919, -0.689152, 0.586227,
+0.475528, -0.809017, 0.345491, 0.800000, 0.800000, 0.425919, -0.689152, 0.586227,
+0.654509, -0.587785, 0.475528, 0.800000, 0.700000, 0.425919, -0.689152, 0.586227,
+0.475528, -0.809017, 0.345491, 0.800000, 0.800000, 0.689152, -0.689152, 0.223919,
+0.587785, -0.809017, 0.000000, 0.900000, 0.800000, 0.689152, -0.689152, 0.223919,
+0.809017, -0.587785, 0.000000, 0.900000, 0.700000, 0.689152, -0.689152, 0.223919,
+0.587785, -0.809017, 0.000000, 0.900000, 0.800000, 0.689152, -0.689152, -0.223919,
+0.475528, -0.809017, -0.345492, 1.000000, 0.800000, 0.689152, -0.689152, -0.223919,
+0.654509, -0.587785, -0.475528, 1.000000, 0.700000, 0.689152, -0.689152, -0.223919,
+0.654509, -0.587785, -0.475528, 0.000000, 0.700000, 0.528952, -0.436083, -0.728040,
+0.250000, -0.587785, -0.769421, 0.100000, 0.700000, 0.528952, -0.436083, -0.728040,
+0.293893, -0.309017, -0.904509, 0.100000, 0.600000, 0.528952, -0.436083, -0.728040,
+0.250000, -0.587785, -0.769421, 0.100000, 0.700000, -0.000000, -0.436083, -0.899906,
+-0.250000, -0.587785, -0.769421, 0.200000, 0.700000, -0.000000, -0.436083, -0.899906,
+-0.293893, -0.309017, -0.904509, 0.200000, 0.600000, -0.000000, -0.436083, -0.899906,
+-0.250000, -0.587785, -0.769421, 0.200000, 0.700000, -0.528952, -0.436083, -0.728040,
+-0.654509, -0.587785, -0.475528, 0.300000, 0.700000, -0.528952, -0.436083, -0.728040,
+-0.769421, -0.309017, -0.559017, 0.300000, 0.600000, -0.528952, -0.436083, -0.728040,
+-0.654509, -0.587785, -0.475528, 0.300000, 0.700000, -0.855862, -0.436083, -0.278086,
+-0.809017, -0.587785, 0.000000, 0.400000, 0.700000, -0.855862, -0.436083, -0.278086,
+-0.951057, -0.309017, 0.000000, 0.400000, 0.600000, -0.855862, -0.436083, -0.278086,
+-0.809017, -0.587785, 0.000000, 0.400000, 0.700000, -0.855862, -0.436083, 0.278086,
+-0.654509, -0.587785, 0.475528, 0.500000, 0.700000, -0.855862, -0.436083, 0.278086,
+-0.769421, -0.309017, 0.559017, 0.500000, 0.600000, -0.855862, -0.436083, 0.278086,
+-0.654509, -0.587785, 0.475528, 0.500000, 0.700000, -0.528952, -0.436083, 0.728040,
+-0.250000, -0.587785, 0.769421, 0.600000, 0.700000, -0.528952, -0.436083, 0.728039,
+-0.293893, -0.309017, 0.904509, 0.600000, 0.600000, -0.528952, -0.436083, 0.728039,
+-0.250000, -0.587785, 0.769421, 0.600000, 0.700000, 0.000000, -0.436083, 0.899906,
+0.250000, -0.587785, 0.769421, 0.700000, 0.700000, 0.000000, -0.436083, 0.899906,
+0.293893, -0.309017, 0.904509, 0.700000, 0.600000, 0.000000, -0.436083, 0.899906,
+0.250000, -0.587785, 0.769421, 0.700000, 0.700000, 0.528952, -0.436083, 0.728039,
+0.654509, -0.587785, 0.475528, 0.800000, 0.700000, 0.528952, -0.436083, 0.728040,
+0.769421, -0.309017, 0.559017, 0.800000, 0.600000, 0.528952, -0.436083, 0.728040,
+0.654509, -0.587785, 0.475528, 0.800000, 0.700000, 0.855862, -0.436083, 0.278086,
+0.809017, -0.587785, 0.000000, 0.900000, 0.700000, 0.855862, -0.436083, 0.278086,
+0.951057, -0.309017, 0.000000, 0.900000, 0.600000, 0.855862, -0.436083, 0.278086,
+0.809017, -0.587785, 0.000000, 0.900000, 0.700000, 0.855862, -0.436084, -0.278086,
+0.654509, -0.587785, -0.475528, 1.000000, 0.700000, 0.855862, -0.436084, -0.278086,
+0.769421, -0.309017, -0.559017, 1.000000, 0.600000, 0.855862, -0.436084, -0.278086,
+0.769421, -0.309017, -0.559017, 0.000000, 0.600000, 0.581228, -0.148952, -0.799992,
+0.293893, -0.309017, -0.904509, 0.100000, 0.600000, 0.581228, -0.148952, -0.799992,
+0.309017, 0.000000, -0.951057, 0.100000, 0.500000, 0.581228, -0.148952, -0.799992,
+0.293893, -0.309017, -0.904509, 0.100000, 0.600000, -0.000000, -0.148952, -0.988844,
+-0.293893, -0.309017, -0.904509, 0.200000, 0.600000, -0.000000, -0.148952, -0.988844,
+-0.309017, 0.000000, -0.951057, 0.200000, 0.500000, -0.000000, -0.148952, -0.988844,
+-0.293893, -0.309017, -0.904509, 0.200000, 0.600000, -0.581228, -0.148952, -0.799992,
+-0.769421, -0.309017, -0.559017, 0.300000, 0.600000, -0.581228, -0.148952, -0.799992,
+-0.809017, 0.000000, -0.587785, 0.300000, 0.500000, -0.581228, -0.148952, -0.799992,
+-0.769421, -0.309017, -0.559017, 0.300000, 0.600000, -0.940447, -0.148952, -0.305570,
+-0.951057, -0.309017, 0.000000, 0.400000, 0.600000, -0.940447, -0.148952, -0.305570,
+-1.000000, 0.000000, 0.000000, 0.400000, 0.500000, -0.940447, -0.148952, -0.305570,
+-0.951057, -0.309017, 0.000000, 0.400000, 0.600000, -0.940447, -0.148952, 0.305570,
+-0.769421, -0.309017, 0.559017, 0.500000, 0.600000, -0.940447, -0.148952, 0.305570,
+-0.809017, 0.000000, 0.587785, 0.500000, 0.500000, -0.940447, -0.148952, 0.305570,
+-0.769421, -0.309017, 0.559017, 0.500000, 0.600000, -0.581228, -0.148952, 0.799992,
+-0.293893, -0.309017, 0.904509, 0.600000, 0.600000, -0.581228, -0.148952, 0.799992,
+-0.309017, 0.000000, 0.951057, 0.600000, 0.500000, -0.581228, -0.148952, 0.799992,
+-0.293893, -0.309017, 0.904509, 0.600000, 0.600000, 0.000000, -0.148952, 0.988844,
+0.293893, -0.309017, 0.904509, 0.700000, 0.600000, 0.000000, -0.148952, 0.988844,
+0.309017, 0.000000, 0.951057, 0.700000, 0.500000, 0.000000, -0.148952, 0.988844,
+0.293893, -0.309017, 0.904509, 0.700000, 0.600000, 0.581228, -0.148952, 0.799992,
+0.769421, -0.309017, 0.559017, 0.800000, 0.600000, 0.581228, -0.148952, 0.799992,
+0.809017, 0.000000, 0.587785, 0.800000, 0.500000, 0.581228, -0.148952, 0.799992,
+0.769421, -0.309017, 0.559017, 0.800000, 0.600000, 0.940447, -0.148952, 0.305570,
+0.951057, -0.309017, 0.000000, 0.900000, 0.600000, 0.940447, -0.148952, 0.305570,
+1.000000, 0.000000, 0.000000, 0.900000, 0.500000, 0.940447, -0.148952, 0.305570,
+0.951057, -0.309017, 0.000000, 0.900000, 0.600000, 0.940447, -0.148952, -0.305570,
+0.769421, -0.309017, -0.559017, 1.000000, 0.600000, 0.940447, -0.148952, -0.305570,
+0.809017, 0.000000, -0.587785, 1.000000, 0.500000, 0.940447, -0.148952, -0.305570,
+0.809017, 0.000000, -0.587785, 0.000000, 0.500000, 0.581228, 0.148952, -0.799992,
+0.309017, 0.000000, -0.951057, 0.100000, 0.500000, 0.581228, 0.148952, -0.799992,
+0.293893, 0.309017, -0.904509, 0.100000, 0.400000, 0.581228, 0.148952, -0.799992,
+0.309017, 0.000000, -0.951057, 0.100000, 0.500000, -0.000000, 0.148952, -0.988844,
+-0.309017, 0.000000, -0.951057, 0.200000, 0.500000, -0.000000, 0.148952, -0.988844,
+-0.293893, 0.309017, -0.904509, 0.200000, 0.400000, -0.000000, 0.148952, -0.988844,
+-0.309017, 0.000000, -0.951057, 0.200000, 0.500000, -0.581228, 0.148952, -0.799992,
+-0.809017, 0.000000, -0.587785, 0.300000, 0.500000, -0.581228, 0.148952, -0.799992,
+-0.769421, 0.309017, -0.559017, 0.300000, 0.400000, -0.581228, 0.148952, -0.799992,
+-0.809017, 0.000000, -0.587785, 0.300000, 0.500000, -0.940447, 0.148952, -0.305570,
+-1.000000, 0.000000, 0.000000, 0.400000, 0.500000, -0.940447, 0.148952, -0.305570,
+-0.951057, 0.309017, 0.000000, 0.400000, 0.400000, -0.940447, 0.148952, -0.305570,
+-1.000000, 0.000000, 0.000000, 0.400000, 0.500000, -0.940447, 0.148952, 0.305570,
+-0.809017, 0.000000, 0.587785, 0.500000, 0.500000, -0.940447, 0.148952, 0.305570,
+-0.769421, 0.309017, 0.559017, 0.500000, 0.400000, -0.940447, 0.148952, 0.305570,
+-0.809017, 0.000000, 0.587785, 0.500000, 0.500000, -0.581228, 0.148952, 0.799992,
+-0.309017, 0.000000, 0.951057, 0.600000, 0.500000, -0.581228, 0.148952, 0.799992,
+-0.293893, 0.309017, 0.904509, 0.600000, 0.400000, -0.581228, 0.148952, 0.799992,
+-0.309017, 0.000000, 0.951057, 0.600000, 0.500000, 0.000000, 0.148952, 0.988844,
+0.309017, 0.000000, 0.951057, 0.700000, 0.500000, 0.000000, 0.148952, 0.988844,
+0.293893, 0.309017, 0.904509, 0.700000, 0.400000, 0.000000, 0.148952, 0.988844,
+0.309017, 0.000000, 0.951057, 0.700000, 0.500000, 0.581228, 0.148952, 0.799992,
+0.809017, 0.000000, 0.587785, 0.800000, 0.500000, 0.581228, 0.148952, 0.799992,
+0.769421, 0.309017, 0.559017, 0.800000, 0.400000, 0.581228, 0.148952, 0.799992,
+0.809017, 0.000000, 0.587785, 0.800000, 0.500000, 0.940447, 0.148952, 0.305570,
+1.000000, 0.000000, 0.000000, 0.900000, 0.500000, 0.940447, 0.148952, 0.305570,
+0.951057, 0.309017, 0.000000, 0.900000, 0.400000, 0.940447, 0.148952, 0.305570,
+1.000000, 0.000000, 0.000000, 0.900000, 0.500000, 0.940447, 0.148952, -0.305570,
+0.809017, 0.000000, -0.587785, 1.000000, 0.500000, 0.940447, 0.148952, -0.305570,
+0.769421, 0.309017, -0.559017, 1.000000, 0.400000, 0.940447, 0.148952, -0.305569,
+0.769421, 0.309017, -0.559017, 0.000000, 0.400000, 0.528952, 0.436083, -0.728040,
+0.293893, 0.309017, -0.904509, 0.100000, 0.400000, 0.528952, 0.436083, -0.728040,
+0.250000, 0.587785, -0.769421, 0.100000, 0.300000, 0.528952, 0.436083, -0.728040,
+0.293893, 0.309017, -0.904509, 0.100000, 0.400000, -0.000000, 0.436083, -0.899906,
+-0.293893, 0.309017, -0.904509, 0.200000, 0.400000, -0.000000, 0.436083, -0.899906,
+-0.250000, 0.587785, -0.769421, 0.200000, 0.300000, -0.000000, 0.436083, -0.899906,
+-0.293893, 0.309017, -0.904509, 0.200000, 0.400000, -0.528952, 0.436083, -0.728039,
+-0.769421, 0.309017, -0.559017, 0.300000, 0.400000, -0.528952, 0.436083, -0.728039,
+-0.654509, 0.587785, -0.475528, 0.300000, 0.300000, -0.528952, 0.436083, -0.728039,
+-0.769421, 0.309017, -0.559017, 0.300000, 0.400000, -0.855862, 0.436083, -0.278086,
+-0.951057, 0.309017, 0.000000, 0.400000, 0.400000, -0.855862, 0.436083, -0.278086,
+-0.809017, 0.587785, 0.000000, 0.400000, 0.300000, -0.855862, 0.436083, -0.278086,
+-0.951057, 0.309017, 0.000000, 0.400000, 0.400000, -0.855862, 0.436083, 0.278086,
+-0.769421, 0.309017, 0.559017, 0.500000, 0.400000, -0.855862, 0.436083, 0.278086,
+-0.654509, 0.587785, 0.475528, 0.500000, 0.300000, -0.855862, 0.436083, 0.278086,
+-0.769421, 0.309017, 0.559017, 0.500000, 0.400000, -0.528952, 0.436083, 0.728039,
+-0.293893, 0.309017, 0.904509, 0.600000, 0.400000, -0.528952, 0.436083, 0.728039,
+-0.250000, 0.587785, 0.769421, 0.600000, 0.300000, -0.528952, 0.436083, 0.728039,
+-0.293893, 0.309017, 0.904509, 0.600000, 0.400000, 0.000000, 0.436083, 0.899906,
+0.293893, 0.309017, 0.904509, 0.700000, 0.400000, 0.000000, 0.436083, 0.899906,
+0.250000, 0.587785, 0.769421, 0.700000, 0.300000, 0.000000, 0.436083, 0.899906,
+0.293893, 0.309017, 0.904509, 0.700000, 0.400000, 0.528952, 0.436083, 0.728040,
+0.769421, 0.309017, 0.559017, 0.800000, 0.400000, 0.528952, 0.436083, 0.728040,
+0.654509, 0.587785, 0.475528, 0.800000, 0.300000, 0.528952, 0.436083, 0.728040,
+0.769421, 0.309017, 0.559017, 0.800000, 0.400000, 0.855862, 0.436083, 0.278086,
+0.951057, 0.309017, 0.000000, 0.900000, 0.400000, 0.855862, 0.436083, 0.278086,
+0.809017, 0.587785, 0.000000, 0.900000, 0.300000, 0.855862, 0.436083, 0.278086,
+0.951057, 0.309017, 0.000000, 0.900000, 0.400000, 0.855862, 0.436084, -0.278086,
+0.769421, 0.309017, -0.559017, 1.000000, 0.400000, 0.855862, 0.436084, -0.278086,
+0.654509, 0.587785, -0.475528, 1.000000, 0.300000, 0.855862, 0.436084, -0.278086,
+0.654509, 0.587785, -0.475528, 0.000000, 0.300000, 0.425919, 0.689152, -0.586227,
+0.250000, 0.587785, -0.769421, 0.100000, 0.300000, 0.425919, 0.689152, -0.586227,
+0.181636, 0.809017, -0.559017, 0.100000, 0.200000, 0.425919, 0.689152, -0.586227,
+0.250000, 0.587785, -0.769421, 0.100000, 0.300000, -0.000000, 0.689152, -0.724617,
+-0.250000, 0.587785, -0.769421, 0.200000, 0.300000, -0.000000, 0.689152, -0.724617,
+-0.181636, 0.809017, -0.559017, 0.200000, 0.200000, -0.000000, 0.689152, -0.724617,
+-0.250000, 0.587785, -0.769421, 0.200000, 0.300000, -0.425919, 0.689152, -0.586227,
+-0.654509, 0.587785, -0.475528, 0.300000, 0.300000, -0.425919, 0.689152, -0.586227,
+-0.475528, 0.809017, -0.345491, 0.300000, 0.200000, -0.425919, 0.689152, -0.586227,
+-0.654509, 0.587785, -0.475528, 0.300000, 0.300000, -0.689152, 0.689152, -0.223919,
+-0.809017, 0.587785, 0.000000, 0.400000, 0.300000, -0.689152, 0.689152, -0.223919,
+-0.587785, 0.809017, 0.000000, 0.400000, 0.200000, -0.689152, 0.689152, -0.223919,
+-0.809017, 0.587785, 0.000000, 0.400000, 0.300000, -0.689152, 0.689152, 0.223919,
+-0.654509, 0.587785, 0.475528, 0.500000, 0.300000, -0.689152, 0.689152, 0.223919,
+-0.475528, 0.809017, 0.345492, 0.500000, 0.200000, -0.689152, 0.689152, 0.223919,
+-0.654509, 0.587785, 0.475528, 0.500000, 0.300000, -0.425919, 0.689152, 0.586228,
+-0.250000, 0.587785, 0.769421, 0.600000, 0.300000, -0.425919, 0.689152, 0.586228,
+-0.181636, 0.809017, 0.559017, 0.600000, 0.200000, -0.425919, 0.689152, 0.586228,
+-0.250000, 0.587785, 0.769421, 0.600000, 0.300000, 0.000000, 0.689152, 0.724617,
+0.250000, 0.587785, 0.769421, 0.700000, 0.300000, 0.000000, 0.689152, 0.724617,
+0.181636, 0.809017, 0.559017, 0.700000, 0.200000, 0.000000, 0.689152, 0.724617,
+0.250000, 0.587785, 0.769421, 0.700000, 0.300000, 0.425919, 0.689152, 0.586227,
+0.654509, 0.587785, 0.475528, 0.800000, 0.300000, 0.425919, 0.689152, 0.586227,
+0.475528, 0.809017, 0.345491, 0.800000, 0.200000, 0.425919, 0.689152, 0.586227,
+0.654509, 0.587785, 0.475528, 0.800000, 0.300000, 0.689152, 0.689152, 0.223919,
+0.809017, 0.587785, 0.000000, 0.900000, 0.300000, 0.689152, 0.689152, 0.223919,
+0.587785, 0.809017, 0.000000, 0.900000, 0.200000, 0.689152, 0.689152, 0.223919,
+0.809017, 0.587785, 0.000000, 0.900000, 0.300000, 0.689152, 0.689152, -0.223919,
+0.654509, 0.587785, -0.475528, 1.000000, 0.300000, 0.689152, 0.689152, -0.223919,
+0.475528, 0.809017, -0.345492, 1.000000, 0.200000, 0.689152, 0.689152, -0.223919,
+0.475528, 0.809017, -0.345492, 0.000000, 0.200000, 0.277578, 0.881468, -0.382053,
+0.181636, 0.809017, -0.559017, 0.100000, 0.200000, 0.277578, 0.881468, -0.382053,
+0.095491, 0.951057, -0.293893, 0.100000, 0.100000, 0.277578, 0.881468, -0.382053,
+0.181636, 0.809017, -0.559017, 0.100000, 0.200000, -0.000000, 0.881468, -0.472244,
+-0.181636, 0.809017, -0.559017, 0.200000, 0.200000, -0.000000, 0.881468, -0.472244,
+-0.095492, 0.951057, -0.293893, 0.200000, 0.100000, -0.000000, 0.881468, -0.472244,
+-0.181636, 0.809017, -0.559017, 0.200000, 0.200000, -0.277578, 0.881468, -0.382053,
+-0.475528, 0.809017, -0.345491, 0.300000, 0.200000, -0.277578, 0.881468, -0.382053,
+-0.250000, 0.951057, -0.181636, 0.300000, 0.100000, -0.277578, 0.881468, -0.382053,
+-0.475528, 0.809017, -0.345491, 0.300000, 0.200000, -0.449130, 0.881468, -0.145931,
+-0.587785, 0.809017, 0.000000, 0.400000, 0.200000, -0.449130, 0.881468, -0.145931,
+-0.309017, 0.951057, 0.000000, 0.400000, 0.100000, -0.449130, 0.881468, -0.145931,
+-0.587785, 0.809017, 0.000000, 0.400000, 0.200000, -0.449130, 0.881468, 0.145931,
+-0.475528, 0.809017, 0.345492, 0.500000, 0.200000, -0.449130, 0.881468, 0.145931,
+-0.250000, 0.951057, 0.181636, 0.500000, 0.100000, -0.449131, 0.881468, 0.145931,
+-0.475528, 0.809017, 0.345492, 0.500000, 0.200000, -0.277578, 0.881468, 0.382053,
+-0.181636, 0.809017, 0.559017, 0.600000, 0.200000, -0.277578, 0.881468, 0.382053,
+-0.095491, 0.951057, 0.293893, 0.600000, 0.100000, -0.277578, 0.881468, 0.382053,
+-0.181636, 0.809017, 0.559017, 0.600000, 0.200000, 0.000000, 0.881468, 0.472244,
+0.181636, 0.809017, 0.559017, 0.700000, 0.200000, 0.000000, 0.881468, 0.472244,
+0.095492, 0.951057, 0.293893, 0.700000, 0.100000, 0.000000, 0.881468, 0.472244,
+0.181636, 0.809017, 0.559017, 0.700000, 0.200000, 0.277578, 0.881468, 0.382053,
+0.475528, 0.809017, 0.345491, 0.800000, 0.200000, 0.277578, 0.881468, 0.382053,
+0.250000, 0.951057, 0.181636, 0.800000, 0.100000, 0.277578, 0.881468, 0.382053,
+0.475528, 0.809017, 0.345491, 0.800000, 0.200000, 0.449131, 0.881468, 0.145931,
+0.587785, 0.809017, 0.000000, 0.900000, 0.200000, 0.449131, 0.881468, 0.145931,
+0.309017, 0.951057, 0.000000, 0.900000, 0.100000, 0.449130, 0.881468, 0.145931,
+0.587785, 0.809017, 0.000000, 0.900000, 0.200000, 0.449131, 0.881468, -0.145931,
+0.475528, 0.809017, -0.345492, 1.000000, 0.200000, 0.449131, 0.881468, -0.145931,
+0.250000, 0.951057, -0.181636, 1.000000, 0.100000, 0.449131, 0.881468, -0.145931,
+0.095491, -0.951057, -0.293893, 0.100000, 0.900000, 0.096557, -0.986415, -0.132899,
+0.250000, -0.951057, -0.181636, 0.000000, 0.900000, 0.096557, -0.986415, -0.132899,
+0.000000, -1.000000, 0.000000, 0.050000, 1.000000, 0.096557, -0.986415, -0.132899,
+-0.095492, -0.951057, -0.293893, 0.200000, 0.900000, -0.000000, -0.986415, -0.164272,
+0.095491, -0.951057, -0.293893, 0.100000, 0.900000, -0.000000, -0.986415, -0.164272,
+0.000000, -1.000000, 0.000000, 0.150000, 1.000000, -0.000000, -0.986415, -0.164272,
+-0.250000, -0.951057, -0.181636, 0.300000, 0.900000, -0.096557, -0.986415, -0.132899,
+-0.095492, -0.951057, -0.293893, 0.200000, 0.900000, -0.096557, -0.986415, -0.132899,
+0.000000, -1.000000, 0.000000, 0.250000, 1.000000, -0.096557, -0.986415, -0.132899,
+-0.309017, -0.951057, 0.000000, 0.400000, 0.900000, -0.156233, -0.986415, -0.050763,
+-0.250000, -0.951057, -0.181636, 0.300000, 0.900000, -0.156233, -0.986415, -0.050763,
+0.000000, -1.000000, 0.000000, 0.350000, 1.000000, -0.156233, -0.986415, -0.050763,
+-0.250000, -0.951057, 0.181636, 0.500000, 0.900000, -0.156233, -0.986415, 0.050763,
+-0.309017, -0.951057, 0.000000, 0.400000, 0.900000, -0.156233, -0.986415, 0.050763,
+0.000000, -1.000000, 0.000000, 0.450000, 1.000000, -0.156233, -0.986415, 0.050763,
+-0.095491, -0.951057, 0.293893, 0.600000, 0.900000, -0.096557, -0.986415, 0.132899,
+-0.250000, -0.951057, 0.181636, 0.500000, 0.900000, -0.096557, -0.986415, 0.132899,
+0.000000, -1.000000, 0.000000, 0.550000, 1.000000, -0.096557, -0.986415, 0.132899,
+0.095492, -0.951057, 0.293893, 0.700000, 0.900000, 0.000000, -0.986415, 0.164272,
+-0.095491, -0.951057, 0.293893, 0.600000, 0.900000, 0.000000, -0.986415, 0.164272,
+0.000000, -1.000000, 0.000000, 0.650000, 1.000000, 0.000000, -0.986415, 0.164272,
+0.250000, -0.951057, 0.181636, 0.800000, 0.900000, 0.096557, -0.986415, 0.132899,
+0.095492, -0.951057, 0.293893, 0.700000, 0.900000, 0.096557, -0.986415, 0.132899,
+0.000000, -1.000000, 0.000000, 0.750000, 1.000000, 0.096557, -0.986415, 0.132899,
+0.309017, -0.951057, 0.000000, 0.900000, 0.900000, 0.156233, -0.986415, 0.050763,
+0.250000, -0.951057, 0.181636, 0.800000, 0.900000, 0.156233, -0.986415, 0.050763,
+0.000000, -1.000000, 0.000000, 0.850000, 1.000000, 0.156233, -0.986415, 0.050763,
+0.250000, -0.951057, -0.181636, 1.000000, 0.900000, 0.156233, -0.986415, -0.050763,
+0.309017, -0.951057, 0.000000, 0.900000, 0.900000, 0.156233, -0.986415, -0.050763,
+0.000000, -1.000000, 0.000000, 0.950000, 1.000000, 0.156233, -0.986415, -0.050763,
+0.250000, 0.951057, -0.181636, 0.000000, 0.100000, 0.096557, 0.986415, -0.132899,
+0.095491, 0.951057, -0.293893, 0.100000, 0.100000, 0.096557, 0.986415, -0.132899,
+0.000000, 1.000000, 0.000000, 0.050000, 0.000000, 0.096557, 0.986415, -0.132899,
+0.095491, 0.951057, -0.293893, 0.100000, 0.100000, -0.000000, 0.986415, -0.164272,
+-0.095492, 0.951057, -0.293893, 0.200000, 0.100000, -0.000000, 0.986415, -0.164272,
+0.000000, 1.000000, 0.000000, 0.150000, 0.000000, -0.000000, 0.986415, -0.164272,
+-0.095492, 0.951057, -0.293893, 0.200000, 0.100000, -0.096557, 0.986415, -0.132899,
+-0.250000, 0.951057, -0.181636, 0.300000, 0.100000, -0.096557, 0.986415, -0.132899,
+0.000000, 1.000000, 0.000000, 0.250000, 0.000000, -0.096557, 0.986415, -0.132899,
+-0.250000, 0.951057, -0.181636, 0.300000, 0.100000, -0.156233, 0.986415, -0.050763,
+-0.309017, 0.951057, 0.000000, 0.400000, 0.100000, -0.156233, 0.986415, -0.050763,
+0.000000, 1.000000, 0.000000, 0.350000, 0.000000, -0.156233, 0.986415, -0.050763,
+-0.309017, 0.951057, 0.000000, 0.400000, 0.100000, -0.156233, 0.986415, 0.050763,
+-0.250000, 0.951057, 0.181636, 0.500000, 0.100000, -0.156233, 0.986415, 0.050763,
+0.000000, 1.000000, 0.000000, 0.450000, 0.000000, -0.156233, 0.986415, 0.050763,
+-0.250000, 0.951057, 0.181636, 0.500000, 0.100000, -0.096557, 0.986415, 0.132899,
+-0.095491, 0.951057, 0.293893, 0.600000, 0.100000, -0.096557, 0.986415, 0.132899,
+0.000000, 1.000000, 0.000000, 0.550000, 0.000000, -0.096557, 0.986415, 0.132899,
+-0.095491, 0.951057, 0.293893, 0.600000, 0.100000, 0.000000, 0.986415, 0.164272,
+0.095492, 0.951057, 0.293893, 0.700000, 0.100000, 0.000000, 0.986415, 0.164272,
+0.000000, 1.000000, 0.000000, 0.650000, 0.000000, 0.000000, 0.986415, 0.164272,
+0.095492, 0.951057, 0.293893, 0.700000, 0.100000, 0.096557, 0.986415, 0.132899,
+0.250000, 0.951057, 0.181636, 0.800000, 0.100000, 0.096557, 0.986415, 0.132899,
+0.000000, 1.000000, 0.000000, 0.750000, 0.000000, 0.096557, 0.986415, 0.132899,
+0.250000, 0.951057, 0.181636, 0.800000, 0.100000, 0.156233, 0.986415, 0.050763,
+0.309017, 0.951057, 0.000000, 0.900000, 0.100000, 0.156233, 0.986415, 0.050763,
+0.000000, 1.000000, 0.000000, 0.850000, 0.000000, 0.156233, 0.986415, 0.050763,
+0.309017, 0.951057, 0.000000, 0.900000, 0.100000, 0.156233, 0.986415, -0.050763,
+0.250000, 0.951057, -0.181636, 1.000000, 0.100000, 0.156233, 0.986415, -0.050763,
+0.000000, 1.000000, 0.000000, 0.950000, 0.000000, 0.156233, 0.986415, -0.050763,
+};
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/LightGeometryData.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/LightGeometryData.h
new file mode 100644
index 0000000..ed21841
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/LightGeometryData.h
@@ -0,0 +1,269 @@
+const int num_faces = 88;
+
+// pos.xyz, uv.uv, normal.xyz
+float vertices[88*3*8] = {
+2.977119, 2.977121, -34.306633, 0.375000, 0.687500, 0.177861, 0.429396, -0.885429,
+0.000000, 4.210287, -34.306633, 0.406250, 0.687500, 0.177861, 0.429396, -0.885429,
+0.000000, 9.084861, -31.942669, 0.406250, 0.640508, 0.177861, 0.429396, -0.885429,
+0.000000, 4.210287, -34.306633, 0.406250, 0.687500, -0.177861, 0.429396, -0.885429,
+-2.977119, 2.977121, -34.306633, 0.437500, 0.687500, -0.177861, 0.429396, -0.885429,
+-6.423970, 6.423968, -31.942669, 0.437500, 0.640508, -0.177861, 0.429396, -0.885429,
+-2.977119, 2.977121, -34.306633, 0.437500, 0.687500, -0.429395, 0.177862, -0.885430,
+-4.210285, 0.000002, -34.306633, 0.468750, 0.687500, -0.429395, 0.177862, -0.885430,
+-9.084864, -0.000001, -31.942669, 0.468750, 0.640508, -0.429395, 0.177862, -0.885429,
+-4.210285, 0.000002, -34.306633, 0.468750, 0.687500, -0.429395, -0.177862, -0.885430,
+-2.977119, -2.977118, -34.306633, 0.500000, 0.687500, -0.429395, -0.177862, -0.885430,
+-6.423970, -6.423972, -31.942667, 0.500000, 0.640508, -0.429395, -0.177862, -0.885430,
+-2.977119, -2.977118, -34.306633, 0.500000, 0.687500, -0.177861, -0.429395, -0.885429,
+0.000000, -4.210283, -34.306633, 0.531250, 0.687500, -0.177861, -0.429395, -0.885429,
+0.000000, -9.084865, -31.942671, 0.531250, 0.640508, -0.177861, -0.429395, -0.885429,
+0.000000, -4.210283, -34.306633, 0.531250, 0.687500, 0.177862, -0.429395, -0.885429,
+2.977120, -2.977118, -34.306633, 0.562500, 0.687500, 0.177862, -0.429395, -0.885429,
+6.423971, -6.423972, -31.942667, 0.562500, 0.640508, 0.177862, -0.429395, -0.885429,
+2.977120, -2.977118, -34.306633, 0.562500, 0.687500, 0.429395, -0.177862, -0.885430,
+4.210286, 0.000002, -34.306633, 0.593750, 0.687500, 0.429395, -0.177862, -0.885430,
+9.084865, -0.000001, -31.942669, 0.593750, 0.640508, 0.429395, -0.177862, -0.885429,
+4.210286, 0.000002, -34.306633, 0.593750, 0.687500, 0.429395, 0.177862, -0.885429,
+2.977119, 2.977121, -34.306633, 0.625000, 0.687500, 0.429395, 0.177862, -0.885429,
+6.423971, 6.423968, -31.942669, 0.625000, 0.640508, 0.429395, 0.177862, -0.885429,
+-4.210285, 0.000002, -34.306633, 0.343750, 0.843750, -0.124125, -0.051414, -0.990934,
+0.000000, 0.000002, -34.834015, 0.500000, 0.843750, -0.124125, -0.051414, -0.990934,
+-2.977119, -2.977118, -34.306633, 0.389515, 0.733265, -0.124125, -0.051414, -0.990934,
+10.861003, 0.000000, -10.002398, 0.593750, 0.499530, 0.791070, 0.327672, -0.516564,
+7.679888, 7.679888, -10.002398, 0.625000, 0.499530, 0.791071, 0.327672, -0.516564,
+12.349342, 12.349340, 0.110407, 0.625000, 0.311560, 0.791070, 0.327672, -0.516564,
+7.679889, -7.679889, -10.002397, 0.562500, 0.499530, 0.791071, -0.327672, -0.516564,
+10.861003, 0.000000, -10.002398, 0.593750, 0.499530, 0.791070, -0.327672, -0.516564,
+17.464600, 0.000000, 0.110407, 0.593750, 0.311560, 0.791070, -0.327672, -0.516564,
+0.000000, -10.861002, -10.002398, 0.531250, 0.499530, 0.327672, -0.791071, -0.516564,
+7.679889, -7.679889, -10.002397, 0.562500, 0.499530, 0.327672, -0.791071, -0.516564,
+12.349343, -12.349342, 0.110407, 0.562500, 0.311560, 0.327672, -0.791071, -0.516564,
+-7.679888, -7.679888, -10.002398, 0.500000, 0.499530, -0.327672, -0.791071, -0.516564,
+0.000000, -10.861002, -10.002398, 0.531250, 0.499530, -0.327672, -0.791071, -0.516564,
+0.000001, -17.464596, 0.110407, 0.531250, 0.311560, -0.327672, -0.791071, -0.516564,
+-10.861002, 0.000000, -10.002398, 0.468750, 0.499530, -0.791071, -0.327672, -0.516564,
+-7.679888, -7.679888, -10.002398, 0.500000, 0.499530, -0.791071, -0.327672, -0.516564,
+-12.349340, -12.349340, 0.110407, 0.500000, 0.311560, -0.791071, -0.327672, -0.516564,
+-7.679888, 7.679888, -10.002398, 0.437500, 0.499530, -0.791071, 0.327672, -0.516564,
+-10.861002, 0.000000, -10.002398, 0.468750, 0.499530, -0.791071, 0.327672, -0.516564,
+-17.464596, 0.000000, 0.110407, 0.468750, 0.311560, -0.791071, 0.327672, -0.516564,
+0.000000, 10.861002, -10.002398, 0.406250, 0.499530, -0.327672, 0.791071, -0.516564,
+-7.679888, 7.679888, -10.002398, 0.437500, 0.499530, -0.327672, 0.791071, -0.516564,
+-12.349340, 12.349340, 0.110407, 0.437500, 0.311560, -0.327672, 0.791071, -0.516564,
+7.679888, 7.679888, -10.002398, 0.375000, 0.499530, 0.327672, 0.791071, -0.516564,
+0.000000, 10.861002, -10.002398, 0.406250, 0.499530, 0.327672, 0.791071, -0.516564,
+0.000001, 17.464598, 0.110407, 0.406250, 0.311560, 0.327672, 0.791071, -0.516564,
+10.861003, -0.000001, -29.138687, 0.593750, 0.593515, 0.923880, 0.382683, 0.000000,
+7.679888, 7.679889, -29.138687, 0.625000, 0.593515, 0.923880, 0.382683, 0.000000,
+7.679888, 7.679888, -10.002398, 0.625000, 0.499530, 0.923880, 0.382683, 0.000000,
+7.679889, -7.679891, -29.138687, 0.562500, 0.593515, 0.923880, -0.382683, 0.000000,
+10.861003, -0.000001, -29.138687, 0.593750, 0.593515, 0.923880, -0.382683, 0.000000,
+10.861003, 0.000000, -10.002398, 0.593750, 0.499530, 0.923880, -0.382683, 0.000000,
+0.000000, -10.861003, -29.138685, 0.531250, 0.593515, 0.382683, -0.923880, 0.000000,
+7.679889, -7.679891, -29.138687, 0.562500, 0.593515, 0.382683, -0.923880, 0.000000,
+7.679889, -7.679889, -10.002397, 0.562500, 0.499530, 0.382683, -0.923880, 0.000000,
+-7.679888, -7.679889, -29.138689, 0.500000, 0.593515, -0.382683, -0.923880, 0.000000,
+0.000000, -10.861003, -29.138685, 0.531250, 0.593515, -0.382683, -0.923880, 0.000000,
+0.000000, -10.861002, -10.002398, 0.531250, 0.499530, -0.382683, -0.923880, 0.000000,
+-10.861002, -0.000001, -29.138687, 0.468750, 0.593515, -0.923880, -0.382683, 0.000000,
+-7.679888, -7.679889, -29.138689, 0.500000, 0.593515, -0.923880, -0.382683, 0.000000,
+-7.679888, -7.679888, -10.002398, 0.500000, 0.499530, -0.923880, -0.382683, 0.000000,
+-7.679888, 7.679889, -29.138687, 0.437500, 0.593515, -0.923880, 0.382683, 0.000000,
+-10.861002, -0.000001, -29.138687, 0.468750, 0.593515, -0.923880, 0.382683, 0.000000,
+-10.861002, 0.000000, -10.002398, 0.468750, 0.499530, -0.923880, 0.382683, 0.000000,
+0.000000, 10.860999, -29.138687, 0.406250, 0.593515, -0.382683, 0.923880, -0.000000,
+-7.679888, 7.679889, -29.138687, 0.437500, 0.593515, -0.382683, 0.923880, -0.000000,
+-7.679888, 7.679888, -10.002398, 0.437500, 0.499530, -0.382683, 0.923880, -0.000000,
+7.679888, 7.679889, -29.138687, 0.375000, 0.593515, 0.382683, 0.923880, -0.000000,
+0.000000, 10.860999, -29.138687, 0.406250, 0.593515, 0.382683, 0.923880, -0.000000,
+0.000000, 10.861002, -10.002398, 0.406250, 0.499530, 0.382683, 0.923880, -0.000000,
+9.084865, -0.000001, -31.942669, 0.593750, 0.640508, 0.797373, 0.330283, -0.505083,
+6.423971, 6.423968, -31.942669, 0.625000, 0.640508, 0.797373, 0.330283, -0.505083,
+7.679888, 7.679889, -29.138687, 0.625000, 0.593515, 0.797373, 0.330283, -0.505083,
+6.423971, -6.423972, -31.942667, 0.562500, 0.640508, 0.797373, -0.330283, -0.505083,
+9.084865, -0.000001, -31.942669, 0.593750, 0.640508, 0.797373, -0.330283, -0.505083,
+10.861003, -0.000001, -29.138687, 0.593750, 0.593515, 0.797373, -0.330283, -0.505083,
+0.000000, -9.084865, -31.942671, 0.531250, 0.640508, 0.330283, -0.797373, -0.505083,
+6.423971, -6.423972, -31.942667, 0.562500, 0.640508, 0.330283, -0.797373, -0.505083,
+7.679889, -7.679891, -29.138687, 0.562500, 0.593515, 0.330283, -0.797373, -0.505083,
+-6.423970, -6.423972, -31.942667, 0.500000, 0.640508, -0.330283, -0.797373, -0.505083,
+0.000000, -9.084865, -31.942671, 0.531250, 0.640508, -0.330283, -0.797373, -0.505083,
+0.000000, -10.861003, -29.138685, 0.531250, 0.593515, -0.330283, -0.797373, -0.505083,
+-9.084864, -0.000001, -31.942669, 0.468750, 0.640508, -0.797373, -0.330283, -0.505083,
+-6.423970, -6.423972, -31.942667, 0.500000, 0.640508, -0.797374, -0.330282, -0.505083,
+-7.679888, -7.679889, -29.138689, 0.500000, 0.593515, -0.797374, -0.330282, -0.505083,
+-6.423970, 6.423968, -31.942669, 0.437500, 0.640508, -0.797373, 0.330283, -0.505083,
+-9.084864, -0.000001, -31.942669, 0.468750, 0.640508, -0.797373, 0.330283, -0.505083,
+-10.861002, -0.000001, -29.138687, 0.468750, 0.593515, -0.797373, 0.330283, -0.505083,
+0.000000, 9.084861, -31.942669, 0.406250, 0.640508, -0.330282, 0.797373, -0.505084,
+-6.423970, 6.423968, -31.942669, 0.437500, 0.640508, -0.330282, 0.797373, -0.505084,
+-7.679888, 7.679889, -29.138687, 0.437500, 0.593515, -0.330282, 0.797373, -0.505084,
+6.423971, 6.423968, -31.942669, 0.375000, 0.640508, 0.330282, 0.797373, -0.505084,
+0.000000, 9.084861, -31.942669, 0.406250, 0.640508, 0.330282, 0.797373, -0.505084,
+0.000000, 10.860999, -29.138687, 0.406250, 0.593515, 0.330282, 0.797373, -0.505084,
+2.977119, 2.977121, -34.306633, 0.610485, 0.954235, 0.124125, 0.051414, -0.990934,
+4.210286, 0.000002, -34.306633, 0.656250, 0.843750, 0.124125, 0.051414, -0.990934,
+0.000000, 0.000002, -34.834015, 0.500000, 0.843750, 0.124125, 0.051414, -0.990934,
+0.000000, 0.000002, -34.834015, 0.500000, 0.843750, 0.124125, -0.051414, -0.990934,
+4.210286, 0.000002, -34.306633, 0.656250, 0.843750, 0.124125, -0.051414, -0.990934,
+2.977120, -2.977118, -34.306633, 0.610485, 0.733265, 0.124125, -0.051414, -0.990934,
+0.000000, 0.000002, -34.834015, 0.500000, 0.843750, 0.051415, -0.124125, -0.990934,
+2.977120, -2.977118, -34.306633, 0.610485, 0.733265, 0.051415, -0.124125, -0.990934,
+0.000000, -4.210283, -34.306633, 0.500000, 0.687500, 0.051415, -0.124125, -0.990934,
+0.000000, 0.000002, -34.834015, 0.500000, 0.843750, -0.051414, -0.124125, -0.990934,
+0.000000, -4.210283, -34.306633, 0.500000, 0.687500, -0.051414, -0.124125, -0.990934,
+-2.977119, -2.977118, -34.306633, 0.389515, 0.733265, -0.051414, -0.124125, -0.990934,
+-2.977119, 2.977121, -34.306633, 0.389515, 0.954235, -0.124125, 0.051414, -0.990934,
+0.000000, 0.000002, -34.834015, 0.500000, 0.843750, -0.124125, 0.051414, -0.990934,
+-4.210285, 0.000002, -34.306633, 0.343750, 0.843750, -0.124125, 0.051414, -0.990934,
+0.000000, 4.210287, -34.306633, 0.500000, 1.000000, -0.051414, 0.124125, -0.990934,
+0.000000, 0.000002, -34.834015, 0.500000, 0.843750, -0.051414, 0.124125, -0.990934,
+-2.977119, 2.977121, -34.306633, 0.389515, 0.954235, -0.051414, 0.124125, -0.990934,
+2.977119, 2.977121, -34.306633, 0.610485, 0.954235, 0.051414, 0.124125, -0.990934,
+0.000000, 0.000002, -34.834015, 0.500000, 0.843750, 0.051414, 0.124125, -0.990934,
+0.000000, 4.210287, -34.306633, 0.500000, 1.000000, 0.051414, 0.124125, -0.990934,
+12.349342, 12.349340, 0.110407, 0.610485, 0.045765, 0.382683, 0.923880, 0.000000,
+0.000001, 17.464598, 0.110407, 0.500000, 0.000000, 0.382683, 0.923880, 0.000000,
+0.000001, 17.464598, 1.144262, 0.500000, 0.000000, 0.382683, 0.923880, 0.000000,
+0.000001, 17.464598, 0.110407, 0.500000, 0.000000, -0.382683, 0.923880, -0.000000,
+-12.349340, 12.349340, 0.110407, 0.389515, 0.045765, -0.382683, 0.923880, -0.000000,
+-12.349340, 12.349340, 1.144262, 0.389515, 0.045765, -0.382683, 0.923880, -0.000000,
+-12.349340, 12.349340, 0.110407, 0.389515, 0.045765, -0.923880, 0.382683, 0.000000,
+-17.464596, 0.000000, 0.110407, 0.343750, 0.156250, -0.923880, 0.382683, 0.000000,
+-17.464596, 0.000000, 1.144262, 0.343750, 0.156250, -0.923880, 0.382683, 0.000000,
+-17.464596, 0.000000, 0.110407, 0.343750, 0.156250, -0.923880, -0.382683, 0.000000,
+-12.349340, -12.349340, 0.110407, 0.389515, 0.266735, -0.923880, -0.382683, 0.000000,
+-12.349340, -12.349340, 1.144262, 0.389515, 0.266735, -0.923880, -0.382683, 0.000000,
+-12.349340, -12.349340, 0.110407, 0.389515, 0.266735, -0.382683, -0.923880, -0.000002,
+0.000001, -17.464596, 0.110407, 0.500000, 0.312500, -0.382683, -0.923880, -0.000002,
+0.000001, -17.464600, 1.144262, 0.500000, 0.312500, -0.382683, -0.923880, -0.000002,
+0.000001, -17.464596, 0.110407, 0.500000, 0.312500, 0.382683, -0.923880, -0.000002,
+12.349343, -12.349342, 0.110407, 0.610485, 0.266735, 0.382683, -0.923880, -0.000002,
+12.349343, -12.349342, 1.144262, 0.610485, 0.266735, 0.382683, -0.923880, -0.000002,
+12.349343, -12.349342, 0.110407, 0.610485, 0.266735, 0.923880, -0.382683, 0.000000,
+17.464600, 0.000000, 0.110407, 0.656250, 0.156250, 0.923880, -0.382683, 0.000000,
+17.464600, 0.000000, 1.144262, 0.656250, 0.156250, 0.923880, -0.382683, 0.000000,
+17.464600, 0.000000, 0.110407, 0.656250, 0.156250, 0.923880, 0.382683, 0.000000,
+12.349342, 12.349340, 0.110407, 0.610485, 0.045765, 0.923880, 0.382683, 0.000000,
+12.349342, 12.349340, 1.144262, 0.610485, 0.045765, 0.923880, 0.382683, 0.000000,
+12.349342, 12.349340, 1.144262, 0.610485, 0.045765, -0.117337, -0.283277, 0.951833,
+0.000001, 17.464598, 1.144262, 0.500000, 0.000000, -0.117337, -0.283277, 0.951833,
+0.000001, 15.735191, 0.629568, 0.500000, 0.000000, -0.117337, -0.283277, 0.951833,
+0.000001, 17.464598, 1.144262, 0.500000, 0.000000, 0.117337, -0.283277, 0.951833,
+-12.349340, 12.349340, 1.144262, 0.389515, 0.045765, 0.117337, -0.283277, 0.951833,
+-11.126453, 11.126453, 0.629568, 0.389515, 0.045765, 0.117337, -0.283277, 0.951833,
+-12.349340, 12.349340, 1.144262, 0.389515, 0.045765, 0.283277, -0.117337, 0.951833,
+-17.464596, 0.000000, 1.144262, 0.343750, 0.156250, 0.283277, -0.117337, 0.951833,
+-15.735189, 0.000000, 0.629568, 0.343750, 0.156250, 0.283277, -0.117337, 0.951833,
+-17.464596, 0.000000, 1.144262, 0.343750, 0.156250, 0.283277, 0.117337, 0.951833,
+-12.349340, -12.349340, 1.144262, 0.389515, 0.266735, 0.283277, 0.117337, 0.951833,
+-11.126453, -11.126453, 0.629568, 0.389515, 0.266735, 0.283277, 0.117337, 0.951833,
+-12.349340, -12.349340, 1.144262, 0.389515, 0.266735, 0.117337, 0.283277, 0.951833,
+0.000001, -17.464600, 1.144262, 0.500000, 0.312500, 0.117337, 0.283277, 0.951833,
+0.000001, -15.735191, 0.629568, 0.500000, 0.312500, 0.117337, 0.283277, 0.951833,
+0.000001, -17.464600, 1.144262, 0.500000, 0.312500, -0.117337, 0.283277, 0.951833,
+12.349343, -12.349342, 1.144262, 0.610485, 0.266735, -0.117337, 0.283277, 0.951833,
+11.126457, -11.126455, 0.629568, 0.610485, 0.266735, -0.117337, 0.283277, 0.951833,
+12.349343, -12.349342, 1.144262, 0.610485, 0.266735, -0.283277, 0.117337, 0.951833,
+17.464600, 0.000000, 1.144262, 0.656250, 0.156250, -0.283277, 0.117337, 0.951833,
+15.735193, 0.000000, 0.629568, 0.656250, 0.156250, -0.283277, 0.117337, 0.951833,
+17.464600, 0.000000, 1.144262, 0.656250, 0.156250, -0.283277, -0.117337, 0.951833,
+12.349342, 12.349340, 1.144262, 0.610485, 0.045765, -0.283277, -0.117337, 0.951833,
+11.126455, 11.126453, 0.629568, 0.610485, 0.045765, -0.283277, -0.117337, 0.951833,
+15.735193, 0.000000, 0.629568, 0.656250, 0.156250, -0.301379, -0.124836, 0.945297,
+11.126455, 11.126453, 0.629568, 0.610485, 0.045765, -0.301379, -0.124836, 0.945297,
+1.172339, 1.172337, -3.858527, 0.610485, 0.045765, -0.301379, -0.124836, 0.945297,
+11.126455, 11.126453, 0.629568, 0.610485, 0.045765, -0.124835, -0.301379, 0.945297,
+0.000001, 15.735191, 0.629568, 0.500000, 0.000000, -0.124835, -0.301379, 0.945297,
+0.000001, 1.657940, -3.858527, 0.500000, 0.000000, -0.124835, -0.301379, 0.945297,
+0.000001, 15.735191, 0.629568, 0.500000, 0.000000, 0.124835, -0.301379, 0.945297,
+-11.126453, 11.126453, 0.629568, 0.389515, 0.045765, 0.124835, -0.301379, 0.945297,
+-1.172335, 1.172337, -3.858527, 0.389515, 0.045765, 0.124835, -0.301379, 0.945297,
+-11.126453, 11.126453, 0.629568, 0.389515, 0.045765, 0.301379, -0.124835, 0.945297,
+-15.735189, 0.000000, 0.629568, 0.343750, 0.156250, 0.301379, -0.124835, 0.945297,
+-1.657938, 0.000000, -3.858527, 0.343750, 0.156250, 0.301379, -0.124835, 0.945297,
+-15.735189, 0.000000, 0.629568, 0.343750, 0.156250, 0.301379, 0.124835, 0.945297,
+-11.126453, -11.126453, 0.629568, 0.389515, 0.266735, 0.301379, 0.124835, 0.945297,
+-1.172335, -1.172337, -3.858527, 0.389515, 0.266735, 0.301379, 0.124835, 0.945297,
+-11.126453, -11.126453, 0.629568, 0.389515, 0.266735, 0.124836, 0.301379, 0.945297,
+0.000001, -15.735191, 0.629568, 0.500000, 0.312500, 0.124835, 0.301379, 0.945297,
+0.000001, -1.657940, -3.858527, 0.500000, 0.312500, 0.124836, 0.301379, 0.945297,
+0.000001, -15.735191, 0.629568, 0.500000, 0.312500, -0.124835, 0.301379, 0.945297,
+11.126457, -11.126455, 0.629568, 0.610485, 0.266735, -0.124835, 0.301379, 0.945297,
+1.172339, -1.172337, -3.858527, 0.610485, 0.266735, -0.124835, 0.301379, 0.945297,
+11.126457, -11.126455, 0.629568, 0.610485, 0.266735, -0.301379, 0.124835, 0.945297,
+15.735193, 0.000000, 0.629568, 0.656250, 0.156250, -0.301379, 0.124835, 0.945297,
+1.657941, 0.000000, -3.858527, 0.656250, 0.156250, -0.301379, 0.124835, 0.945297,
+1.657941, 0.000000, -3.858527, 0.656250, 0.156250, 0.923878, 0.382687, 0.000000,
+1.172339, 1.172337, -3.858527, 0.610485, 0.045765, 0.923878, 0.382687, 0.000000,
+1.172338, 1.172337, 18.507620, 0.610485, 0.045765, 0.890349, 0.368798, -0.266959,
+1.172339, 1.172337, -3.858527, 0.610485, 0.045765, 0.382687, 0.923878, 0.000000,
+0.000001, 1.657940, -3.858527, 0.500000, 0.000000, 0.382687, 0.923878, 0.000000,
+0.000001, 1.657940, 18.507620, 0.500000, 0.000000, 0.368799, 0.890348, -0.266960,
+0.000001, 1.657940, -3.858527, 0.500000, 0.000000, -0.382687, 0.923878, -0.000000,
+-1.172335, 1.172337, -3.858527, 0.389515, 0.045765, -0.382687, 0.923878, -0.000000,
+-1.172336, 1.172337, 18.507620, 0.389515, 0.045765, -0.368799, 0.890348, -0.266959,
+-1.172335, 1.172337, -3.858527, 0.389515, 0.045765, -0.923878, 0.382687, -0.000000,
+-1.657938, 0.000000, -3.858527, 0.343750, 0.156250, -0.923878, 0.382687, -0.000000,
+-1.657939, 0.000000, 18.507620, 0.343750, 0.156250, -0.890348, 0.368798, -0.266960,
+-1.657938, 0.000000, -3.858527, 0.343750, 0.156250, -0.923878, -0.382687, -0.000000,
+-1.172335, -1.172337, -3.858527, 0.389515, 0.266735, -0.923878, -0.382687, -0.000000,
+-1.172336, -1.172337, 18.507620, 0.389515, 0.266735, -0.890348, -0.368798, -0.266959,
+-1.172335, -1.172337, -3.858527, 0.389515, 0.266735, -0.382687, -0.923878, -0.000000,
+0.000001, -1.657940, -3.858527, 0.500000, 0.312500, -0.382687, -0.923878, -0.000000,
+0.000001, -1.657940, 18.507620, 0.500000, 0.312500, -0.368799, -0.890348, -0.266960,
+0.000001, -1.657940, -3.858527, 0.500000, 0.312500, 0.382687, -0.923878, 0.000000,
+1.172339, -1.172337, -3.858527, 0.610485, 0.266735, 0.382687, -0.923878, 0.000000,
+1.172338, -1.172337, 18.507620, 0.610485, 0.266735, 0.368799, -0.890348, -0.266959,
+1.172339, -1.172337, -3.858527, 0.610485, 0.266735, 0.923878, -0.382687, 0.000000,
+1.657941, 0.000000, -3.858527, 0.656250, 0.156250, 0.923878, -0.382687, 0.000000,
+1.657941, 0.000000, 18.507620, 0.656250, 0.156250, 0.890348, -0.368798, -0.266960,
+1.657941, 0.000000, 18.507620, 0.656250, 0.156250, 0.890348, 0.368798, -0.266960,
+1.172338, 1.172337, 18.507620, 0.610485, 0.045765, 0.890349, 0.368798, -0.266959,
+3.204545, 3.204544, 18.507618, 0.610485, 0.045765, 0.916255, 0.379530, 0.128197,
+1.172338, -1.172337, 18.507620, 0.610485, 0.266735, 0.890349, -0.368798, -0.266959,
+1.657941, 0.000000, 18.507620, 0.656250, 0.156250, 0.890348, -0.368798, -0.266960,
+4.531928, 0.000000, 18.507618, 0.656250, 0.156250, 0.916255, -0.379530, 0.128199,
+0.000001, -1.657940, 18.507620, 0.500000, 0.312500, 0.368799, -0.890348, -0.266960,
+1.172338, -1.172337, 18.507620, 0.610485, 0.266735, 0.368799, -0.890348, -0.266959,
+3.204545, -3.204544, 18.507618, 0.610485, 0.266735, 0.379530, -0.916255, 0.128197,
+-1.172336, -1.172337, 18.507620, 0.389515, 0.266735, -0.368799, -0.890348, -0.266959,
+0.000001, -1.657940, 18.507620, 0.500000, 0.312500, -0.368799, -0.890348, -0.266960,
+0.000000, -4.531925, 18.507618, 0.500000, 0.312500, -0.379530, -0.916255, 0.128199,
+-1.657939, 0.000000, 18.507620, 0.343750, 0.156250, -0.890348, -0.368798, -0.266960,
+-1.172336, -1.172337, 18.507620, 0.389515, 0.266735, -0.890348, -0.368798, -0.266959,
+-3.204544, -3.204544, 18.507618, 0.389515, 0.266735, -0.916255, -0.379530, 0.128197,
+-1.172336, 1.172337, 18.507620, 0.389515, 0.045765, -0.890348, 0.368798, -0.266959,
+-1.657939, 0.000000, 18.507620, 0.343750, 0.156250, -0.890348, 0.368798, -0.266960,
+-4.531927, 0.000000, 18.507618, 0.343750, 0.156250, -0.916254, 0.379530, 0.128199,
+0.000001, 1.657940, 18.507620, 0.500000, 0.000000, -0.368799, 0.890348, -0.266960,
+-1.172336, 1.172337, 18.507620, 0.389515, 0.045765, -0.368799, 0.890348, -0.266959,
+-3.204544, 3.204544, 18.507618, 0.389515, 0.045765, -0.379530, 0.916255, 0.128197,
+1.172338, 1.172337, 18.507620, 0.610485, 0.045765, 0.368799, 0.890348, -0.266959,
+0.000001, 1.657940, 18.507620, 0.500000, 0.000000, 0.368799, 0.890348, -0.266960,
+0.000000, 4.531925, 18.507618, 0.500000, 0.000000, 0.379530, 0.916255, 0.128199,
+3.204545, -3.204544, 18.507618, 0.610485, 0.266735, 0.916255, -0.379530, 0.128197,
+4.531928, 0.000000, 18.507618, 0.656250, 0.156250, 0.916255, -0.379530, 0.128199,
+0.000000, 0.000000, 27.158279, 0.500000, 0.156250, 0.831594, -0.344462, 0.435657,
+0.000000, -4.531925, 18.507618, 0.500000, 0.312500, 0.379530, -0.916255, 0.128199,
+3.204545, -3.204544, 18.507618, 0.610485, 0.266735, 0.379530, -0.916255, 0.128197,
+0.000000, 0.000000, 27.158279, 0.500000, 0.156250, 0.344462, -0.831594, 0.435657,
+-3.204544, -3.204544, 18.507618, 0.389515, 0.266735, -0.379530, -0.916255, 0.128197,
+0.000000, -4.531925, 18.507618, 0.500000, 0.312500, -0.379530, -0.916255, 0.128199,
+0.000000, 0.000000, 27.158279, 0.500000, 0.156250, -0.344462, -0.831594, 0.435657,
+-4.531927, 0.000000, 18.507618, 0.343750, 0.156250, -0.916254, -0.379530, 0.128199,
+-3.204544, -3.204544, 18.507618, 0.389515, 0.266735, -0.916255, -0.379530, 0.128197,
+0.000000, 0.000000, 27.158279, 0.500000, 0.156250, -0.831594, -0.344462, 0.435657,
+-3.204544, 3.204544, 18.507618, 0.389515, 0.045765, -0.916255, 0.379530, 0.128197,
+-4.531927, 0.000000, 18.507618, 0.343750, 0.156250, -0.916254, 0.379530, 0.128199,
+0.000000, 0.000000, 27.158279, 0.500000, 0.156250, -0.831594, 0.344462, 0.435657,
+0.000000, 4.531925, 18.507618, 0.500000, 0.000000, -0.379530, 0.916255, 0.128199,
+-3.204544, 3.204544, 18.507618, 0.389515, 0.045765, -0.379530, 0.916255, 0.128197,
+0.000000, 0.000000, 27.158279, 0.500000, 0.156250, -0.344462, 0.831594, 0.435657,
+3.204545, 3.204544, 18.507618, 0.610485, 0.045765, 0.379530, 0.916255, 0.128197,
+0.000000, 4.531925, 18.507618, 0.500000, 0.000000, 0.379530, 0.916255, 0.128199,
+0.000000, 0.000000, 27.158279, 0.500000, 0.156250, 0.344462, 0.831594, 0.435657,
+4.531928, 0.000000, 18.507618, 0.656250, 0.156250, 0.916255, 0.379530, 0.128199,
+3.204545, 3.204544, 18.507618, 0.610485, 0.045765, 0.916255, 0.379530, 0.128197,
+0.000000, 0.000000, 27.158279, 0.500000, 0.156250, 0.831594, 0.344462, 0.435657,
+};
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/WindGeometryData.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/WindGeometryData.h
new file mode 100644
index 0000000..3d1390a
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/GeometryData/WindGeometryData.h
@@ -0,0 +1,2513 @@
+const int num_faces = 836;
+
+// pos.xyz, uv.uv, normal.xyz
+float vertices[836*3*8] = {
+-1.002737, 3.502487, -29.476650, 1.000000, 0.966243, -0.570521, -0.819696, 0.051023,
+-1.002737, 3.589727, -28.074986, 1.000000, 0.922656, -0.569426, -0.818637, 0.074745,
+-1.336982, 4.293425, -28.133030, 0.500000, 0.922656, -0.999926, -0.012083, 0.001603,
+-1.336982, 4.293425, -28.133030, 0.500000, 0.922656, -0.999926, -0.012083, 0.001603,
+-1.002737, 4.997122, -28.191074, 0.000000, 0.932486, -0.582174, 0.810005, -0.070467,
+-1.002737, 4.921762, -29.530731, 0.000000, 0.966243, -0.582241, 0.811733, -0.045666,
+-1.002737, 5.199909, -26.333269, 0.000000, 0.859409, -0.582690, 0.803052, -0.124820,
+-1.002737, 4.997122, -28.191074, 0.000000, 0.932486, -0.582174, 0.810005, -0.070467,
+-1.336982, 4.293425, -28.133030, 0.500000, 0.922656, -0.999926, -0.012083, 0.001603,
+-1.336982, 4.293425, -28.133030, 0.500000, 0.922656, -0.999926, -0.012083, 0.001603,
+-1.002737, 3.589727, -28.074986, 1.000000, 0.922656, -0.569426, -0.818637, 0.074745,
+-1.002737, 3.807196, -26.139326, 1.000000, 0.859409, -0.566467, -0.814177, 0.127399,
+-1.002737, 3.807196, -26.139326, 1.000000, 0.859409, -0.566467, -0.814177, 0.127399,
+-1.002737, 4.261988, -23.779169, 1.000000, 0.775297, -0.564634, -0.800896, 0.199384,
+-1.336982, 4.951294, -23.914915, 0.500000, 0.775297, -0.999837, -0.017439, 0.004781,
+-1.336982, 4.951294, -23.914915, 0.500000, 0.775297, -0.999837, -0.017439, 0.004781,
+-1.002737, 5.640600, -24.050657, 0.000000, 0.786333, -0.583127, 0.787897, -0.197941,
+-1.002737, 5.199909, -26.333269, 0.000000, 0.859409, -0.582690, 0.803052, -0.124820,
+-1.002737, 6.429670, -21.436577, 0.000000, 0.669113, -0.579786, 0.770207, -0.265761,
+-1.002737, 5.640600, -24.050657, 0.000000, 0.786333, -0.583127, 0.787897, -0.197941,
+-1.336982, 4.951294, -23.914915, 0.500000, 0.775297, -0.999837, -0.017439, 0.004781,
+-1.336982, 4.951294, -23.914915, 0.500000, 0.775297, -0.999837, -0.017439, 0.004781,
+-1.002737, 4.261988, -23.779169, 1.000000, 0.775297, -0.564634, -0.800896, 0.199384,
+-1.002737, 5.061195, -21.104027, 1.000000, 0.669113, -0.566458, -0.779905, 0.266220,
+-1.002737, 5.061195, -21.104027, 1.000000, 0.669113, -0.566458, -0.779905, 0.266220,
+-1.002737, 6.120935, -18.335461, 1.000000, 0.547971, -0.566613, -0.758528, 0.321845,
+-1.336982, 6.802818, -18.519814, 0.500000, 0.547971, -0.999946, -0.009100, 0.005070,
+-1.336982, 6.802818, -18.519814, 0.500000, 0.547971, -0.999946, -0.009100, 0.005070,
+-1.002737, 7.484703, -18.704168, 0.000000, 0.551894, -0.576888, 0.751118, -0.320970,
+-1.002737, 6.429670, -21.436577, 0.000000, 0.669113, -0.579786, 0.770207, -0.265761,
+-1.002737, 8.723274, -16.066572, 0.000000, 0.418984, -0.570577, 0.739144, -0.357922,
+-1.002737, 7.484703, -18.704168, 0.000000, 0.551894, -0.576888, 0.751118, -0.320970,
+-1.336982, 6.802818, -18.519814, 0.500000, 0.547971, -0.999946, -0.009100, 0.005070,
+-1.336982, 6.802818, -18.519814, 0.500000, 0.547971, -0.999946, -0.009100, 0.005070,
+-1.002737, 6.120935, -18.335461, 1.000000, 0.547971, -0.566613, -0.758528, 0.321845,
+-1.002737, 7.357327, -15.695049, 1.000000, 0.418984, -0.568348, -0.740553, 0.358555,
+-1.002737, 7.357327, -15.695049, 1.000000, 0.418984, -0.568348, -0.740553, 0.358555,
+-1.002737, 8.627859, -13.158705, 1.000000, 0.282904, -0.571429, -0.737705, 0.359528,
+-1.336982, 9.314625, -13.332255, 0.500000, 0.282904, -0.999983, 0.005125, -0.002905,
+-1.336982, 9.314625, -13.332255, 0.500000, 0.282904, -0.999983, 0.005125, -0.002905,
+-1.002737, 10.001389, -13.505806, 0.000000, 0.286075, -0.565597, 0.742253, -0.359389,
+-1.002737, 8.723274, -16.066572, 0.000000, 0.418984, -0.570577, 0.739144, -0.357922,
+-1.002737, 11.175043, -11.003893, 0.000000, 0.140482, -0.562513, 0.757929, -0.330337,
+-1.002737, 10.001389, -13.505806, 0.000000, 0.286075, -0.565597, 0.742253, -0.359389,
+-1.336982, 9.314625, -13.332255, 0.500000, 0.282904, -0.999983, 0.005125, -0.002905,
+-1.336982, 9.314625, -13.332255, 0.500000, 0.282904, -0.999983, 0.005125, -0.002905,
+-1.002737, 8.627859, -13.158705, 1.000000, 0.282904, -0.571429, -0.737705, 0.359528,
+-1.002737, 9.790028, -10.702334, 1.000000, 0.140482, -0.576949, -0.747604, 0.328966,
+-1.002737, 9.790028, -10.702334, 1.000000, 0.140482, -0.576949, -0.747604, 0.328966,
+-1.003346, 10.657795, -8.543959, 1.020833, -0.009381, -0.588551, -0.767718, 0.253411,
+-1.337592, 11.355911, -8.670841, 0.583333, -0.069211, -0.999594, 0.026023, -0.011609,
+-1.337592, 11.355911, -8.670841, 0.583333, -0.069211, -0.999594, 0.026023, -0.011609,
+-1.003346, 12.054029, -8.797724, 0.000000, -0.005111, -0.560047, 0.787144, -0.258362,
+-1.002737, 11.175043, -11.003893, 0.000000, 0.140482, -0.562513, 0.757929, -0.330337,
+-1.005175, 12.448139, -7.124194, 0.666667, -0.726194, -0.564732, 0.815815, -0.124590,
+-1.003346, 12.054029, -8.797724, 0.000000, -0.005111, -0.560047, 0.787144, -0.258362,
+-1.337592, 11.355911, -8.670841, 0.583333, -0.069211, -0.999594, 0.026023, -0.011609,
+-1.337592, 11.355911, -8.670841, 0.583333, -0.069211, -0.999594, 0.026023, -0.011609,
+-1.003346, 10.657795, -8.543959, 1.020833, -0.009381, -0.588551, -0.767718, 0.253411,
+-1.005175, 11.045135, -6.901599, 1.083333, -0.167786, -0.591577, -0.797310, 0.119726,
+-1.005175, 11.045135, -6.901599, 1.083333, -0.167786, -0.591577, -0.797310, 0.119726,
+-1.006394, 11.114811, -5.517140, 1.000000, -0.170915, -0.583093, -0.812392, -0.004755,
+-1.340640, 11.818584, -5.617008, 1.166667, -0.809096, -0.999853, 0.017074, 0.001872,
+-1.340640, 11.818584, -5.617008, 1.166667, -0.809096, -0.999853, 0.017074, 0.001872,
+-1.006394, 12.522362, -5.716876, 1.333333, -1.447277, -0.566040, 0.824377, 0.001632,
+-1.005175, 12.448139, -7.124194, 0.666667, -0.726194, -0.564732, 0.815815, -0.124590,
+-1.002737, 11.560024, -0.158328, 0.000000, -0.503387, -0.548128, 0.812439, 0.198744,
+-1.003346, 12.142200, -2.567771, 0.000000, -0.336720, -0.545383, 0.819886, 0.174196,
+-1.337592, 11.435898, -2.488622, 0.500000, -0.336720, -0.999671, 0.024155, 0.008634,
+-1.337592, 11.435898, -2.488622, 0.500000, -0.336720, -0.999671, 0.024155, 0.008634,
+-1.003346, 10.729588, -2.409474, 1.000000, -0.336720, -0.568927, -0.804482, -0.170679,
+-1.002737, 10.154959, -0.010050, 1.000000, -0.503387, -0.554465, -0.809442, -0.193318,
+-1.002737, 10.154959, -0.010050, 1.000000, -0.503387, -0.554465, -0.809442, -0.193318,
+-1.002737, 9.503082, 2.725576, 1.000000, -0.671927, -0.543427, -0.820485, -0.177458,
+-1.336982, 10.194935, 2.646095, 0.500000, -0.671927, -0.999975, -0.006839, -0.001674,
+-1.336982, 10.194935, 2.646095, 0.500000, -0.671927, -0.999975, -0.006839, -0.001674,
+-1.002737, 10.886791, 2.566613, 0.000000, -0.670054, -0.549613, 0.814083, 0.187601,
+-1.002737, 11.560024, -0.158328, 0.000000, -0.503387, -0.548128, 0.812439, 0.198744,
+-1.002737, 10.314148, 5.254678, 0.000000, -0.844213, -0.550065, 0.824042, 0.135588,
+-1.002737, 10.886791, 2.566613, 0.000000, -0.670054, -0.549613, 0.814083, 0.187601,
+-1.336982, 10.194935, 2.646095, 0.500000, -0.671927, -0.999975, -0.006839, -0.001674,
+-1.336982, 10.194935, 2.646095, 0.500000, -0.671927, -0.999975, -0.006839, -0.001674,
+-1.002737, 9.503082, 2.725576, 1.000000, -0.671927, -0.543427, -0.820485, -0.177458,
+-1.002737, 8.971350, 5.457178, 1.000000, -0.844213, -0.532911, -0.837943, -0.117722,
+-1.002737, 8.971350, 5.457178, 1.000000, -0.844213, -0.532911, -0.837943, -0.117722,
+-1.002737, 8.743584, 8.108688, 1.000000, -1.016250, -0.522039, -0.852900, 0.006099,
+-1.336982, 9.384014, 7.968127, 0.500000, -1.016250, -0.999385, -0.034959, -0.002597,
+-1.336982, 9.384014, 7.968127, 0.500000, -1.016250, -0.999385, -0.034959, -0.002597,
+-1.002737, 10.024443, 7.827566, 0.000000, -1.018373, -0.552727, 0.833125, 0.019881,
+-1.002737, 10.314148, 5.254678, 0.000000, -0.844213, -0.550065, 0.824042, 0.135588,
+-1.002737, 10.200031, 10.206976, 0.000000, -1.184038, -0.545898, 0.826469, -0.137636,
+-1.002737, 10.024443, 7.827566, 0.000000, -1.018373, -0.552727, 0.833125, 0.019881,
+-1.336982, 9.384014, 7.968127, 0.500000, -1.016250, -0.999385, -0.034959, -0.002597,
+-1.336982, 9.384014, 7.968127, 0.500000, -1.016250, -0.999385, -0.034959, -0.002597,
+-1.002737, 8.743584, 8.108688, 1.000000, -1.016250, -0.522039, -0.852900, 0.006099,
+-1.002737, 9.003599, 10.604042, 1.000000, -1.184038, -0.512969, -0.841946, 0.167304,
+-1.002737, 9.003599, 10.604042, 1.000000, -1.184038, -0.512969, -0.841946, 0.167304,
+-1.002737, 9.694744, 12.910284, 1.000000, -1.349954, -0.500990, -0.803388, 0.321833,
+-1.336982, 10.239292, 12.641662, 0.500000, -1.349954, -0.999218, -0.036495, 0.015192,
+-1.336982, 10.239292, 12.641662, 0.500000, -1.349954, -0.999218, -0.036495, 0.015192,
+-1.002737, 10.783842, 12.373039, 0.000000, -1.349704, -0.535040, 0.792292, -0.293266,
+-1.002737, 10.200031, 10.206976, 0.000000, -1.184038, -0.545898, 0.826469, -0.137636,
+-1.002737, 11.718807, 14.305887, 0.000000, -1.516370, -0.524951, 0.731928, -0.434405,
+-1.002737, 10.783842, 12.373039, 0.000000, -1.349704, -0.535040, 0.792292, -0.293266,
+-1.336982, 10.239292, 12.641662, 0.500000, -1.349954, -0.999218, -0.036495, 0.015192,
+-1.336982, 10.239292, 12.641662, 0.500000, -1.349954, -0.999218, -0.036495, 0.015192,
+-1.002737, 9.694744, 12.910284, 1.000000, -1.349954, -0.500990, -0.803388, 0.321833,
+-1.002737, 10.760361, 14.994465, 1.000000, -1.516370, -0.490912, -0.740187, 0.459488,
+-1.002737, 10.760361, 14.994465, 1.000000, -1.516370, -0.490912, -0.740187, 0.459488,
+-1.002737, 12.090717, 16.772659, 1.000000, -1.679268, -0.484165, -0.653669, 0.581636,
+-1.336982, 12.495934, 16.355419, 0.500000, -1.679268, -0.999037, -0.033130, 0.028753,
+-1.336982, 12.495934, 16.355419, 0.500000, -1.679268, -0.999037, -0.033130, 0.028753,
+-1.002737, 12.901150, 15.938179, 0.000000, -1.683037, -0.520176, 0.645820, -0.558867,
+-1.002737, 11.718807, 14.305887, 0.000000, -1.516370, -0.524951, 0.731928, -0.434405,
+-1.002737, 14.227100, 17.202572, 0.000000, -1.834628, -0.519663, 0.527798, -0.671848,
+-1.002737, 12.901150, 15.938179, 0.000000, -1.683037, -0.520176, 0.645820, -0.558867,
+-1.336982, 12.495934, 16.355419, 0.500000, -1.679268, -0.999037, -0.033130, 0.028753,
+-1.336982, 12.495934, 16.355419, 0.500000, -1.679268, -0.999037, -0.033130, 0.028753,
+-1.002737, 12.090717, 16.772659, 1.000000, -1.679268, -0.484165, -0.653669, 0.581636,
+-1.002737, 13.576077, 18.160946, 1.000000, -1.834628, -0.481336, -0.535363, 0.694048,
+-1.002737, 13.576077, 18.160946, 1.000000, -1.834628, -0.481336, -0.535363, 0.694048,
+-1.002737, 15.212280, 19.181923, 1.000000, -1.988039, -0.480827, -0.389724, 0.785443,
+-1.336982, 15.450417, 18.654261, 0.500000, -1.988039, -0.998886, -0.021466, 0.042031,
+-1.336982, 15.450417, 18.654261, 0.500000, -1.988039, -0.998886, -0.021466, 0.042031,
+-1.002737, 15.688553, 18.126600, 0.000000, -1.986219, -0.519424, 0.384311, -0.763219,
+-1.002737, 14.227100, 17.202572, 0.000000, -1.834628, -0.519663, 0.527798, -0.671848,
+-1.002737, 17.277420, 18.737804, 0.000000, -2.145087, -0.519855, 0.222506, -0.824768,
+-1.002737, 15.688553, 18.126600, 0.000000, -1.986219, -0.519424, 0.384311, -0.763219,
+-1.336982, 15.450417, 18.654261, 0.500000, -1.988039, -0.998886, -0.021466, 0.042031,
+-1.336982, 15.450417, 18.654261, 0.500000, -1.988039, -0.998886, -0.021466, 0.042031,
+-1.002737, 15.212280, 19.181923, 1.000000, -1.988039, -0.480827, -0.389724, 0.785443,
+-1.002737, 16.995155, 19.858189, 1.000000, -2.145087, -0.479530, -0.225145, 0.848151,
+-1.002737, 16.995155, 19.858189, 1.000000, -2.145087, -0.479530, -0.225145, 0.848151,
+-1.002737, 18.890533, 20.158619, 1.000000, -2.305904, -0.477686, -0.044014, 0.877427,
+-1.336982, 18.926823, 19.584188, 0.500000, -2.305904, -0.998704, -0.001978, 0.050855,
+-1.336982, 18.926823, 19.584188, 0.500000, -2.305904, -0.998704, -0.001978, 0.050855,
+-1.002737, 18.963112, 19.009758, 0.000000, -2.303954, -0.519106, 0.044200, -0.853567,
+-1.002737, 17.277420, 18.737804, 0.000000, -2.145087, -0.519855, 0.222506, -0.824768,
+-1.002737, 20.715042, 18.916035, 0.000000, -2.470621, -0.518180, -0.147145, -0.842519,
+-1.002737, 18.963112, 19.009758, 0.000000, -2.303954, -0.519106, 0.044200, -0.853567,
+-1.336982, 18.926823, 19.584188, 0.500000, -2.305904, -0.998704, -0.001978, 0.050855,
+-1.336982, 18.926823, 19.584188, 0.500000, -2.305904, -0.998704, -0.001978, 0.050855,
+-1.002737, 18.890533, 20.158619, 1.000000, -2.305904, -0.477686, -0.044014, 0.877427,
+-1.002737, 20.864250, 20.052088, 1.000000, -2.470621, -0.474232, 0.150976, 0.867358,
+-1.002737, 20.864250, 20.052088, 1.000000, -2.470621, -0.474232, 0.150976, 0.867358,
+-1.002737, 22.911228, 19.457972, 1.000000, -2.646001, -0.471248, 0.342725, 0.812690,
+-1.336982, 22.719658, 18.922981, 0.500000, -2.646001, -0.998523, 0.022590, 0.049420,
+-1.336982, 22.719658, 18.922981, 0.500000, -2.646001, -0.998523, 0.022590, 0.049420,
+-1.002737, 22.528088, 18.387989, 0.000000, -2.637287, -0.514483, -0.334572, -0.789537,
+-1.002737, 20.715042, 18.916035, 0.000000, -2.470621, -0.518180, -0.147145, -0.842519,
+-1.002737, 24.397125, 17.356983, 0.000000, -2.838810, -0.512162, -0.495528, -0.701529,
+-1.002737, 22.528088, 18.387989, 0.000000, -2.637287, -0.514483, -0.334572, -0.789537,
+-1.336982, 22.719658, 18.922981, 0.500000, -2.646001, -0.998523, 0.022590, 0.049420,
+-1.336982, 22.719658, 18.922981, 0.500000, -2.646001, -0.998523, 0.022590, 0.049420,
+-1.002737, 22.911228, 19.457972, 1.000000, -2.646001, -0.471248, 0.342725, 0.812690,
+-1.002737, 25.026405, 18.295650, 1.000000, -2.838810, -0.470077, 0.507995, 0.721781,
+-1.002737, 25.026405, 18.295650, 1.000000, -2.838810, -0.470077, 0.507995, 0.721781,
+-1.002737, 26.982025, 16.592329, 1.000000, -3.038383, -0.470672, 0.656259, 0.589739,
+-1.336982, 26.551086, 16.221825, 0.500000, -3.038383, -0.998387, 0.041476, 0.038776,
+-1.336982, 26.551086, 16.221825, 0.500000, -3.038383, -0.998387, 0.041476, 0.038776,
+-1.002737, 26.120163, 15.851318, 0.000000, -3.040334, -0.515999, -0.637877, -0.571716,
+-1.002737, 24.397125, 17.356983, 0.000000, -2.838810, -0.512162, -0.495528, -0.701529,
+-1.002737, 27.495193, 13.899298, 0.000000, -3.234054, -0.529173, -0.759785, -0.377761,
+-1.002737, 26.120163, 15.851318, 0.000000, -3.040334, -0.515999, -0.637877, -0.571716,
+-1.336982, 26.551086, 16.221825, 0.500000, -3.038383, -0.998387, 0.041476, 0.038776,
+-1.336982, 26.551086, 16.221825, 0.500000, -3.038383, -0.998387, 0.041476, 0.038776,
+-1.002737, 26.982025, 16.592329, 1.000000, -3.038383, -0.470672, 0.656259, 0.589739,
+-1.002737, 28.550339, 14.375221, 1.000000, -3.234054, -0.475606, 0.784875, 0.397203,
+-1.002737, 28.550339, 14.375221, 1.000000, -3.234054, -0.475606, 0.784875, 0.397203,
+-1.002737, 29.425041, 11.768046, 1.000000, -3.421010, -0.486094, 0.865825, 0.118573,
+-1.336982, 28.829937, 11.681159, 0.500000, -3.421010, -0.997287, 0.072725, 0.011376,
+-1.336982, 28.829937, 11.681159, 0.500000, -3.421010, -0.997287, 0.072725, 0.011376,
+-1.002737, 28.234837, 11.594271, 0.000000, -3.427773, -0.549861, -0.829859, -0.094800,
+-1.002737, 27.495193, 13.899298, 0.000000, -3.234054, -0.529173, -0.759785, -0.377761,
+-1.002737, 28.051701, 9.029581, 0.000000, -3.594440, -0.552394, -0.818572, 0.157487,
+-1.002737, 28.234837, 11.594271, 0.000000, -3.427773, -0.549861, -0.829859, -0.094800,
+-1.336982, 28.829937, 11.681159, 0.500000, -3.421010, -0.997287, 0.072725, 0.011376,
+-1.336982, 28.829937, 11.681159, 0.500000, -3.421010, -0.997287, 0.072725, 0.011376,
+-1.002737, 29.425041, 11.768046, 1.000000, -3.421010, -0.486094, 0.865825, 0.118573,
+-1.002737, 29.299828, 8.894522, 1.000000, -3.594440, -0.508085, 0.850361, -0.136877,
+-1.002737, 29.299828, 8.894522, 1.000000, -3.594440, -0.508085, 0.850361, -0.136877,
+-1.002737, 28.522129, 6.172330, 1.000000, -3.741287, -0.527924, 0.793569, -0.302563,
+-1.336982, 27.897224, 6.377859, 0.500000, -3.741288, -0.999306, 0.035287, -0.011950,
+-1.336982, 27.897224, 6.377859, 0.500000, -3.741288, -0.999306, 0.035287, -0.011950,
+-1.002737, 27.272324, 6.583387, 0.000000, -3.761107, -0.563170, -0.762896, 0.317537,
+-1.002737, 28.051701, 9.029581, 0.000000, -3.594440, -0.552394, -0.818572, 0.157487,
+-1.002737, 26.223228, 4.633848, 0.000000, -3.848496, -0.571231, -0.699650, 0.429169,
+-1.002737, 27.272324, 6.583387, 0.000000, -3.761107, -0.563170, -0.762896, 0.317537,
+-1.336982, 27.897224, 6.377859, 0.500000, -3.741288, -0.999306, 0.035287, -0.011950,
+-1.336982, 27.897224, 6.377859, 0.500000, -3.741288, -0.999306, 0.035287, -0.011950,
+-1.002737, 28.522129, 6.172330, 1.000000, -3.741287, -0.527924, 0.793569, -0.302563,
+-1.002737, 27.439381, 4.019153, 1.000000, -3.848496, -0.545786, 0.725589, -0.419091,
+-1.002737, 27.439381, 4.019153, 1.000000, -3.848496, -0.545786, 0.725589, -0.419091,
+-1.002737, 26.363422, 2.436586, 1.020833, -3.882167, -0.561369, 0.675750, -0.477732,
+-1.336982, 25.778152, 2.814326, 0.583333, -3.762508, -0.999924, 0.011227, -0.005182,
+-1.336982, 25.778152, 2.814326, 0.583333, -3.762508, -0.999924, 0.011227, -0.005182,
+-1.002737, 25.192875, 3.192066, 0.000000, -3.935886, -0.573805, -0.657830, 0.487860,
+-1.002737, 26.223228, 4.633848, 0.000000, -3.848496, -0.571231, -0.699650, 0.429169,
+-1.002737, 24.600067, 1.327282, 1.166667, -2.723639, -0.595697, -0.491752, -0.635079,
+-0.742768, 24.296909, 1.783397, 1.333333, -1.447277, -0.428917, -0.894621, -0.125234,
+-1.002737, 24.469711, 2.269146, 0.666667, -2.691582, -0.583534, -0.710408, 0.393458,
+-1.002737, 24.469711, 2.269146, 0.666667, -2.691582, -0.583534, -0.710408, 0.393458,
+-1.002737, 25.192875, 3.192066, 0.000000, -3.935886, -0.573805, -0.657830, 0.487860,
+-1.336982, 25.778152, 2.814326, 0.583333, -3.762508, -0.999924, 0.011227, -0.005182,
+-1.336982, 25.778152, 2.814326, 0.583333, -3.762508, -0.999924, 0.011227, -0.005182,
+-1.002737, 26.363422, 2.436586, 1.020833, -3.882167, -0.561369, 0.675750, -0.477732,
+-1.002737, 25.606094, 1.426226, 1.083333, -3.808398, -0.572183, 0.564519, -0.594916,
+-1.002737, 25.606094, 1.426226, 1.083333, -3.808398, -0.572183, 0.564519, -0.594916,
+-0.742768, 25.130249, 1.141007, 1.000000, -4.000000, -0.424007, 0.088516, -0.901323,
+-1.002737, 24.600067, 1.327282, 1.166667, -2.723639, -0.595697, -0.491752, -0.635079,
+1.002737, 3.502487, -29.476650, 2.000000, 0.966243, 0.570521, -0.819696, 0.051023,
+1.002737, 3.589725, -28.074989, 2.000000, 0.922656, 0.569426, -0.818637, 0.074745,
+0.000000, 3.355162, -28.055641, 1.500000, 0.922656, -0.000000, -0.995829, 0.091245,
+0.000000, 3.355162, -28.055641, 1.500000, 0.922656, -0.000000, -0.995829, 0.091245,
+-1.002737, 3.589727, -28.074986, 1.000000, 0.922656, -0.569426, -0.818637, 0.074745,
+-1.002737, 3.502487, -29.476650, 1.000000, 0.966243, -0.570521, -0.819696, 0.051023,
+-1.002737, 3.807196, -26.139326, 1.000000, 0.859409, -0.566467, -0.814177, 0.127399,
+-1.002737, 3.589727, -28.074986, 1.000000, 0.922656, -0.569426, -0.818637, 0.074745,
+0.000000, 3.355162, -28.055641, 1.500000, 0.922656, -0.000000, -0.995829, 0.091245,
+0.000000, 3.355162, -28.055641, 1.500000, 0.922656, -0.000000, -0.995829, 0.091245,
+1.002737, 3.589725, -28.074989, 2.000000, 0.922656, 0.569426, -0.818637, 0.074745,
+1.002737, 3.807196, -26.139326, 2.000000, 0.859409, 0.566467, -0.814178, 0.127399,
+1.002737, 3.807196, -26.139326, 2.000000, 0.859409, 0.566467, -0.814178, 0.127399,
+1.002737, 4.261988, -23.779171, 2.000000, 0.775297, 0.564634, -0.800896, 0.199384,
+0.000000, 4.032219, -23.733923, 1.500000, 0.775297, 0.000000, -0.970479, 0.241185,
+0.000000, 4.032219, -23.733923, 1.500000, 0.775297, 0.000000, -0.970479, 0.241185,
+-1.002737, 4.261988, -23.779169, 1.000000, 0.775297, -0.564634, -0.800896, 0.199384,
+-1.002737, 3.807196, -26.139326, 1.000000, 0.859409, -0.566467, -0.814177, 0.127399,
+-1.002737, 5.061195, -21.104027, 1.000000, 0.669113, -0.566458, -0.779905, 0.266220,
+-1.002737, 4.261988, -23.779169, 1.000000, 0.775297, -0.564634, -0.800896, 0.199384,
+0.000000, 4.032219, -23.733923, 1.500000, 0.775297, 0.000000, -0.970479, 0.241185,
+0.000000, 4.032219, -23.733923, 1.500000, 0.775297, 0.000000, -0.970479, 0.241185,
+1.002737, 4.261988, -23.779171, 2.000000, 0.775297, 0.564634, -0.800896, 0.199384,
+1.002737, 5.061195, -21.104025, 2.000000, 0.669113, 0.566458, -0.779905, 0.266220,
+1.002737, 5.061195, -21.104025, 2.000000, 0.669113, 0.566458, -0.779905, 0.266220,
+1.002737, 6.120935, -18.335461, 2.000000, 0.547971, 0.566613, -0.758528, 0.321845,
+0.000000, 5.893641, -18.274008, 1.500000, 0.547971, -0.000000, -0.920850, 0.389917,
+0.000000, 5.893641, -18.274008, 1.500000, 0.547971, -0.000000, -0.920850, 0.389917,
+-1.002737, 6.120935, -18.335461, 1.000000, 0.547971, -0.566613, -0.758528, 0.321845,
+-1.002737, 5.061195, -21.104027, 1.000000, 0.669113, -0.566458, -0.779905, 0.266220,
+-1.002737, 7.357327, -15.695049, 1.000000, 0.418984, -0.568348, -0.740553, 0.358555,
+-1.002737, 6.120935, -18.335461, 1.000000, 0.547971, -0.566613, -0.758528, 0.321845,
+0.000000, 5.893641, -18.274008, 1.500000, 0.547971, -0.000000, -0.920850, 0.389917,
+0.000000, 5.893641, -18.274008, 1.500000, 0.547971, -0.000000, -0.920850, 0.389917,
+1.002737, 6.120935, -18.335461, 2.000000, 0.547971, 0.566613, -0.758528, 0.321845,
+1.002737, 7.357327, -15.695049, 2.000000, 0.418984, 0.568348, -0.740553, 0.358555,
+1.002737, 7.357327, -15.695049, 2.000000, 0.418984, 0.568348, -0.740553, 0.358555,
+1.002737, 8.627859, -13.158705, 2.000000, 0.282904, 0.571429, -0.737705, 0.359528,
+0.000000, 8.398937, -13.100854, 1.500000, 0.282904, 0.000000, -0.898731, 0.438502,
+0.000000, 8.398937, -13.100854, 1.500000, 0.282904, 0.000000, -0.898731, 0.438502,
+-1.002737, 8.627859, -13.158705, 1.000000, 0.282904, -0.571429, -0.737705, 0.359528,
+-1.002737, 7.357327, -15.695049, 1.000000, 0.418984, -0.568348, -0.740553, 0.358555,
+-1.002737, 9.790028, -10.702334, 1.000000, 0.140482, -0.576949, -0.747604, 0.328966,
+-1.002737, 8.627859, -13.158705, 1.000000, 0.282904, -0.571429, -0.737705, 0.359528,
+0.000000, 8.398937, -13.100854, 1.500000, 0.282904, 0.000000, -0.898731, 0.438502,
+0.000000, 8.398937, -13.100854, 1.500000, 0.282904, 0.000000, -0.898731, 0.438502,
+1.002737, 8.627859, -13.158705, 2.000000, 0.282904, 0.571429, -0.737705, 0.359528,
+1.002737, 9.790028, -10.702334, 2.000000, 0.140482, 0.576977, -0.747533, 0.329077,
+1.002737, 9.790028, -10.702334, 2.000000, 0.140482, 0.576977, -0.747533, 0.329077,
+1.002127, 10.657795, -8.543959, 2.000000, 0.010562, 0.588607, -0.767452, 0.254084,
+-0.000610, 10.425087, -8.501664, 1.500000, 0.010562, 0.000044, -0.949091, 0.315003,
+-0.000610, 10.425087, -8.501664, 1.500000, 0.010562, 0.000044, -0.949091, 0.315003,
+-1.003346, 10.657795, -8.543959, 1.020833, -0.009381, -0.588551, -0.767718, 0.253411,
+-1.002737, 9.790028, -10.702334, 1.000000, 0.140482, -0.576949, -0.747604, 0.328966,
+-1.005175, 11.045135, -6.901599, 1.083333, -0.167786, -0.591577, -0.797310, 0.119726,
+-1.003346, 10.657795, -8.543959, 1.020833, -0.009381, -0.588551, -0.767718, 0.253411,
+-0.000610, 10.425087, -8.501664, 1.500000, 0.010562, 0.000044, -0.949091, 0.315003,
+-0.000610, 10.425087, -8.501664, 1.500000, 0.010562, 0.000044, -0.949091, 0.315003,
+1.002127, 10.657795, -8.543959, 2.000000, 0.010562, 0.588607, -0.767452, 0.254084,
+1.000299, 11.045135, -6.901599, 2.000000, -0.088013, 0.591516, -0.797171, 0.120947,
+1.000299, 11.045135, -6.901599, 2.000000, -0.088013, 0.591516, -0.797171, 0.120947,
+0.999079, 11.114811, -5.517140, 2.000000, -0.170915, 0.582792, -0.812607, -0.004817,
+-0.003657, 10.880220, -5.483850, 1.500000, -0.170915, -0.000127, -0.999975, -0.007088,
+-0.003657, 10.880220, -5.483850, 1.500000, -0.170915, -0.000127, -0.999975, -0.007088,
+-1.006394, 11.114811, -5.517140, 1.000000, -0.170915, -0.583093, -0.812392, -0.004755,
+-1.005175, 11.045135, -6.901599, 1.083333, -0.167786, -0.591577, -0.797310, 0.119726,
+-1.002737, 10.154959, -0.010050, 1.000000, -0.503387, -0.554465, -0.809442, -0.193318,
+-1.003346, 10.729588, -2.409474, 1.000000, -0.336720, -0.568927, -0.804482, -0.170679,
+-0.000610, 10.494156, -2.383091, 1.500000, -0.336720, 0.000040, -0.977947, -0.208854,
+-0.000610, 10.494156, -2.383091, 1.500000, -0.336720, 0.000040, -0.977947, -0.208854,
+1.002127, 10.729588, -2.409474, 2.000000, -0.336720, 0.568931, -0.804350, -0.171283,
+1.002737, 10.154957, -0.010050, 2.000000, -0.503387, 0.554487, -0.809403, -0.193422,
+1.002737, 10.154957, -0.010050, 2.000000, -0.503387, 0.554487, -0.809403, -0.193422,
+1.002737, 9.503082, 2.725576, 2.000000, -0.671927, 0.543427, -0.820485, -0.177458,
+0.000000, 9.272461, 2.752070, 1.500000, -0.671927, -0.000000, -0.977791, -0.209581,
+0.000000, 9.272461, 2.752070, 1.500000, -0.671927, -0.000000, -0.977791, -0.209581,
+-1.002737, 9.503082, 2.725576, 1.000000, -0.671927, -0.543427, -0.820485, -0.177458,
+-1.002737, 10.154959, -0.010050, 1.000000, -0.503387, -0.554465, -0.809442, -0.193318,
+-1.002737, 8.971350, 5.457178, 1.000000, -0.844213, -0.532911, -0.837943, -0.117722,
+-1.002737, 9.503082, 2.725576, 1.000000, -0.671927, -0.543427, -0.820485, -0.177458,
+0.000000, 9.272461, 2.752070, 1.500000, -0.671927, -0.000000, -0.977791, -0.209581,
+0.000000, 9.272461, 2.752070, 1.500000, -0.671927, -0.000000, -0.977791, -0.209581,
+1.002737, 9.503082, 2.725576, 2.000000, -0.671927, 0.543427, -0.820485, -0.177458,
+1.002737, 8.971350, 5.457179, 2.000000, -0.844213, 0.532911, -0.837943, -0.117722,
+1.002737, 8.971350, 5.457179, 2.000000, -0.844213, 0.532911, -0.837943, -0.117722,
+1.002737, 8.743584, 8.108689, 2.000000, -1.016250, 0.522039, -0.852900, 0.006099,
+0.000000, 8.530107, 8.155542, 1.500000, -1.016250, 0.000000, -0.999937, 0.011225,
+0.000000, 8.530107, 8.155542, 1.500000, -1.016250, 0.000000, -0.999937, 0.011225,
+-1.002737, 8.743584, 8.108688, 1.000000, -1.016250, -0.522039, -0.852900, 0.006099,
+-1.002737, 8.971350, 5.457178, 1.000000, -0.844213, -0.532911, -0.837943, -0.117722,
+-1.002737, 9.003599, 10.604042, 1.000000, -1.184038, -0.512969, -0.841946, 0.167304,
+-1.002737, 8.743584, 8.108688, 1.000000, -1.016250, -0.522039, -0.852900, 0.006099,
+0.000000, 8.530107, 8.155542, 1.500000, -1.016250, 0.000000, -0.999937, 0.011225,
+0.000000, 8.530107, 8.155542, 1.500000, -1.016250, 0.000000, -0.999937, 0.011225,
+1.002737, 8.743584, 8.108689, 2.000000, -1.016250, 0.522039, -0.852900, 0.006099,
+1.002737, 9.003599, 10.604041, 2.000000, -1.184038, 0.512969, -0.841946, 0.167304,
+1.002737, 9.003599, 10.604041, 2.000000, -1.184038, 0.512969, -0.841946, 0.167304,
+1.002737, 9.694744, 12.910284, 2.000000, -1.349954, 0.500990, -0.803388, 0.321833,
+0.000000, 9.513226, 12.999825, 1.500000, -1.349954, 0.000000, -0.927387, 0.374104,
+0.000000, 9.513226, 12.999825, 1.500000, -1.349954, 0.000000, -0.927387, 0.374104,
+-1.002737, 9.694744, 12.910284, 1.000000, -1.349954, -0.500990, -0.803388, 0.321833,
+-1.002737, 9.003599, 10.604042, 1.000000, -1.184038, -0.512969, -0.841946, 0.167304,
+-1.002737, 10.760361, 14.994465, 1.000000, -1.516370, -0.490912, -0.740187, 0.459488,
+-1.002737, 9.694744, 12.910284, 1.000000, -1.349954, -0.500990, -0.803388, 0.321833,
+0.000000, 9.513226, 12.999825, 1.500000, -1.349954, 0.000000, -0.927387, 0.374104,
+0.000000, 9.513226, 12.999825, 1.500000, -1.349954, 0.000000, -0.927387, 0.374104,
+1.002737, 9.694744, 12.910284, 2.000000, -1.349954, 0.500990, -0.803388, 0.321833,
+1.002737, 10.760361, 14.994465, 2.000000, -1.516370, 0.490912, -0.740187, 0.459488,
+1.002737, 10.760361, 14.994465, 2.000000, -1.516370, 0.490912, -0.740187, 0.459488,
+1.002737, 12.090717, 16.772659, 2.000000, -1.679268, 0.484165, -0.653669, 0.581636,
+0.000000, 11.955647, 16.911739, 1.500000, -1.679268, 0.000000, -0.746148, 0.665780,
+0.000000, 11.955647, 16.911739, 1.500000, -1.679268, 0.000000, -0.746148, 0.665780,
+-1.002737, 12.090717, 16.772659, 1.000000, -1.679268, -0.484165, -0.653669, 0.581636,
+-1.002737, 10.760361, 14.994465, 1.000000, -1.516370, -0.490912, -0.740187, 0.459488,
+-1.002737, 13.576077, 18.160946, 1.000000, -1.834628, -0.481336, -0.535363, 0.694048,
+-1.002737, 12.090717, 16.772659, 1.000000, -1.679268, -0.484165, -0.653669, 0.581636,
+0.000000, 11.955647, 16.911739, 1.500000, -1.679268, 0.000000, -0.746148, 0.665780,
+0.000000, 11.955647, 16.911739, 1.500000, -1.679268, 0.000000, -0.746148, 0.665780,
+1.002737, 12.090717, 16.772659, 2.000000, -1.679268, 0.484165, -0.653669, 0.581636,
+1.002737, 13.576080, 18.160946, 2.000000, -1.834628, 0.481336, -0.535363, 0.694048,
+1.002737, 13.576080, 18.160946, 2.000000, -1.834628, 0.481336, -0.535363, 0.694048,
+1.002737, 15.212280, 19.181923, 2.000000, -1.988039, 0.480828, -0.389724, 0.785442,
+0.000000, 15.132900, 19.357809, 1.500000, -1.988039, 0.000001, -0.443892, 0.896080,
+0.000000, 15.132900, 19.357809, 1.500000, -1.988039, 0.000001, -0.443892, 0.896080,
+-1.002737, 15.212280, 19.181923, 1.000000, -1.988039, -0.480827, -0.389724, 0.785443,
+-1.002737, 13.576077, 18.160946, 1.000000, -1.834628, -0.481336, -0.535363, 0.694048,
+-1.002737, 16.995155, 19.858189, 1.000000, -2.145087, -0.479530, -0.225145, 0.848151,
+-1.002737, 15.212280, 19.181923, 1.000000, -1.988039, -0.480827, -0.389724, 0.785443,
+0.000000, 15.132900, 19.357809, 1.500000, -1.988039, 0.000001, -0.443892, 0.896080,
+0.000000, 15.132900, 19.357809, 1.500000, -1.988039, 0.000001, -0.443892, 0.896080,
+1.002737, 15.212280, 19.181923, 2.000000, -1.988039, 0.480828, -0.389724, 0.785442,
+1.002737, 16.995155, 19.858189, 2.000000, -2.145087, 0.479530, -0.225145, 0.848151,
+1.002737, 16.995155, 19.858189, 2.000000, -2.145087, 0.479530, -0.225145, 0.848151,
+1.002737, 18.890533, 20.158619, 2.000000, -2.305904, 0.477686, -0.044014, 0.877427,
+0.000000, 18.878441, 20.350098, 1.500000, -2.305904, 0.000000, -0.050074, 0.998746,
+0.000000, 18.878441, 20.350098, 1.500000, -2.305904, 0.000000, -0.050074, 0.998746,
+-1.002737, 18.890533, 20.158619, 1.000000, -2.305904, -0.477686, -0.044014, 0.877427,
+-1.002737, 16.995155, 19.858189, 1.000000, -2.145087, -0.479530, -0.225145, 0.848151,
+-1.002737, 20.864250, 20.052088, 1.000000, -2.470621, -0.474232, 0.150976, 0.867358,
+-1.002737, 18.890533, 20.158619, 1.000000, -2.305904, -0.477686, -0.044014, 0.877427,
+0.000000, 18.878441, 20.350098, 1.500000, -2.305904, 0.000000, -0.050074, 0.998746,
+0.000000, 18.878441, 20.350098, 1.500000, -2.305904, 0.000000, -0.050074, 0.998746,
+1.002737, 18.890533, 20.158619, 2.000000, -2.305904, 0.477686, -0.044014, 0.877427,
+1.002737, 20.864250, 20.052088, 2.000000, -2.470621, 0.474231, 0.150976, 0.867359,
+1.002737, 20.864250, 20.052088, 2.000000, -2.470621, 0.474231, 0.150976, 0.867359,
+1.002737, 22.911228, 19.457972, 2.000000, -2.646001, 0.471248, 0.342725, 0.812690,
+0.000000, 22.975082, 19.636301, 1.500000, -2.646001, 0.000000, 0.388135, 0.921603,
+0.000000, 22.975082, 19.636301, 1.500000, -2.646001, 0.000000, 0.388135, 0.921603,
+-1.002737, 22.911228, 19.457972, 1.000000, -2.646001, -0.471248, 0.342725, 0.812690,
+-1.002737, 20.864250, 20.052088, 1.000000, -2.470621, -0.474232, 0.150976, 0.867358,
+-1.002737, 25.026405, 18.295650, 1.000000, -2.838810, -0.470077, 0.507995, 0.721781,
+-1.002737, 22.911228, 19.457972, 1.000000, -2.646001, -0.471248, 0.342725, 0.812690,
+0.000000, 22.975082, 19.636301, 1.500000, -2.646001, 0.000000, 0.388135, 0.921603,
+0.000000, 22.975082, 19.636301, 1.500000, -2.646001, 0.000000, 0.388135, 0.921603,
+1.002737, 22.911228, 19.457972, 2.000000, -2.646001, 0.471248, 0.342725, 0.812690,
+1.002737, 25.026405, 18.295650, 2.000000, -2.838810, 0.470077, 0.507995, 0.721781,
+1.002737, 25.026405, 18.295650, 2.000000, -2.838810, 0.470077, 0.507995, 0.721781,
+1.002737, 26.982021, 16.592329, 2.000000, -3.038383, 0.470672, 0.656258, 0.589740,
+0.000000, 27.125668, 16.715830, 1.500000, -3.038383, 0.000001, 0.743876, 0.668318,
+0.000000, 27.125668, 16.715830, 1.500000, -3.038383, 0.000001, 0.743876, 0.668318,
+-1.002737, 26.982025, 16.592329, 1.000000, -3.038383, -0.470672, 0.656259, 0.589739,
+-1.002737, 25.026405, 18.295650, 1.000000, -2.838810, -0.470077, 0.507995, 0.721781,
+-1.002737, 28.550339, 14.375221, 1.000000, -3.234054, -0.475606, 0.784875, 0.397203,
+-1.002737, 26.982025, 16.592329, 1.000000, -3.038383, -0.470672, 0.656259, 0.589739,
+0.000000, 27.125668, 16.715830, 1.500000, -3.038383, 0.000001, 0.743876, 0.668318,
+0.000000, 27.125668, 16.715830, 1.500000, -3.038383, 0.000001, 0.743876, 0.668318,
+1.002737, 26.982021, 16.592329, 2.000000, -3.038383, 0.470672, 0.656258, 0.589740,
+1.002737, 28.550339, 14.375221, 2.000000, -3.234054, 0.475606, 0.784875, 0.397204,
+1.002737, 28.550339, 14.375221, 2.000000, -3.234054, 0.475606, 0.784875, 0.397204,
+1.002737, 29.425041, 11.768046, 2.000000, -3.421010, 0.486093, 0.865826, 0.118573,
+0.000000, 29.623409, 11.797009, 1.500000, -3.421010, 0.000000, 0.990552, 0.137137,
+0.000000, 29.623409, 11.797009, 1.500000, -3.421010, 0.000000, 0.990552, 0.137137,
+-1.002737, 29.425041, 11.768046, 1.000000, -3.421010, -0.486094, 0.865825, 0.118573,
+-1.002737, 28.550339, 14.375221, 1.000000, -3.234054, -0.475606, 0.784875, 0.397203,
+-1.002737, 29.299828, 8.894522, 1.000000, -3.594440, -0.508085, 0.850361, -0.136877,
+-1.002737, 29.425041, 11.768046, 1.000000, -3.421010, -0.486094, 0.865825, 0.118573,
+0.000000, 29.623409, 11.797009, 1.500000, -3.421010, 0.000000, 0.990552, 0.137137,
+0.000000, 29.623409, 11.797009, 1.500000, -3.421010, 0.000000, 0.990552, 0.137137,
+1.002737, 29.425041, 11.768046, 2.000000, -3.421010, 0.486093, 0.865826, 0.118573,
+1.002737, 29.299828, 8.894522, 2.000000, -3.594440, 0.508084, 0.850362, -0.136877,
+1.002737, 29.299828, 8.894522, 2.000000, -3.594440, 0.508084, 0.850362, -0.136877,
+1.002737, 28.522129, 6.172330, 2.000000, -3.741287, 0.527923, 0.793569, -0.302564,
+0.000000, 28.730427, 6.103821, 1.500000, -3.741288, 0.000000, 0.935308, -0.353834,
+0.000000, 28.730427, 6.103821, 1.500000, -3.741288, 0.000000, 0.935308, -0.353834,
+-1.002737, 28.522129, 6.172330, 1.000000, -3.741287, -0.527924, 0.793569, -0.302563,
+-1.002737, 29.299828, 8.894522, 1.000000, -3.594440, -0.508085, 0.850361, -0.136877,
+-1.002737, 27.439381, 4.019153, 1.000000, -3.848496, -0.545786, 0.725589, -0.419091,
+-1.002737, 28.522129, 6.172330, 1.000000, -3.741287, -0.527924, 0.793569, -0.302563,
+0.000000, 28.730427, 6.103821, 1.500000, -3.741288, 0.000000, 0.935308, -0.353834,
+0.000000, 28.730427, 6.103821, 1.500000, -3.741288, 0.000000, 0.935308, -0.353834,
+1.002737, 28.522129, 6.172330, 2.000000, -3.741287, 0.527923, 0.793569, -0.302564,
+1.002737, 27.439377, 4.019153, 2.000000, -3.848496, 0.545786, 0.725589, -0.419091,
+1.002737, 27.439377, 4.019153, 2.000000, -3.848496, 0.545786, 0.725589, -0.419091,
+1.002737, 26.363422, 2.436586, 2.000000, -3.922053, 0.561369, 0.675750, -0.477732,
+0.000000, 26.558514, 2.310673, 1.500000, -3.922053, 0.000001, 0.817607, -0.575776,
+0.000000, 26.558514, 2.310673, 1.500000, -3.922053, 0.000001, 0.817607, -0.575776,
+-1.002737, 26.363422, 2.436586, 1.020833, -3.882167, -0.561369, 0.675750, -0.477732,
+-1.002737, 27.439381, 4.019153, 1.000000, -3.848496, -0.545786, 0.725589, -0.419091,
+0.000000, 25.158775, 0.885566, 1.500000, -4.000000, 0.000000, 0.098978, -0.995090,
+-0.742768, 25.130249, 1.141007, 1.000000, -4.000000, -0.424007, 0.088516, -0.901323,
+-1.002737, 25.606094, 1.426226, 1.083333, -3.808398, -0.572183, 0.564519, -0.594916,
+-1.002737, 25.606094, 1.426226, 1.083333, -3.808398, -0.572183, 0.564519, -0.594916,
+-1.002737, 26.363422, 2.436586, 1.020833, -3.882167, -0.561369, 0.675750, -0.477732,
+0.000000, 26.558514, 2.310673, 1.500000, -3.922053, 0.000001, 0.817607, -0.575776,
+0.000000, 26.558514, 2.310673, 1.500000, -3.922053, 0.000001, 0.817607, -0.575776,
+1.002737, 26.363422, 2.436586, 2.000000, -3.922053, 0.561369, 0.675750, -0.477732,
+1.002737, 25.606094, 1.426226, 2.000000, -3.967943, 0.572183, 0.564519, -0.594916,
+1.002737, 25.606094, 1.426226, 2.000000, -3.967943, 0.572183, 0.564519, -0.594916,
+0.742768, 25.130249, 1.141007, 2.000000, -4.000000, 0.424007, 0.088516, -0.901323,
+0.000000, 25.158775, 0.885566, 1.500000, -4.000000, 0.000000, 0.098978, -0.995090,
+1.002737, 4.921762, -29.530731, 3.000000, 0.966243, 0.582240, 0.811733, -0.045667,
+1.002737, 4.997122, -28.191074, 3.000000, 0.922656, 0.582175, 0.810004, -0.070467,
+1.336982, 4.293425, -28.133030, 2.500000, 0.922656, 0.999926, -0.012083, 0.001603,
+1.336982, 4.293425, -28.133030, 2.500000, 0.922656, 0.999926, -0.012083, 0.001603,
+1.002737, 3.589725, -28.074989, 2.000000, 0.922656, 0.569426, -0.818637, 0.074745,
+1.002737, 3.502487, -29.476650, 2.000000, 0.966243, 0.570521, -0.819696, 0.051023,
+1.002737, 3.807196, -26.139326, 2.000000, 0.859409, 0.566467, -0.814178, 0.127399,
+1.002737, 3.589725, -28.074989, 2.000000, 0.922656, 0.569426, -0.818637, 0.074745,
+1.336982, 4.293425, -28.133030, 2.500000, 0.922656, 0.999926, -0.012083, 0.001603,
+1.336982, 4.293425, -28.133030, 2.500000, 0.922656, 0.999926, -0.012083, 0.001603,
+1.002737, 4.997122, -28.191074, 3.000000, 0.922656, 0.582175, 0.810004, -0.070467,
+1.002737, 5.199909, -26.333269, 3.000000, 0.859409, 0.582690, 0.803052, -0.124820,
+1.002737, 5.199909, -26.333269, 3.000000, 0.859409, 0.582690, 0.803052, -0.124820,
+1.002737, 5.640600, -24.050657, 3.000000, 0.775297, 0.583127, 0.787897, -0.197941,
+1.336982, 4.951294, -23.914915, 2.500000, 0.775297, 0.999837, -0.017439, 0.004781,
+1.336982, 4.951294, -23.914915, 2.500000, 0.775297, 0.999837, -0.017439, 0.004781,
+1.002737, 4.261988, -23.779171, 2.000000, 0.775297, 0.564634, -0.800896, 0.199384,
+1.002737, 3.807196, -26.139326, 2.000000, 0.859409, 0.566467, -0.814178, 0.127399,
+1.002737, 5.061195, -21.104025, 2.000000, 0.669113, 0.566458, -0.779905, 0.266220,
+1.002737, 4.261988, -23.779171, 2.000000, 0.775297, 0.564634, -0.800896, 0.199384,
+1.336982, 4.951294, -23.914915, 2.500000, 0.775297, 0.999837, -0.017439, 0.004781,
+1.336982, 4.951294, -23.914915, 2.500000, 0.775297, 0.999837, -0.017439, 0.004781,
+1.002737, 5.640600, -24.050657, 3.000000, 0.775297, 0.583127, 0.787897, -0.197941,
+1.002737, 6.429670, -21.436577, 3.000000, 0.669113, 0.579786, 0.770207, -0.265761,
+1.002737, 6.429670, -21.436577, 3.000000, 0.669113, 0.579786, 0.770207, -0.265761,
+1.002737, 7.484703, -18.704170, 3.000000, 0.547971, 0.576888, 0.751119, -0.320970,
+1.336982, 6.802818, -18.519814, 2.500000, 0.547971, 0.999946, -0.009100, 0.005070,
+1.336982, 6.802818, -18.519814, 2.500000, 0.547971, 0.999946, -0.009100, 0.005070,
+1.002737, 6.120935, -18.335461, 2.000000, 0.547971, 0.566613, -0.758528, 0.321845,
+1.002737, 5.061195, -21.104025, 2.000000, 0.669113, 0.566458, -0.779905, 0.266220,
+1.002737, 7.357327, -15.695049, 2.000000, 0.418984, 0.568348, -0.740553, 0.358555,
+1.002737, 6.120935, -18.335461, 2.000000, 0.547971, 0.566613, -0.758528, 0.321845,
+1.336982, 6.802818, -18.519814, 2.500000, 0.547971, 0.999946, -0.009100, 0.005070,
+1.336982, 6.802818, -18.519814, 2.500000, 0.547971, 0.999946, -0.009100, 0.005070,
+1.002737, 7.484703, -18.704170, 3.000000, 0.547971, 0.576888, 0.751119, -0.320970,
+1.002737, 8.723274, -16.066572, 3.000000, 0.418984, 0.570576, 0.739144, -0.357922,
+1.002737, 8.723274, -16.066572, 3.000000, 0.418984, 0.570576, 0.739144, -0.357922,
+1.002737, 10.001389, -13.505806, 3.000000, 0.282904, 0.565597, 0.742254, -0.359389,
+1.336982, 9.314625, -13.332256, 2.500000, 0.282904, 0.999983, 0.005126, -0.002905,
+1.336982, 9.314625, -13.332256, 2.500000, 0.282904, 0.999983, 0.005126, -0.002905,
+1.002737, 8.627859, -13.158705, 2.000000, 0.282904, 0.571429, -0.737705, 0.359528,
+1.002737, 7.357327, -15.695049, 2.000000, 0.418984, 0.568348, -0.740553, 0.358555,
+1.002737, 9.790028, -10.702334, 2.000000, 0.140482, 0.576977, -0.747533, 0.329077,
+1.002737, 8.627859, -13.158705, 2.000000, 0.282904, 0.571429, -0.737705, 0.359528,
+1.336982, 9.314625, -13.332256, 2.500000, 0.282904, 0.999983, 0.005126, -0.002905,
+1.336982, 9.314625, -13.332256, 2.500000, 0.282904, 0.999983, 0.005126, -0.002905,
+1.002737, 10.001389, -13.505806, 3.000000, 0.282904, 0.565597, 0.742254, -0.359389,
+1.002737, 11.175043, -11.003893, 3.000000, 0.140482, 0.562569, 0.757951, -0.330192,
+1.002737, 11.175043, -11.003893, 3.000000, 0.140482, 0.562569, 0.757951, -0.330192,
+1.002127, 12.054029, -8.797724, 2.958333, -0.009381, 0.560195, 0.787255, -0.257702,
+1.336373, 11.355911, -8.670841, 2.500000, 0.010562, 0.999602, 0.026239, -0.010414,
+1.336373, 11.355911, -8.670841, 2.500000, 0.010562, 0.999602, 0.026239, -0.010414,
+1.002127, 10.657795, -8.543959, 2.000000, 0.010562, 0.588607, -0.767452, 0.254084,
+1.002737, 9.790028, -10.702334, 2.000000, 0.140482, 0.576977, -0.747533, 0.329077,
+1.333325, 11.818588, -5.617008, 2.500000, -0.170915, 0.999852, 0.017082, 0.001868,
+0.999079, 11.114811, -5.517140, 2.000000, -0.170915, 0.582792, -0.812607, -0.004817,
+1.000299, 11.045135, -6.901599, 2.000000, -0.088013, 0.591516, -0.797171, 0.120947,
+1.000299, 11.045135, -6.901599, 2.000000, -0.088013, 0.591516, -0.797171, 0.120947,
+1.002127, 10.657795, -8.543959, 2.000000, 0.010562, 0.588607, -0.767452, 0.254084,
+1.336373, 11.355911, -8.670841, 2.500000, 0.010562, 0.999602, 0.026239, -0.010414,
+1.336373, 11.355911, -8.670841, 2.500000, 0.010562, 0.999602, 0.026239, -0.010414,
+1.002127, 12.054029, -8.797724, 2.958333, -0.009381, 0.560195, 0.787255, -0.257702,
+1.000299, 12.448139, -7.124194, 2.833333, -0.167786, 0.564659, 0.816023, -0.123558,
+1.000299, 12.448139, -7.124194, 2.833333, -0.167786, 0.564659, 0.816023, -0.123558,
+0.999079, 12.522362, -5.716876, 3.000000, -0.170915, 0.565733, 0.824587, 0.001687,
+1.333325, 11.818588, -5.617008, 2.500000, -0.170915, 0.999852, 0.017082, 0.001868,
+1.002737, 10.154957, -0.010050, 2.000000, -0.503387, 0.554487, -0.809403, -0.193422,
+1.002127, 10.729588, -2.409474, 2.000000, -0.336720, 0.568931, -0.804350, -0.171283,
+1.336373, 11.435898, -2.488622, 2.500000, -0.336720, 0.999684, 0.024018, 0.007427,
+1.336373, 11.435898, -2.488622, 2.500000, -0.336720, 0.999684, 0.024018, 0.007427,
+1.002127, 12.142200, -2.567771, 3.000000, -0.336720, 0.545588, 0.819894, 0.173516,
+1.002737, 11.560024, -0.158328, 3.000000, -0.503387, 0.548192, 0.812432, 0.198592,
+1.002737, 11.560024, -0.158328, 3.000000, -0.503387, 0.548192, 0.812432, 0.198592,
+1.002737, 10.886791, 2.566613, 3.000000, -0.671927, 0.549613, 0.814083, 0.187601,
+1.336982, 10.194935, 2.646095, 2.500000, -0.671927, 0.999975, -0.006839, -0.001674,
+1.336982, 10.194935, 2.646095, 2.500000, -0.671927, 0.999975, -0.006839, -0.001674,
+1.002737, 9.503082, 2.725576, 2.000000, -0.671927, 0.543427, -0.820485, -0.177458,
+1.002737, 10.154957, -0.010050, 2.000000, -0.503387, 0.554487, -0.809403, -0.193422,
+1.002737, 8.971350, 5.457179, 2.000000, -0.844213, 0.532911, -0.837943, -0.117722,
+1.002737, 9.503082, 2.725576, 2.000000, -0.671927, 0.543427, -0.820485, -0.177458,
+1.336982, 10.194935, 2.646095, 2.500000, -0.671927, 0.999975, -0.006839, -0.001674,
+1.336982, 10.194935, 2.646095, 2.500000, -0.671927, 0.999975, -0.006839, -0.001674,
+1.002737, 10.886791, 2.566613, 3.000000, -0.671927, 0.549613, 0.814083, 0.187601,
+1.002737, 10.314148, 5.254678, 3.000000, -0.844213, 0.550065, 0.824042, 0.135587,
+1.002737, 10.314148, 5.254678, 3.000000, -0.844213, 0.550065, 0.824042, 0.135587,
+1.002737, 10.024445, 7.827566, 3.000000, -1.016250, 0.552727, 0.833125, 0.019881,
+1.336982, 9.384014, 7.968127, 2.500000, -1.016250, 0.999385, -0.034959, -0.002597,
+1.336982, 9.384014, 7.968127, 2.500000, -1.016250, 0.999385, -0.034959, -0.002597,
+1.002737, 8.743584, 8.108689, 2.000000, -1.016250, 0.522039, -0.852900, 0.006099,
+1.002737, 8.971350, 5.457179, 2.000000, -0.844213, 0.532911, -0.837943, -0.117722,
+1.002737, 9.003599, 10.604041, 2.000000, -1.184038, 0.512969, -0.841946, 0.167304,
+1.002737, 8.743584, 8.108689, 2.000000, -1.016250, 0.522039, -0.852900, 0.006099,
+1.336982, 9.384014, 7.968127, 2.500000, -1.016250, 0.999385, -0.034959, -0.002597,
+1.336982, 9.384014, 7.968127, 2.500000, -1.016250, 0.999385, -0.034959, -0.002597,
+1.002737, 10.024445, 7.827566, 3.000000, -1.016250, 0.552727, 0.833125, 0.019881,
+1.002737, 10.200031, 10.206976, 3.000000, -1.184038, 0.545898, 0.826469, -0.137636,
+1.002737, 10.200031, 10.206976, 3.000000, -1.184038, 0.545898, 0.826469, -0.137636,
+1.002737, 10.783842, 12.373039, 3.000000, -1.349954, 0.535040, 0.792292, -0.293267,
+1.336982, 10.239292, 12.641662, 2.500000, -1.349954, 0.999218, -0.036495, 0.015192,
+1.336982, 10.239292, 12.641662, 2.500000, -1.349954, 0.999218, -0.036495, 0.015192,
+1.002737, 9.694744, 12.910284, 2.000000, -1.349954, 0.500990, -0.803388, 0.321833,
+1.002737, 9.003599, 10.604041, 2.000000, -1.184038, 0.512969, -0.841946, 0.167304,
+1.002737, 10.760361, 14.994465, 2.000000, -1.516370, 0.490912, -0.740187, 0.459488,
+1.002737, 9.694744, 12.910284, 2.000000, -1.349954, 0.500990, -0.803388, 0.321833,
+1.336982, 10.239292, 12.641662, 2.500000, -1.349954, 0.999218, -0.036495, 0.015192,
+1.336982, 10.239292, 12.641662, 2.500000, -1.349954, 0.999218, -0.036495, 0.015192,
+1.002737, 10.783842, 12.373039, 3.000000, -1.349954, 0.535040, 0.792292, -0.293267,
+1.002737, 11.718807, 14.305887, 3.000000, -1.516370, 0.524951, 0.731928, -0.434405,
+1.002737, 11.718807, 14.305887, 3.000000, -1.516370, 0.524951, 0.731928, -0.434405,
+1.002737, 12.901150, 15.938179, 3.000000, -1.679268, 0.520177, 0.645820, -0.558867,
+1.336982, 12.495934, 16.355419, 2.500000, -1.679268, 0.999037, -0.033131, 0.028753,
+1.336982, 12.495934, 16.355419, 2.500000, -1.679268, 0.999037, -0.033131, 0.028753,
+1.002737, 12.090717, 16.772659, 2.000000, -1.679268, 0.484165, -0.653669, 0.581636,
+1.002737, 10.760361, 14.994465, 2.000000, -1.516370, 0.490912, -0.740187, 0.459488,
+1.002737, 13.576080, 18.160946, 2.000000, -1.834628, 0.481336, -0.535363, 0.694048,
+1.002737, 12.090717, 16.772659, 2.000000, -1.679268, 0.484165, -0.653669, 0.581636,
+1.336982, 12.495934, 16.355419, 2.500000, -1.679268, 0.999037, -0.033131, 0.028753,
+1.336982, 12.495934, 16.355419, 2.500000, -1.679268, 0.999037, -0.033131, 0.028753,
+1.002737, 12.901150, 15.938179, 3.000000, -1.679268, 0.520177, 0.645820, -0.558867,
+1.002737, 14.227100, 17.202572, 3.000000, -1.834628, 0.519663, 0.527798, -0.671848,
+1.002737, 14.227100, 17.202572, 3.000000, -1.834628, 0.519663, 0.527798, -0.671848,
+1.002737, 15.688553, 18.126600, 3.000000, -1.988039, 0.519424, 0.384311, -0.763219,
+1.336982, 15.450417, 18.654261, 2.500000, -1.988039, 0.998886, -0.021467, 0.042031,
+1.336982, 15.450417, 18.654261, 2.500000, -1.988039, 0.998886, -0.021467, 0.042031,
+1.002737, 15.212280, 19.181923, 2.000000, -1.988039, 0.480828, -0.389724, 0.785442,
+1.002737, 13.576080, 18.160946, 2.000000, -1.834628, 0.481336, -0.535363, 0.694048,
+1.002737, 16.995155, 19.858189, 2.000000, -2.145087, 0.479530, -0.225145, 0.848151,
+1.002737, 15.212280, 19.181923, 2.000000, -1.988039, 0.480828, -0.389724, 0.785442,
+1.336982, 15.450417, 18.654261, 2.500000, -1.988039, 0.998886, -0.021467, 0.042031,
+1.336982, 15.450417, 18.654261, 2.500000, -1.988039, 0.998886, -0.021467, 0.042031,
+1.002737, 15.688553, 18.126600, 3.000000, -1.988039, 0.519424, 0.384311, -0.763219,
+1.002737, 17.277420, 18.737804, 3.000000, -2.145087, 0.519855, 0.222506, -0.824768,
+1.002737, 17.277420, 18.737804, 3.000000, -2.145087, 0.519855, 0.222506, -0.824768,
+1.002737, 18.963112, 19.009758, 3.000000, -2.305904, 0.519106, 0.044200, -0.853567,
+1.336982, 18.926823, 19.584188, 2.500000, -2.305904, 0.998704, -0.001978, 0.050856,
+1.336982, 18.926823, 19.584188, 2.500000, -2.305904, 0.998704, -0.001978, 0.050856,
+1.002737, 18.890533, 20.158619, 2.000000, -2.305904, 0.477686, -0.044014, 0.877427,
+1.002737, 16.995155, 19.858189, 2.000000, -2.145087, 0.479530, -0.225145, 0.848151,
+1.002737, 20.864250, 20.052088, 2.000000, -2.470621, 0.474231, 0.150976, 0.867359,
+1.002737, 18.890533, 20.158619, 2.000000, -2.305904, 0.477686, -0.044014, 0.877427,
+1.336982, 18.926823, 19.584188, 2.500000, -2.305904, 0.998704, -0.001978, 0.050856,
+1.336982, 18.926823, 19.584188, 2.500000, -2.305904, 0.998704, -0.001978, 0.050856,
+1.002737, 18.963112, 19.009758, 3.000000, -2.305904, 0.519106, 0.044200, -0.853567,
+1.002737, 20.715042, 18.916035, 3.000000, -2.470621, 0.518180, -0.147145, -0.842519,
+1.002737, 20.715042, 18.916035, 3.000000, -2.470621, 0.518180, -0.147145, -0.842519,
+1.002737, 22.528091, 18.387989, 3.000000, -2.646001, 0.514483, -0.334572, -0.789537,
+1.336982, 22.719658, 18.922981, 2.500000, -2.646001, 0.998523, 0.022591, 0.049420,
+1.336982, 22.719658, 18.922981, 2.500000, -2.646001, 0.998523, 0.022591, 0.049420,
+1.002737, 22.911228, 19.457972, 2.000000, -2.646001, 0.471248, 0.342725, 0.812690,
+1.002737, 20.864250, 20.052088, 2.000000, -2.470621, 0.474231, 0.150976, 0.867359,
+1.002737, 25.026405, 18.295650, 2.000000, -2.838810, 0.470077, 0.507995, 0.721781,
+1.002737, 22.911228, 19.457972, 2.000000, -2.646001, 0.471248, 0.342725, 0.812690,
+1.336982, 22.719658, 18.922981, 2.500000, -2.646001, 0.998523, 0.022591, 0.049420,
+1.336982, 22.719658, 18.922981, 2.500000, -2.646001, 0.998523, 0.022591, 0.049420,
+1.002737, 22.528091, 18.387989, 3.000000, -2.646001, 0.514483, -0.334572, -0.789537,
+1.002737, 24.397125, 17.356983, 3.000000, -2.838810, 0.512162, -0.495528, -0.701529,
+1.002737, 24.397125, 17.356983, 3.000000, -2.838810, 0.512162, -0.495528, -0.701529,
+1.002737, 26.120163, 15.851318, 3.000000, -3.038383, 0.515999, -0.637877, -0.571716,
+1.336982, 26.551086, 16.221825, 2.500000, -3.038383, 0.998387, 0.041476, 0.038776,
+1.336982, 26.551086, 16.221825, 2.500000, -3.038383, 0.998387, 0.041476, 0.038776,
+1.002737, 26.982021, 16.592329, 2.000000, -3.038383, 0.470672, 0.656258, 0.589740,
+1.002737, 25.026405, 18.295650, 2.000000, -2.838810, 0.470077, 0.507995, 0.721781,
+1.002737, 28.550339, 14.375221, 2.000000, -3.234054, 0.475606, 0.784875, 0.397204,
+1.002737, 26.982021, 16.592329, 2.000000, -3.038383, 0.470672, 0.656258, 0.589740,
+1.336982, 26.551086, 16.221825, 2.500000, -3.038383, 0.998387, 0.041476, 0.038776,
+1.336982, 26.551086, 16.221825, 2.500000, -3.038383, 0.998387, 0.041476, 0.038776,
+1.002737, 26.120163, 15.851318, 3.000000, -3.038383, 0.515999, -0.637877, -0.571716,
+1.002737, 27.495193, 13.899298, 3.000000, -3.234054, 0.529173, -0.759785, -0.377761,
+1.002737, 27.495193, 13.899298, 3.000000, -3.234054, 0.529173, -0.759785, -0.377761,
+1.002737, 28.234837, 11.594270, 3.000000, -3.421010, 0.549862, -0.829858, -0.094800,
+1.336982, 28.829941, 11.681159, 2.500000, -3.421010, 0.997287, 0.072725, 0.011376,
+1.336982, 28.829941, 11.681159, 2.500000, -3.421010, 0.997287, 0.072725, 0.011376,
+1.002737, 29.425041, 11.768046, 2.000000, -3.421010, 0.486093, 0.865826, 0.118573,
+1.002737, 28.550339, 14.375221, 2.000000, -3.234054, 0.475606, 0.784875, 0.397204,
+1.002737, 29.299828, 8.894522, 2.000000, -3.594440, 0.508084, 0.850362, -0.136877,
+1.002737, 29.425041, 11.768046, 2.000000, -3.421010, 0.486093, 0.865826, 0.118573,
+1.336982, 28.829941, 11.681159, 2.500000, -3.421010, 0.997287, 0.072725, 0.011376,
+1.336982, 28.829941, 11.681159, 2.500000, -3.421010, 0.997287, 0.072725, 0.011376,
+1.002737, 28.234837, 11.594270, 3.000000, -3.421010, 0.549862, -0.829858, -0.094800,
+1.002737, 28.051701, 9.029581, 3.000000, -3.594440, 0.552395, -0.818570, 0.157487,
+1.002737, 28.051701, 9.029581, 3.000000, -3.594440, 0.552395, -0.818570, 0.157487,
+1.002737, 27.272324, 6.583387, 3.000000, -3.741287, 0.563171, -0.762895, 0.317537,
+1.336982, 27.897228, 6.377859, 2.500000, -3.741288, 0.999306, 0.035287, -0.011950,
+1.336982, 27.897228, 6.377859, 2.500000, -3.741288, 0.999306, 0.035287, -0.011950,
+1.002737, 28.522129, 6.172330, 2.000000, -3.741287, 0.527923, 0.793569, -0.302564,
+1.002737, 29.299828, 8.894522, 2.000000, -3.594440, 0.508084, 0.850362, -0.136877,
+1.002737, 27.439377, 4.019153, 2.000000, -3.848496, 0.545786, 0.725589, -0.419091,
+1.002737, 28.522129, 6.172330, 2.000000, -3.741287, 0.527923, 0.793569, -0.302564,
+1.336982, 27.897228, 6.377859, 2.500000, -3.741288, 0.999306, 0.035287, -0.011950,
+1.336982, 27.897228, 6.377859, 2.500000, -3.741288, 0.999306, 0.035287, -0.011950,
+1.002737, 27.272324, 6.583387, 3.000000, -3.741287, 0.563171, -0.762895, 0.317537,
+1.002737, 26.223228, 4.633848, 3.000000, -3.848496, 0.571231, -0.699649, 0.429169,
+1.002737, 26.223228, 4.633848, 3.000000, -3.848496, 0.571231, -0.699649, 0.429169,
+1.002737, 25.192875, 3.192066, 3.000000, -3.922053, 0.573805, -0.657830, 0.487860,
+1.336982, 25.778152, 2.814326, 2.500000, -3.922053, 0.999924, 0.011227, -0.005182,
+1.336982, 25.778152, 2.814326, 2.500000, -3.922053, 0.999924, 0.011227, -0.005182,
+1.002737, 26.363422, 2.436586, 2.000000, -3.922053, 0.561369, 0.675750, -0.477732,
+1.002737, 27.439377, 4.019153, 2.000000, -3.848496, 0.545786, 0.725589, -0.419091,
+1.002737, 24.600067, 1.327282, 2.500000, -4.000000, 0.595697, -0.491752, -0.635079,
+0.742768, 25.130249, 1.141007, 2.000000, -4.000000, 0.424007, 0.088516, -0.901323,
+1.002737, 25.606094, 1.426226, 2.000000, -3.967943, 0.572183, 0.564519, -0.594916,
+1.002737, 25.606094, 1.426226, 2.000000, -3.967943, 0.572183, 0.564519, -0.594916,
+1.002737, 26.363422, 2.436586, 2.000000, -3.922053, 0.561369, 0.675750, -0.477732,
+1.336982, 25.778152, 2.814326, 2.500000, -3.922053, 0.999924, 0.011227, -0.005182,
+1.336982, 25.778152, 2.814326, 2.500000, -3.922053, 0.999924, 0.011227, -0.005182,
+1.002737, 25.192875, 3.192066, 3.000000, -3.922053, 0.573805, -0.657830, 0.487860,
+1.002737, 24.469711, 2.269146, 3.000000, -3.967943, 0.583534, -0.710408, 0.393458,
+1.002737, 24.469711, 2.269146, 3.000000, -3.967943, 0.583534, -0.710408, 0.393458,
+0.742768, 24.296909, 1.783397, 3.000000, -4.000000, 0.428917, -0.894621, -0.125234,
+1.002737, 24.600067, 1.327282, 2.500000, -4.000000, 0.595697, -0.491752, -0.635079,
+-1.002737, 4.921762, -29.530731, 4.000000, 0.966243, -0.582241, 0.811733, -0.045666,
+-1.002737, 4.997122, -28.191074, 4.000000, 0.932486, -0.582174, 0.810005, -0.070467,
+0.000000, 5.231688, -28.210423, 3.500000, 0.922656, 0.000000, 0.996270, -0.086288,
+0.000000, 5.231688, -28.210423, 3.500000, 0.922656, 0.000000, 0.996270, -0.086288,
+1.002737, 4.997122, -28.191074, 3.000000, 0.922656, 0.582175, 0.810004, -0.070467,
+1.002737, 4.921762, -29.530731, 3.000000, 0.966243, 0.582240, 0.811733, -0.045667,
+1.002737, 5.199909, -26.333269, 3.000000, 0.859409, 0.582690, 0.803052, -0.124820,
+1.002737, 4.997122, -28.191074, 3.000000, 0.922656, 0.582175, 0.810004, -0.070467,
+0.000000, 5.231688, -28.210423, 3.500000, 0.922656, 0.000000, 0.996270, -0.086288,
+0.000000, 5.231688, -28.210423, 3.500000, 0.922656, 0.000000, 0.996270, -0.086288,
+-1.002737, 4.997122, -28.191074, 4.000000, 0.932486, -0.582174, 0.810005, -0.070467,
+-1.002737, 5.199909, -26.333269, 4.000000, 0.859409, -0.582690, 0.803052, -0.124820,
+-1.002737, 5.199909, -26.333269, 4.000000, 0.859409, -0.582690, 0.803052, -0.124820,
+-1.002737, 5.640600, -24.050657, 4.000000, 0.786333, -0.583127, 0.787897, -0.197941,
+0.000000, 5.870369, -24.095905, 3.500000, 0.775297, 0.000000, 0.969755, -0.244081,
+0.000000, 5.870369, -24.095905, 3.500000, 0.775297, 0.000000, 0.969755, -0.244081,
+1.002737, 5.640600, -24.050657, 3.000000, 0.775297, 0.583127, 0.787897, -0.197941,
+1.002737, 5.199909, -26.333269, 3.000000, 0.859409, 0.582690, 0.803052, -0.124820,
+1.002737, 6.429670, -21.436577, 3.000000, 0.669113, 0.579786, 0.770207, -0.265761,
+1.002737, 5.640600, -24.050657, 3.000000, 0.775297, 0.583127, 0.787897, -0.197941,
+0.000000, 5.870369, -24.095905, 3.500000, 0.775297, 0.000000, 0.969755, -0.244081,
+0.000000, 5.870369, -24.095905, 3.500000, 0.775297, 0.000000, 0.969755, -0.244081,
+-1.002737, 5.640600, -24.050657, 4.000000, 0.786333, -0.583127, 0.787897, -0.197941,
+-1.002737, 6.429670, -21.436577, 4.000000, 0.669113, -0.579786, 0.770207, -0.265761,
+-1.002737, 6.429670, -21.436577, 4.000000, 0.669113, -0.579786, 0.770207, -0.265761,
+-1.002737, 7.484703, -18.704168, 4.000000, 0.551894, -0.576888, 0.751118, -0.320970,
+0.000000, 7.711994, -18.765621, 3.500000, 0.547971, -0.000000, 0.919277, -0.393611,
+0.000000, 7.711994, -18.765621, 3.500000, 0.547971, -0.000000, 0.919277, -0.393611,
+1.002737, 7.484703, -18.704170, 3.000000, 0.547971, 0.576888, 0.751119, -0.320970,
+1.002737, 6.429670, -21.436577, 3.000000, 0.669113, 0.579786, 0.770207, -0.265761,
+1.002737, 8.723274, -16.066572, 3.000000, 0.418984, 0.570576, 0.739144, -0.357922,
+1.002737, 7.484703, -18.704170, 3.000000, 0.547971, 0.576888, 0.751119, -0.320970,
+0.000000, 7.711994, -18.765621, 3.500000, 0.547971, -0.000000, 0.919277, -0.393611,
+0.000000, 7.711994, -18.765621, 3.500000, 0.547971, -0.000000, 0.919277, -0.393611,
+-1.002737, 7.484703, -18.704168, 4.000000, 0.551894, -0.576888, 0.751118, -0.320970,
+-1.002737, 8.723274, -16.066572, 4.000000, 0.418984, -0.570577, 0.739144, -0.357922,
+-1.002737, 8.723274, -16.066572, 4.000000, 0.418984, -0.570577, 0.739144, -0.357922,
+-1.002737, 10.001389, -13.505806, 4.000000, 0.286075, -0.565597, 0.742253, -0.359389,
+0.000000, 10.230309, -13.563657, 3.500000, 0.282904, -0.000000, 0.900257, -0.435359,
+0.000000, 10.230309, -13.563657, 3.500000, 0.282904, -0.000000, 0.900257, -0.435359,
+1.002737, 10.001389, -13.505806, 3.000000, 0.282904, 0.565597, 0.742254, -0.359389,
+1.002737, 8.723274, -16.066572, 3.000000, 0.418984, 0.570576, 0.739144, -0.357922,
+1.002737, 11.175043, -11.003893, 3.000000, 0.140482, 0.562569, 0.757951, -0.330192,
+1.002737, 10.001389, -13.505806, 3.000000, 0.282904, 0.565597, 0.742254, -0.359389,
+0.000000, 10.230309, -13.563657, 3.500000, 0.282904, -0.000000, 0.900257, -0.435359,
+0.000000, 10.230309, -13.563657, 3.500000, 0.282904, -0.000000, 0.900257, -0.435359,
+-1.002737, 10.001389, -13.505806, 4.000000, 0.286075, -0.565597, 0.742253, -0.359389,
+-1.002737, 11.175043, -11.003893, 4.000000, 0.140482, -0.562513, 0.757929, -0.330337,
+-1.002737, 11.175043, -11.003893, 4.000000, 0.140482, -0.562513, 0.757929, -0.330337,
+-1.003346, 12.054029, -8.797724, 4.000000, -0.005111, -0.560047, 0.787144, -0.258362,
+-0.000610, 12.286734, -8.840019, 3.333333, -0.069211, 0.000044, 0.950614, -0.310377,
+-0.000610, 12.286734, -8.840019, 3.333333, -0.069211, 0.000044, 0.950614, -0.310377,
+1.002127, 12.054029, -8.797724, 2.958333, -0.009381, 0.560195, 0.787255, -0.257702,
+1.002737, 11.175043, -11.003893, 3.000000, 0.140482, 0.562569, 0.757951, -0.330192,
+1.000299, 12.448139, -7.124194, 2.833333, -0.167786, 0.564659, 0.816023, -0.123558,
+1.002127, 12.054029, -8.797724, 2.958333, -0.009381, 0.560195, 0.787255, -0.257702,
+-0.000610, 12.286734, -8.840019, 3.333333, -0.069211, 0.000044, 0.950614, -0.310377,
+-0.000610, 12.286734, -8.840019, 3.333333, -0.069211, 0.000044, 0.950614, -0.310377,
+-1.003346, 12.054029, -8.797724, 4.000000, -0.005111, -0.560047, 0.787144, -0.258362,
+-1.005175, 12.448139, -7.124194, 2.666667, -0.726194, -0.564732, 0.815815, -0.124590,
+-1.005175, 12.448139, -7.124194, 2.666667, -0.726194, -0.564732, 0.815815, -0.124590,
+-1.006394, 12.522362, -5.716876, 1.333333, -1.447277, -0.566040, 0.824377, 0.001632,
+-0.003657, 12.756954, -5.750165, 2.166667, -0.809096, -0.000126, 1.000000, 0.000870,
+-0.003657, 12.756954, -5.750165, 2.166667, -0.809096, -0.000126, 1.000000, 0.000870,
+0.999079, 12.522362, -5.716876, 3.000000, -0.170915, 0.565733, 0.824587, 0.001687,
+1.000299, 12.448139, -7.124194, 2.833333, -0.167786, 0.564659, 0.816023, -0.123558,
+1.002737, 11.560024, -0.158328, 3.000000, -0.503387, 0.548192, 0.812432, 0.198592,
+1.002127, 12.142200, -2.567771, 3.000000, -0.336720, 0.545588, 0.819894, 0.173516,
+-0.000610, 12.377636, -2.594154, 3.500000, -0.336720, 0.000041, 0.978486, 0.206311,
+-0.000610, 12.377636, -2.594154, 3.500000, -0.336720, 0.000041, 0.978486, 0.206311,
+-1.003346, 12.142200, -2.567771, 4.000000, -0.336720, -0.545383, 0.819886, 0.174196,
+-1.002737, 11.560024, -0.158328, 4.000000, -0.503387, -0.548128, 0.812439, 0.198744,
+-1.002737, 11.560024, -0.158328, 4.000000, -0.503387, -0.548128, 0.812439, 0.198744,
+-1.002737, 10.886791, 2.566613, 4.000000, -0.670054, -0.549613, 0.814083, 0.187601,
+0.000000, 11.117409, 2.540119, 3.500000, -0.671927, 0.000000, 0.974103, 0.226104,
+0.000000, 11.117409, 2.540119, 3.500000, -0.671927, 0.000000, 0.974103, 0.226104,
+1.002737, 10.886791, 2.566613, 3.000000, -0.671927, 0.549613, 0.814083, 0.187601,
+1.002737, 11.560024, -0.158328, 3.000000, -0.503387, 0.548192, 0.812432, 0.198592,
+1.002737, 10.314148, 5.254678, 3.000000, -0.844213, 0.550065, 0.824042, 0.135587,
+1.002737, 10.886791, 2.566613, 3.000000, -0.671927, 0.549613, 0.814083, 0.187601,
+0.000000, 11.117409, 2.540119, 3.500000, -0.671927, 0.000000, 0.974103, 0.226104,
+0.000000, 11.117409, 2.540119, 3.500000, -0.671927, 0.000000, 0.974103, 0.226104,
+-1.002737, 10.886791, 2.566613, 4.000000, -0.670054, -0.549613, 0.814083, 0.187601,
+-1.002737, 10.314148, 5.254678, 4.000000, -0.844213, -0.550065, 0.824042, 0.135588,
+-1.002737, 10.314148, 5.254678, 4.000000, -0.844213, -0.550065, 0.824042, 0.135588,
+-1.002737, 10.024443, 7.827566, 4.000000, -1.018373, -0.552727, 0.833125, 0.019881,
+0.000000, 10.237921, 7.780712, 3.500000, -1.016250, -0.000000, 0.999593, 0.028523,
+0.000000, 10.237921, 7.780712, 3.500000, -1.016250, -0.000000, 0.999593, 0.028523,
+1.002737, 10.024445, 7.827566, 3.000000, -1.016250, 0.552727, 0.833125, 0.019881,
+1.002737, 10.314148, 5.254678, 3.000000, -0.844213, 0.550065, 0.824042, 0.135587,
+1.002737, 10.200031, 10.206976, 3.000000, -1.184038, 0.545898, 0.826469, -0.137636,
+1.002737, 10.024445, 7.827566, 3.000000, -1.016250, 0.552727, 0.833125, 0.019881,
+0.000000, 10.237921, 7.780712, 3.500000, -1.016250, -0.000000, 0.999593, 0.028523,
+0.000000, 10.237921, 7.780712, 3.500000, -1.016250, -0.000000, 0.999593, 0.028523,
+-1.002737, 10.024443, 7.827566, 4.000000, -1.018373, -0.552727, 0.833125, 0.019881,
+-1.002737, 10.200031, 10.206976, 4.000000, -1.184038, -0.545898, 0.826469, -0.137636,
+-1.002737, 10.200031, 10.206976, 4.000000, -1.184038, -0.545898, 0.826469, -0.137636,
+-1.002737, 10.783842, 12.373039, 4.000000, -1.349704, -0.535040, 0.792292, -0.293266,
+0.000000, 10.965359, 12.283498, 3.500000, -1.349954, -0.000000, 0.938935, -0.344095,
+0.000000, 10.965359, 12.283498, 3.500000, -1.349954, -0.000000, 0.938935, -0.344095,
+1.002737, 10.783842, 12.373039, 3.000000, -1.349954, 0.535040, 0.792292, -0.293267,
+1.002737, 10.200031, 10.206976, 3.000000, -1.184038, 0.545898, 0.826469, -0.137636,
+1.002737, 11.718807, 14.305887, 3.000000, -1.516370, 0.524951, 0.731928, -0.434405,
+1.002737, 10.783842, 12.373039, 3.000000, -1.349954, 0.535040, 0.792292, -0.293267,
+0.000000, 10.965359, 12.283498, 3.500000, -1.349954, -0.000000, 0.938935, -0.344095,
+0.000000, 10.965359, 12.283498, 3.500000, -1.349954, -0.000000, 0.938935, -0.344095,
+-1.002737, 10.783842, 12.373039, 4.000000, -1.349704, -0.535040, 0.792292, -0.293266,
+-1.002737, 11.718807, 14.305887, 4.000000, -1.516370, -0.524951, 0.731928, -0.434405,
+-1.002737, 11.718807, 14.305887, 4.000000, -1.516370, -0.524951, 0.731928, -0.434405,
+-1.002737, 12.901150, 15.938179, 4.000000, -1.683037, -0.520176, 0.645820, -0.558867,
+0.000000, 13.036221, 15.799099, 3.500000, -1.679268, 0.000000, 0.757369, -0.652987,
+0.000000, 13.036221, 15.799099, 3.500000, -1.679268, 0.000000, 0.757369, -0.652987,
+1.002737, 12.901150, 15.938179, 3.000000, -1.679268, 0.520177, 0.645820, -0.558867,
+1.002737, 11.718807, 14.305887, 3.000000, -1.516370, 0.524951, 0.731928, -0.434405,
+1.002737, 14.227100, 17.202572, 3.000000, -1.834628, 0.519663, 0.527798, -0.671848,
+1.002737, 12.901150, 15.938179, 3.000000, -1.679268, 0.520177, 0.645820, -0.558867,
+0.000000, 13.036221, 15.799099, 3.500000, -1.679268, 0.000000, 0.757369, -0.652987,
+0.000000, 13.036221, 15.799099, 3.500000, -1.679268, 0.000000, 0.757369, -0.652987,
+-1.002737, 12.901150, 15.938179, 4.000000, -1.683037, -0.520176, 0.645820, -0.558867,
+-1.002737, 14.227100, 17.202572, 4.000000, -1.834628, -0.519663, 0.527798, -0.671848,
+-1.002737, 14.227100, 17.202572, 4.000000, -1.834628, -0.519663, 0.527798, -0.671848,
+-1.002737, 15.688553, 18.126600, 4.000000, -1.986219, -0.519424, 0.384311, -0.763219,
+0.000000, 15.767933, 17.950714, 3.500000, -1.988039, 0.000000, 0.450479, -0.892787,
+0.000000, 15.767933, 17.950714, 3.500000, -1.988039, 0.000000, 0.450479, -0.892787,
+1.002737, 15.688553, 18.126600, 3.000000, -1.988039, 0.519424, 0.384311, -0.763219,
+1.002737, 14.227100, 17.202572, 3.000000, -1.834628, 0.519663, 0.527798, -0.671848,
+1.002737, 17.277420, 18.737804, 3.000000, -2.145087, 0.519855, 0.222506, -0.824768,
+1.002737, 15.688553, 18.126600, 3.000000, -1.988039, 0.519424, 0.384311, -0.763219,
+0.000000, 15.767933, 17.950714, 3.500000, -1.988039, 0.000000, 0.450479, -0.892787,
+0.000000, 15.767933, 17.950714, 3.500000, -1.988039, 0.000000, 0.450479, -0.892787,
+-1.002737, 15.688553, 18.126600, 4.000000, -1.986219, -0.519424, 0.384311, -0.763219,
+-1.002737, 17.277420, 18.737804, 4.000000, -2.145087, -0.519855, 0.222506, -0.824768,
+-1.002737, 17.277420, 18.737804, 4.000000, -2.145087, -0.519855, 0.222506, -0.824768,
+-1.002737, 18.963112, 19.009758, 4.000000, -2.303954, -0.519106, 0.044200, -0.853567,
+0.000000, 18.975204, 18.818281, 3.500000, -2.305904, -0.000000, 0.051821, -0.998656,
+0.000000, 18.975204, 18.818281, 3.500000, -2.305904, -0.000000, 0.051821, -0.998656,
+1.002737, 18.963112, 19.009758, 3.000000, -2.305904, 0.519106, 0.044200, -0.853567,
+1.002737, 17.277420, 18.737804, 3.000000, -2.145087, 0.519855, 0.222506, -0.824768,
+1.002737, 20.715042, 18.916035, 3.000000, -2.470621, 0.518180, -0.147145, -0.842519,
+1.002737, 18.963112, 19.009758, 3.000000, -2.305904, 0.519106, 0.044200, -0.853567,
+0.000000, 18.975204, 18.818281, 3.500000, -2.305904, -0.000000, 0.051821, -0.998656,
+0.000000, 18.975204, 18.818281, 3.500000, -2.305904, -0.000000, 0.051821, -0.998656,
+-1.002737, 18.963112, 19.009758, 4.000000, -2.303954, -0.519106, 0.044200, -0.853567,
+-1.002737, 20.715042, 18.916035, 4.000000, -2.470621, -0.518180, -0.147145, -0.842519,
+-1.002737, 20.715042, 18.916035, 4.000000, -2.470621, -0.518180, -0.147145, -0.842519,
+-1.002737, 22.528088, 18.387989, 4.000000, -2.637287, -0.514483, -0.334572, -0.789537,
+0.000000, 22.464233, 18.209660, 3.500000, -2.646001, -0.000000, -0.390600, -0.920561,
+0.000000, 22.464233, 18.209660, 3.500000, -2.646001, -0.000000, -0.390600, -0.920561,
+1.002737, 22.528091, 18.387989, 3.000000, -2.646001, 0.514483, -0.334572, -0.789537,
+1.002737, 20.715042, 18.916035, 3.000000, -2.470621, 0.518180, -0.147145, -0.842519,
+1.002737, 24.397125, 17.356983, 3.000000, -2.838810, 0.512162, -0.495528, -0.701529,
+1.002737, 22.528091, 18.387989, 3.000000, -2.646001, 0.514483, -0.334572, -0.789537,
+0.000000, 22.464233, 18.209660, 3.500000, -2.646001, -0.000000, -0.390600, -0.920561,
+0.000000, 22.464233, 18.209660, 3.500000, -2.646001, -0.000000, -0.390600, -0.920561,
+-1.002737, 22.528088, 18.387989, 4.000000, -2.637287, -0.514483, -0.334572, -0.789537,
+-1.002737, 24.397125, 17.356983, 4.000000, -2.838810, -0.512162, -0.495528, -0.701529,
+-1.002737, 24.397125, 17.356983, 4.000000, -2.838810, -0.512162, -0.495528, -0.701529,
+-1.002737, 26.120163, 15.851318, 4.000000, -3.040334, -0.515999, -0.637877, -0.571716,
+0.000000, 25.976517, 15.727814, 3.500000, -3.038383, -0.000000, -0.744667, -0.667436,
+0.000000, 25.976517, 15.727814, 3.500000, -3.038383, -0.000000, -0.744667, -0.667436,
+1.002737, 26.120163, 15.851318, 3.000000, -3.038383, 0.515999, -0.637877, -0.571716,
+1.002737, 24.397125, 17.356983, 3.000000, -2.838810, 0.512162, -0.495528, -0.701529,
+1.002737, 27.495193, 13.899298, 3.000000, -3.234054, 0.529173, -0.759785, -0.377761,
+1.002737, 26.120163, 15.851318, 3.000000, -3.038383, 0.515999, -0.637877, -0.571716,
+0.000000, 25.976517, 15.727814, 3.500000, -3.038383, -0.000000, -0.744667, -0.667436,
+0.000000, 25.976517, 15.727814, 3.500000, -3.038383, -0.000000, -0.744667, -0.667436,
+-1.002737, 26.120163, 15.851318, 4.000000, -3.040334, -0.515999, -0.637877, -0.571716,
+-1.002737, 27.495193, 13.899298, 4.000000, -3.234054, -0.529173, -0.759785, -0.377761,
+-1.002737, 27.495193, 13.899298, 4.000000, -3.234054, -0.529173, -0.759785, -0.377761,
+-1.002737, 28.234837, 11.594271, 4.000000, -3.427773, -0.549861, -0.829859, -0.094800,
+0.000000, 28.036469, 11.565307, 3.500000, -3.421010, -0.000000, -0.993846, -0.110776,
+0.000000, 28.036469, 11.565307, 3.500000, -3.421010, -0.000000, -0.993846, -0.110776,
+1.002737, 28.234837, 11.594270, 3.000000, -3.421010, 0.549862, -0.829858, -0.094800,
+1.002737, 27.495193, 13.899298, 3.000000, -3.234054, 0.529173, -0.759785, -0.377761,
+1.002737, 28.051701, 9.029581, 3.000000, -3.594440, 0.552395, -0.818570, 0.157487,
+1.002737, 28.234837, 11.594270, 3.000000, -3.421010, 0.549862, -0.829858, -0.094800,
+0.000000, 28.036469, 11.565307, 3.500000, -3.421010, -0.000000, -0.993846, -0.110776,
+0.000000, 28.036469, 11.565307, 3.500000, -3.421010, -0.000000, -0.993846, -0.110776,
+-1.002737, 28.234837, 11.594271, 4.000000, -3.427773, -0.549861, -0.829859, -0.094800,
+-1.002737, 28.051701, 9.029581, 4.000000, -3.594440, -0.552394, -0.818572, 0.157487,
+-1.002737, 28.051701, 9.029581, 4.000000, -3.594440, -0.552394, -0.818572, 0.157487,
+-1.002737, 27.272324, 6.583387, 4.000000, -3.761107, -0.563170, -0.762896, 0.317537,
+0.000000, 27.064018, 6.651896, 3.500000, -3.741288, 0.000000, -0.921832, 0.387591,
+0.000000, 27.064018, 6.651896, 3.500000, -3.741288, 0.000000, -0.921832, 0.387591,
+1.002737, 27.272324, 6.583387, 3.000000, -3.741287, 0.563171, -0.762895, 0.317537,
+1.002737, 28.051701, 9.029581, 3.000000, -3.594440, 0.552395, -0.818570, 0.157487,
+1.002737, 26.223228, 4.633848, 3.000000, -3.848496, 0.571231, -0.699649, 0.429169,
+1.002737, 27.272324, 6.583387, 3.000000, -3.741287, 0.563171, -0.762895, 0.317537,
+0.000000, 27.064018, 6.651896, 3.500000, -3.741288, 0.000000, -0.921832, 0.387591,
+0.000000, 27.064018, 6.651896, 3.500000, -3.741288, 0.000000, -0.921832, 0.387591,
+-1.002737, 27.272324, 6.583387, 4.000000, -3.761107, -0.563170, -0.762896, 0.317537,
+-1.002737, 26.223228, 4.633848, 4.000000, -3.848496, -0.571231, -0.699650, 0.429169,
+-1.002737, 26.223228, 4.633848, 4.000000, -3.848496, -0.571231, -0.699650, 0.429169,
+-1.002737, 25.192875, 3.192066, 4.000000, -3.935886, -0.573805, -0.657830, 0.487860,
+0.000000, 24.997784, 3.317980, 3.500000, -3.922053, -0.000000, -0.801896, 0.597463,
+0.000000, 24.997784, 3.317980, 3.500000, -3.922053, -0.000000, -0.801896, 0.597463,
+1.002737, 25.192875, 3.192066, 3.000000, -3.922053, 0.573805, -0.657830, 0.487860,
+1.002737, 26.223228, 4.633848, 3.000000, -3.848496, 0.571231, -0.699649, 0.429169,
+0.000000, 24.041351, 1.768998, 3.500000, -4.000000, 0.000000, -0.991299, -0.131630,
+0.742768, 24.296909, 1.783397, 3.000000, -4.000000, 0.428917, -0.894621, -0.125234,
+1.002737, 24.469711, 2.269146, 3.000000, -3.967943, 0.583534, -0.710408, 0.393458,
+1.002737, 24.469711, 2.269146, 3.000000, -3.967943, 0.583534, -0.710408, 0.393458,
+1.002737, 25.192875, 3.192066, 3.000000, -3.922053, 0.573805, -0.657830, 0.487860,
+0.000000, 24.997784, 3.317980, 3.500000, -3.922053, -0.000000, -0.801896, 0.597463,
+0.000000, 24.997784, 3.317980, 3.500000, -3.922053, -0.000000, -0.801896, 0.597463,
+-1.002737, 25.192875, 3.192066, 4.000000, -3.935886, -0.573805, -0.657830, 0.487860,
+-1.002737, 24.469711, 2.269146, 4.000000, -3.967943, -0.583534, -0.710408, 0.393458,
+-1.002737, 24.469711, 2.269146, 4.000000, -3.967943, -0.583534, -0.710408, 0.393458,
+-0.742768, 24.296909, 1.783397, 4.000000, -4.000000, -0.428917, -0.894621, -0.125234,
+0.000000, 24.041351, 1.768998, 3.500000, -4.000000, 0.000000, -0.991299, -0.131630,
+-1.002737, -1.292564, -32.294178, 1.000000, 0.972854, -0.576236, -0.817066, 0.018853,
+-1.002737, -1.259859, -30.876823, 1.000000, 0.937170, -0.573164, -0.818796, 0.032517,
+-1.336982, -0.552929, -30.921089, 0.500000, 0.937170, -0.999978, -0.006540, 0.000687,
+-1.336982, -0.552929, -30.921089, 0.500000, 0.937170, -0.999978, -0.006540, 0.000687,
+-1.002737, 0.153999, -30.965355, 0.000000, 0.945709, -0.580105, 0.814042, -0.028521,
+-1.002737, 0.129889, -32.334755, 0.000000, 0.972854, -0.578352, 0.815661, -0.014359,
+-1.002737, 0.245815, -29.027195, 0.000000, 0.884407, -0.580554, 0.811733, -0.063605,
+-1.002737, 0.153999, -30.965355, 0.000000, 0.945709, -0.580105, 0.814042, -0.028521,
+-1.336982, -0.552929, -30.921089, 0.500000, 0.937170, -0.999978, -0.006540, 0.000687,
+-1.336982, -0.552929, -30.921089, 0.500000, 0.937170, -0.999978, -0.006540, 0.000687,
+-1.002737, -1.259859, -30.876823, 1.000000, 0.937170, -0.573164, -0.818796, 0.032517,
+-1.002737, -1.156864, -28.875961, 1.000000, 0.884407, -0.570246, -0.818776, 0.066533,
+-1.002737, -1.156864, -28.875961, 1.000000, 0.884407, -0.570246, -0.818776, 0.066533,
+-1.002737, -0.895025, -26.385366, 1.000000, 0.812277, -0.568649, -0.814249, 0.116778,
+-1.336982, -0.199492, -26.493555, 0.500000, 0.812277, -0.999928, -0.011914, 0.001651,
+-1.336982, -0.199492, -26.493555, 0.500000, 0.812277, -0.999928, -0.011914, 0.001651,
+-1.002737, 0.496042, -26.601746, 0.000000, 0.823105, -0.581048, 0.805721, -0.114877,
+-1.002737, 0.245815, -29.027195, 0.000000, 0.884407, -0.580554, 0.811733, -0.063605,
+-1.002737, 0.995396, -23.770485, 0.000000, 0.718491, -0.583417, 0.789634, -0.190008,
+-1.002737, 0.496042, -26.601746, 0.000000, 0.823105, -0.581048, 0.805721, -0.114877,
+-1.336982, -0.199492, -26.493555, 0.500000, 0.812277, -0.999928, -0.011914, 0.001651,
+-1.336982, -0.199492, -26.493555, 0.500000, 0.812277, -0.999928, -0.011914, 0.001651,
+-1.002737, -0.895025, -26.385366, 1.000000, 0.812277, -0.568649, -0.814249, 0.116778,
+-1.002737, -0.385786, -23.498796, 1.000000, 0.718491, -0.565019, -0.802220, 0.192863,
+-1.002737, -0.385786, -23.498796, 1.000000, 0.718491, -0.565019, -0.802220, 0.192863,
+-1.000716, 0.522999, -20.483551, 1.046875, 0.600702, -0.555184, -0.771596, 0.310500,
+-1.334961, 1.211163, -20.628946, 0.687500, 0.612715, -0.999676, -0.020934, 0.014474,
+-1.334961, 1.211163, -20.628946, 0.687500, 0.612715, -0.999676, -0.020934, 0.014474,
+-1.000716, 1.899328, -20.774343, 0.000000, 0.613877, -0.578823, 0.757196, -0.302684,
+-1.002737, 0.995396, -23.770485, 0.000000, 0.718491, -0.583417, 0.789634, -0.190008,
+-0.994652, 3.363289, -17.854239, 1.500000, 0.568689, -0.554925, 0.739714, -0.380633,
+-1.000716, 1.899328, -20.774343, 0.000000, 0.613877, -0.578823, 0.757196, -0.302684,
+-1.334961, 1.211163, -20.628946, 0.687500, 0.612715, -0.999676, -0.020934, 0.014474,
+-1.334961, 1.211163, -20.628946, 0.687500, 0.612715, -0.999676, -0.020934, 0.014474,
+-1.000716, 0.522999, -20.483551, 1.046875, 0.600702, -0.555184, -0.771596, 0.310500,
+-0.994652, 1.983473, -17.606916, 1.187500, 0.456561, -0.553223, -0.737418, 0.387504,
+-0.994652, 1.983473, -17.606916, 1.187500, 0.456561, -0.553223, -0.737418, 0.387504,
+-0.990610, 3.544037, -14.721523, 1.000000, 0.267209, -0.562098, -0.749029, 0.350717,
+-1.324855, 4.237772, -14.807808, 2.000000, 0.395355, -0.999804, 0.015791, -0.011962,
+-1.324855, 4.237772, -14.807808, 2.000000, 0.395355, -0.999804, 0.015791, -0.011962,
+-0.990610, 4.931509, -14.894089, 3.000000, 0.523501, -0.544986, 0.762408, -0.348891,
+-0.994652, 3.363289, -17.854239, 1.500000, 0.568689, -0.554925, 0.739714, -0.380633,
+-1.002737, 6.556976, -6.071414, 0.000000, -0.308178, -0.553122, 0.818963, 0.152824,
+-1.000716, 6.770885, -8.754030, 0.000000, -0.079458, -0.549751, 0.833161, -0.060139,
+-1.334961, 6.071638, -8.749280, 0.500000, -0.079458, -0.999000, 0.044233, -0.006500,
+-1.334961, 6.071638, -8.749280, 0.500000, -0.079458, -0.999000, 0.044233, -0.006500,
+-1.000716, 5.372389, -8.744530, 1.000000, -0.079458, -0.594849, -0.801661, 0.059106,
+-1.002737, 5.163677, -6.177338, 1.000000, -0.308178, -0.587361, -0.794674, -0.153298,
+-1.002737, 5.163677, -6.177338, 1.000000, -0.308178, -0.587361, -0.794674, -0.153298,
+-1.002737, 4.402004, -3.694788, 1.000000, -0.537451, -0.571136, -0.774985, -0.270559,
+-1.336982, 5.093796, -3.594290, 0.500000, -0.537451, -0.999877, 0.014256, 0.006545,
+-1.336982, 5.093796, -3.594290, 0.500000, -0.537451, -0.999877, 0.014256, 0.006545,
+-1.002737, 5.785589, -3.493792, 0.000000, -0.536897, -0.556039, 0.785897, 0.270530,
+-1.002737, 6.556976, -6.071414, 0.000000, -0.308178, -0.553122, 0.818963, 0.152824,
+-1.002737, 4.735826, -0.785002, 0.000000, -0.767833, -0.563593, 0.774459, 0.287360,
+-1.002737, 5.785589, -3.493792, 0.000000, -0.536897, -0.556039, 0.785897, 0.270530,
+-1.336982, 5.093796, -3.594290, 0.500000, -0.537451, -0.999877, 0.014256, 0.006545,
+-1.336982, 5.093796, -3.594290, 0.500000, -0.537451, -0.999877, 0.014256, 0.006545,
+-1.002737, 4.402004, -3.694788, 1.000000, -0.537451, -0.571136, -0.774985, -0.270559,
+-1.002737, 3.362402, -1.013249, 1.000000, -0.767833, -0.559574, -0.778227, -0.285025,
+-1.002737, 3.362402, -1.013249, 1.000000, -0.767833, -0.559574, -0.778227, -0.285025,
+-1.002737, 2.394936, 1.783656, 1.046875, -0.973474, -0.550621, -0.806194, -0.216490,
+-1.336982, 3.076645, 1.877820, 0.687500, -0.955495, -0.999725, -0.022213, -0.007478,
+-1.336982, 3.076645, 1.877820, 0.687500, -0.955495, -0.999725, -0.022213, -0.007478,
+-1.002737, 3.758350, 1.971984, 0.000000, -0.998770, -0.573360, 0.788967, 0.220880,
+-1.002737, 4.735826, -0.785002, 0.000000, -0.767833, -0.563593, 0.774459, 0.287360,
+-1.002737, 3.203825, 4.694192, 1.500000, -0.960717, -0.573166, 0.812586, 0.105755,
+-1.002737, 3.758350, 1.971984, 0.000000, -0.998770, -0.573360, 0.788967, 0.220880,
+-1.336982, 3.076645, 1.877820, 0.687500, -0.955495, -0.999725, -0.022213, -0.007478,
+-1.336982, 3.076645, 1.877820, 0.687500, -0.955495, -0.999725, -0.022213, -0.007478,
+-1.002737, 2.394936, 1.783656, 1.046875, -0.973474, -0.550621, -0.806194, -0.216490,
+-1.002737, 1.849670, 4.612304, 1.187500, -1.128520, -0.548005, -0.830422, -0.100446,
+-1.002737, 1.849670, 4.612304, 1.187500, -1.128520, -0.548005, -0.830422, -0.100446,
+-1.002737, 1.707661, 7.456823, 1.000000, -1.306215, -0.546192, -0.837529, 0.014826,
+-1.336982, 2.380295, 7.427917, 2.000000, -1.114440, -0.999670, -0.025705, 0.000199,
+-1.336982, 2.380295, 7.427917, 2.000000, -1.114440, -0.999670, -0.025705, 0.000199,
+-1.002737, 3.052929, 7.399012, 3.000000, -0.922665, -0.571504, 0.820505, -0.012461,
+-1.002737, 3.203825, 4.694192, 1.500000, -0.960717, -0.573166, 0.812586, 0.105755,
+-1.022346, 4.637777, 15.286472, 1.333333, -1.667888, -0.574184, 0.765044, -0.291584,
+-1.007639, 3.836994, 12.751901, 0.000000, -1.613659, -0.571038, 0.793815, -0.209219,
+-1.341885, 3.176014, 12.915927, 0.500000, -1.613659, -0.999798, -0.020077, 0.001135,
+-1.341885, 3.176014, 12.915927, 0.500000, -1.613659, -0.999798, -0.020077, 0.001135,
+-1.007639, 2.515034, 13.079953, 1.000000, -1.613659, -0.551445, -0.808533, 0.205386,
+-1.022346, 3.341311, 15.726742, 1.166667, -1.691614, -0.553953, -0.781075, 0.288198,
+-1.022346, 3.341311, 15.726742, 1.166667, -1.691614, -0.553953, -0.781075, 0.288198,
+-1.032151, 4.412262, 18.174877, 1.000000, -1.776346, -0.555665, -0.740194, 0.378615,
+-1.366396, 5.044981, 17.903212, 1.833333, -1.749232, -0.999757, -0.019426, 0.010462,
+-1.366396, 5.044981, 17.903212, 1.833333, -1.749232, -0.999757, -0.019426, 0.010462,
+-1.032151, 5.677700, 17.631544, 2.666667, -1.722117, -0.577835, 0.723604, -0.377496,
+-1.022346, 4.637777, 15.286472, 1.333333, -1.667888, -0.574184, 0.765044, -0.291584,
+-1.002737, 8.987209, 23.827108, 0.500000, -2.000000, -0.690086, 0.408969, 0.597098,
+-0.742768, 9.282909, 23.329664, 0.000000, -2.000000, -0.487251, 0.872639, 0.032983,
+-1.002737, 9.038933, 22.663582, 0.000000, -1.969517, -0.582357, 0.720010, -0.377421,
+-1.002737, 9.038933, 22.663582, 0.000000, -1.969517, -0.582357, 0.720010, -0.377421,
+-1.007639, 8.160118, 21.422651, 0.000000, -1.939034, -0.574068, 0.669723, -0.471080,
+-1.341885, 7.556932, 21.789433, 0.500000, -1.939034, -0.999989, 0.000304, 0.004665,
+-1.341885, 7.556932, 21.789433, 0.500000, -1.939034, -0.999989, 0.000304, 0.004665,
+-1.007639, 6.953747, 22.156216, 1.000000, -1.939034, -0.571627, -0.672843, 0.469600,
+-1.002737, 7.854620, 23.452549, 1.000000, -1.969517, -0.579230, -0.604597, 0.546768,
+-1.002737, 7.854620, 23.452549, 1.000000, -1.969517, -0.579230, -0.604597, 0.546768,
+-0.742768, 8.411285, 23.925793, 1.000000, -2.000000, -0.485429, -0.281111, 0.827850,
+-1.002737, 8.987209, 23.827108, 0.500000, -2.000000, -0.690086, 0.408969, 0.597098,
+1.002737, -1.292564, -32.294174, 2.000000, 0.972854, 0.576237, -0.817066, 0.018853,
+1.002737, -1.259859, -30.876823, 2.000000, 0.937170, 0.573164, -0.818795, 0.032517,
+0.000000, -1.495502, -30.862072, 1.500000, 0.937170, 0.000000, -0.999196, 0.040090,
+0.000000, -1.495502, -30.862072, 1.500000, 0.937170, 0.000000, -0.999196, 0.040090,
+-1.002737, -1.259859, -30.876823, 1.000000, 0.937170, -0.573164, -0.818796, 0.032517,
+-1.002737, -1.292564, -32.294178, 1.000000, 0.972854, -0.576236, -0.817066, 0.018853,
+-1.002737, -1.156864, -28.875961, 1.000000, 0.884407, -0.570246, -0.818776, 0.066533,
+-1.002737, -1.259859, -30.876823, 1.000000, 0.937170, -0.573164, -0.818796, 0.032517,
+0.000000, -1.495502, -30.862072, 1.500000, 0.937170, 0.000000, -0.999196, 0.040090,
+0.000000, -1.495502, -30.862072, 1.500000, 0.937170, 0.000000, -0.999196, 0.040090,
+1.002737, -1.259859, -30.876823, 2.000000, 0.937170, 0.573164, -0.818795, 0.032517,
+1.002737, -1.156864, -28.875965, 2.000000, 0.884407, 0.570246, -0.818775, 0.066533,
+1.002737, -1.156864, -28.875965, 2.000000, 0.884407, 0.570246, -0.818775, 0.066533,
+1.002737, -0.895025, -26.385365, 2.000000, 0.812277, 0.568649, -0.814249, 0.116778,
+0.000000, -1.126870, -26.349302, 1.500000, 0.812277, 0.000000, -0.989855, 0.142082,
+0.000000, -1.126870, -26.349302, 1.500000, 0.812277, 0.000000, -0.989855, 0.142082,
+-1.002737, -0.895025, -26.385366, 1.000000, 0.812277, -0.568649, -0.814249, 0.116778,
+-1.002737, -1.156864, -28.875961, 1.000000, 0.884407, -0.570246, -0.818776, 0.066533,
+-1.002737, -0.385786, -23.498796, 1.000000, 0.718491, -0.565019, -0.802220, 0.192863,
+-1.002737, -0.895025, -26.385366, 1.000000, 0.812277, -0.568649, -0.814249, 0.116778,
+0.000000, -1.126870, -26.349302, 1.500000, 0.812277, 0.000000, -0.989855, 0.142082,
+0.000000, -1.126870, -26.349302, 1.500000, 0.812277, 0.000000, -0.989855, 0.142082,
+1.002737, -0.895025, -26.385365, 2.000000, 0.812277, 0.568649, -0.814249, 0.116778,
+1.002737, -0.385786, -23.498796, 2.000000, 0.718491, 0.564910, -0.802377, 0.192532,
+1.002737, -0.385786, -23.498796, 2.000000, 0.718491, 0.564910, -0.802377, 0.192532,
+1.004758, 0.522999, -20.483551, 2.000000, 0.596697, 0.555081, -0.772140, 0.309331,
+0.002021, 0.293610, -20.435085, 1.500000, 0.596697, -0.000089, -0.928581, 0.371129,
+0.002021, 0.293610, -20.435085, 1.500000, 0.596697, -0.000089, -0.928581, 0.371129,
+-1.000716, 0.522999, -20.483551, 1.046875, 0.600702, -0.555184, -0.771596, 0.310500,
+-1.002737, -0.385786, -23.498796, 1.000000, 0.718491, -0.565019, -0.802220, 0.192863,
+-0.994652, 1.983473, -17.606916, 1.187500, 0.456561, -0.553223, -0.737418, 0.387504,
+-1.000716, 0.522999, -20.483551, 1.046875, 0.600702, -0.555184, -0.771596, 0.310500,
+0.002021, 0.293610, -20.435085, 1.500000, 0.596697, -0.000089, -0.928581, 0.371129,
+0.002021, 0.293610, -20.435085, 1.500000, 0.596697, -0.000089, -0.928581, 0.371129,
+1.004758, 0.522999, -20.483551, 2.000000, 0.596697, 0.555081, -0.772140, 0.309331,
+1.010821, 1.983473, -17.606916, 2.000000, 0.440543, 0.553586, -0.738015, 0.385845,
+1.010821, 1.983473, -17.606916, 2.000000, 0.440543, 0.553586, -0.738015, 0.385845,
+1.014864, 3.544037, -14.721523, 2.000000, 0.267209, 0.562535, -0.748836, 0.350428,
+0.012127, 3.312792, -14.692760, 1.500000, 0.267209, 0.000169, -0.904592, 0.426279,
+0.012127, 3.312792, -14.692760, 1.500000, 0.267209, 0.000169, -0.904592, 0.426279,
+-0.990610, 3.544037, -14.721523, 1.000000, 0.267209, -0.562098, -0.749029, 0.350717,
+-0.994652, 1.983473, -17.606916, 1.187500, 0.456561, -0.553223, -0.737418, 0.387504,
+-1.002737, 5.163677, -6.177338, 1.000000, -0.308178, -0.587361, -0.794674, -0.153298,
+-1.000716, 5.372389, -8.744530, 1.000000, -0.079458, -0.594849, -0.801661, 0.059106,
+0.002021, 5.139305, -8.742946, 1.500000, -0.079458, -0.000101, -0.997122, 0.075814,
+0.002021, 5.139305, -8.742946, 1.500000, -0.079458, -0.000101, -0.997122, 0.075814,
+1.004758, 5.372389, -8.744530, 2.000000, -0.079458, 0.594556, -0.801738, 0.060986,
+1.002737, 5.163681, -6.177338, 2.000000, -0.308178, 0.587260, -0.794834, -0.152858,
+1.002737, 5.163681, -6.177338, 2.000000, -0.308178, 0.587260, -0.794834, -0.152858,
+1.002737, 4.402004, -3.694788, 2.000000, -0.537451, 0.571136, -0.774985, -0.270560,
+0.000000, 4.171406, -3.728287, 1.500000, -0.537451, 0.000000, -0.943782, -0.330570,
+0.000000, 4.171406, -3.728287, 1.500000, -0.537451, 0.000000, -0.943782, -0.330570,
+-1.002737, 4.402004, -3.694788, 1.000000, -0.537451, -0.571136, -0.774985, -0.270559,
+-1.002737, 5.163677, -6.177338, 1.000000, -0.308178, -0.587361, -0.794674, -0.153298,
+-1.002737, 3.362402, -1.013249, 1.000000, -0.767833, -0.559574, -0.778227, -0.285025,
+-1.002737, 4.402004, -3.694788, 1.000000, -0.537451, -0.571136, -0.774985, -0.270559,
+0.000000, 4.171406, -3.728287, 1.500000, -0.537451, 0.000000, -0.943782, -0.330570,
+0.000000, 4.171406, -3.728287, 1.500000, -0.537451, 0.000000, -0.943782, -0.330570,
+1.002737, 4.402004, -3.694788, 2.000000, -0.537451, 0.571136, -0.774985, -0.270560,
+1.002737, 3.362402, -1.013249, 2.000000, -0.767833, 0.559574, -0.778227, -0.285025,
+1.002737, 3.362402, -1.013249, 2.000000, -0.767833, 0.559574, -0.778227, -0.285025,
+1.002737, 2.394936, 1.783656, 2.000000, -0.979466, 0.550621, -0.806194, -0.216490,
+0.000000, 2.167702, 1.752268, 1.500000, -0.979466, -0.000000, -0.966229, -0.257685,
+0.000000, 2.167702, 1.752268, 1.500000, -0.979466, -0.000000, -0.966229, -0.257685,
+-1.002737, 2.394936, 1.783656, 1.046875, -0.973474, -0.550621, -0.806194, -0.216490,
+-1.002737, 3.362402, -1.013249, 1.000000, -0.767833, -0.559574, -0.778227, -0.285025,
+-1.002737, 1.849670, 4.612304, 1.187500, -1.128520, -0.548005, -0.830422, -0.100446,
+-1.002737, 2.394936, 1.783656, 1.046875, -0.973474, -0.550621, -0.806194, -0.216490,
+0.000000, 2.167702, 1.752268, 1.500000, -0.979466, -0.000000, -0.966229, -0.257685,
+0.000000, 2.167702, 1.752268, 1.500000, -0.979466, -0.000000, -0.966229, -0.257685,
+1.002737, 2.394936, 1.783656, 2.000000, -0.979466, 0.550621, -0.806194, -0.216490,
+1.002737, 1.849670, 4.612304, 2.000000, -1.152493, 0.548005, -0.830422, -0.100446,
+1.002737, 1.849670, 4.612304, 2.000000, -1.152493, 0.548005, -0.830422, -0.100446,
+1.002737, 1.707661, 7.456823, 2.000000, -1.306215, 0.546192, -0.837529, 0.014826,
+0.000000, 1.483450, 7.466458, 1.500000, -1.306215, 0.000000, -0.999837, 0.018050,
+0.000000, 1.483450, 7.466458, 1.500000, -1.306215, 0.000000, -0.999837, 0.018050,
+-1.002737, 1.707661, 7.456823, 1.000000, -1.306215, -0.546192, -0.837529, 0.014826,
+-1.002737, 1.849670, 4.612304, 1.187500, -1.128520, -0.548005, -0.830422, -0.100446,
+-1.022346, 3.341311, 15.726742, 1.166667, -1.691614, -0.553953, -0.781075, 0.288198,
+-1.007639, 2.515034, 13.079953, 1.000000, -1.613659, -0.551445, -0.808533, 0.205386,
+-0.004902, 2.294706, 13.134627, 1.500000, -1.613659, 0.000247, -0.968748, 0.248048,
+-0.004902, 2.294706, 13.134627, 1.500000, -1.613659, 0.000247, -0.968748, 0.248048,
+0.997835, 2.515034, 13.079953, 2.000000, -1.613659, 0.552074, -0.807195, 0.208929,
+0.983128, 3.341311, 15.726744, 2.000000, -1.695003, 0.553551, -0.779630, 0.292845,
+0.983128, 3.341311, 15.726744, 2.000000, -1.695003, 0.553551, -0.779630, 0.292845,
+0.973323, 4.412262, 18.174875, 2.000000, -1.776346, 0.554281, -0.740975, 0.379115,
+-0.029414, 4.201355, 18.265430, 1.500000, -1.776346, -0.000535, -0.890739, 0.454514,
+-0.029414, 4.201355, 18.265430, 1.500000, -1.776346, -0.000535, -0.890739, 0.454514,
+-1.032151, 4.412262, 18.174877, 1.000000, -1.776346, -0.555665, -0.740194, 0.378615,
+-1.022346, 3.341311, 15.726742, 1.166667, -1.691614, -0.553953, -0.781075, 0.288198,
+0.000000, 8.401409, 24.234768, 1.500000, -2.000000, -0.000001, -0.291501, 0.956571,
+-0.742768, 8.411285, 23.925793, 1.000000, -2.000000, -0.485429, -0.281111, 0.827850,
+-1.002737, 7.854620, 23.452549, 1.000000, -1.969517, -0.579230, -0.604597, 0.546768,
+-1.002737, 7.854620, 23.452549, 1.000000, -1.969517, -0.579230, -0.604597, 0.546768,
+-1.007639, 6.953747, 22.156216, 1.000000, -1.939034, -0.571627, -0.672843, 0.469600,
+-0.004902, 6.752687, 22.278475, 1.500000, -1.939034, 0.000369, -0.822635, 0.568570,
+-0.004902, 6.752687, 22.278475, 1.500000, -1.939034, 0.000369, -0.822635, 0.568570,
+0.997835, 6.953747, 22.156214, 2.000000, -1.939034, 0.572743, -0.675634, 0.464203,
+1.002737, 7.854620, 23.452549, 2.000000, -1.969517, 0.580173, -0.605657, 0.544591,
+1.002737, 7.854620, 23.452549, 2.000000, -1.969517, 0.580173, -0.605657, 0.544591,
+0.742768, 8.411285, 23.925795, 2.000000, -2.000000, 0.485428, -0.281111, 0.827851,
+0.000000, 8.401409, 24.234768, 1.500000, -2.000000, -0.000001, -0.291501, 0.956571,
+1.002737, 0.129889, -32.334755, 2.937500, 0.946466, 0.578352, 0.815661, -0.014359,
+1.002737, 0.153999, -30.965355, 2.906250, 0.897588, 0.580105, 0.814042, -0.028521,
+1.336982, -0.552929, -30.921089, 2.500000, 0.937170, 0.999978, -0.006539, 0.000687,
+1.336982, -0.552929, -30.921089, 2.500000, 0.937170, 0.999978, -0.006539, 0.000687,
+1.002737, -1.259859, -30.876823, 2.000000, 0.937170, 0.573164, -0.818795, 0.032517,
+1.002737, -1.292564, -32.294174, 2.000000, 0.972854, 0.576237, -0.817066, 0.018853,
+1.002737, -1.156864, -28.875965, 2.000000, 0.884407, 0.570246, -0.818775, 0.066533,
+1.002737, -1.259859, -30.876823, 2.000000, 0.937170, 0.573164, -0.818795, 0.032517,
+1.336982, -0.552929, -30.921089, 2.500000, 0.937170, 0.999978, -0.006539, 0.000687,
+1.336982, -0.552929, -30.921089, 2.500000, 0.937170, 0.999978, -0.006539, 0.000687,
+1.002737, 0.153999, -30.965355, 2.906250, 0.897588, 0.580105, 0.814042, -0.028521,
+1.002737, 0.245815, -29.027195, 2.937500, 0.858019, 0.580554, 0.811733, -0.063605,
+1.002737, 0.245815, -29.027195, 2.937500, 0.858019, 0.580554, 0.811733, -0.063605,
+1.002737, 0.496042, -26.601746, 2.968750, 0.804268, 0.581048, 0.805721, -0.114877,
+1.336982, -0.199492, -26.493555, 2.500000, 0.812277, 0.999928, -0.011914, 0.001651,
+1.336982, -0.199492, -26.493555, 2.500000, 0.812277, 0.999928, -0.011914, 0.001651,
+1.002737, -0.895025, -26.385365, 2.000000, 0.812277, 0.568649, -0.814249, 0.116778,
+1.002737, -1.156864, -28.875965, 2.000000, 0.884407, 0.570246, -0.818775, 0.066533,
+1.002737, -0.385786, -23.498796, 2.000000, 0.718491, 0.564910, -0.802377, 0.192532,
+1.002737, -0.895025, -26.385365, 2.000000, 0.812277, 0.568649, -0.814249, 0.116778,
+1.336982, -0.199492, -26.493555, 2.500000, 0.812277, 0.999928, -0.011914, 0.001651,
+1.336982, -0.199492, -26.493555, 2.500000, 0.812277, 0.999928, -0.011914, 0.001651,
+1.002737, 0.496042, -26.601746, 2.968750, 0.804268, 0.581048, 0.805721, -0.114877,
+1.002737, 0.995396, -23.770485, 2.937500, 0.712843, 0.583294, 0.789623, -0.190427,
+1.002737, 0.995396, -23.770485, 2.937500, 0.712843, 0.583294, 0.789623, -0.190427,
+1.004758, 1.899328, -20.774343, 2.890625, 0.592229, 0.578470, 0.756840, -0.304248,
+1.339004, 1.211163, -20.628948, 2.500000, 0.596697, 0.999699, -0.021427, 0.011933,
+1.339004, 1.211163, -20.628948, 2.500000, 0.596697, 0.999699, -0.021427, 0.011933,
+1.004758, 0.522999, -20.483551, 2.000000, 0.596697, 0.555081, -0.772140, 0.309331,
+1.002737, -0.385786, -23.498796, 2.000000, 0.718491, 0.564910, -0.802377, 0.192532,
+1.010821, 1.983473, -17.606916, 2.000000, 0.440543, 0.553586, -0.738015, 0.385845,
+1.004758, 0.522999, -20.483551, 2.000000, 0.596697, 0.555081, -0.772140, 0.309331,
+1.339004, 1.211163, -20.628948, 2.500000, 0.596697, 0.999699, -0.021427, 0.011933,
+1.339004, 1.211163, -20.628948, 2.500000, 0.596697, 0.999699, -0.021427, 0.011933,
+1.004758, 1.899328, -20.774343, 2.890625, 0.592229, 0.578470, 0.756840, -0.304248,
+1.010821, 3.363289, -17.854240, 2.875000, 0.450913, 0.554791, 0.739026, -0.382161,
+1.010821, 3.363289, -17.854240, 2.875000, 0.450913, 0.554791, 0.739026, -0.382161,
+1.014864, 4.931509, -14.894089, 3.000000, 0.267209, 0.545447, 0.762198, -0.348629,
+1.349109, 4.237772, -14.807808, 2.500000, 0.267209, 0.999805, 0.015731, -0.011963,
+1.349109, 4.237772, -14.807808, 2.500000, 0.267209, 0.999805, 0.015731, -0.011963,
+1.014864, 3.544037, -14.721523, 2.000000, 0.267209, 0.562535, -0.748836, 0.350428,
+1.010821, 1.983473, -17.606916, 2.000000, 0.440543, 0.553586, -0.738015, 0.385845,
+1.002737, 5.163681, -6.177338, 2.000000, -0.308178, 0.587260, -0.794834, -0.152858,
+1.004758, 5.372389, -8.744530, 2.000000, -0.079458, 0.594556, -0.801738, 0.060986,
+1.339004, 6.071638, -8.749280, 2.500000, -0.079458, 0.999013, 0.044275, -0.003633,
+1.339004, 6.071638, -8.749280, 2.500000, -0.079458, 0.999013, 0.044275, -0.003633,
+1.004758, 6.770885, -8.754030, 3.000000, -0.079458, 0.549543, 0.833398, -0.058740,
+1.002737, 6.556976, -6.071414, 2.937500, -0.360878, 0.552962, 0.818993, 0.153246,
+1.002737, 6.556976, -6.071414, 2.937500, -0.360878, 0.552962, 0.818993, 0.153246,
+1.002737, 5.785589, -3.493792, 2.968750, -0.549437, 0.556039, 0.785897, 0.270530,
+1.336982, 5.093796, -3.594290, 2.500000, -0.537451, 0.999877, 0.014256, 0.006545,
+1.336982, 5.093796, -3.594290, 2.500000, -0.537451, 0.999877, 0.014256, 0.006545,
+1.002737, 4.402004, -3.694788, 2.000000, -0.537451, 0.571136, -0.774985, -0.270560,
+1.002737, 5.163681, -6.177338, 2.000000, -0.308178, 0.587260, -0.794834, -0.152858,
+1.002737, 3.362402, -1.013249, 2.000000, -0.767833, 0.559574, -0.778227, -0.285025,
+1.002737, 4.402004, -3.694788, 2.000000, -0.537451, 0.571136, -0.774985, -0.270560,
+1.336982, 5.093796, -3.594290, 2.500000, -0.537451, 0.999877, 0.014256, 0.006545,
+1.336982, 5.093796, -3.594290, 2.500000, -0.537451, 0.999877, 0.014256, 0.006545,
+1.002737, 5.785589, -3.493792, 2.968750, -0.549437, 0.556039, 0.785897, 0.270530,
+1.002737, 4.735826, -0.785002, 2.937500, -0.763077, 0.563593, 0.774459, 0.287360,
+1.002737, 4.735826, -0.785002, 2.937500, -0.763077, 0.563593, 0.774459, 0.287360,
+1.002737, 3.758350, 1.971984, 2.890625, -0.966339, 0.573361, 0.788967, 0.220880,
+1.336982, 3.076645, 1.877820, 2.500000, -0.979466, 0.999725, -0.022213, -0.007478,
+1.336982, 3.076645, 1.877820, 2.500000, -0.979466, 0.999725, -0.022213, -0.007478,
+1.002737, 2.394936, 1.783656, 2.000000, -0.979466, 0.550621, -0.806194, -0.216490,
+1.002737, 3.362402, -1.013249, 2.000000, -0.767833, 0.559574, -0.778227, -0.285025,
+1.336982, 2.380295, 7.427917, 2.500000, -1.306215, 0.999670, -0.025705, 0.000199,
+1.002737, 1.707661, 7.456823, 2.000000, -1.306215, 0.546192, -0.837529, 0.014826,
+1.002737, 1.849670, 4.612304, 2.000000, -1.152493, 0.548005, -0.830422, -0.100446,
+1.002737, 1.849670, 4.612304, 2.000000, -1.152493, 0.548005, -0.830422, -0.100446,
+1.002737, 2.394936, 1.783656, 2.000000, -0.979466, 0.550621, -0.806194, -0.216490,
+1.336982, 3.076645, 1.877820, 2.500000, -0.979466, 0.999725, -0.022213, -0.007478,
+1.336982, 3.076645, 1.877820, 2.500000, -0.979466, 0.999725, -0.022213, -0.007478,
+1.002737, 3.758350, 1.971984, 2.890625, -0.966339, 0.573361, 0.788967, 0.220880,
+1.002737, 3.203825, 4.694192, 2.875000, -1.123764, 0.573167, 0.812586, 0.105755,
+1.002737, 3.203825, 4.694192, 2.875000, -1.123764, 0.573167, 0.812586, 0.105755,
+1.002737, 3.052929, 7.399012, 3.000000, -1.306215, 0.571504, 0.820504, -0.012461,
+1.336982, 2.380295, 7.427917, 2.500000, -1.306215, 0.999670, -0.025705, 0.000199,
+0.983128, 3.341311, 15.726744, 2.000000, -1.695003, 0.553551, -0.779630, 0.292845,
+0.997835, 2.515034, 13.079953, 2.000000, -1.613659, 0.552074, -0.807195, 0.208929,
+1.332080, 3.176014, 12.915927, 2.500000, -1.613659, 0.999801, -0.018232, 0.008046,
+1.332080, 3.176014, 12.915927, 2.500000, -1.613659, 0.999801, -0.018232, 0.008046,
+0.997834, 3.836994, 12.751901, 3.000000, -1.613659, 0.571655, 0.794480, -0.204969,
+0.983128, 4.637777, 15.286472, 2.833333, -1.698392, 0.573967, 0.767126, -0.286495,
+0.983128, 4.637777, 15.286472, 2.833333, -1.698392, 0.573967, 0.767126, -0.286495,
+0.973323, 5.677700, 17.631544, 3.000000, -1.776346, 0.576561, 0.724323, -0.378066,
+1.307569, 5.044981, 17.903212, 2.500000, -1.776346, 0.999751, -0.019683, 0.010530,
+1.307569, 5.044981, 17.903212, 2.500000, -1.776346, 0.999751, -0.019683, 0.010530,
+0.973323, 4.412262, 18.174875, 2.000000, -1.776346, 0.554281, -0.740975, 0.379115,
+0.983128, 3.341311, 15.726744, 2.000000, -1.695003, 0.553551, -0.779630, 0.292845,
+1.002737, 8.987209, 23.827108, 2.500000, -2.000000, 0.690085, 0.408969, 0.597099,
+0.742768, 8.411285, 23.925795, 2.000000, -2.000000, 0.485428, -0.281111, 0.827851,
+1.002737, 7.854620, 23.452549, 2.000000, -1.969517, 0.580173, -0.605657, 0.544591,
+1.002737, 7.854620, 23.452549, 2.000000, -1.969517, 0.580173, -0.605657, 0.544591,
+0.997835, 6.953747, 22.156214, 2.000000, -1.939034, 0.572743, -0.675634, 0.464203,
+1.332080, 7.556932, 21.789433, 2.500000, -1.939034, 0.999977, -0.005048, -0.004524,
+1.332080, 7.556932, 21.789433, 2.500000, -1.939034, 0.999977, -0.005048, -0.004524,
+0.997834, 8.160118, 21.422651, 3.000000, -1.939034, 0.574744, 0.665807, -0.475784,
+1.002737, 9.038933, 22.663582, 3.000000, -1.969517, 0.583232, 0.718345, -0.379238,
+1.002737, 9.038933, 22.663582, 3.000000, -1.969517, 0.583232, 0.718345, -0.379238,
+0.742768, 9.282909, 23.329664, 3.000000, -2.000000, 0.487250, 0.872639, 0.032983,
+1.002737, 8.987209, 23.827108, 2.500000, -2.000000, 0.690085, 0.408969, 0.597099,
+-1.002737, 0.129889, -32.334755, 3.500000, 0.761751, -0.578352, 0.815661, -0.014359,
+-1.002737, 0.153999, -30.965355, 3.000000, 0.523501, -0.580105, 0.814042, -0.028521,
+0.000000, 0.389645, -30.980114, 3.125000, 0.778842, -0.000000, 0.999403, -0.034561,
+0.000000, 0.389645, -30.980114, 3.125000, 0.778842, -0.000000, 0.999403, -0.034561,
+1.002737, 0.153999, -30.965355, 2.906250, 0.897588, 0.580105, 0.814042, -0.028521,
+1.002737, 0.129889, -32.334755, 2.937500, 0.946466, 0.578352, 0.815661, -0.014359,
+1.002737, 0.245815, -29.027195, 2.937500, 0.858019, 0.580554, 0.811733, -0.063605,
+1.002737, 0.153999, -30.965355, 2.906250, 0.897588, 0.580105, 0.814042, -0.028521,
+0.000000, 0.389645, -30.980114, 3.125000, 0.778842, -0.000000, 0.999403, -0.034561,
+0.000000, 0.389645, -30.980114, 3.125000, 0.778842, -0.000000, 0.999403, -0.034561,
+-1.002737, 0.153999, -30.965355, 3.000000, 0.523501, -0.580105, 0.814042, -0.028521,
+-1.002737, 0.245815, -29.027195, 3.500000, 0.673303, -0.580554, 0.811733, -0.063605,
+-1.002737, 0.245815, -29.027195, 3.500000, 0.673303, -0.580554, 0.811733, -0.063605,
+-1.002737, 0.496042, -26.601746, 4.000000, 0.823105, -0.581048, 0.805721, -0.114877,
+0.000000, 0.727886, -26.637808, 3.375000, 0.780241, 0.000000, 0.990007, -0.141020,
+0.000000, 0.727886, -26.637808, 3.375000, 0.780241, 0.000000, 0.990007, -0.141020,
+1.002737, 0.496042, -26.601746, 2.968750, 0.804268, 0.581048, 0.805721, -0.114877,
+1.002737, 0.245815, -29.027195, 2.937500, 0.858019, 0.580554, 0.811733, -0.063605,
+1.002737, 0.995396, -23.770485, 2.937500, 0.712843, 0.583294, 0.789623, -0.190427,
+1.002737, 0.496042, -26.601746, 2.968750, 0.804268, 0.581048, 0.805721, -0.114877,
+0.000000, 0.727886, -26.637808, 3.375000, 0.780241, 0.000000, 0.990007, -0.141020,
+0.000000, 0.727886, -26.637808, 3.375000, 0.780241, 0.000000, 0.990007, -0.141020,
+-1.002737, 0.496042, -26.601746, 4.000000, 0.823105, -0.581048, 0.805721, -0.114877,
+-1.002737, 0.995396, -23.770485, 3.500000, 0.673303, -0.583417, 0.789634, -0.190008,
+-1.002737, 0.995396, -23.770485, 3.500000, 0.673303, -0.583417, 0.789634, -0.190008,
+-1.000716, 1.899328, -20.774343, 3.000000, 0.523501, -0.578823, 0.757196, -0.302684,
+0.002021, 2.128716, -20.822807, 3.062500, 0.578824, -0.000086, 0.927679, -0.373379,
+0.002021, 2.128716, -20.822807, 3.062500, 0.578824, -0.000086, 0.927679, -0.373379,
+1.004758, 1.899328, -20.774343, 2.890625, 0.592229, 0.578470, 0.756840, -0.304248,
+1.002737, 0.995396, -23.770485, 2.937500, 0.712843, 0.583294, 0.789623, -0.190427,
+0.012127, 5.162754, -14.922852, 3.000000, 0.395355, 0.000167, 0.910359, -0.413819,
+1.014864, 4.931509, -14.894089, 3.000000, 0.267209, 0.545447, 0.762198, -0.348629,
+1.010821, 3.363289, -17.854240, 2.875000, 0.450913, 0.554791, 0.739026, -0.382161,
+1.010821, 3.363289, -17.854240, 2.875000, 0.450913, 0.554791, 0.739026, -0.382161,
+1.004758, 1.899328, -20.774343, 2.890625, 0.592229, 0.578470, 0.756840, -0.304248,
+0.002021, 2.128716, -20.822807, 3.062500, 0.578824, -0.000086, 0.927679, -0.373379,
+0.002021, 2.128716, -20.822807, 3.062500, 0.578824, -0.000086, 0.927679, -0.373379,
+-1.000716, 1.899328, -20.774343, 3.000000, 0.523501, -0.578823, 0.757196, -0.302684,
+-0.994652, 3.363289, -17.854239, 3.000000, 0.523501, -0.554925, 0.739714, -0.380633,
+-0.994652, 3.363289, -17.854239, 3.000000, 0.523501, -0.554925, 0.739714, -0.380633,
+-0.990610, 4.931509, -14.894089, 3.000000, 0.523501, -0.544986, 0.762408, -0.348891,
+0.012127, 5.162754, -14.922852, 3.000000, 0.395355, 0.000167, 0.910359, -0.413819,
+1.002737, 6.556976, -6.071414, 2.937500, -0.360878, 0.552962, 0.818993, 0.153246,
+1.004758, 6.770885, -8.754030, 3.000000, -0.079458, 0.549543, 0.833398, -0.058740,
+0.002021, 7.003967, -8.755614, 3.000000, -0.501061, -0.000102, 0.997541, -0.070087,
+0.002021, 7.003967, -8.755614, 3.000000, -0.501061, -0.000102, 0.997541, -0.070087,
+-1.000716, 6.770885, -8.754030, 3.000000, -0.922665, -0.549751, 0.833161, -0.060139,
+-1.002737, 6.556976, -6.071414, 3.500000, -0.729781, -0.553122, 0.818963, 0.152824,
+-1.002737, 6.556976, -6.071414, 3.500000, -0.729781, -0.553122, 0.818963, 0.152824,
+-1.002737, 5.785589, -3.493792, 4.000000, -0.536897, -0.556039, 0.785897, 0.270530,
+0.000000, 6.016188, -3.460293, 3.375000, -0.585395, -0.000000, 0.945916, 0.324411,
+0.000000, 6.016188, -3.460293, 3.375000, -0.585395, -0.000000, 0.945916, 0.324411,
+1.002737, 5.785589, -3.493792, 2.968750, -0.549437, 0.556039, 0.785897, 0.270530,
+1.002737, 6.556976, -6.071414, 2.937500, -0.360878, 0.552962, 0.818993, 0.153246,
+1.002737, 4.735826, -0.785002, 2.937500, -0.763077, 0.563593, 0.774459, 0.287360,
+1.002737, 5.785589, -3.493792, 2.968750, -0.549437, 0.556039, 0.785897, 0.270530,
+0.000000, 6.016188, -3.460293, 3.375000, -0.585395, -0.000000, 0.945916, 0.324411,
+0.000000, 6.016188, -3.460293, 3.375000, -0.585395, -0.000000, 0.945916, 0.324411,
+-1.002737, 5.785589, -3.493792, 4.000000, -0.536897, -0.556039, 0.785897, 0.270530,
+-1.002737, 4.735826, -0.785002, 3.500000, -0.729781, -0.563593, 0.774459, 0.287360,
+-1.002737, 4.735826, -0.785002, 3.500000, -0.729781, -0.563593, 0.774459, 0.287360,
+-1.002737, 3.758350, 1.971984, 3.000000, -0.922665, -0.573360, 0.788967, 0.220880,
+0.000000, 3.985586, 2.003372, 3.062500, -0.926955, 0.000000, 0.962477, 0.271365,
+0.000000, 3.985586, 2.003372, 3.062500, -0.926955, 0.000000, 0.962477, 0.271365,
+1.002737, 3.758350, 1.971984, 2.890625, -0.966339, 0.573361, 0.788967, 0.220880,
+1.002737, 4.735826, -0.785002, 2.937500, -0.763077, 0.563593, 0.774459, 0.287360,
+1.002737, 3.203825, 4.694192, 2.875000, -1.123764, 0.573167, 0.812586, 0.105755,
+1.002737, 3.758350, 1.971984, 2.890625, -0.966339, 0.573361, 0.788967, 0.220880,
+0.000000, 3.985586, 2.003372, 3.062500, -0.926955, 0.000000, 0.962477, 0.271365,
+0.000000, 3.985586, 2.003372, 3.062500, -0.926955, 0.000000, 0.962477, 0.271365,
+-1.002737, 3.758350, 1.971984, 3.000000, -0.922665, -0.573360, 0.788967, 0.220880,
+-1.002737, 3.203825, 4.694192, 3.000000, -0.922665, -0.573166, 0.812586, 0.105755,
+-1.002737, 3.203825, 4.694192, 3.000000, -0.922665, -0.573166, 0.812586, 0.105755,
+-1.002737, 3.052929, 7.399012, 3.000000, -0.922665, -0.571504, 0.820505, -0.012461,
+0.000000, 3.277142, 7.389376, 3.000000, -1.114440, 0.000000, 0.999891, -0.014768,
+0.000000, 3.277142, 7.389376, 3.000000, -1.114440, 0.000000, 0.999891, -0.014768,
+1.002737, 3.052929, 7.399012, 3.000000, -1.306215, 0.571504, 0.820504, -0.012461,
+1.002737, 3.203825, 4.694192, 2.875000, -1.123764, 0.573167, 0.812586, 0.105755,
+-0.029414, 5.888605, 17.540989, 2.833333, -1.749232, -0.000556, 0.885983, -0.463718,
+0.973323, 5.677700, 17.631544, 3.000000, -1.776346, 0.576561, 0.724323, -0.378066,
+0.983128, 4.637777, 15.286472, 2.833333, -1.698392, 0.573967, 0.767126, -0.286495,
+0.983128, 4.637777, 15.286472, 2.833333, -1.698392, 0.573967, 0.767126, -0.286495,
+0.997834, 3.836994, 12.751901, 3.000000, -1.613659, 0.571655, 0.794480, -0.204969,
+-0.004902, 4.057320, 12.697225, 2.833333, -1.667888, 0.000259, 0.967531, -0.252752,
+-0.004902, 4.057320, 12.697225, 2.833333, -1.667888, 0.000259, 0.967531, -0.252752,
+-1.007639, 3.836994, 12.751901, 2.666667, -1.722117, -0.571038, 0.793815, -0.209219,
+-1.022346, 4.637777, 15.286472, 2.666667, -1.722117, -0.574184, 0.765044, -0.291584,
+-1.022346, 4.637777, 15.286472, 2.666667, -1.722117, -0.574184, 0.765044, -0.291584,
+-1.032151, 5.677700, 17.631544, 2.666667, -1.722117, -0.577835, 0.723604, -0.377496,
+-0.029414, 5.888605, 17.540989, 2.833333, -1.749232, -0.000556, 0.885983, -0.463718,
+0.000000, 9.573013, 23.419453, 3.500000, -2.000000, -0.000000, 0.997856, 0.065453,
+0.742768, 9.282909, 23.329664, 3.000000, -2.000000, 0.487250, 0.872639, 0.032983,
+1.002737, 9.038933, 22.663582, 3.000000, -1.969517, 0.583232, 0.718345, -0.379238,
+1.002737, 9.038933, 22.663582, 3.000000, -1.969517, 0.583232, 0.718345, -0.379238,
+0.997834, 8.160118, 21.422651, 3.000000, -1.939034, 0.574744, 0.665807, -0.475784,
+-0.004902, 8.361179, 21.300390, 3.500000, -1.939034, 0.000389, 0.815229, -0.579139,
+-0.004902, 8.361179, 21.300390, 3.500000, -1.939034, 0.000389, 0.815229, -0.579139,
+-1.007639, 8.160118, 21.422651, 4.000000, -1.939034, -0.574068, 0.669723, -0.471080,
+-1.002737, 9.038933, 22.663582, 4.000000, -1.969517, -0.582357, 0.720010, -0.377421,
+-1.002737, 9.038933, 22.663582, 4.000000, -1.969517, -0.582357, 0.720010, -0.377421,
+-0.742768, 9.282909, 23.329664, 4.000000, -2.000000, -0.487251, 0.872639, 0.032983,
+0.000000, 9.573013, 23.419453, 3.500000, -2.000000, -0.000000, 0.997856, 0.065453,
+-1.002737, -2.734034, 6.657467, 1.500000, 0.761751, -0.582703, 0.762742, 0.280503,
+-1.002737, -1.996943, 4.816424, 0.000000, 1.000000, -0.580237, 0.756078, 0.302774,
+-1.336982, -2.618040, 4.463405, 0.500000, 1.000000, -0.999977, -0.006223, -0.002555,
+-1.336982, -2.618040, 4.463405, 0.500000, 1.000000, -0.999977, -0.006223, -0.002555,
+-1.002737, -3.239137, 4.110385, 1.000000, 1.000000, -0.573276, -0.760494, -0.304965,
+-1.002737, -3.988198, 5.977939, 1.187500, 0.890530, -0.568961, -0.771457, -0.284847,
+-1.002737, -3.988198, 5.977939, 1.187500, 0.890530, -0.568961, -0.771457, -0.284847,
+-1.002737, -4.824668, 8.406097, 1.000000, 0.817855, -0.564875, -0.790113, -0.237986,
+-1.336982, -4.187579, 8.722692, 2.000000, 0.670678, -0.999851, -0.016874, -0.003651,
+-1.336982, -4.187579, 8.722692, 2.000000, 0.670678, -0.999851, -0.016874, -0.003651,
+-1.002737, -3.550490, 9.039287, 3.000000, 0.523501, -0.582189, 0.779143, 0.232362,
+-1.002737, -2.734034, 6.657467, 1.500000, 0.761751, -0.582703, 0.762742, 0.280503,
+-1.002737, -4.339600, 12.037193, 0.000000, 0.651188, -0.578711, 0.795540, 0.179472,
+-1.002737, -3.550490, 9.039287, 0.000000, 0.817855, -0.582189, 0.779143, 0.232362,
+-1.336982, -4.187579, 8.722692, 0.500000, 0.817855, -0.999851, -0.016874, -0.003651,
+-1.336982, -4.187579, 8.722692, 0.500000, 0.817855, -0.999851, -0.016874, -0.003651,
+-1.002737, -4.824668, 8.406097, 1.000000, 0.817855, -0.564875, -0.790113, -0.237986,
+-1.002737, -5.641894, 11.472322, 1.000000, 0.651188, -0.564280, -0.804601, -0.184946,
+-1.002737, -5.641894, 11.472322, 1.000000, 0.651188, -0.564280, -0.804601, -0.184946,
+-1.002737, -6.318611, 14.911804, 1.000000, 0.470545, -0.563019, -0.816504, -0.127790,
+-1.336982, -5.652997, 15.157051, 0.500000, 0.470545, -0.999903, -0.013895, -0.000479,
+-1.336982, -5.652997, 15.157051, 0.500000, 0.470545, -0.999903, -0.013895, -0.000479,
+-1.002737, -4.987385, 15.402298, 0.000000, 0.484521, -0.576620, 0.807781, 0.122473,
+-1.002737, -4.339600, 12.037193, 0.000000, 0.651188, -0.578711, 0.795540, 0.179472,
+-1.002737, -5.379865, 18.885717, 0.000000, 0.261948, -0.572718, 0.816712, 0.070540,
+-1.002737, -4.987385, 15.402298, 0.000000, 0.484521, -0.576620, 0.807781, 0.122473,
+-1.336982, -5.652997, 15.157051, 0.500000, 0.470545, -0.999903, -0.013895, -0.000479,
+-1.336982, -5.652997, 15.157051, 0.500000, 0.470545, -0.999903, -0.013895, -0.000479,
+-1.002737, -6.318611, 14.911804, 1.000000, 0.470545, -0.563019, -0.816504, -0.127790,
+-1.002737, -6.733546, 18.459730, 1.000000, 0.261948, -0.564150, -0.822280, -0.074773,
+-1.002737, -6.733546, 18.459730, 1.000000, 0.261948, -0.564150, -0.822280, -0.074773,
+-1.002737, -6.957025, 21.947737, 1.000000, 0.047044, -0.566391, -0.823173, -0.039848,
+-1.336982, -6.271589, 22.133167, 0.500000, 0.047044, -0.999991, -0.004281, 0.000323,
+-1.336982, -6.271589, 22.133167, 0.500000, 0.047044, -0.999991, -0.004281, 0.000323,
+-1.002737, -5.586154, 22.318600, 0.000000, 0.039374, -0.570604, 0.820419, 0.036373,
+-1.002737, -5.379865, 18.885717, 0.000000, 0.261948, -0.572718, 0.816712, 0.070540,
+-1.002737, -5.675372, 25.532089, 0.000000, -0.152521, -0.572885, 0.819555, 0.011471,
+-1.002737, -5.586154, 22.318600, 0.000000, 0.039374, -0.570604, 0.820419, 0.036373,
+-1.336982, -6.271589, 22.133167, 0.500000, 0.047044, -0.999991, -0.004281, 0.000323,
+-1.336982, -6.271589, 22.133167, 0.500000, 0.047044, -0.999991, -0.004281, 0.000323,
+-1.002737, -6.957025, 21.947737, 1.000000, 0.047044, -0.566391, -0.823173, -0.039848,
+-1.002737, -7.059372, 25.207462, 1.000000, -0.152521, -0.565822, -0.824400, -0.014526,
+-1.002737, -7.059372, 25.207462, 1.000000, -0.152521, -0.565822, -0.824400, -0.014526,
+-1.002737, -7.074721, 28.664906, 1.000000, -0.338108, -0.564757, -0.825254, 0.002341,
+-1.336982, -6.377152, 28.805500, 0.500000, -0.338108, -0.999930, -0.011845, 0.000045,
+-1.336982, -6.377152, 28.805500, 0.500000, -0.338108, -0.999930, -0.011845, 0.000045,
+-1.002737, -5.679584, 28.946095, 0.000000, -0.344415, -0.577055, 0.816690, -0.004975,
+-1.002737, -5.675372, 25.532089, 0.000000, -0.152521, -0.572885, 0.819555, 0.011471,
+-1.002737, -5.630855, 32.893612, 0.000000, -0.511082, -0.132943, 0.189166, -0.972904,
+-1.002737, -5.679584, 28.946095, 0.000000, -0.344415, -0.577055, 0.816690, -0.004975,
+-1.336982, -6.377152, 28.805500, 0.500000, -0.338108, -0.999930, -0.011845, 0.000045,
+-1.336982, -6.377152, 28.805500, 0.500000, -0.338108, -0.999930, -0.011845, 0.000045,
+-1.002737, -7.074721, 28.664906, 1.000000, -0.338108, -0.564757, -0.825254, 0.002341,
+-1.002737, -7.037199, 32.893612, 1.000000, -0.511082, -0.140149, -0.202450, -0.969212,
+-1.002737, -7.037199, 32.893612, 1.000000, -0.511082, -0.140149, -0.202450, -0.969212,
+-4.193409, -10.256766, 32.893612, 1.027778, -0.557378, -0.685012, -0.716396, 0.132421,
+-5.620958, -6.307936, 32.893612, 0.625000, -0.573582, -0.991757, -0.001005, 0.128133,
+-5.620958, -6.307936, 32.893612, 0.625000, -0.573582, -0.991757, -0.001005, 0.128133,
+-4.193409, -2.445326, 32.893612, 0.000000, -0.594415, -0.686924, 0.716419, 0.121978,
+-1.002737, -5.630855, 32.893612, 0.000000, -0.511082, -0.132943, 0.189166, -0.972904,
+-1.002737, -3.988198, 5.977939, 1.187500, 0.890530, -0.568961, -0.771457, -0.284847,
+-1.002737, -3.239137, 4.110385, 1.000000, 1.000000, -0.573276, -0.760494, -0.304965,
+0.000000, -3.446170, 3.992712, 1.500000, 1.000000, 0.000000, -0.928140, -0.372231,
+0.000000, -3.446170, 3.992712, 1.500000, 1.000000, 0.000000, -0.928140, -0.372231,
+1.002737, -3.239137, 4.110385, 2.000000, 1.000000, 0.573276, -0.760494, -0.304965,
+1.002737, -3.988198, 5.977940, 2.000000, 0.908927, 0.568961, -0.771457, -0.284847,
+1.002737, -3.988198, 5.977940, 2.000000, 0.908927, 0.568961, -0.771457, -0.284847,
+1.002737, -4.824668, 8.406097, 2.000000, 0.798956, 0.564875, -0.790113, -0.237986,
+0.000000, -5.037031, 8.300566, 1.500000, 0.798956, 0.000000, -0.957267, -0.289205,
+0.000000, -5.037031, 8.300566, 1.500000, 0.798956, 0.000000, -0.957267, -0.289205,
+-1.002737, -4.824668, 8.406097, 1.000000, 0.817855, -0.564875, -0.790113, -0.237986,
+-1.002737, -3.988198, 5.977939, 1.187500, 0.890530, -0.568961, -0.771457, -0.284847,
+-1.002737, -5.641894, 11.472322, 1.000000, 0.651188, -0.564280, -0.804601, -0.184946,
+-1.002737, -4.824668, 8.406097, 1.000000, 0.817855, -0.564875, -0.790113, -0.237986,
+0.000000, -5.037031, 8.300566, 1.500000, 0.798956, 0.000000, -0.957267, -0.289205,
+0.000000, -5.037031, 8.300566, 1.500000, 0.798956, 0.000000, -0.957267, -0.289205,
+1.002737, -4.824668, 8.406097, 2.000000, 0.798956, 0.564875, -0.790113, -0.237986,
+1.002737, -5.641894, 11.472323, 2.000000, 0.651188, 0.564280, -0.804601, -0.184946,
+1.002737, -5.641894, 11.472323, 2.000000, 0.651188, 0.564280, -0.804601, -0.184946,
+1.002737, -6.318611, 14.911802, 2.000000, 0.470545, 0.563019, -0.816504, -0.127790,
+0.000000, -6.540482, 14.830055, 1.500000, 0.470545, -0.000000, -0.987788, -0.155806,
+0.000000, -6.540482, 14.830055, 1.500000, 0.470545, -0.000000, -0.987788, -0.155806,
+-1.002737, -6.318611, 14.911804, 1.000000, 0.470545, -0.563019, -0.816504, -0.127790,
+-1.002737, -5.641894, 11.472322, 1.000000, 0.651188, -0.564280, -0.804601, -0.184946,
+-1.002737, -6.733546, 18.459730, 1.000000, 0.261948, -0.564150, -0.822280, -0.074773,
+-1.002737, -6.318611, 14.911804, 1.000000, 0.470545, -0.563019, -0.816504, -0.127790,
+0.000000, -6.540482, 14.830055, 1.500000, 0.470545, -0.000000, -0.987788, -0.155806,
+0.000000, -6.540482, 14.830055, 1.500000, 0.470545, -0.000000, -0.987788, -0.155806,
+1.002737, -6.318611, 14.911802, 2.000000, 0.470545, 0.563019, -0.816504, -0.127790,
+1.002737, -6.733546, 18.459730, 2.000000, 0.261948, 0.564150, -0.822280, -0.074773,
+1.002737, -6.733546, 18.459730, 2.000000, 0.261948, 0.564150, -0.822280, -0.074773,
+1.002737, -6.957025, 21.947737, 2.000000, 0.047044, 0.566391, -0.823173, -0.039848,
+0.000000, -7.185503, 21.885925, 1.500000, 0.047044, 0.000000, -0.998796, -0.049054,
+0.000000, -7.185503, 21.885925, 1.500000, 0.047044, 0.000000, -0.998796, -0.049054,
+-1.002737, -6.957025, 21.947737, 1.000000, 0.047044, -0.566391, -0.823173, -0.039848,
+-1.002737, -6.733546, 18.459730, 1.000000, 0.261948, -0.564150, -0.822280, -0.074773,
+-1.002737, -7.059372, 25.207462, 1.000000, -0.152521, -0.565822, -0.824400, -0.014526,
+-1.002737, -6.957025, 21.947737, 1.000000, 0.047044, -0.566391, -0.823173, -0.039848,
+0.000000, -7.185503, 21.885925, 1.500000, 0.047044, 0.000000, -0.998796, -0.049054,
+0.000000, -7.185503, 21.885925, 1.500000, 0.047044, 0.000000, -0.998796, -0.049054,
+1.002737, -6.957025, 21.947737, 2.000000, 0.047044, 0.566391, -0.823173, -0.039848,
+1.002737, -7.059372, 25.207462, 2.000000, -0.152521, 0.565821, -0.824400, -0.014526,
+1.002737, -7.059372, 25.207462, 2.000000, -0.152521, 0.565821, -0.824400, -0.014526,
+1.002737, -7.074721, 28.664906, 2.000000, -0.338108, 0.564757, -0.825254, 0.002341,
+0.000000, -7.307243, 28.618042, 1.500000, -0.338108, 0.000000, -0.999997, 0.002440,
+0.000000, -7.307243, 28.618042, 1.500000, -0.338108, 0.000000, -0.999997, 0.002440,
+-1.002737, -7.074721, 28.664906, 1.000000, -0.338108, -0.564757, -0.825254, 0.002341,
+-1.002737, -7.059372, 25.207462, 1.000000, -0.152521, -0.565822, -0.824400, -0.014526,
+-1.002737, -7.037199, 32.893612, 1.000000, -0.511082, -0.140149, -0.202450, -0.969212,
+-1.002737, -7.074721, 28.664906, 1.000000, -0.338108, -0.564757, -0.825254, 0.002341,
+0.000000, -7.307243, 28.618042, 1.500000, -0.338108, 0.000000, -0.999997, 0.002440,
+0.000000, -7.307243, 28.618042, 1.500000, -0.338108, 0.000000, -0.999997, 0.002440,
+1.002737, -7.074721, 28.664906, 2.000000, -0.338108, 0.564757, -0.825254, 0.002341,
+1.002737, -7.037199, 32.893612, 2.000000, -0.511082, 0.140149, -0.202450, -0.969212,
+1.002737, -7.037199, 32.893612, 2.000000, -0.511082, 0.140149, -0.202450, -0.969212,
+4.193409, -10.256766, 32.893612, 1.972222, -0.557378, 0.680284, -0.725440, 0.104643,
+0.000000, -11.548096, 32.893612, 1.500000, -0.573582, -0.004203, -0.998166, 0.060395,
+0.000000, -11.548096, 32.893612, 1.500000, -0.573582, -0.004203, -0.998166, 0.060395,
+-4.193409, -10.256766, 32.893612, 1.027778, -0.557378, -0.685012, -0.716396, 0.132421,
+-1.002737, -7.037199, 32.893612, 1.000000, -0.511082, -0.140149, -0.202450, -0.969212,
+1.002737, -3.988198, 5.977940, 2.000000, 0.908927, 0.568961, -0.771457, -0.284847,
+1.002737, -3.239137, 4.110385, 2.000000, 1.000000, 0.573276, -0.760494, -0.304965,
+1.336982, -2.618040, 4.463405, 2.500000, 1.000000, 0.999977, -0.006223, -0.002555,
+1.336982, -2.618040, 4.463405, 2.500000, 1.000000, 0.999977, -0.006223, -0.002555,
+1.002737, -1.996943, 4.816424, 3.000000, 1.000000, 0.580237, 0.756078, 0.302774,
+1.002737, -2.734034, 6.657467, 3.000000, 0.908927, 0.582703, 0.762742, 0.280503,
+1.002737, -2.734034, 6.657467, 3.000000, 0.908927, 0.582703, 0.762742, 0.280503,
+1.002737, -3.550490, 9.039287, 3.000000, 0.798956, 0.582189, 0.779143, 0.232362,
+1.336982, -4.187579, 8.722693, 2.500000, 0.798956, 0.999851, -0.016874, -0.003651,
+1.336982, -4.187579, 8.722693, 2.500000, 0.798956, 0.999851, -0.016874, -0.003651,
+1.002737, -4.824668, 8.406097, 2.000000, 0.798956, 0.564875, -0.790113, -0.237986,
+1.002737, -3.988198, 5.977940, 2.000000, 0.908927, 0.568961, -0.771457, -0.284847,
+1.002737, -5.641894, 11.472323, 2.000000, 0.651188, 0.564280, -0.804601, -0.184946,
+1.002737, -4.824668, 8.406097, 2.000000, 0.798956, 0.564875, -0.790113, -0.237986,
+1.336982, -4.187579, 8.722693, 2.500000, 0.798956, 0.999851, -0.016874, -0.003651,
+1.336982, -4.187579, 8.722693, 2.500000, 0.798956, 0.999851, -0.016874, -0.003651,
+1.002737, -3.550490, 9.039287, 3.000000, 0.798956, 0.582189, 0.779143, 0.232362,
+1.002737, -4.339600, 12.037193, 3.000000, 0.651188, 0.578711, 0.795540, 0.179472,
+1.002737, -4.339600, 12.037193, 3.000000, 0.651188, 0.578711, 0.795540, 0.179472,
+1.002737, -4.987385, 15.402298, 3.000000, 0.470545, 0.576620, 0.807781, 0.122473,
+1.336982, -5.652997, 15.157051, 2.500000, 0.470545, 0.999903, -0.013895, -0.000479,
+1.336982, -5.652997, 15.157051, 2.500000, 0.470545, 0.999903, -0.013895, -0.000479,
+1.002737, -6.318611, 14.911802, 2.000000, 0.470545, 0.563019, -0.816504, -0.127790,
+1.002737, -5.641894, 11.472323, 2.000000, 0.651188, 0.564280, -0.804601, -0.184946,
+1.002737, -6.733546, 18.459730, 2.000000, 0.261948, 0.564150, -0.822280, -0.074773,
+1.002737, -6.318611, 14.911802, 2.000000, 0.470545, 0.563019, -0.816504, -0.127790,
+1.336982, -5.652997, 15.157051, 2.500000, 0.470545, 0.999903, -0.013895, -0.000479,
+1.336982, -5.652997, 15.157051, 2.500000, 0.470545, 0.999903, -0.013895, -0.000479,
+1.002737, -4.987385, 15.402298, 3.000000, 0.470545, 0.576620, 0.807781, 0.122473,
+1.002737, -5.379865, 18.885717, 3.000000, 0.261948, 0.572718, 0.816712, 0.070540,
+1.002737, -5.379865, 18.885717, 3.000000, 0.261948, 0.572718, 0.816712, 0.070540,
+1.002737, -5.586154, 22.318600, 3.000000, 0.047044, 0.570604, 0.820419, 0.036373,
+1.336982, -6.271589, 22.133167, 2.500000, 0.047044, 0.999991, -0.004281, 0.000323,
+1.336982, -6.271589, 22.133167, 2.500000, 0.047044, 0.999991, -0.004281, 0.000323,
+1.002737, -6.957025, 21.947737, 2.000000, 0.047044, 0.566391, -0.823173, -0.039848,
+1.002737, -6.733546, 18.459730, 2.000000, 0.261948, 0.564150, -0.822280, -0.074773,
+1.002737, -7.059372, 25.207462, 2.000000, -0.152521, 0.565821, -0.824400, -0.014526,
+1.002737, -6.957025, 21.947737, 2.000000, 0.047044, 0.566391, -0.823173, -0.039848,
+1.336982, -6.271589, 22.133167, 2.500000, 0.047044, 0.999991, -0.004281, 0.000323,
+1.336982, -6.271589, 22.133167, 2.500000, 0.047044, 0.999991, -0.004281, 0.000323,
+1.002737, -5.586154, 22.318600, 3.000000, 0.047044, 0.570604, 0.820419, 0.036373,
+1.002737, -5.675372, 25.532089, 3.000000, -0.152521, 0.572885, 0.819555, 0.011471,
+1.002737, -5.675372, 25.532089, 3.000000, -0.152521, 0.572885, 0.819555, 0.011471,
+1.002737, -5.679584, 28.946095, 3.000000, -0.338108, 0.577055, 0.816690, -0.004975,
+1.336982, -6.377152, 28.805500, 2.500000, -0.338108, 0.999930, -0.011845, 0.000045,
+1.336982, -6.377152, 28.805500, 2.500000, -0.338108, 0.999930, -0.011845, 0.000045,
+1.002737, -7.074721, 28.664906, 2.000000, -0.338108, 0.564757, -0.825254, 0.002341,
+1.002737, -7.059372, 25.207462, 2.000000, -0.152521, 0.565821, -0.824400, -0.014526,
+1.002737, -7.037199, 32.893612, 2.000000, -0.511082, 0.140149, -0.202450, -0.969212,
+1.002737, -7.074721, 28.664906, 2.000000, -0.338108, 0.564757, -0.825254, 0.002341,
+1.336982, -6.377152, 28.805500, 2.500000, -0.338108, 0.999930, -0.011845, 0.000045,
+1.336982, -6.377152, 28.805500, 2.500000, -0.338108, 0.999930, -0.011845, 0.000045,
+1.002737, -5.679584, 28.946095, 3.000000, -0.338108, 0.577055, 0.816690, -0.004975,
+1.002737, -5.630855, 32.893612, 3.000000, -0.511082, 0.132943, 0.189166, -0.972904,
+1.002737, -5.630855, 32.893612, 3.000000, -0.511082, 0.132943, 0.189166, -0.972904,
+4.193409, -2.445326, 32.893612, 3.000000, -0.594415, 0.682263, 0.725032, 0.094055,
+5.620958, -6.307936, 32.893612, 2.375000, -0.573582, 0.996241, -0.000983, 0.086619,
+5.620958, -6.307936, 32.893612, 2.375000, -0.573582, 0.996241, -0.000983, 0.086619,
+4.193409, -10.256766, 32.893612, 1.972222, -0.557378, 0.680284, -0.725440, 0.104643,
+1.002737, -7.037199, 32.893612, 2.000000, -0.511082, 0.140149, -0.202450, -0.969212,
+-1.002737, -1.445931, 3.440848, 2.500000, -1.666667, -0.596303, 0.745197, 0.298504,
+-1.002737, -1.996943, 4.816424, 3.000000, -1.666667, -0.580237, 0.756078, 0.302774,
+0.000000, -1.789911, 4.934098, 3.000000, -1.833333, -0.000000, 0.928348, 0.371713,
+0.000000, -1.789911, 4.934098, 3.000000, -1.833333, -0.000000, 0.928348, 0.371713,
+1.002737, -1.996943, 4.816424, 3.000000, -2.000000, 0.580237, 0.756078, 0.302774,
+1.002737, -1.445931, 3.440848, 2.500000, -2.000000, 0.596303, 0.745197, 0.298504,
+1.002737, -2.734034, 6.657467, 3.000000, 0.908927, 0.582703, 0.762742, 0.280503,
+1.002737, -1.996943, 4.816424, 3.000000, 1.000000, 0.580237, 0.756078, 0.302774,
+0.000000, -1.789911, 4.934098, 3.500000, 1.000000, -0.000000, 0.928348, 0.371713,
+0.000000, -1.789911, 4.934098, 3.500000, 1.000000, -0.000000, 0.928348, 0.371713,
+-1.002737, -1.996943, 4.816424, 4.000000, 1.000000, -0.580237, 0.756078, 0.302774,
+-1.002737, -2.734034, 6.657467, 4.000000, 0.908927, -0.582703, 0.762742, 0.280503,
+-1.002737, -2.734034, 6.657467, 4.000000, 0.908927, -0.582703, 0.762742, 0.280503,
+-1.002737, -3.550490, 9.039287, 4.000000, 0.817855, -0.582189, 0.779143, 0.232362,
+0.000000, -3.338127, 9.144818, 3.500000, 0.798956, 0.000000, 0.958542, 0.284953,
+0.000000, -3.338127, 9.144818, 3.500000, 0.798956, 0.000000, 0.958542, 0.284953,
+1.002737, -3.550490, 9.039287, 3.000000, 0.798956, 0.582189, 0.779143, 0.232362,
+1.002737, -2.734034, 6.657467, 3.000000, 0.908927, 0.582703, 0.762742, 0.280503,
+1.002737, -4.339600, 12.037193, 3.000000, 0.651188, 0.578711, 0.795540, 0.179472,
+1.002737, -3.550490, 9.039287, 3.000000, 0.798956, 0.582189, 0.779143, 0.232362,
+0.000000, -3.338127, 9.144818, 3.500000, 0.798956, 0.000000, 0.958542, 0.284953,
+0.000000, -3.338127, 9.144818, 3.500000, 0.798956, 0.000000, 0.958542, 0.284953,
+-1.002737, -3.550490, 9.039287, 4.000000, 0.817855, -0.582189, 0.779143, 0.232362,
+-1.002737, -4.339600, 12.037193, 4.000000, 0.651188, -0.578711, 0.795540, 0.179472,
+-1.002737, -4.339600, 12.037193, 4.000000, 0.651188, -0.578711, 0.795540, 0.179472,
+-1.002737, -4.987385, 15.402298, 4.000000, 0.484521, -0.576620, 0.807781, 0.122473,
+0.000000, -4.765513, 15.484047, 3.500000, 0.470545, 0.000000, 0.988884, 0.148690,
+0.000000, -4.765513, 15.484047, 3.500000, 0.470545, 0.000000, 0.988884, 0.148690,
+1.002737, -4.987385, 15.402298, 3.000000, 0.470545, 0.576620, 0.807781, 0.122473,
+1.002737, -4.339600, 12.037193, 3.000000, 0.651188, 0.578711, 0.795540, 0.179472,
+1.002737, -5.379865, 18.885717, 3.000000, 0.261948, 0.572718, 0.816712, 0.070540,
+1.002737, -4.987385, 15.402298, 3.000000, 0.470545, 0.576620, 0.807781, 0.122473,
+0.000000, -4.765513, 15.484047, 3.500000, 0.470545, 0.000000, 0.988884, 0.148690,
+0.000000, -4.765513, 15.484047, 3.500000, 0.470545, 0.000000, 0.988884, 0.148690,
+-1.002737, -4.987385, 15.402298, 4.000000, 0.484521, -0.576620, 0.807781, 0.122473,
+-1.002737, -5.379865, 18.885717, 4.000000, 0.261948, -0.572718, 0.816712, 0.070540,
+-1.002737, -5.379865, 18.885717, 4.000000, 0.261948, -0.572718, 0.816712, 0.070540,
+-1.002737, -5.586154, 22.318600, 4.000000, 0.039374, -0.570604, 0.820419, 0.036373,
+0.000000, -5.357677, 22.380409, 3.500000, 0.047044, -0.000000, 0.999050, 0.043579,
+0.000000, -5.357677, 22.380409, 3.500000, 0.047044, -0.000000, 0.999050, 0.043579,
+1.002737, -5.586154, 22.318600, 3.000000, 0.047044, 0.570604, 0.820419, 0.036373,
+1.002737, -5.379865, 18.885717, 3.000000, 0.261948, 0.572718, 0.816712, 0.070540,
+1.002737, -5.675372, 25.532089, 3.000000, -0.152521, 0.572885, 0.819555, 0.011471,
+1.002737, -5.586154, 22.318600, 3.000000, 0.047044, 0.570604, 0.820419, 0.036373,
+0.000000, -5.357677, 22.380409, 3.500000, 0.047044, -0.000000, 0.999050, 0.043579,
+0.000000, -5.357677, 22.380409, 3.500000, 0.047044, -0.000000, 0.999050, 0.043579,
+-1.002737, -5.586154, 22.318600, 4.000000, 0.039374, -0.570604, 0.820419, 0.036373,
+-1.002737, -5.675372, 25.532089, 4.000000, -0.152521, -0.572885, 0.819555, 0.011471,
+-1.002737, -5.675372, 25.532089, 4.000000, -0.152521, -0.572885, 0.819555, 0.011471,
+-1.002737, -5.679584, 28.946095, 4.000000, -0.344415, -0.577055, 0.816690, -0.004975,
+0.000000, -5.447061, 28.992958, 3.500000, -0.338108, 0.000000, 0.999979, -0.006525,
+0.000000, -5.447061, 28.992958, 3.500000, -0.338108, 0.000000, 0.999979, -0.006525,
+1.002737, -5.679584, 28.946095, 3.000000, -0.338108, 0.577055, 0.816690, -0.004975,
+1.002737, -5.675372, 25.532089, 3.000000, -0.152521, 0.572885, 0.819555, 0.011471,
+1.002737, -5.630855, 32.893612, 3.000000, -0.511082, 0.132943, 0.189166, -0.972904,
+1.002737, -5.679584, 28.946095, 3.000000, -0.338108, 0.577055, 0.816690, -0.004975,
+0.000000, -5.447061, 28.992958, 3.500000, -0.338108, 0.000000, 0.999979, -0.006525,
+0.000000, -5.447061, 28.992958, 3.500000, -0.338108, 0.000000, 0.999979, -0.006525,
+-1.002737, -5.679584, 28.946095, 4.000000, -0.344415, -0.577055, 0.816690, -0.004975,
+-1.002737, -5.630855, 32.893612, 4.000000, -0.511082, -0.132943, 0.189166, -0.972904,
+-1.002737, -5.630855, 32.893612, 4.000000, -0.511082, -0.132943, 0.189166, -0.972904,
+-4.193409, -2.445326, 32.893612, 4.000000, -0.594415, -0.686924, 0.716419, 0.121978,
+0.000000, -1.067776, 32.893612, 3.500000, -0.594415, -0.004492, 0.998437, 0.055707,
+0.000000, -1.067776, 32.893612, 3.500000, -0.594415, -0.004492, 0.998437, 0.055707,
+4.193409, -2.445326, 32.893612, 3.000000, -0.594415, 0.682263, 0.725032, 0.094055,
+1.002737, -5.630855, 32.893612, 3.000000, -0.511082, 0.132943, 0.189166, -0.972904,
+-1.002737, -2.684134, 2.725971, 3.500000, -1.666667, -0.555812, -0.771611, -0.309336,
+-1.002737, -3.239137, 4.110385, 4.000000, -1.666667, -0.573276, -0.760494, -0.304965,
+-1.336982, -2.618040, 4.463405, 4.000000, -1.833333, -0.999977, -0.006223, -0.002555,
+-1.336982, -2.618040, 4.463405, 4.000000, -1.833333, -0.999977, -0.006223, -0.002555,
+-1.002737, -1.996943, 4.816424, 4.000000, -2.000000, -0.580237, 0.756078, 0.302774,
+-1.002737, -1.445931, 3.440848, 3.500000, -2.000000, -0.596303, 0.745197, 0.298504,
+1.002737, -2.684134, 2.725971, 4.500000, -1.666667, 0.555812, -0.771611, -0.309336,
+1.002737, -3.239137, 4.110385, 5.000000, -1.666667, 0.573276, -0.760494, -0.304965,
+0.000000, -3.446170, 3.992712, 5.000000, -1.833333, 0.000000, -0.928140, -0.372231,
+0.000000, -3.446170, 3.992712, 5.000000, -1.833333, 0.000000, -0.928140, -0.372231,
+-1.002737, -3.239137, 4.110385, 5.000000, -2.000000, -0.573276, -0.760494, -0.304965,
+-1.002737, -2.684134, 2.725971, 4.500000, -2.000000, -0.555812, -0.771611, -0.309336,
+-1.336982, -22.914524, -4.929887, 7.000000, -1.833333, -0.999805, -0.016666, 0.010584,
+-1.002737, -22.289114, -5.237599, 7.000000, -1.666667, -0.580101, 0.726129, -0.369081,
+-1.002737, -22.791559, -6.324653, 6.500000, -1.666667, -0.585182, 0.679392, -0.442706,
+-1.002737, -22.791559, -6.324653, 6.500000, -1.666667, -0.585182, 0.679392, -0.442706,
+-0.742768, -23.169422, -6.772669, 6.000000, -1.666667, -0.444774, 0.383424, -0.809421,
+-1.002737, -23.736286, -6.771559, 6.000000, -1.833333, -0.633041, -0.276747, -0.722959,
+-1.002737, -23.736286, -6.771559, 6.000000, -1.833333, -0.633041, -0.276747, -0.722959,
+-0.742768, -24.152987, -6.401496, 6.000000, -2.000000, -0.455754, -0.834431, -0.309862,
+-1.002737, -24.101816, -5.795360, 6.500000, -2.000000, -0.571338, -0.788867, 0.226409,
+-1.002737, -24.101816, -5.795360, 6.500000, -2.000000, -0.571338, -0.788867, 0.226409,
+-1.002737, -23.539934, -4.622173, 7.000000, -2.000000, -0.559738, -0.733607, 0.385376,
+-1.336982, -22.914524, -4.929887, 7.000000, -1.833333, -0.999805, -0.016666, 0.010584,
+-1.336982, -20.877926, -1.798224, 0.500000, 4.901888, -0.999242, -0.027513, 0.027552,
+-1.002737, -20.362839, -2.232996, 1.000000, 4.901887, -0.577401, 0.607255, -0.545756,
+-1.002737, -21.510138, -3.803390, 1.000000, 4.957545, -0.579339, 0.686160, -0.439944,
+-1.002737, -21.510138, -3.803390, 1.000000, 4.957545, -0.579339, 0.686160, -0.439944,
+-1.002737, -22.289114, -5.237599, 1.000000, 5.000000, -0.580101, 0.726129, -0.369081,
+-1.336982, -22.914524, -4.929887, 0.500000, 5.000000, -0.999805, -0.016666, 0.010584,
+-1.336982, -22.914524, -4.929887, 0.500000, 5.000000, -0.999805, -0.016666, 0.010584,
+-1.002737, -23.539934, -4.622173, 0.000000, 5.000000, -0.559738, -0.733607, 0.385376,
+-1.002737, -22.670450, -3.070609, 0.000000, 4.957545, -0.549531, -0.697669, 0.459646,
+-1.002737, -22.670450, -3.070609, 0.000000, 4.957545, -0.549531, -0.697669, 0.459646,
+-1.002737, -21.393009, -1.363454, 0.000000, 4.915090, -0.538985, -0.621423, 0.568620,
+-1.336982, -20.877926, -1.798224, 0.500000, 4.901888, -0.999242, -0.027513, 0.027552,
+-1.336982, -17.125900, 1.021948, 0.500000, 4.706708, -0.998755, -0.017888, 0.046575,
+-1.002737, -16.806824, 0.450041, 1.000000, 4.706708, -0.570721, 0.333495, -0.750372,
+-1.002737, -18.755436, -0.737389, 1.000000, 4.819824, -0.571841, 0.493951, -0.654989,
+-1.002737, -18.755436, -0.737389, 1.000000, 4.819824, -0.571841, 0.493951, -0.654989,
+-1.002737, -20.362839, -2.232996, 1.000000, 4.901887, -0.577401, 0.607255, -0.545756,
+-1.336982, -20.877926, -1.798224, 0.500000, 4.901888, -0.999242, -0.027513, 0.027552,
+-1.336982, -20.877926, -1.798224, 0.500000, 4.901888, -0.999242, -0.027513, 0.027552,
+-1.002737, -21.393009, -1.363454, 0.000000, 4.915090, -0.538985, -0.621423, 0.568620,
+-1.002737, -19.607264, 0.276508, 0.000000, 4.819824, -0.531663, -0.507888, 0.677779,
+-1.002737, -19.607264, 0.276508, 0.000000, 4.819824, -0.531663, -0.507888, 0.677779,
+-1.002737, -17.444981, 1.593854, 0.000000, 4.724558, -0.523473, -0.350048, 0.776815,
+-1.336982, -17.125900, 1.021948, 0.500000, 4.706708, -0.998755, -0.017888, 0.046575,
+-1.336982, -12.461710, 1.998980, 0.500000, 4.382352, -0.999581, -0.002143, 0.028884,
+-1.002737, -12.384212, 1.352605, 1.000000, 4.382352, -0.556840, 0.051516, -0.829021,
+-1.002737, -14.635897, 1.095908, 1.000000, 4.557891, -0.560822, 0.165222, -0.811283,
+-1.002737, -14.635897, 1.095908, 1.000000, 4.557891, -0.560822, 0.165222, -0.811283,
+-1.002737, -16.806824, 0.450041, 1.000000, 4.706708, -0.570721, 0.333495, -0.750372,
+-1.336982, -17.125900, 1.021948, 0.500000, 4.706708, -0.998755, -0.017888, 0.046575,
+-1.336982, -17.125900, 1.021948, 0.500000, 4.706708, -0.998755, -0.017888, 0.046575,
+-1.002737, -17.444981, 1.593854, 0.000000, 4.724558, -0.523473, -0.350048, 0.776815,
+-1.002737, -15.037928, 2.333167, 0.000000, 4.557892, -0.524224, -0.178780, 0.832603,
+-1.002737, -15.037928, 2.333167, 0.000000, 4.557892, -0.524224, -0.178780, 0.832603,
+-1.002737, -12.539209, 2.645355, 0.000000, 4.391225, -0.529316, -0.059790, 0.846315,
+-1.336982, -12.461710, 1.998980, 0.500000, 4.382352, -0.999581, -0.002143, 0.028884,
+-1.336982, -8.028582, 1.726443, 0.500000, 3.977933, -0.998903, 0.011916, 0.045285,
+-1.002737, -8.188779, 1.086162, 1.000000, 3.977933, -0.571796, -0.203921, -0.794648,
+-1.002737, -10.193326, 1.372527, 1.000000, 4.189068, -0.563923, -0.052320, -0.824168,
+-1.002737, -10.193326, 1.372527, 1.000000, 4.189068, -0.563923, -0.052320, -0.824168,
+-1.002737, -12.384212, 1.352605, 1.000000, 4.382352, -0.556840, 0.051516, -0.829021,
+-1.336982, -12.461710, 1.998980, 0.500000, 4.382352, -0.999581, -0.002143, 0.028884,
+-1.336982, -12.461710, 1.998980, 0.500000, 4.382352, -0.999581, -0.002143, 0.028884,
+-1.002737, -12.539209, 2.645355, 0.000000, 4.391225, -0.529316, -0.059790, 0.846315,
+-1.002737, -10.101929, 2.681329, 0.000000, 4.189068, -0.529646, 0.050516, 0.846713,
+-1.002737, -10.101929, 2.681329, 0.000000, 4.189068, -0.529646, 0.050516, 0.846713,
+-1.002737, -7.868385, 2.366725, 0.000000, 3.986911, -0.526810, 0.210598, 0.823480,
+-1.336982, -8.028582, 1.726443, 0.500000, 3.977933, -0.998903, 0.011916, 0.045285,
+-1.336982, -4.681401, -0.053863, 0.500000, 3.518014, -0.999076, 0.030579, 0.030219,
+-1.002737, -5.023273, -0.595701, 1.000000, 3.518014, -0.554291, -0.537252, -0.635706,
+-1.002737, -6.496116, 0.423996, 1.000000, 3.748844, -0.567467, -0.386666, -0.726960,
+-1.002737, -6.496116, 0.423996, 1.000000, 3.748844, -0.567467, -0.386666, -0.726960,
+-1.002737, -8.188779, 1.086162, 1.000000, 3.977933, -0.571796, -0.203921, -0.794648,
+-1.336982, -8.028582, 1.726443, 0.500000, 3.977933, -0.998903, 0.011916, 0.045285,
+-1.336982, -8.028582, 1.726443, 0.500000, 3.977933, -0.998903, 0.011916, 0.045285,
+-1.002737, -7.868385, 2.366725, 0.000000, 3.986911, -0.526810, 0.210598, 0.823480,
+-1.002737, -5.980879, 1.627182, 0.000000, 3.748844, -0.522694, 0.400366, 0.752661,
+-1.002737, -5.980879, 1.627182, 0.000000, 3.748844, -0.522694, 0.400366, 0.752661,
+-1.002737, -4.339529, 0.487975, 0.000000, 3.510776, -0.515414, 0.553092, 0.654552,
+-1.336982, -4.681401, -0.053863, 0.500000, 3.518014, -0.999076, 0.030579, 0.030219,
+-1.336982, -2.032626, -3.152671, 0.500000, 3.096704, -0.999446, 0.028671, 0.016899,
+-1.002737, -2.514818, -3.530164, 1.000000, 3.096704, -0.535283, -0.710141, -0.457353,
+-1.002737, -3.678185, -1.954659, 1.000000, 3.301661, -0.541786, -0.639146, -0.545858,
+-1.002737, -3.678185, -1.954659, 1.000000, 3.301661, -0.541786, -0.639146, -0.545858,
+-1.002737, -5.023273, -0.595701, 1.000000, 3.518014, -0.554291, -0.537252, -0.635706,
+-1.336982, -4.681401, -0.053863, 0.500000, 3.518014, -0.999076, 0.030579, 0.030219,
+-1.336982, -4.681401, -0.053863, 0.500000, 3.518014, -0.999076, 0.030579, 0.030219,
+-1.002737, -4.339529, 0.487975, 0.000000, 3.510776, -0.515414, 0.553092, 0.654552,
+-1.002737, -2.844458, -1.025621, 0.000000, 3.301661, -0.509526, 0.653879, 0.559309,
+-1.002737, -2.844458, -1.025621, 0.000000, 3.301661, -0.509526, 0.653879, 0.559309,
+-1.002737, -1.550434, -2.775177, 0.000000, 3.092546, -0.505987, 0.723592, 0.469458,
+-1.336982, -2.032626, -3.152671, 0.500000, 3.096704, -0.999446, 0.028671, 0.016899,
+-1.336982, -0.371475, -6.820555, 0.500000, 2.714038, -0.999078, 0.041649, 0.010372,
+-1.002737, -0.955311, -7.018215, 1.000000, 2.714038, -0.543592, -0.816934, -0.192683,
+-1.002737, -1.587135, -5.199499, 1.000000, 2.900065, -0.538039, -0.769598, -0.343850,
+-1.002737, -1.587135, -5.199499, 1.000000, 2.900065, -0.538039, -0.769598, -0.343850,
+-1.002737, -2.514818, -3.530164, 1.000000, 3.096704, -0.535283, -0.710141, -0.457353,
+-1.336982, -2.032626, -3.152671, 0.500000, 3.096704, -0.999446, 0.028671, 0.016899,
+-1.336982, -2.032626, -3.152671, 0.500000, 3.096704, -0.999446, 0.028671, 0.016899,
+-1.002737, -1.550434, -2.775177, 0.000000, 3.092546, -0.505987, 0.723592, 0.469458,
+-1.002737, -0.512230, -4.622262, 0.000000, 2.900065, -0.503207, 0.785550, 0.360132,
+-1.002737, -0.512230, -4.622262, 0.000000, 2.900065, -0.503207, 0.785550, 0.360132,
+-1.002737, 0.212360, -6.622896, 0.000000, 2.707584, -0.505652, 0.835716, 0.214230,
+-1.336982, -0.371475, -6.820555, 0.500000, 2.714038, -0.999078, 0.041649, 0.010372,
+-1.336982, -0.183937, -11.115767, 0.500000, 2.371212, -0.999002, 0.043336, -0.010816,
+-1.002737, -0.835270, -11.133001, 1.000000, 2.371212, -0.556778, -0.814518, 0.162970,
+-1.002737, -0.679522, -9.041862, 1.000000, 2.540917, -0.550509, -0.834486, -0.023924,
+-1.002737, -0.679522, -9.041862, 1.000000, 2.540917, -0.550509, -0.834486, -0.023924,
+-1.002737, -0.955311, -7.018215, 1.000000, 2.714038, -0.543592, -0.816934, -0.192683,
+-1.336982, -0.371475, -6.820555, 0.500000, 2.714038, -0.999078, 0.041649, 0.010372,
+-1.336982, -0.371475, -6.820555, 0.500000, 2.714038, -0.999078, 0.041649, 0.010372,
+-1.002737, 0.212360, -6.622896, 0.000000, 2.707584, -0.505652, 0.835716, 0.214230,
+-1.002737, 0.565540, -8.833092, 0.000000, 2.540917, -0.512670, 0.857167, 0.049331,
+-1.002737, 0.565540, -8.833092, 0.000000, 2.540917, -0.512670, 0.857167, 0.049331,
+-1.002737, 0.467394, -11.098533, 0.000000, 2.374251, -0.517497, 0.844529, -0.137721,
+-1.336982, -0.183937, -11.115767, 0.500000, 2.371212, -0.999002, 0.043336, -0.010816,
+-1.336982, -1.762512, -15.300098, 0.500000, 2.020624, -0.999977, 0.006790, -0.000522,
+-1.002737, -2.439466, -15.191065, 1.000000, 2.020624, -0.552162, -0.756555, 0.350343,
+-1.002737, -1.498060, -13.154191, 1.000000, 2.195430, -0.550846, -0.775955, 0.307348,
+-1.002737, -1.498060, -13.154191, 1.000000, 2.195430, -0.550846, -0.775955, 0.307348,
+-1.002737, -0.835270, -11.133001, 1.000000, 2.371212, -0.556778, -0.814518, 0.162970,
+-1.336982, -0.183937, -11.115767, 0.500000, 2.371212, -0.999002, 0.043336, -0.010816,
+-1.336982, -0.183937, -11.115767, 0.500000, 2.371212, -0.999002, 0.043336, -0.010816,
+-1.002737, 0.467394, -11.098533, 0.000000, 2.374251, -0.517497, 0.844529, -0.137721,
+-1.002737, -0.161999, -13.264900, 0.000000, 2.195430, -0.528455, 0.798898, -0.287224,
+-1.002737, -0.161999, -13.264900, 0.000000, 2.195430, -0.528455, 0.798898, -0.287224,
+-1.002737, -1.085560, -15.409132, 0.000000, 2.016609, -0.545979, 0.767296, -0.336399,
+-1.336982, -1.762512, -15.300098, 0.500000, 2.020624, -0.999977, 0.006790, -0.000522,
+-1.336982, -3.677238, -19.700720, 0.500000, 1.696742, -0.999943, -0.009227, 0.005371,
+-1.002737, -4.363696, -19.552979, 1.000000, 1.696742, -0.563275, -0.773529, 0.290474,
+-1.002737, -3.431055, -17.329250, 1.000000, 1.853850, -0.559291, -0.758482, 0.334513,
+-1.002737, -3.431055, -17.329250, 1.000000, 1.853850, -0.559291, -0.758482, 0.334513,
+-1.002737, -2.439466, -15.191065, 1.000000, 2.020624, -0.552162, -0.756555, 0.350343,
+-1.336982, -1.762512, -15.300098, 0.500000, 2.020624, -0.999977, 0.006790, -0.000522,
+-1.336982, -1.762512, -15.300098, 0.500000, 2.020624, -0.999977, 0.006790, -0.000522,
+-1.002737, -1.085560, -15.409132, 0.000000, 2.016609, -0.545979, 0.767296, -0.336399,
+-1.002737, -2.066217, -17.608171, 0.000000, 1.853850, -0.561407, 0.760416, -0.326481,
+-1.002737, -2.066217, -17.608171, 0.000000, 1.853850, -0.561407, 0.760416, -0.326481,
+-1.002737, -2.990782, -19.848455, 0.000000, 1.691091, -0.573541, 0.767562, -0.286181,
+-1.336982, -3.677238, -19.700720, 0.500000, 1.696742, -0.999943, -0.009227, 0.005371,
+-1.336982, -4.998410, -24.141369, 0.500000, 1.417808, -0.999879, -0.015054, 0.003873,
+-1.002737, -5.694758, -24.033106, 1.000000, 1.417808, -0.566494, -0.804616, 0.177981,
+-1.002737, -5.128252, -21.846479, 1.000000, 1.550938, -0.566340, -0.790066, 0.234638,
+-1.002737, -5.128252, -21.846479, 1.000000, 1.550938, -0.566340, -0.790066, 0.234638,
+-1.002737, -4.363696, -19.552979, 1.000000, 1.696742, -0.563275, -0.773529, 0.290474,
+-1.336982, -3.677238, -19.700720, 0.500000, 1.696742, -0.999943, -0.009227, 0.005371,
+-1.336982, -3.677238, -19.700720, 0.500000, 1.696742, -0.999943, -0.009227, 0.005371,
+-1.002737, -2.990782, -19.848455, 0.000000, 1.691091, -0.573541, 0.767562, -0.286181,
+-1.002737, -3.746061, -22.116426, 0.000000, 1.550938, -0.578794, 0.781497, -0.232937,
+-1.002737, -3.746061, -22.116426, 0.000000, 1.550938, -0.578794, 0.781497, -0.232937,
+-1.002737, -4.302059, -24.249632, 0.000000, 1.410785, -0.582444, 0.793471, -0.176531,
+-1.336982, -4.998410, -24.141369, 0.500000, 1.417808, -0.999879, -0.015054, 0.003873,
+-1.336982, -5.505962, -27.491592, 0.500000, 1.186658, -0.999932, -0.011525, 0.001722,
+-1.002737, -6.213656, -27.449341, 1.000000, 1.186658, -0.570758, -0.816393, 0.087968,
+-1.002737, -6.033253, -25.936214, 1.000000, 1.298722, -0.568446, -0.813396, 0.123515,
+-1.002737, -6.033253, -25.936214, 1.000000, 1.298722, -0.568446, -0.813396, 0.123515,
+-1.002737, -5.694758, -24.033106, 1.000000, 1.417808, -0.566494, -0.804616, 0.177981,
+-1.336982, -4.998410, -24.141369, 0.500000, 1.417808, -0.999879, -0.015054, 0.003873,
+-1.336982, -4.998410, -24.141369, 0.500000, 1.417808, -0.999879, -0.015054, 0.003873,
+-1.002737, -4.302059, -24.249632, 0.000000, 1.410785, -0.582444, 0.793471, -0.176531,
+-1.002737, -4.628780, -26.085621, 0.000000, 1.298722, -0.582983, 0.803361, -0.121414,
+-1.002737, -4.628780, -26.085621, 0.000000, 1.298722, -0.582983, 0.803361, -0.121414,
+-1.002737, -4.798269, -27.533844, 0.000000, 1.186658, -0.583018, 0.808019, -0.084825,
+-1.336982, -5.505962, -27.491592, 0.500000, 1.186658, -0.999932, -0.011525, 0.001722,
+-1.002737, -6.305892, -28.466030, 0.500000, 1.053028, -0.565626, -0.821288, 0.074517,
+-1.002737, -6.213656, -27.449341, 1.000000, 1.053028, -0.570758, -0.816393, 0.087968,
+-1.336982, -5.505962, -27.491592, 1.000000, 1.119843, -0.999932, -0.011525, 0.001722,
+-1.336982, -5.505962, -27.491592, 1.000000, 1.119843, -0.999932, -0.011525, 0.001722,
+-1.002737, -4.798269, -27.533844, 1.000000, 1.186658, -0.583018, 0.808019, -0.084825,
+-1.002737, -4.882575, -28.503754, 0.500000, 1.186658, -0.589040, 0.805068, -0.069986,
+0.000000, -22.080643, -5.340171, 1.000000, 1.026514, 0.000000, 0.892013, -0.452009,
+1.002737, -22.289114, -5.237599, 1.000000, 1.053028, 0.580101, 0.726128, -0.369081,
+1.002737, -22.791559, -6.324653, 0.500000, 1.053028, 0.585182, 0.679392, -0.442706,
+1.002737, -22.791559, -6.324653, 0.500000, 1.053028, 0.585182, 0.679392, -0.442706,
+0.742768, -23.169422, -6.772669, 0.000000, 1.053028, 0.444774, 0.383425, -0.809421,
+0.000000, -23.066525, -7.012697, 0.000000, 1.026514, -0.000000, 0.424976, -0.905205,
+0.000000, -23.066525, -7.012697, 0.000000, 1.026514, -0.000000, 0.424976, -0.905205,
+-0.742768, -23.169422, -6.772669, 0.000000, 1.000000, -0.444774, 0.383424, -0.809421,
+-1.002737, -22.791559, -6.324653, 0.500000, 1.000000, -0.585182, 0.679392, -0.442706,
+-1.002737, -22.791559, -6.324653, 0.500000, 1.000000, -0.585182, 0.679392, -0.442706,
+-1.002737, -22.289114, -5.237599, 1.000000, 1.000000, -0.580101, 0.726129, -0.369081,
+0.000000, -22.080643, -5.340171, 1.000000, 1.026514, 0.000000, 0.892013, -0.452009,
+0.000000, -20.191145, -2.377919, 1.500000, 4.901888, 0.000000, 0.744223, -0.667931,
+1.002737, -20.362839, -2.232996, 2.000000, 4.901887, 0.577401, 0.607255, -0.545756,
+1.002737, -21.510138, -3.803390, 2.000000, 4.957545, 0.579339, 0.686160, -0.439944,
+1.002737, -21.510138, -3.803390, 2.000000, 4.957545, 0.579339, 0.686160, -0.439944,
+1.002737, -22.289114, -5.237599, 2.000000, 5.000000, 0.580101, 0.726128, -0.369081,
+0.000000, -22.080643, -5.340171, 1.500000, 5.000000, 0.000000, 0.892013, -0.452009,
+0.000000, -22.080643, -5.340171, 1.500000, 5.000000, 0.000000, 0.892013, -0.452009,
+-1.002737, -22.289114, -5.237599, 1.000000, 5.000000, -0.580101, 0.726129, -0.369081,
+-1.002737, -21.510138, -3.803390, 1.000000, 4.957545, -0.579339, 0.686160, -0.439944,
+-1.002737, -21.510138, -3.803390, 1.000000, 4.957545, -0.579339, 0.686160, -0.439944,
+-1.002737, -20.362839, -2.232996, 1.000000, 4.901887, -0.577401, 0.607255, -0.545756,
+0.000000, -20.191145, -2.377919, 1.500000, 4.901888, 0.000000, 0.744223, -0.667931,
+0.000000, -16.700464, 0.259406, 1.500000, 4.706708, -0.000000, 0.404784, -0.914412,
+1.002737, -16.806824, 0.450041, 2.000000, 4.706708, 0.570721, 0.333495, -0.750372,
+1.002737, -18.755436, -0.737389, 2.000000, 4.819824, 0.571841, 0.493951, -0.654989,
+1.002737, -18.755436, -0.737389, 2.000000, 4.819824, 0.571841, 0.493951, -0.654989,
+1.002737, -20.362839, -2.232996, 2.000000, 4.901887, 0.577401, 0.607255, -0.545756,
+0.000000, -20.191145, -2.377919, 1.500000, 4.901888, 0.000000, 0.744223, -0.667931,
+0.000000, -20.191145, -2.377919, 1.500000, 4.901888, 0.000000, 0.744223, -0.667931,
+-1.002737, -20.362839, -2.232996, 1.000000, 4.901887, -0.577401, 0.607255, -0.545756,
+-1.002737, -18.755436, -0.737389, 1.000000, 4.819824, -0.571841, 0.493951, -0.654989,
+-1.002737, -18.755436, -0.737389, 1.000000, 4.819824, -0.571841, 0.493951, -0.654989,
+-1.002737, -16.806824, 0.450041, 1.000000, 4.706708, -0.570721, 0.333495, -0.750372,
+0.000000, -16.700464, 0.259406, 1.500000, 4.706708, -0.000000, 0.404784, -0.914412,
+0.000000, -12.358379, 1.137146, 1.500000, 4.382352, 0.000000, 0.060964, -0.998140,
+1.002737, -12.384212, 1.352605, 2.000000, 4.382352, 0.556840, 0.051516, -0.829021,
+1.002737, -14.635897, 1.095908, 2.000000, 4.557891, 0.560822, 0.165222, -0.811283,
+1.002737, -14.635897, 1.095908, 2.000000, 4.557891, 0.560822, 0.165222, -0.811283,
+1.002737, -16.806824, 0.450041, 2.000000, 4.706708, 0.570721, 0.333495, -0.750372,
+0.000000, -16.700464, 0.259406, 1.500000, 4.706708, -0.000000, 0.404784, -0.914412,
+0.000000, -16.700464, 0.259406, 1.500000, 4.706708, -0.000000, 0.404784, -0.914412,
+-1.002737, -16.806824, 0.450041, 1.000000, 4.706708, -0.570721, 0.333495, -0.750372,
+-1.002737, -14.635897, 1.095908, 1.000000, 4.557891, -0.560822, 0.165222, -0.811283,
+-1.002737, -14.635897, 1.095908, 1.000000, 4.557891, -0.560822, 0.165222, -0.811283,
+-1.002737, -12.384212, 1.352605, 1.000000, 4.382352, -0.556840, 0.051516, -0.829021,
+0.000000, -12.358379, 1.137146, 1.500000, 4.382352, 0.000000, 0.060964, -0.998140,
+0.000000, -8.242178, 0.872734, 1.500000, 3.977933, 0.000000, -0.248755, -0.968567,
+1.002737, -8.188779, 1.086162, 2.000000, 3.977933, 0.571796, -0.203921, -0.794648,
+1.002737, -10.193325, 1.372527, 2.000000, 4.189068, 0.563923, -0.052320, -0.824168,
+1.002737, -10.193325, 1.372527, 2.000000, 4.189068, 0.563923, -0.052320, -0.824168,
+1.002737, -12.384212, 1.352605, 2.000000, 4.382352, 0.556840, 0.051516, -0.829021,
+0.000000, -12.358379, 1.137146, 1.500000, 4.382352, 0.000000, 0.060964, -0.998140,
+0.000000, -12.358379, 1.137146, 1.500000, 4.382352, 0.000000, 0.060964, -0.998140,
+-1.002737, -12.384212, 1.352605, 1.000000, 4.382352, -0.556840, 0.051516, -0.829021,
+-1.002737, -10.193326, 1.372527, 1.000000, 4.189068, -0.563923, -0.052320, -0.824168,
+-1.002737, -10.193326, 1.372527, 1.000000, 4.189068, -0.563923, -0.052320, -0.824168,
+-1.002737, -8.188779, 1.086162, 1.000000, 3.977933, -0.571796, -0.203921, -0.794648,
+0.000000, -8.242178, 0.872734, 1.500000, 3.977933, 0.000000, -0.248755, -0.968567,
+0.000000, -5.137229, -0.776313, 1.500000, 3.518014, -0.000000, -0.646205, -0.763164,
+1.002737, -5.023273, -0.595701, 2.000000, 3.518014, 0.554291, -0.537252, -0.635706,
+1.002737, -6.496116, 0.423996, 2.000000, 3.748844, 0.567467, -0.386666, -0.726960,
+1.002737, -6.496116, 0.423996, 2.000000, 3.748844, 0.567467, -0.386666, -0.726960,
+1.002737, -8.188779, 1.086162, 2.000000, 3.977933, 0.571796, -0.203921, -0.794648,
+0.000000, -8.242178, 0.872734, 1.500000, 3.977933, 0.000000, -0.248755, -0.968567,
+0.000000, -8.242178, 0.872734, 1.500000, 3.977933, 0.000000, -0.248755, -0.968567,
+-1.002737, -8.188779, 1.086162, 1.000000, 3.977933, -0.571796, -0.203921, -0.794648,
+-1.002737, -6.496116, 0.423996, 1.000000, 3.748844, -0.567467, -0.386666, -0.726960,
+-1.002737, -6.496116, 0.423996, 1.000000, 3.748844, -0.567467, -0.386666, -0.726960,
+-1.002737, -5.023273, -0.595701, 1.000000, 3.518014, -0.554291, -0.537252, -0.635706,
+0.000000, -5.137229, -0.776313, 1.500000, 3.518014, -0.000000, -0.646205, -0.763164,
+0.000000, -2.675549, -3.655995, 1.500000, 3.096704, -0.000000, -0.841132, -0.540830,
+1.002737, -2.514818, -3.530164, 2.000000, 3.096704, 0.535283, -0.710141, -0.457354,
+1.002737, -3.678185, -1.954659, 2.000000, 3.301661, 0.541785, -0.639146, -0.545858,
+1.002737, -3.678185, -1.954659, 2.000000, 3.301661, 0.541785, -0.639146, -0.545858,
+1.002737, -5.023273, -0.595701, 2.000000, 3.518014, 0.554291, -0.537252, -0.635706,
+0.000000, -5.137229, -0.776313, 1.500000, 3.518014, -0.000000, -0.646205, -0.763164,
+0.000000, -5.137229, -0.776313, 1.500000, 3.518014, -0.000000, -0.646205, -0.763164,
+-1.002737, -5.023273, -0.595701, 1.000000, 3.518014, -0.554291, -0.537252, -0.635706,
+-1.002737, -3.678185, -1.954659, 1.000000, 3.301661, -0.541786, -0.639146, -0.545858,
+-1.002737, -3.678185, -1.954659, 1.000000, 3.301661, -0.541786, -0.639146, -0.545858,
+-1.002737, -2.514818, -3.530164, 1.000000, 3.096704, -0.535283, -0.710141, -0.457353,
+0.000000, -2.675549, -3.655995, 1.500000, 3.096704, -0.000000, -0.841132, -0.540830,
+0.000000, -1.149923, -7.084101, 1.500000, 2.714038, 0.000000, -0.973883, -0.227050,
+1.002737, -0.955311, -7.018215, 2.000000, 2.714038, 0.543591, -0.816934, -0.192683,
+1.002737, -1.587135, -5.199499, 2.000000, 2.900065, 0.538039, -0.769598, -0.343850,
+1.002737, -1.587135, -5.199499, 2.000000, 2.900065, 0.538039, -0.769598, -0.343850,
+1.002737, -2.514818, -3.530164, 2.000000, 3.096704, 0.535283, -0.710141, -0.457354,
+0.000000, -2.675549, -3.655995, 1.500000, 3.096704, -0.000000, -0.841132, -0.540830,
+0.000000, -2.675549, -3.655995, 1.500000, 3.096704, -0.000000, -0.841132, -0.540830,
+-1.002737, -2.514818, -3.530164, 1.000000, 3.096704, -0.535283, -0.710141, -0.457353,
+-1.002737, -1.587135, -5.199499, 1.000000, 2.900065, -0.538039, -0.769598, -0.343850,
+-1.002737, -1.587135, -5.199499, 1.000000, 2.900065, -0.538039, -0.769598, -0.343850,
+-1.002737, -0.955311, -7.018215, 1.000000, 2.714038, -0.543592, -0.816934, -0.192683,
+0.000000, -1.149923, -7.084101, 1.500000, 2.714038, 0.000000, -0.973883, -0.227050,
+0.000000, -1.052381, -11.138744, 1.500000, 2.371212, 0.000000, -0.979438, 0.201745,
+1.002737, -0.835270, -11.133000, 2.000000, 2.371212, 0.556778, -0.814518, 0.162970,
+1.002737, -0.679521, -9.041862, 2.000000, 2.540917, 0.550509, -0.834486, -0.023924,
+1.002737, -0.679521, -9.041862, 2.000000, 2.540917, 0.550509, -0.834486, -0.023924,
+1.002737, -0.955311, -7.018215, 2.000000, 2.714038, 0.543591, -0.816934, -0.192683,
+0.000000, -1.149923, -7.084101, 1.500000, 2.714038, 0.000000, -0.973883, -0.227050,
+0.000000, -1.149923, -7.084101, 1.500000, 2.714038, 0.000000, -0.973883, -0.227050,
+-1.002737, -0.955311, -7.018215, 1.000000, 2.714038, -0.543592, -0.816934, -0.192683,
+-1.002737, -0.679522, -9.041862, 1.000000, 2.540917, -0.550509, -0.834486, -0.023924,
+-1.002737, -0.679522, -9.041862, 1.000000, 2.540917, -0.550509, -0.834486, -0.023924,
+-1.002737, -0.835270, -11.133001, 1.000000, 2.371212, -0.556778, -0.814518, 0.162970,
+0.000000, -1.052381, -11.138744, 1.500000, 2.371212, 0.000000, -0.979438, 0.201745,
+0.000000, -2.665116, -15.154720, 1.500000, 2.020624, -0.000000, -0.906717, 0.421740,
+1.002737, -2.439466, -15.191065, 2.000000, 2.020624, 0.552162, -0.756556, 0.350343,
+1.002737, -1.498060, -13.154191, 2.000000, 2.195430, 0.550846, -0.775955, 0.307348,
+1.002737, -1.498060, -13.154191, 2.000000, 2.195430, 0.550846, -0.775955, 0.307348,
+1.002737, -0.835270, -11.133000, 2.000000, 2.371212, 0.556778, -0.814518, 0.162970,
+0.000000, -1.052381, -11.138744, 1.500000, 2.371212, 0.000000, -0.979438, 0.201745,
+0.000000, -1.052381, -11.138744, 1.500000, 2.371212, 0.000000, -0.979438, 0.201745,
+-1.002737, -0.835270, -11.133001, 1.000000, 2.371212, -0.556778, -0.814518, 0.162970,
+-1.002737, -1.498060, -13.154191, 1.000000, 2.195430, -0.550846, -0.775955, 0.307348,
+-1.002737, -1.498060, -13.154191, 1.000000, 2.195430, -0.550846, -0.775955, 0.307348,
+-1.002737, -2.439466, -15.191065, 1.000000, 2.020624, -0.552162, -0.756555, 0.350343,
+0.000000, -2.665116, -15.154720, 1.500000, 2.020624, -0.000000, -0.906717, 0.421740,
+0.000000, -4.592515, -19.503733, 1.500000, 1.696742, -0.000000, -0.936315, 0.351162,
+1.002737, -4.363696, -19.552979, 2.000000, 1.696742, 0.563275, -0.773529, 0.290474,
+1.002737, -3.431055, -17.329250, 2.000000, 1.853850, 0.559291, -0.758482, 0.334513,
+1.002737, -3.431055, -17.329250, 2.000000, 1.853850, 0.559291, -0.758482, 0.334513,
+1.002737, -2.439466, -15.191065, 2.000000, 2.020624, 0.552162, -0.756556, 0.350343,
+0.000000, -2.665116, -15.154720, 1.500000, 2.020624, -0.000000, -0.906717, 0.421740,
+0.000000, -2.665116, -15.154720, 1.500000, 2.020624, -0.000000, -0.906717, 0.421740,
+-1.002737, -2.439466, -15.191065, 1.000000, 2.020624, -0.552162, -0.756555, 0.350343,
+-1.002737, -3.431055, -17.329250, 1.000000, 1.853850, -0.559291, -0.758482, 0.334513,
+-1.002737, -3.431055, -17.329250, 1.000000, 1.853850, -0.559291, -0.758482, 0.334513,
+-1.002737, -4.363696, -19.552979, 1.000000, 1.696742, -0.563275, -0.773529, 0.290474,
+0.000000, -4.592515, -19.503733, 1.500000, 1.696742, -0.000000, -0.936315, 0.351162,
+0.000000, -5.926875, -23.997019, 1.500000, 1.417808, -0.000000, -0.976472, 0.215645,
+1.002737, -5.694758, -24.033106, 2.000000, 1.417808, 0.566494, -0.804616, 0.177981,
+1.002737, -5.128252, -21.846479, 2.000000, 1.550938, 0.566340, -0.790066, 0.234638,
+1.002737, -5.128252, -21.846479, 2.000000, 1.550938, 0.566340, -0.790066, 0.234638,
+1.002737, -4.363696, -19.552979, 2.000000, 1.696742, 0.563275, -0.773529, 0.290474,
+0.000000, -4.592515, -19.503733, 1.500000, 1.696742, -0.000000, -0.936315, 0.351162,
+0.000000, -4.592515, -19.503733, 1.500000, 1.696742, -0.000000, -0.936315, 0.351162,
+-1.002737, -4.363696, -19.552979, 1.000000, 1.696742, -0.563275, -0.773529, 0.290474,
+-1.002737, -5.128252, -21.846479, 1.000000, 1.550938, -0.566340, -0.790066, 0.234638,
+-1.002737, -5.128252, -21.846479, 1.000000, 1.550938, -0.566340, -0.790066, 0.234638,
+-1.002737, -5.694758, -24.033106, 1.000000, 1.417808, -0.566494, -0.804616, 0.177981,
+0.000000, -5.926875, -23.997019, 1.500000, 1.417808, -0.000000, -0.976472, 0.215645,
+0.000000, -6.449554, -27.435261, 1.500000, 1.186658, -0.000000, -0.994229, 0.107280,
+1.002737, -6.213656, -27.449341, 2.000000, 1.186658, 0.570758, -0.816393, 0.087968,
+1.002737, -6.033253, -25.936216, 2.000000, 1.298722, 0.568446, -0.813396, 0.123515,
+1.002737, -6.033253, -25.936216, 2.000000, 1.298722, 0.568446, -0.813396, 0.123515,
+1.002737, -5.694758, -24.033106, 2.000000, 1.417808, 0.566494, -0.804616, 0.177981,
+0.000000, -5.926875, -23.997019, 1.500000, 1.417808, -0.000000, -0.976472, 0.215645,
+0.000000, -5.926875, -23.997019, 1.500000, 1.417808, -0.000000, -0.976472, 0.215645,
+-1.002737, -5.694758, -24.033106, 1.000000, 1.417808, -0.566494, -0.804616, 0.177981,
+-1.002737, -6.033253, -25.936214, 1.000000, 1.298722, -0.568446, -0.813396, 0.123515,
+-1.002737, -6.033253, -25.936214, 1.000000, 1.298722, -0.568446, -0.813396, 0.123515,
+-1.002737, -6.213656, -27.449341, 1.000000, 1.186658, -0.570758, -0.816393, 0.087968,
+0.000000, -6.449554, -27.435261, 1.500000, 1.186658, -0.000000, -0.994229, 0.107280,
+1.002737, -6.305892, -28.466030, 1.500000, 1.053028, 0.565626, -0.821288, 0.074517,
+1.002737, -6.213656, -27.449341, 2.000000, 1.053028, 0.570758, -0.816393, 0.087968,
+0.000000, -6.449554, -27.435261, 2.000000, 1.119843, -0.000000, -0.994229, 0.107280,
+0.000000, -6.449554, -27.435261, 2.000000, 1.119843, -0.000000, -0.994229, 0.107280,
+-1.002737, -6.213656, -27.449341, 2.000000, 1.186658, -0.570758, -0.816393, 0.087968,
+-1.002737, -6.305892, -28.466030, 1.500000, 1.186658, -0.565626, -0.821288, 0.074517,
+1.336982, -22.914524, -4.929887, 2.000000, 1.026514, 0.999805, -0.016666, 0.010584,
+1.002737, -23.539934, -4.622173, 2.000000, 1.053028, 0.559738, -0.733607, 0.385376,
+1.002737, -24.101816, -5.795360, 1.500000, 1.053028, 0.571338, -0.788867, 0.226409,
+1.002737, -24.101816, -5.795360, 1.500000, 1.053028, 0.571338, -0.788867, 0.226409,
+0.742768, -24.152987, -6.401496, 1.000000, 1.053028, 0.455754, -0.834430, -0.309862,
+1.002737, -23.736286, -6.771559, 1.000000, 1.026514, 0.633041, -0.276748, -0.722959,
+1.002737, -23.736286, -6.771559, 1.000000, 1.026514, 0.633041, -0.276748, -0.722959,
+0.742768, -23.169422, -6.772669, 1.000000, 1.000000, 0.444774, 0.383425, -0.809421,
+1.002737, -22.791559, -6.324653, 1.500000, 1.000000, 0.585182, 0.679392, -0.442706,
+1.002737, -22.791559, -6.324653, 1.500000, 1.000000, 0.585182, 0.679392, -0.442706,
+1.002737, -22.289114, -5.237599, 2.000000, 1.000000, 0.580101, 0.726128, -0.369081,
+1.336982, -22.914524, -4.929887, 2.000000, 1.026514, 0.999805, -0.016666, 0.010584,
+1.336982, -20.877926, -1.798224, 2.500000, 4.901888, 0.999242, -0.027513, 0.027552,
+1.002737, -21.393009, -1.363454, 3.000000, 4.901887, 0.538985, -0.621423, 0.568620,
+1.002737, -22.670450, -3.070609, 3.000000, 4.957545, 0.549531, -0.697669, 0.459646,
+1.002737, -22.670450, -3.070609, 3.000000, 4.957545, 0.549531, -0.697669, 0.459646,
+1.002737, -23.539934, -4.622173, 3.000000, 5.000000, 0.559738, -0.733607, 0.385376,
+1.336982, -22.914524, -4.929887, 2.500000, 5.000000, 0.999805, -0.016666, 0.010584,
+1.336982, -22.914524, -4.929887, 2.500000, 5.000000, 0.999805, -0.016666, 0.010584,
+1.002737, -22.289114, -5.237599, 2.000000, 5.000000, 0.580101, 0.726128, -0.369081,
+1.002737, -21.510138, -3.803390, 2.000000, 4.957545, 0.579339, 0.686160, -0.439944,
+1.002737, -21.510138, -3.803390, 2.000000, 4.957545, 0.579339, 0.686160, -0.439944,
+1.002737, -20.362839, -2.232996, 2.000000, 4.901887, 0.577401, 0.607255, -0.545756,
+1.336982, -20.877926, -1.798224, 2.500000, 4.901888, 0.999242, -0.027513, 0.027552,
+1.336982, -17.125900, 1.021948, 2.500000, 4.706708, 0.998755, -0.017888, 0.046575,
+1.002737, -17.444981, 1.593854, 3.000000, 4.706708, 0.523473, -0.350048, 0.776815,
+1.002737, -19.607264, 0.276508, 3.000000, 4.819824, 0.531663, -0.507888, 0.677779,
+1.002737, -19.607264, 0.276508, 3.000000, 4.819824, 0.531663, -0.507888, 0.677779,
+1.002737, -21.393009, -1.363454, 3.000000, 4.901887, 0.538985, -0.621423, 0.568620,
+1.336982, -20.877926, -1.798224, 2.500000, 4.901888, 0.999242, -0.027513, 0.027552,
+1.336982, -20.877926, -1.798224, 2.500000, 4.901888, 0.999242, -0.027513, 0.027552,
+1.002737, -20.362839, -2.232996, 2.000000, 4.901887, 0.577401, 0.607255, -0.545756,
+1.002737, -18.755436, -0.737389, 2.000000, 4.819824, 0.571841, 0.493951, -0.654989,
+1.002737, -18.755436, -0.737389, 2.000000, 4.819824, 0.571841, 0.493951, -0.654989,
+1.002737, -16.806824, 0.450041, 2.000000, 4.706708, 0.570721, 0.333495, -0.750372,
+1.336982, -17.125900, 1.021948, 2.500000, 4.706708, 0.998755, -0.017888, 0.046575,
+1.336982, -12.461710, 1.998980, 2.500000, 4.382352, 0.999581, -0.002143, 0.028884,
+1.002737, -12.539209, 2.645355, 3.000000, 4.382352, 0.529316, -0.059790, 0.846315,
+1.002737, -15.037928, 2.333167, 3.000000, 4.557891, 0.524224, -0.178780, 0.832603,
+1.002737, -15.037928, 2.333167, 3.000000, 4.557891, 0.524224, -0.178780, 0.832603,
+1.002737, -17.444981, 1.593854, 3.000000, 4.706708, 0.523473, -0.350048, 0.776815,
+1.336982, -17.125900, 1.021948, 2.500000, 4.706708, 0.998755, -0.017888, 0.046575,
+1.336982, -17.125900, 1.021948, 2.500000, 4.706708, 0.998755, -0.017888, 0.046575,
+1.002737, -16.806824, 0.450041, 2.000000, 4.706708, 0.570721, 0.333495, -0.750372,
+1.002737, -14.635897, 1.095908, 2.000000, 4.557891, 0.560822, 0.165222, -0.811283,
+1.002737, -14.635897, 1.095908, 2.000000, 4.557891, 0.560822, 0.165222, -0.811283,
+1.002737, -12.384212, 1.352605, 2.000000, 4.382352, 0.556840, 0.051516, -0.829021,
+1.336982, -12.461710, 1.998980, 2.500000, 4.382352, 0.999581, -0.002143, 0.028884,
+1.336982, -8.028582, 1.726443, 2.500000, 3.977933, 0.998903, 0.011916, 0.045285,
+1.002737, -7.868385, 2.366725, 3.000000, 3.977933, 0.526810, 0.210598, 0.823480,
+1.002737, -10.101929, 2.681329, 3.000000, 4.189068, 0.529646, 0.050516, 0.846713,
+1.002737, -10.101929, 2.681329, 3.000000, 4.189068, 0.529646, 0.050516, 0.846713,
+1.002737, -12.539209, 2.645355, 3.000000, 4.382352, 0.529316, -0.059790, 0.846315,
+1.336982, -12.461710, 1.998980, 2.500000, 4.382352, 0.999581, -0.002143, 0.028884,
+1.336982, -12.461710, 1.998980, 2.500000, 4.382352, 0.999581, -0.002143, 0.028884,
+1.002737, -12.384212, 1.352605, 2.000000, 4.382352, 0.556840, 0.051516, -0.829021,
+1.002737, -10.193325, 1.372527, 2.000000, 4.189068, 0.563923, -0.052320, -0.824168,
+1.002737, -10.193325, 1.372527, 2.000000, 4.189068, 0.563923, -0.052320, -0.824168,
+1.002737, -8.188779, 1.086162, 2.000000, 3.977933, 0.571796, -0.203921, -0.794648,
+1.336982, -8.028582, 1.726443, 2.500000, 3.977933, 0.998903, 0.011916, 0.045285,
+1.336982, -4.681401, -0.053863, 2.500000, 3.518014, 0.999076, 0.030579, 0.030219,
+1.002737, -4.339529, 0.487975, 3.000000, 3.518014, 0.515414, 0.553092, 0.654552,
+1.002737, -5.980879, 1.627182, 3.000000, 3.748844, 0.522693, 0.400366, 0.752661,
+1.002737, -5.980879, 1.627182, 3.000000, 3.748844, 0.522693, 0.400366, 0.752661,
+1.002737, -7.868385, 2.366725, 3.000000, 3.977933, 0.526810, 0.210598, 0.823480,
+1.336982, -8.028582, 1.726443, 2.500000, 3.977933, 0.998903, 0.011916, 0.045285,
+1.336982, -8.028582, 1.726443, 2.500000, 3.977933, 0.998903, 0.011916, 0.045285,
+1.002737, -8.188779, 1.086162, 2.000000, 3.977933, 0.571796, -0.203921, -0.794648,
+1.002737, -6.496116, 0.423996, 2.000000, 3.748844, 0.567467, -0.386666, -0.726960,
+1.002737, -6.496116, 0.423996, 2.000000, 3.748844, 0.567467, -0.386666, -0.726960,
+1.002737, -5.023273, -0.595701, 2.000000, 3.518014, 0.554291, -0.537252, -0.635706,
+1.336982, -4.681401, -0.053863, 2.500000, 3.518014, 0.999076, 0.030579, 0.030219,
+1.336982, -2.032627, -3.152670, 2.500000, 3.096704, 0.999446, 0.028671, 0.016899,
+1.002737, -1.550435, -2.775177, 3.000000, 3.096704, 0.505988, 0.723592, 0.469458,
+1.002737, -2.844458, -1.025621, 3.000000, 3.301661, 0.509526, 0.653879, 0.559309,
+1.002737, -2.844458, -1.025621, 3.000000, 3.301661, 0.509526, 0.653879, 0.559309,
+1.002737, -4.339529, 0.487975, 3.000000, 3.518014, 0.515414, 0.553092, 0.654552,
+1.336982, -4.681401, -0.053863, 2.500000, 3.518014, 0.999076, 0.030579, 0.030219,
+1.336982, -4.681401, -0.053863, 2.500000, 3.518014, 0.999076, 0.030579, 0.030219,
+1.002737, -5.023273, -0.595701, 2.000000, 3.518014, 0.554291, -0.537252, -0.635706,
+1.002737, -3.678185, -1.954659, 2.000000, 3.301661, 0.541785, -0.639146, -0.545858,
+1.002737, -3.678185, -1.954659, 2.000000, 3.301661, 0.541785, -0.639146, -0.545858,
+1.002737, -2.514818, -3.530164, 2.000000, 3.096704, 0.535283, -0.710141, -0.457354,
+1.336982, -2.032627, -3.152670, 2.500000, 3.096704, 0.999446, 0.028671, 0.016899,
+1.336982, -0.371475, -6.820555, 2.500000, 2.714038, 0.999079, 0.041649, 0.010372,
+1.002737, 0.212362, -6.622896, 3.000000, 2.714038, 0.505651, 0.835716, 0.214230,
+1.002737, -0.512230, -4.622262, 3.000000, 2.900065, 0.503207, 0.785549, 0.360132,
+1.002737, -0.512230, -4.622262, 3.000000, 2.900065, 0.503207, 0.785549, 0.360132,
+1.002737, -1.550435, -2.775177, 3.000000, 3.096704, 0.505988, 0.723592, 0.469458,
+1.336982, -2.032627, -3.152670, 2.500000, 3.096704, 0.999446, 0.028671, 0.016899,
+1.336982, -2.032627, -3.152670, 2.500000, 3.096704, 0.999446, 0.028671, 0.016899,
+1.002737, -2.514818, -3.530164, 2.000000, 3.096704, 0.535283, -0.710141, -0.457354,
+1.002737, -1.587135, -5.199499, 2.000000, 2.900065, 0.538039, -0.769598, -0.343850,
+1.002737, -1.587135, -5.199499, 2.000000, 2.900065, 0.538039, -0.769598, -0.343850,
+1.002737, -0.955311, -7.018215, 2.000000, 2.714038, 0.543591, -0.816934, -0.192683,
+1.336982, -0.371475, -6.820555, 2.500000, 2.714038, 0.999079, 0.041649, 0.010372,
+1.336982, -0.183937, -11.115767, 2.500000, 2.371212, 0.999002, 0.043336, -0.010816,
+1.002737, 0.467394, -11.098533, 3.000000, 2.371212, 0.517497, 0.844529, -0.137721,
+1.002737, 0.565540, -8.833092, 3.000000, 2.540917, 0.512670, 0.857168, 0.049331,
+1.002737, 0.565540, -8.833092, 3.000000, 2.540917, 0.512670, 0.857168, 0.049331,
+1.002737, 0.212362, -6.622896, 3.000000, 2.714038, 0.505651, 0.835716, 0.214230,
+1.336982, -0.371475, -6.820555, 2.500000, 2.714038, 0.999079, 0.041649, 0.010372,
+1.336982, -0.371475, -6.820555, 2.500000, 2.714038, 0.999079, 0.041649, 0.010372,
+1.002737, -0.955311, -7.018215, 2.000000, 2.714038, 0.543591, -0.816934, -0.192683,
+1.002737, -0.679521, -9.041862, 2.000000, 2.540917, 0.550509, -0.834486, -0.023924,
+1.002737, -0.679521, -9.041862, 2.000000, 2.540917, 0.550509, -0.834486, -0.023924,
+1.002737, -0.835270, -11.133000, 2.000000, 2.371212, 0.556778, -0.814518, 0.162970,
+1.336982, -0.183937, -11.115767, 2.500000, 2.371212, 0.999002, 0.043336, -0.010816,
+1.336982, -1.762512, -15.300098, 2.500000, 2.020624, 0.999977, 0.006790, -0.000522,
+1.002737, -1.085560, -15.409132, 3.000000, 2.020624, 0.545979, 0.767296, -0.336399,
+1.002737, -0.161999, -13.264900, 3.000000, 2.195430, 0.528455, 0.798898, -0.287224,
+1.002737, -0.161999, -13.264900, 3.000000, 2.195430, 0.528455, 0.798898, -0.287224,
+1.002737, 0.467394, -11.098533, 3.000000, 2.371212, 0.517497, 0.844529, -0.137721,
+1.336982, -0.183937, -11.115767, 2.500000, 2.371212, 0.999002, 0.043336, -0.010816,
+1.336982, -0.183937, -11.115767, 2.500000, 2.371212, 0.999002, 0.043336, -0.010816,
+1.002737, -0.835270, -11.133000, 2.000000, 2.371212, 0.556778, -0.814518, 0.162970,
+1.002737, -1.498060, -13.154191, 2.000000, 2.195430, 0.550846, -0.775955, 0.307348,
+1.002737, -1.498060, -13.154191, 2.000000, 2.195430, 0.550846, -0.775955, 0.307348,
+1.002737, -2.439466, -15.191065, 2.000000, 2.020624, 0.552162, -0.756556, 0.350343,
+1.336982, -1.762512, -15.300098, 2.500000, 2.020624, 0.999977, 0.006790, -0.000522,
+1.336982, -3.677238, -19.700720, 2.500000, 1.696742, 0.999943, -0.009227, 0.005371,
+1.002737, -2.990782, -19.848455, 3.000000, 1.696742, 0.573541, 0.767561, -0.286181,
+1.002737, -2.066217, -17.608171, 3.000000, 1.853850, 0.561407, 0.760416, -0.326481,
+1.002737, -2.066217, -17.608171, 3.000000, 1.853850, 0.561407, 0.760416, -0.326481,
+1.002737, -1.085560, -15.409132, 3.000000, 2.020624, 0.545979, 0.767296, -0.336399,
+1.336982, -1.762512, -15.300098, 2.500000, 2.020624, 0.999977, 0.006790, -0.000522,
+1.336982, -1.762512, -15.300098, 2.500000, 2.020624, 0.999977, 0.006790, -0.000522,
+1.002737, -2.439466, -15.191065, 2.000000, 2.020624, 0.552162, -0.756556, 0.350343,
+1.002737, -3.431055, -17.329250, 2.000000, 1.853850, 0.559291, -0.758482, 0.334513,
+1.002737, -3.431055, -17.329250, 2.000000, 1.853850, 0.559291, -0.758482, 0.334513,
+1.002737, -4.363696, -19.552979, 2.000000, 1.696742, 0.563275, -0.773529, 0.290474,
+1.336982, -3.677238, -19.700720, 2.500000, 1.696742, 0.999943, -0.009227, 0.005371,
+1.336982, -4.998410, -24.141369, 2.500000, 1.417808, 0.999879, -0.015055, 0.003873,
+1.002737, -4.302059, -24.249632, 3.000000, 1.417808, 0.582444, 0.793471, -0.176531,
+1.002737, -3.746061, -22.116426, 3.000000, 1.550938, 0.578794, 0.781497, -0.232937,
+1.002737, -3.746061, -22.116426, 3.000000, 1.550938, 0.578794, 0.781497, -0.232937,
+1.002737, -2.990782, -19.848455, 3.000000, 1.696742, 0.573541, 0.767561, -0.286181,
+1.336982, -3.677238, -19.700720, 2.500000, 1.696742, 0.999943, -0.009227, 0.005371,
+1.336982, -3.677238, -19.700720, 2.500000, 1.696742, 0.999943, -0.009227, 0.005371,
+1.002737, -4.363696, -19.552979, 2.000000, 1.696742, 0.563275, -0.773529, 0.290474,
+1.002737, -5.128252, -21.846479, 2.000000, 1.550938, 0.566340, -0.790066, 0.234638,
+1.002737, -5.128252, -21.846479, 2.000000, 1.550938, 0.566340, -0.790066, 0.234638,
+1.002737, -5.694758, -24.033106, 2.000000, 1.417808, 0.566494, -0.804616, 0.177981,
+1.336982, -4.998410, -24.141369, 2.500000, 1.417808, 0.999879, -0.015055, 0.003873,
+1.336982, -5.505962, -27.491592, 2.500000, 1.186658, 0.999932, -0.011526, 0.001722,
+1.002737, -4.798269, -27.533844, 3.000000, 1.186658, 0.583019, 0.808019, -0.084825,
+1.002737, -4.628780, -26.085621, 3.000000, 1.298722, 0.582983, 0.803361, -0.121414,
+1.002737, -4.628780, -26.085621, 3.000000, 1.298722, 0.582983, 0.803361, -0.121414,
+1.002737, -4.302059, -24.249632, 3.000000, 1.417808, 0.582444, 0.793471, -0.176531,
+1.336982, -4.998410, -24.141369, 2.500000, 1.417808, 0.999879, -0.015055, 0.003873,
+1.336982, -4.998410, -24.141369, 2.500000, 1.417808, 0.999879, -0.015055, 0.003873,
+1.002737, -5.694758, -24.033106, 2.000000, 1.417808, 0.566494, -0.804616, 0.177981,
+1.002737, -6.033253, -25.936216, 2.000000, 1.298722, 0.568446, -0.813396, 0.123515,
+1.002737, -6.033253, -25.936216, 2.000000, 1.298722, 0.568446, -0.813396, 0.123515,
+1.002737, -6.213656, -27.449341, 2.000000, 1.186658, 0.570758, -0.816393, 0.087968,
+1.336982, -5.505962, -27.491592, 2.500000, 1.186658, 0.999932, -0.011526, 0.001722,
+1.002737, -4.882575, -28.503754, 2.500000, 1.053028, 0.589040, 0.805067, -0.069986,
+1.002737, -4.798269, -27.533844, 3.000000, 1.053028, 0.583019, 0.808019, -0.084825,
+1.336982, -5.505962, -27.491592, 3.000000, 1.119843, 0.999932, -0.011526, 0.001722,
+1.336982, -5.505962, -27.491592, 3.000000, 1.119843, 0.999932, -0.011526, 0.001722,
+1.002737, -6.213656, -27.449341, 3.000000, 1.186658, 0.570758, -0.816393, 0.087968,
+1.002737, -6.305892, -28.466030, 2.500000, 1.186658, 0.565626, -0.821288, 0.074517,
+0.000000, -23.748404, -4.519603, 3.000000, 1.026514, -0.000000, -0.884854, 0.465869,
+-1.002737, -23.539934, -4.622173, 3.000000, 1.053028, -0.559738, -0.733607, 0.385376,
+-1.002737, -24.101816, -5.795360, 2.500000, 1.053028, -0.571338, -0.788867, 0.226409,
+-1.002737, -24.101816, -5.795360, 2.500000, 1.053028, -0.571338, -0.788867, 0.226409,
+-0.742768, -24.152987, -6.401496, 2.000000, 1.053028, -0.455754, -0.834431, -0.309862,
+0.000000, -24.406044, -6.530420, 2.000000, 1.026514, 0.000000, -0.933376, -0.358900,
+0.000000, -24.406044, -6.530420, 2.000000, 1.026514, 0.000000, -0.933376, -0.358900,
+0.742768, -24.152987, -6.401496, 2.000000, 1.000000, 0.455754, -0.834430, -0.309862,
+1.002737, -24.101816, -5.795360, 2.500000, 1.000000, 0.571338, -0.788867, 0.226409,
+1.002737, -24.101816, -5.795360, 2.500000, 1.000000, 0.571338, -0.788867, 0.226409,
+1.002737, -23.539934, -4.622173, 3.000000, 1.000000, 0.559738, -0.733607, 0.385376,
+0.000000, -23.748404, -4.519603, 3.000000, 1.026514, -0.000000, -0.884854, 0.465869,
+0.000000, -21.564705, -1.218530, 3.500000, 4.901888, 0.000000, -0.737549, 0.675293,
+-1.002737, -21.393009, -1.363454, 4.000000, 4.915090, -0.538985, -0.621423, 0.568620,
+-1.002737, -22.670450, -3.070609, 4.000000, 4.957545, -0.549531, -0.697669, 0.459646,
+-1.002737, -22.670450, -3.070609, 4.000000, 4.957545, -0.549531, -0.697669, 0.459646,
+-1.002737, -23.539934, -4.622173, 4.000000, 5.000000, -0.559738, -0.733607, 0.385376,
+0.000000, -23.748404, -4.519603, 3.500000, 5.000000, -0.000000, -0.884854, 0.465869,
+0.000000, -23.748404, -4.519603, 3.500000, 5.000000, -0.000000, -0.884854, 0.465869,
+1.002737, -23.539934, -4.622173, 3.000000, 5.000000, 0.559738, -0.733607, 0.385376,
+1.002737, -22.670450, -3.070609, 3.000000, 4.957545, 0.549531, -0.697669, 0.459646,
+1.002737, -22.670450, -3.070609, 3.000000, 4.957545, 0.549531, -0.697669, 0.459646,
+1.002737, -21.393009, -1.363454, 3.000000, 4.901887, 0.538985, -0.621423, 0.568620,
+0.000000, -21.564705, -1.218530, 3.500000, 4.901888, 0.000000, -0.737549, 0.675293,
+0.000000, -17.551340, 1.784490, 3.500000, 4.706708, -0.000000, -0.412059, 0.911157,
+-1.002737, -17.444981, 1.593854, 4.000000, 4.724558, -0.523473, -0.350048, 0.776815,
+-1.002737, -19.607264, 0.276508, 4.000000, 4.819824, -0.531663, -0.507888, 0.677779,
+-1.002737, -19.607264, 0.276508, 4.000000, 4.819824, -0.531663, -0.507888, 0.677779,
+-1.002737, -21.393009, -1.363454, 4.000000, 4.915090, -0.538985, -0.621423, 0.568620,
+0.000000, -21.564705, -1.218530, 3.500000, 4.901888, 0.000000, -0.737549, 0.675293,
+0.000000, -21.564705, -1.218530, 3.500000, 4.901888, 0.000000, -0.737549, 0.675293,
+1.002737, -21.393009, -1.363454, 3.000000, 4.901887, 0.538985, -0.621423, 0.568620,
+1.002737, -19.607264, 0.276508, 3.000000, 4.819824, 0.531663, -0.507888, 0.677779,
+1.002737, -19.607264, 0.276508, 3.000000, 4.819824, 0.531663, -0.507888, 0.677779,
+1.002737, -17.444981, 1.593854, 3.000000, 4.706708, 0.523473, -0.350048, 0.776815,
+0.000000, -17.551340, 1.784490, 3.500000, 4.706708, -0.000000, -0.412059, 0.911157,
+0.000000, -12.565042, 2.860814, 3.500000, 4.382352, -0.000000, -0.071332, 0.997453,
+-1.002737, -12.539209, 2.645355, 4.000000, 4.391225, -0.529316, -0.059790, 0.846315,
+-1.002737, -15.037928, 2.333167, 4.000000, 4.557892, -0.524224, -0.178780, 0.832603,
+-1.002737, -15.037928, 2.333167, 4.000000, 4.557892, -0.524224, -0.178780, 0.832603,
+-1.002737, -17.444981, 1.593854, 4.000000, 4.724558, -0.523473, -0.350048, 0.776815,
+0.000000, -17.551340, 1.784490, 3.500000, 4.706708, -0.000000, -0.412059, 0.911157,
+0.000000, -17.551340, 1.784490, 3.500000, 4.706708, -0.000000, -0.412059, 0.911157,
+1.002737, -17.444981, 1.593854, 3.000000, 4.706708, 0.523473, -0.350048, 0.776815,
+1.002737, -15.037928, 2.333167, 3.000000, 4.557891, 0.524224, -0.178780, 0.832603,
+1.002737, -15.037928, 2.333167, 3.000000, 4.557891, 0.524224, -0.178780, 0.832603,
+1.002737, -12.539209, 2.645355, 3.000000, 4.382352, 0.529316, -0.059790, 0.846315,
+0.000000, -12.565042, 2.860814, 3.500000, 4.382352, -0.000000, -0.071332, 0.997453,
+0.000000, -7.814985, 2.580152, 3.500000, 3.977933, -0.000000, 0.247588, 0.968866,
+-1.002737, -7.868385, 2.366725, 4.000000, 3.986911, -0.526810, 0.210598, 0.823480,
+-1.002737, -10.101929, 2.681329, 4.000000, 4.189068, -0.529646, 0.050516, 0.846713,
+-1.002737, -10.101929, 2.681329, 4.000000, 4.189068, -0.529646, 0.050516, 0.846713,
+-1.002737, -12.539209, 2.645355, 4.000000, 4.391225, -0.529316, -0.059790, 0.846315,
+0.000000, -12.565042, 2.860814, 3.500000, 4.382352, -0.000000, -0.071332, 0.997453,
+0.000000, -12.565042, 2.860814, 3.500000, 4.382352, -0.000000, -0.071332, 0.997453,
+1.002737, -12.539209, 2.645355, 3.000000, 4.382352, 0.529316, -0.059790, 0.846315,
+1.002737, -10.101929, 2.681329, 3.000000, 4.189068, 0.529646, 0.050516, 0.846713,
+1.002737, -10.101929, 2.681329, 3.000000, 4.189068, 0.529646, 0.050516, 0.846713,
+1.002737, -7.868385, 2.366725, 3.000000, 3.977933, 0.526810, 0.210598, 0.823480,
+0.000000, -7.814985, 2.580152, 3.500000, 3.977933, -0.000000, 0.247588, 0.968866,
+0.000000, -4.225573, 0.668588, 3.500000, 3.518014, -0.000000, 0.644556, 0.764557,
+-1.002737, -4.339529, 0.487975, 4.000000, 3.510776, -0.515414, 0.553092, 0.654552,
+-1.002737, -5.980879, 1.627182, 4.000000, 3.748844, -0.522694, 0.400366, 0.752661,
+-1.002737, -5.980879, 1.627182, 4.000000, 3.748844, -0.522694, 0.400366, 0.752661,
+-1.002737, -7.868385, 2.366725, 4.000000, 3.986911, -0.526810, 0.210598, 0.823480,
+0.000000, -7.814985, 2.580152, 3.500000, 3.977933, -0.000000, 0.247588, 0.968866,
+0.000000, -7.814985, 2.580152, 3.500000, 3.977933, -0.000000, 0.247588, 0.968866,
+1.002737, -7.868385, 2.366725, 3.000000, 3.977933, 0.526810, 0.210598, 0.823480,
+1.002737, -5.980879, 1.627182, 3.000000, 3.748844, 0.522693, 0.400366, 0.752661,
+1.002737, -5.980879, 1.627182, 3.000000, 3.748844, 0.522693, 0.400366, 0.752661,
+1.002737, -4.339529, 0.487975, 3.000000, 3.518014, 0.515414, 0.553092, 0.654552,
+0.000000, -4.225573, 0.668588, 3.500000, 3.518014, -0.000000, 0.644556, 0.764557,
+0.000000, -1.389704, -2.649346, 3.500000, 3.096704, 0.000000, 0.838537, 0.544844,
+-1.002737, -1.550434, -2.775177, 4.000000, 3.092546, -0.505987, 0.723592, 0.469458,
+-1.002737, -2.844458, -1.025621, 4.000000, 3.301661, -0.509526, 0.653879, 0.559309,
+-1.002737, -2.844458, -1.025621, 4.000000, 3.301661, -0.509526, 0.653879, 0.559309,
+-1.002737, -4.339529, 0.487975, 4.000000, 3.510776, -0.515414, 0.553092, 0.654552,
+0.000000, -4.225573, 0.668588, 3.500000, 3.518014, -0.000000, 0.644556, 0.764557,
+0.000000, -4.225573, 0.668588, 3.500000, 3.518014, -0.000000, 0.644556, 0.764557,
+1.002737, -4.339529, 0.487975, 3.000000, 3.518014, 0.515414, 0.553092, 0.654552,
+1.002737, -2.844458, -1.025621, 3.000000, 3.301661, 0.509526, 0.653879, 0.559309,
+1.002737, -2.844458, -1.025621, 3.000000, 3.301661, 0.509526, 0.653879, 0.559309,
+1.002737, -1.550435, -2.775177, 3.000000, 3.096704, 0.505988, 0.723592, 0.469458,
+0.000000, -1.389704, -2.649346, 3.500000, 3.096704, 0.000000, 0.838537, 0.544844,
+0.000000, 0.406973, -6.557009, 3.500000, 2.714038, -0.000000, 0.968208, 0.250145,
+-1.002737, 0.212360, -6.622896, 4.000000, 2.707584, -0.505652, 0.835716, 0.214230,
+-1.002737, -0.512230, -4.622262, 4.000000, 2.900065, -0.503207, 0.785550, 0.360132,
+-1.002737, -0.512230, -4.622262, 4.000000, 2.900065, -0.503207, 0.785550, 0.360132,
+-1.002737, -1.550434, -2.775177, 4.000000, 3.092546, -0.505987, 0.723592, 0.469458,
+0.000000, -1.389704, -2.649346, 3.500000, 3.096704, 0.000000, 0.838537, 0.544844,
+0.000000, -1.389704, -2.649346, 3.500000, 3.096704, 0.000000, 0.838537, 0.544844,
+1.002737, -1.550435, -2.775177, 3.000000, 3.096704, 0.505988, 0.723592, 0.469458,
+1.002737, -0.512230, -4.622262, 3.000000, 2.900065, 0.503207, 0.785549, 0.360132,
+1.002737, -0.512230, -4.622262, 3.000000, 2.900065, 0.503207, 0.785549, 0.360132,
+1.002737, 0.212362, -6.622896, 3.000000, 2.714038, 0.505651, 0.835716, 0.214230,
+0.000000, 0.406973, -6.557009, 3.500000, 2.714038, -0.000000, 0.968208, 0.250145,
+0.000000, 0.684505, -11.092790, 3.500000, 2.371212, 0.000000, 0.987685, -0.156457,
+-1.002737, 0.467394, -11.098533, 4.000000, 2.374251, -0.517497, 0.844529, -0.137721,
+-1.002737, 0.565540, -8.833092, 4.000000, 2.540917, -0.512670, 0.857167, 0.049331,
+-1.002737, 0.565540, -8.833092, 4.000000, 2.540917, -0.512670, 0.857167, 0.049331,
+-1.002737, 0.212360, -6.622896, 4.000000, 2.707584, -0.505652, 0.835716, 0.214230,
+0.000000, 0.406973, -6.557009, 3.500000, 2.714038, -0.000000, 0.968208, 0.250145,
+0.000000, 0.406973, -6.557009, 3.500000, 2.714038, -0.000000, 0.968208, 0.250145,
+1.002737, 0.212362, -6.622896, 3.000000, 2.714038, 0.505651, 0.835716, 0.214230,
+1.002737, 0.565540, -8.833092, 3.000000, 2.540917, 0.512670, 0.857168, 0.049331,
+1.002737, 0.565540, -8.833092, 3.000000, 2.540917, 0.512670, 0.857168, 0.049331,
+1.002737, 0.467394, -11.098533, 3.000000, 2.371212, 0.517497, 0.844529, -0.137721,
+0.000000, 0.684505, -11.092790, 3.500000, 2.371212, 0.000000, 0.987685, -0.156457,
+0.000000, -0.859908, -15.445475, 3.500000, 2.020624, 0.000000, 0.916600, -0.399806,
+-1.002737, -1.085560, -15.409132, 4.000000, 2.016609, -0.545979, 0.767296, -0.336399,
+-1.002737, -0.161999, -13.264900, 4.000000, 2.195430, -0.528455, 0.798898, -0.287224,
+-1.002737, -0.161999, -13.264900, 4.000000, 2.195430, -0.528455, 0.798898, -0.287224,
+-1.002737, 0.467394, -11.098533, 4.000000, 2.374251, -0.517497, 0.844529, -0.137721,
+0.000000, 0.684505, -11.092790, 3.500000, 2.371212, 0.000000, 0.987685, -0.156457,
+0.000000, 0.684505, -11.092790, 3.500000, 2.371212, 0.000000, 0.987685, -0.156457,
+1.002737, 0.467394, -11.098533, 3.000000, 2.371212, 0.517497, 0.844529, -0.137721,
+1.002737, -0.161999, -13.264900, 3.000000, 2.195430, 0.528455, 0.798898, -0.287224,
+1.002737, -0.161999, -13.264900, 3.000000, 2.195430, 0.528455, 0.798898, -0.287224,
+1.002737, -1.085560, -15.409132, 3.000000, 2.020624, 0.545979, 0.767296, -0.336399,
+0.000000, -0.859908, -15.445475, 3.500000, 2.020624, 0.000000, 0.916600, -0.399806,
+0.000000, -2.761963, -19.897703, 3.500000, 1.696742, 0.000000, 0.936891, -0.349623,
+-1.002737, -2.990782, -19.848455, 4.000000, 1.691091, -0.573541, 0.767562, -0.286181,
+-1.002737, -2.066217, -17.608171, 4.000000, 1.853850, -0.561407, 0.760416, -0.326481,
+-1.002737, -2.066217, -17.608171, 4.000000, 1.853850, -0.561407, 0.760416, -0.326481,
+-1.002737, -1.085560, -15.409132, 4.000000, 2.016609, -0.545979, 0.767296, -0.336399,
+0.000000, -0.859908, -15.445475, 3.500000, 2.020624, 0.000000, 0.916600, -0.399806,
+0.000000, -0.859908, -15.445475, 3.500000, 2.020624, 0.000000, 0.916600, -0.399806,
+1.002737, -1.085560, -15.409132, 3.000000, 2.020624, 0.545979, 0.767296, -0.336399,
+1.002737, -2.066217, -17.608171, 3.000000, 1.853850, 0.561407, 0.760416, -0.326481,
+1.002737, -2.066217, -17.608171, 3.000000, 1.853850, 0.561407, 0.760416, -0.326481,
+1.002737, -2.990782, -19.848455, 3.000000, 1.696742, 0.573541, 0.767561, -0.286181,
+0.000000, -2.761963, -19.897703, 3.500000, 1.696742, 0.000000, 0.936891, -0.349623,
+0.000000, -4.069942, -24.285717, 3.500000, 1.417808, 0.000000, 0.976057, -0.217516,
+-1.002737, -4.302059, -24.249632, 4.000000, 1.410785, -0.582444, 0.793471, -0.176531,
+-1.002737, -3.746061, -22.116426, 4.000000, 1.550938, -0.578794, 0.781497, -0.232937,
+-1.002737, -3.746061, -22.116426, 4.000000, 1.550938, -0.578794, 0.781497, -0.232937,
+-1.002737, -2.990782, -19.848455, 4.000000, 1.691091, -0.573541, 0.767562, -0.286181,
+0.000000, -2.761963, -19.897703, 3.500000, 1.696742, 0.000000, 0.936891, -0.349623,
+0.000000, -2.761963, -19.897703, 3.500000, 1.696742, 0.000000, 0.936891, -0.349623,
+1.002737, -2.990782, -19.848455, 3.000000, 1.696742, 0.573541, 0.767561, -0.286181,
+1.002737, -3.746061, -22.116426, 3.000000, 1.550938, 0.578794, 0.781497, -0.232937,
+1.002737, -3.746061, -22.116426, 3.000000, 1.550938, 0.578794, 0.781497, -0.232937,
+1.002737, -4.302059, -24.249632, 3.000000, 1.417808, 0.582444, 0.793471, -0.176531,
+0.000000, -4.069942, -24.285717, 3.500000, 1.417808, 0.000000, 0.976057, -0.217516,
+0.000000, -4.562372, -27.547928, 3.500000, 1.186658, 0.000000, 0.994554, -0.104226,
+-1.002737, -4.798269, -27.533844, 4.000000, 1.186658, -0.583018, 0.808019, -0.084825,
+-1.002737, -4.628780, -26.085621, 4.000000, 1.298722, -0.582983, 0.803361, -0.121414,
+-1.002737, -4.628780, -26.085621, 4.000000, 1.298722, -0.582983, 0.803361, -0.121414,
+-1.002737, -4.302059, -24.249632, 4.000000, 1.410785, -0.582444, 0.793471, -0.176531,
+0.000000, -4.069942, -24.285717, 3.500000, 1.417808, 0.000000, 0.976057, -0.217516,
+0.000000, -4.069942, -24.285717, 3.500000, 1.417808, 0.000000, 0.976057, -0.217516,
+1.002737, -4.302059, -24.249632, 3.000000, 1.417808, 0.582444, 0.793471, -0.176531,
+1.002737, -4.628780, -26.085621, 3.000000, 1.298722, 0.582983, 0.803361, -0.121414,
+1.002737, -4.628780, -26.085621, 3.000000, 1.298722, 0.582983, 0.803361, -0.121414,
+1.002737, -4.798269, -27.533844, 3.000000, 1.186658, 0.583019, 0.808019, -0.084825,
+0.000000, -4.562372, -27.547928, 3.500000, 1.186658, 0.000000, 0.994554, -0.104226,
+-1.002737, -4.882575, -28.503754, 3.500000, 1.053028, -0.589040, 0.805068, -0.069986,
+-1.002737, -4.798269, -27.533844, 4.000000, 1.053028, -0.583018, 0.808019, -0.084825,
+0.000000, -4.562372, -27.547928, 4.000000, 1.119843, 0.000000, 0.994554, -0.104226,
+0.000000, -4.562372, -27.547928, 4.000000, 1.119843, 0.000000, 0.994554, -0.104226,
+1.002737, -4.798269, -27.533844, 4.000000, 1.186658, 0.583019, 0.808019, -0.084825,
+1.002737, -4.882575, -28.503754, 3.500000, 1.186658, 0.589040, 0.805067, -0.069986,
+1.010821, 4.753092, -11.679992, 3.500000, 1.000000, 0.576512, -0.780907, 0.240454,
+1.014864, 3.544037, -14.721523, 3.000000, 1.000000, 0.562535, -0.748836, 0.350428,
+1.349109, 4.237772, -14.807808, 3.000000, 1.026514, 0.999805, 0.015731, -0.011963,
+1.349109, 4.237772, -14.807808, 3.000000, 1.026514, 0.999805, 0.015731, -0.011963,
+1.014864, 4.931509, -14.894089, 3.000000, 1.053028, 0.545447, 0.762198, -0.348629,
+1.010821, 6.148220, -11.777804, 3.500000, 1.053028, 0.548873, 0.801150, -0.238531,
+1.010821, 6.148220, -11.777804, 3.500000, 1.053028, 0.548873, 0.801150, -0.238531,
+1.004758, 6.770885, -8.754030, 4.000000, 1.053028, 0.549543, 0.833398, -0.058740,
+1.339004, 6.071638, -8.749280, 4.000000, 1.026514, 0.999013, 0.044275, -0.003633,
+1.339004, 6.071638, -8.749280, 4.000000, 1.026514, 0.999013, 0.044275, -0.003633,
+1.004758, 5.372389, -8.744530, 4.000000, 1.000000, 0.594556, -0.801738, 0.060986,
+1.010821, 4.753092, -11.679992, 3.500000, 1.000000, 0.576512, -0.780907, 0.240454,
+-0.994652, 4.753092, -11.679992, 2.000000, 0.093876, -0.576606, -0.781401, 0.238616,
+-0.990610, 3.544037, -14.721523, 2.000000, 0.267209, -0.562098, -0.749029, 0.350717,
+0.012127, 3.312792, -14.692760, 2.500000, 0.267209, 0.000169, -0.904592, 0.426279,
+0.012127, 3.312792, -14.692760, 2.500000, 0.267209, 0.000169, -0.904592, 0.426279,
+1.014864, 3.544037, -14.721523, 3.000000, 0.267209, 0.562535, -0.748836, 0.350428,
+1.010821, 4.753092, -11.679992, 3.000000, 0.093875, 0.576512, -0.780907, 0.240454,
+1.010821, 4.753092, -11.679992, 3.000000, 0.093875, 0.576512, -0.780907, 0.240454,
+1.004758, 5.372389, -8.744530, 3.000000, -0.079458, 0.594556, -0.801738, 0.060986,
+0.002021, 5.139305, -8.742946, 2.500000, -0.079458, -0.000101, -0.997122, 0.075814,
+0.002021, 5.139305, -8.742946, 2.500000, -0.079458, -0.000101, -0.997122, 0.075814,
+-1.000716, 5.372389, -8.744530, 2.000000, -0.079458, -0.594849, -0.801661, 0.059106,
+-0.994652, 4.753092, -11.679992, 2.000000, 0.093876, -0.576606, -0.781401, 0.238616,
+-0.994652, 6.148220, -11.777804, 1.187500, 0.109894, -0.548576, 0.800857, -0.240193,
+-0.990610, 4.931509, -14.894089, 1.000000, 0.267209, -0.544986, 0.762408, -0.348891,
+-1.324855, 4.237772, -14.807808, 1.500000, 0.267209, -0.999804, 0.015791, -0.011962,
+-1.324855, 4.237772, -14.807808, 1.500000, 0.267209, -0.999804, 0.015791, -0.011962,
+-0.990610, 3.544037, -14.721523, 2.000000, 0.267209, -0.562098, -0.749029, 0.350717,
+-0.994652, 4.753092, -11.679992, 2.000000, 0.093876, -0.576606, -0.781401, 0.238616,
+-0.994652, 4.753092, -11.679992, 2.000000, 0.093876, -0.576606, -0.781401, 0.238616,
+-1.000716, 5.372389, -8.744530, 2.000000, -0.079458, -0.594849, -0.801661, 0.059106,
+-1.334961, 6.071638, -8.749280, 1.500000, -0.079458, -0.999000, 0.044233, -0.006500,
+-1.334961, 6.071638, -8.749280, 1.500000, -0.079458, -0.999000, 0.044233, -0.006500,
+-1.000716, 6.770885, -8.754030, 1.000000, -0.079458, -0.549751, 0.833161, -0.060139,
+-0.994652, 6.148220, -11.777804, 1.187500, 0.109894, -0.548576, 0.800857, -0.240193,
+1.010821, 6.148220, -11.777804, 1.500000, 0.222021, 0.548873, 0.801150, -0.238531,
+1.014864, 4.931509, -14.894089, 3.000000, 0.523501, 0.545447, 0.762198, -0.348629,
+0.012127, 5.162754, -14.922852, 2.000000, 0.395355, 0.000167, 0.910359, -0.413819,
+0.012127, 5.162754, -14.922852, 2.000000, 0.395355, 0.000167, 0.910359, -0.413819,
+-0.990610, 4.931509, -14.894089, 1.000000, 0.267209, -0.544986, 0.762408, -0.348891,
+-0.994652, 6.148220, -11.777804, 1.187500, 0.109894, -0.548576, 0.800857, -0.240193,
+-0.994652, 6.148220, -11.777804, 1.187500, 0.109894, -0.548576, 0.800857, -0.240193,
+-1.000716, 6.770885, -8.754030, 1.000000, -0.079458, -0.549751, 0.833161, -0.060139,
+0.002021, 7.003967, -8.755614, 0.500000, -0.079458, -0.000102, 0.997541, -0.070087,
+0.002021, 7.003967, -8.755614, 0.500000, -0.079458, -0.000102, 0.997541, -0.070087,
+1.004758, 6.770885, -8.754030, 0.000000, -0.079458, 0.549543, 0.833398, -0.058740,
+1.010821, 6.148220, -11.777804, 1.500000, 0.222021, 0.548873, 0.801150, -0.238531,
+-1.002737, 1.949966, 10.301342, 3.000000, 0.093875, -0.548106, -0.827983, 0.118418,
+-1.002737, 1.707661, 7.456823, 3.000000, 0.267209, -0.546192, -0.837529, 0.014826,
+0.000000, 1.483450, 7.466458, 3.000000, 0.395355, 0.000000, -0.999837, 0.018050,
+0.000000, 1.483450, 7.466458, 3.000000, 0.395355, 0.000000, -0.999837, 0.018050,
+1.002737, 1.707661, 7.456823, 3.000000, 0.523501, 0.546192, -0.837529, 0.014826,
+1.002737, 1.949966, 10.301342, 3.000000, -0.199582, 0.548430, -0.827643, 0.119301,
+1.002737, 1.949966, 10.301342, 3.000000, -0.199582, 0.548430, -0.827643, 0.119301,
+0.997835, 2.515034, 13.079953, 3.000000, -0.922665, 0.552074, -0.807195, 0.208929,
+-0.004902, 2.294706, 13.134627, 3.000000, -0.501061, 0.000247, -0.968748, 0.248048,
+-0.004902, 2.294706, 13.134627, 3.000000, -0.501061, 0.000247, -0.968748, 0.248048,
+-1.007639, 2.515034, 13.079953, 3.000000, -0.079458, -0.551445, -0.808533, 0.205386,
+-1.002737, 1.949966, 10.301342, 3.000000, 0.093875, -0.548106, -0.827983, 0.118418,
+-1.002737, 3.286348, 10.103830, 1.187500, -1.435965, -0.570397, 0.812622, -0.119555,
+-1.002737, 3.052929, 7.399012, 1.000000, -1.306215, -0.571504, 0.820505, -0.012461,
+-1.336982, 2.380295, 7.427917, 1.500000, -1.306215, -0.999670, -0.025705, 0.000199,
+-1.336982, 2.380295, 7.427917, 1.500000, -1.306215, -0.999670, -0.025705, 0.000199,
+-1.002737, 1.707661, 7.456823, 2.000000, -1.306215, -0.546192, -0.837529, 0.014826,
+-1.002737, 1.949966, 10.301342, 2.000000, -1.459937, -0.548106, -0.827983, 0.118418,
+-1.002737, 1.949966, 10.301342, 2.000000, -1.459937, -0.548106, -0.827983, 0.118418,
+-1.007639, 2.515034, 13.079953, 2.000000, -1.613659, -0.551445, -0.808533, 0.205386,
+-1.341885, 3.176014, 12.915927, 1.500000, -1.613659, -0.999798, -0.020077, 0.001135,
+-1.341885, 3.176014, 12.915927, 1.500000, -1.613659, -0.999798, -0.020077, 0.001135,
+-1.007639, 3.836994, 12.751901, 1.000000, -1.613659, -0.571038, 0.793815, -0.209219,
+-1.002737, 3.286348, 10.103830, 1.187500, -1.435965, -0.570397, 0.812622, -0.119555,
+1.002737, 3.286348, 10.103830, 1.500000, -1.268162, 0.570686, 0.812576, -0.118478,
+1.002737, 3.052929, 7.399012, 3.000000, -0.922665, 0.571504, 0.820504, -0.012461,
+0.000000, 3.277142, 7.389376, 2.000000, -1.114440, 0.000000, 0.999891, -0.014768,
+0.000000, 3.277142, 7.389376, 2.000000, -1.114440, 0.000000, 0.999891, -0.014768,
+-1.002737, 3.052929, 7.399012, 1.000000, -1.306215, -0.571504, 0.820505, -0.012461,
+-1.002737, 3.286348, 10.103830, 1.187500, -1.435965, -0.570397, 0.812622, -0.119555,
+-1.002737, 3.286348, 10.103830, 1.187500, -1.435965, -0.570397, 0.812622, -0.119555,
+-1.007639, 3.836994, 12.751901, 1.000000, -1.613659, -0.571038, 0.793815, -0.209219,
+-0.004902, 4.057320, 12.697225, 0.500000, -1.613659, 0.000259, 0.967531, -0.252752,
+-0.004902, 4.057320, 12.697225, 0.500000, -1.613659, 0.000259, 0.967531, -0.252752,
+0.997834, 3.836994, 12.751901, 0.000000, -1.613659, 0.571655, 0.794480, -0.204969,
+1.002737, 3.286348, 10.103830, 1.500000, -1.268162, 0.570686, 0.812576, -0.118478,
+1.002737, 1.949966, 10.301342, 3.000000, -1.459937, 0.548430, -0.827643, 0.119301,
+1.002737, 1.707661, 7.456823, 3.000000, -1.306215, 0.546192, -0.837529, 0.014826,
+1.336982, 2.380295, 7.427917, 3.000000, -1.114440, 0.999670, -0.025705, 0.000199,
+1.336982, 2.380295, 7.427917, 3.000000, -1.114440, 0.999670, -0.025705, 0.000199,
+1.002737, 3.052929, 7.399012, 3.000000, -0.922665, 0.571504, 0.820504, -0.012461,
+1.002737, 3.286348, 10.103830, 2.833333, -1.322391, 0.570686, 0.812576, -0.118478,
+1.002737, 3.286348, 10.103830, 2.833333, -1.322391, 0.570686, 0.812576, -0.118478,
+0.997834, 3.836994, 12.751901, 2.666667, -1.722117, 0.571655, 0.794480, -0.204969,
+1.332080, 3.176014, 12.915927, 2.833333, -1.667888, 0.999801, -0.018232, 0.008046,
+1.332080, 3.176014, 12.915927, 2.833333, -1.667888, 0.999801, -0.018232, 0.008046,
+0.997835, 2.515034, 13.079953, 3.000000, -1.613659, 0.552074, -0.807195, 0.208929,
+1.002737, 1.949966, 10.301342, 3.000000, -1.459937, 0.548430, -0.827643, 0.119301,
+0.983128, 5.711351, 20.357510, 2.000000, -1.459937, 0.562328, -0.698593, 0.442442,
+0.973323, 4.412262, 18.174875, 2.000000, -1.306215, 0.554281, -0.740975, 0.379115,
+1.307569, 5.044981, 17.903212, 2.500000, -1.306215, 0.999751, -0.019683, 0.010530,
+1.307569, 5.044981, 17.903212, 2.500000, -1.306215, 0.999751, -0.019683, 0.010530,
+0.973323, 5.677700, 17.631544, 3.000000, -1.306215, 0.576561, 0.724323, -0.378066,
+0.983128, 6.945759, 19.711123, 3.000000, -1.459937, 0.574803, 0.682785, -0.451006,
+0.983128, 6.945759, 19.711123, 3.000000, -1.459937, 0.574803, 0.682785, -0.451006,
+0.997834, 8.160118, 21.422651, 3.000000, -1.613659, 0.574744, 0.665807, -0.475784,
+1.332080, 7.556932, 21.789433, 2.500000, -1.613659, 0.999977, -0.005048, -0.004524,
+1.332080, 7.556932, 21.789433, 2.500000, -1.613659, 0.999977, -0.005048, -0.004524,
+0.997835, 6.953747, 22.156214, 2.000000, -1.613659, 0.572743, -0.675634, 0.464203,
+0.983128, 5.711351, 20.357510, 2.000000, -1.459937, 0.562328, -0.698593, 0.442442,
+-1.022346, 5.711351, 20.357510, 2.000000, -1.857690, -0.562464, -0.695442, 0.447208,
+-1.032151, 4.412262, 18.174877, 2.000000, -1.776346, -0.555665, -0.740194, 0.378615,
+-0.029414, 4.201355, 18.265430, 2.500000, -1.776346, -0.000535, -0.890739, 0.454514,
+-0.029414, 4.201355, 18.265430, 2.500000, -1.776346, -0.000535, -0.890739, 0.454514,
+0.973323, 4.412262, 18.174875, 3.000000, -1.776346, 0.554281, -0.740975, 0.379115,
+0.983128, 5.711351, 20.357510, 3.000000, -1.857690, 0.562328, -0.698593, 0.442442,
+0.983128, 5.711351, 20.357510, 3.000000, -1.857690, 0.562328, -0.698593, 0.442442,
+0.997835, 6.953747, 22.156214, 3.000000, -1.939034, 0.572743, -0.675634, 0.464203,
+-0.004902, 6.752687, 22.278475, 2.500000, -1.939034, 0.000369, -0.822635, 0.568570,
+-0.004902, 6.752687, 22.278475, 2.500000, -1.939034, 0.000369, -0.822635, 0.568570,
+-1.007639, 6.953747, 22.156216, 2.000000, -1.939034, -0.571627, -0.672843, 0.469600,
+-1.022346, 5.711351, 20.357510, 2.000000, -1.857690, -0.562464, -0.695442, 0.447208,
+-1.022346, 6.945759, 19.711123, 1.000000, -1.857690, -0.575450, 0.685898, -0.445422,
+-1.032151, 5.677700, 17.631544, 1.000000, -1.776346, -0.577835, 0.723604, -0.377496,
+-1.366396, 5.044981, 17.903212, 1.500000, -1.776346, -0.999757, -0.019426, 0.010462,
+-1.366396, 5.044981, 17.903212, 1.500000, -1.776346, -0.999757, -0.019426, 0.010462,
+-1.032151, 4.412262, 18.174877, 2.000000, -1.776346, -0.555665, -0.740194, 0.378615,
+-1.022346, 5.711351, 20.357510, 2.000000, -1.857690, -0.562464, -0.695442, 0.447208,
+-1.022346, 5.711351, 20.357510, 2.000000, -1.857690, -0.562464, -0.695442, 0.447208,
+-1.007639, 6.953747, 22.156216, 2.000000, -1.939034, -0.571627, -0.672843, 0.469600,
+-1.341885, 7.556932, 21.789433, 1.500000, -1.939034, -0.999989, 0.000304, 0.004665,
+-1.341885, 7.556932, 21.789433, 1.500000, -1.939034, -0.999989, 0.000304, 0.004665,
+-1.007639, 8.160118, 21.422651, 1.000000, -1.939034, -0.574068, 0.669723, -0.471080,
+-1.022346, 6.945759, 19.711123, 1.000000, -1.857690, -0.575450, 0.685898, -0.445422,
+-1.002737, 8.987209, 23.827108, 1.833333, -1.749232, -0.690086, 0.408969, 0.597098,
+-0.742768, 8.411285, 23.925793, 1.000000, -1.776346, -0.485429, -0.281111, 0.827850,
+0.000000, 8.401409, 24.234768, 1.000000, -1.857690, -0.000001, -0.291501, 0.956571,
+0.000000, 8.401409, 24.234768, 1.000000, -1.857690, -0.000001, -0.291501, 0.956571,
+0.742768, 8.411285, 23.925795, 1.000000, -1.939034, 0.485428, -0.281111, 0.827851,
+1.002737, 8.987209, 23.827108, 0.500000, -1.939034, 0.690085, 0.408969, 0.597099,
+1.002737, 8.987209, 23.827108, 0.500000, -1.939034, 0.690085, 0.408969, 0.597099,
+0.742768, 9.282909, 23.329664, 0.000000, -1.939034, 0.487250, 0.872639, 0.032983,
+0.000000, 9.573013, 23.419453, 1.333333, -1.830575, -0.000000, 0.997856, 0.065453,
+0.000000, 9.573013, 23.419453, 1.333333, -1.830575, -0.000000, 0.997856, 0.065453,
+-0.742768, 9.282909, 23.329664, 2.666667, -1.722117, -0.487251, 0.872639, 0.032983,
+-1.002737, 8.987209, 23.827108, 1.833333, -1.749232, -0.690086, 0.408969, 0.597098,
+0.983128, 6.945759, 19.711123, 1.500000, -2.000000, 0.574803, 0.682785, -0.451006,
+0.973323, 5.677700, 17.631544, 2.000000, -2.000000, 0.576561, 0.724323, -0.378066,
+-0.029414, 5.888605, 17.540989, 2.500000, -2.000000, -0.000556, 0.885983, -0.463718,
+-0.029414, 5.888605, 17.540989, 2.500000, -2.000000, -0.000556, 0.885983, -0.463718,
+-1.032151, 5.677700, 17.631544, 3.000000, -2.000000, -0.577835, 0.723604, -0.377496,
+-1.022346, 6.945759, 19.711123, 3.500000, -2.000000, -0.575450, 0.685898, -0.445422,
+-1.022346, 6.945759, 19.711123, 3.500000, -2.000000, -0.575450, 0.685898, -0.445422,
+-1.007639, 8.160118, 21.422651, 4.000000, -2.000000, -0.574068, 0.669723, -0.471080,
+-0.004902, 8.361179, 21.300390, 2.500000, -2.000000, 0.000389, 0.815229, -0.579139,
+-0.004902, 8.361179, 21.300390, 2.500000, -2.000000, 0.000389, 0.815229, -0.579139,
+0.997834, 8.160118, 21.422651, 1.000000, -2.000000, 0.574744, 0.665807, -0.475784,
+0.983128, 6.945759, 19.711123, 1.500000, -2.000000, 0.574803, 0.682785, -0.451006,
+-1.005175, 11.029587, -4.132468, 3.000000, -1.857690, -0.578521, -0.809497, -0.100142,
+-1.006394, 11.114811, -5.517140, 3.000000, -1.776346, -0.583093, -0.812392, -0.004755,
+-0.003657, 10.880220, -5.483850, 2.833333, -1.749232, -0.000127, -0.999975, -0.007088,
+-0.003657, 10.880220, -5.483850, 2.833333, -1.749232, -0.000127, -0.999975, -0.007088,
+0.999079, 11.114811, -5.517140, 2.666667, -1.722117, 0.582792, -0.812607, -0.004817,
+1.000299, 11.029585, -4.132468, 3.333333, -1.830575, 0.578319, -0.809495, -0.101318,
+1.000299, 11.029585, -4.132468, 3.333333, -1.830575, 0.578319, -0.809495, -0.101318,
+1.002127, 10.729588, -2.409474, 4.000000, -1.939034, 0.568931, -0.804350, -0.171283,
+-0.000610, 10.494156, -2.383091, 3.500000, -1.939034, 0.000040, -0.977947, -0.208854,
+-0.000610, 10.494156, -2.383091, 3.500000, -1.939034, 0.000040, -0.977947, -0.208854,
+-1.003346, 10.729588, -2.409474, 3.000000, -1.939034, -0.568927, -0.804482, -0.170679,
+-1.005175, 11.029587, -4.132468, 3.000000, -1.857690, -0.578521, -0.809497, -0.100142,
+-1.005175, 12.441681, -4.309345, 1.000000, -0.253818, -0.554831, 0.825951, 0.099839,
+-1.006394, 12.522362, -5.716876, 1.000000, -0.170915, -0.566040, 0.824377, 0.001632,
+-1.340640, 11.818584, -5.617008, 1.500000, -0.170915, -0.999853, 0.017074, 0.001872,
+-1.340640, 11.818584, -5.617008, 1.500000, -0.170915, -0.999853, 0.017074, 0.001872,
+-1.006394, 11.114811, -5.517140, 2.000000, -0.170915, -0.583093, -0.812392, -0.004755,
+-1.005175, 11.029587, -4.132468, 2.000000, -0.253818, -0.578521, -0.809497, -0.100142,
+-1.005175, 11.029587, -4.132468, 2.000000, -0.253818, -0.578521, -0.809497, -0.100142,
+-1.003346, 10.729588, -2.409474, 2.000000, -0.336720, -0.568927, -0.804482, -0.170679,
+-1.337592, 11.435898, -2.488622, 1.500000, -0.336720, -0.999671, 0.024155, 0.008634,
+-1.337592, 11.435898, -2.488622, 1.500000, -0.336720, -0.999671, 0.024155, 0.008634,
+-1.003346, 12.142200, -2.567771, 1.000000, -0.336720, -0.545383, 0.819886, 0.174196,
+-1.005175, 12.441681, -4.309345, 1.000000, -0.253818, -0.554831, 0.825951, 0.099839,
+0.000000, 25.158775, 0.885566, 0.666667, -0.891999, 0.000000, 0.098978, -0.995090,
+0.742768, 25.130249, 1.141007, 1.333333, -1.447277, 0.424007, 0.088516, -0.901323,
+1.002737, 24.600067, 1.327282, 1.166667, -0.809096, 0.595697, -0.491752, -0.635079,
+1.002737, 24.600067, 1.327282, 1.166667, -0.809096, 0.595697, -0.491752, -0.635079,
+0.742768, 24.296909, 1.783397, 1.000000, -0.170915, 0.428917, -0.894621, -0.125234,
+0.000000, 24.041351, 1.768998, 1.000000, -0.253818, 0.000000, -0.991299, -0.131630,
+0.000000, 24.041351, 1.768998, 1.000000, -0.253818, 0.000000, -0.991299, -0.131630,
+-0.742768, 24.296909, 1.783397, 1.000000, -0.336720, -0.428917, -0.894621, -0.125234,
+-1.002737, 24.600067, 1.327282, 0.500000, -0.336720, -0.595697, -0.491752, -0.635079,
+-1.002737, 24.600067, 1.327282, 0.500000, -0.336720, -0.595697, -0.491752, -0.635079,
+-0.742768, 25.130249, 1.141007, 0.000000, -0.336720, -0.424007, 0.088516, -0.901323,
+0.000000, 25.158775, 0.885566, 0.666667, -0.891999, 0.000000, 0.098978, -0.995090,
+1.000299, 12.441681, -4.309345, 1.500000, -4.000000, 0.554885, 0.826037, 0.098819,
+0.999079, 12.522362, -5.716876, 2.000000, -4.000000, 0.565733, 0.824587, 0.001687,
+-0.003657, 12.756954, -5.750165, 2.500000, -4.000000, -0.000126, 1.000000, 0.000870,
+-0.003657, 12.756954, -5.750165, 2.500000, -4.000000, -0.000126, 1.000000, 0.000870,
+-1.006394, 12.522362, -5.716876, 3.000000, -4.000000, -0.566040, 0.824377, 0.001632,
+-1.005175, 12.441681, -4.309345, 3.500000, -4.000000, -0.554831, 0.825951, 0.099839,
+-1.005175, 12.441681, -4.309345, 3.500000, -4.000000, -0.554831, 0.825951, 0.099839,
+-1.003346, 12.142200, -2.567771, 4.000000, -4.000000, -0.545383, 0.819886, 0.174196,
+-0.000610, 12.377636, -2.594154, 2.500000, -4.000000, 0.000041, 0.978486, 0.206311,
+-0.000610, 12.377636, -2.594154, 2.500000, -4.000000, 0.000041, 0.978486, 0.206311,
+1.002127, 12.142200, -2.567771, 1.000000, -4.000000, 0.545588, 0.819894, 0.173516,
+1.000299, 12.441681, -4.309345, 1.500000, -4.000000, 0.554885, 0.826037, 0.098819,
+1.000299, 11.029585, -4.132468, 4.000000, -3.848496, 0.578319, -0.809495, -0.101318,
+0.999079, 11.114811, -5.517140, 4.000000, -3.761107, 0.582792, -0.812607, -0.004817,
+1.333325, 11.818588, -5.617008, 4.000000, -3.594440, 0.999852, 0.017082, 0.001868,
+1.333325, 11.818588, -5.617008, 4.000000, -3.594440, 0.999852, 0.017082, 0.001868,
+0.999079, 12.522362, -5.716876, 4.000000, -3.427773, 0.565733, 0.824587, 0.001687,
+1.000299, 12.441681, -4.309345, 4.000000, -3.234054, 0.554885, 0.826037, 0.098819,
+1.000299, 12.441681, -4.309345, 4.000000, -3.234054, 0.554885, 0.826037, 0.098819,
+1.002127, 12.142200, -2.567771, 4.000000, -3.040334, 0.545588, 0.819894, 0.173516,
+1.336373, 11.435898, -2.488622, 4.000000, -3.488110, 0.999684, 0.024018, 0.007427,
+1.336373, 11.435898, -2.488622, 4.000000, -3.488110, 0.999684, 0.024018, 0.007427,
+1.002127, 10.729588, -2.409474, 4.000000, -3.935886, 0.568931, -0.804350, -0.171283,
+1.000299, 11.029585, -4.132468, 4.000000, -3.848496, 0.578319, -0.809495, -0.101318,
+1.002737, -23.736286, -6.771559, 0.500000, 1.053028, 0.633041, -0.276748, -0.722959,
+0.742768, -24.152987, -6.401496, 1.000000, 1.053028, 0.455754, -0.834430, -0.309862,
+0.000000, -24.406044, -6.530420, 1.500000, 1.053028, 0.000000, -0.933376, -0.358900,
+0.000000, -24.406044, -6.530420, 1.500000, 1.053028, 0.000000, -0.933376, -0.358900,
+-0.742768, -24.152987, -6.401496, 2.000000, 1.053028, -0.455754, -0.834431, -0.309862,
+-1.002737, -23.736286, -6.771559, 4.000000, -0.306819, -0.633041, -0.276747, -0.722959,
+-1.002737, -23.736286, -6.771559, 4.000000, -0.306819, -0.633041, -0.276747, -0.722959,
+-0.742768, -23.169422, -6.772669, 6.000000, -1.666667, -0.444774, 0.383424, -0.809421,
+0.000000, -23.066525, -7.012697, 3.000000, -0.306819, -0.000000, 0.424976, -0.905205,
+0.000000, -23.066525, -7.012697, 3.000000, -0.306819, -0.000000, 0.424976, -0.905205,
+0.742768, -23.169422, -6.772669, 0.000000, 1.053028, 0.444774, 0.383425, -0.809421,
+1.002737, -23.736286, -6.771559, 0.500000, 1.053028, 0.633041, -0.276748, -0.722959,
+1.336982, -2.618040, 4.463405, 4.000000, -0.333333, 0.999977, -0.006223, -0.002555,
+1.002737, -3.239137, 4.110385, 5.000000, -1.666667, 0.573276, -0.760494, -0.304965,
+1.002737, -2.684134, 2.725971, 2.500000, -0.689796, 0.555812, -0.771611, -0.309336,
+1.002737, -1.445931, 3.440848, 2.500000, -0.500000, 0.596303, 0.745197, 0.298504,
+1.002737, -1.996943, 4.816424, 3.000000, 1.000000, 0.580237, 0.756078, 0.302774,
+1.336982, -2.618040, 4.463405, 4.000000, -0.333333, 0.999977, -0.006223, -0.002555,
+-1.336982, -0.581338, -32.314465, 0.500000, 0.972854, 0.000000, -0.028514, -0.999593,
+-0.000000, -0.581338, -32.314465, 1.968750, 0.959660, 0.000001, -0.028515, -0.999593,
+-1.002737, -1.292564, -32.294178, 1.000000, 0.972854, 0.000000, -0.028512, -0.999593,
+-1.336982, 4.212124, -29.503693, 0.500000, 0.966243, 0.000000, -0.038077, -0.999275,
+-0.000000, 4.212124, -29.503689, 2.000000, 0.966243, -0.000000, -0.038077, -0.999275,
+-1.002737, 3.502487, -29.476650, 1.000000, 0.966243, 0.000000, -0.038077, -0.999275,
+-1.336982, -5.594234, -28.484890, 0.500000, 1.119843, -0.000004, -0.026495, -0.999649,
+0.000000, -5.594234, -28.484894, 1.500000, 1.053028, -0.000000, -0.026493, -0.999649,
+-1.002737, -6.305892, -28.466030, 0.500000, 1.053028, -0.000002, -0.026494, -0.999649,
+-1.336982, -2.065033, 3.083410, 3.500000, -1.833333, 0.000000, 0.500000, -0.866025,
+0.000000, -2.065034, 3.083410, 3.000000, -1.083333, 0.000000, 0.500000, -0.866025,
+-1.002737, -2.684134, 2.725971, 3.500000, -1.666667, 0.000000, 0.500000, -0.866025,
+1.002737, 0.129889, -32.334755, 2.937500, 0.946466, 0.000002, -0.028517, -0.999593,
+1.336982, -0.581338, -32.314465, 2.500000, 0.972854, 0.000000, -0.028517, -0.999593,
+-0.000000, -0.581338, -32.314465, 1.968750, 0.959660, 0.000001, -0.028515, -0.999593,
+-0.000000, -0.581338, -32.314465, 1.968750, 0.959660, 0.000001, -0.028515, -0.999593,
+1.336982, -0.581338, -32.314465, 2.500000, 0.972854, 0.000000, -0.028517, -0.999593,
+1.002737, -1.292564, -32.294174, 2.000000, 0.972854, 0.000002, -0.028516, -0.999593,
+-0.000000, -0.581338, -32.314465, 1.968750, 0.959660, 0.000001, -0.028515, -0.999593,
+1.002737, -1.292564, -32.294174, 2.000000, 0.972854, 0.000002, -0.028516, -0.999593,
+0.000000, -1.529640, -32.287415, 1.500000, 0.972854, 0.000002, -0.028513, -0.999593,
+-0.000000, -0.581338, -32.314465, 1.968750, 0.959660, 0.000001, -0.028515, -0.999593,
+0.000000, -1.529640, -32.287415, 1.500000, 0.972854, 0.000002, -0.028513, -0.999593,
+-1.002737, -1.292564, -32.294178, 1.000000, 0.972854, 0.000000, -0.028512, -0.999593,
+-1.002737, 0.129889, -32.334755, 3.500000, 0.761751, -0.000002, -0.028517, -0.999593,
+-0.000000, -0.581338, -32.314465, 1.968750, 0.959660, 0.000001, -0.028515, -0.999593,
+-1.336982, -0.581338, -32.314465, 0.500000, 0.972854, 0.000000, -0.028514, -0.999593,
+0.000000, 0.366964, -32.341518, 3.250000, 0.867302, 0.000000, -0.028517, -0.999593,
+-0.000000, -0.581338, -32.314465, 1.968750, 0.959660, 0.000001, -0.028515, -0.999593,
+-1.002737, 0.129889, -32.334755, 3.500000, 0.761751, -0.000002, -0.028517, -0.999593,
+1.002737, 0.129889, -32.334755, 2.937500, 0.946466, 0.000002, -0.028517, -0.999593,
+-0.000000, -0.581338, -32.314465, 1.968750, 0.959660, 0.000001, -0.028515, -0.999593,
+0.000000, 0.366964, -32.341518, 3.250000, 0.867302, 0.000000, -0.028517, -0.999593,
+1.002737, 4.921762, -29.530731, 3.000000, 0.966243, -0.000000, -0.038080, -0.999275,
+1.336982, 4.212124, -29.503689, 2.500000, 0.966243, 0.000000, -0.038077, -0.999275,
+-0.000000, 4.212124, -29.503689, 2.000000, 0.966243, -0.000000, -0.038077, -0.999275,
+-0.000000, 4.212124, -29.503689, 2.000000, 0.966243, -0.000000, -0.038077, -0.999275,
+1.336982, 4.212124, -29.503689, 2.500000, 0.966243, 0.000000, -0.038077, -0.999275,
+1.002737, 3.502487, -29.476650, 2.000000, 0.966243, 0.000000, -0.038075, -0.999275,
+-0.000000, 4.212124, -29.503689, 2.000000, 0.966243, -0.000000, -0.038077, -0.999275,
+1.002737, 3.502487, -29.476650, 2.000000, 0.966243, 0.000000, -0.038075, -0.999275,
+0.000000, 3.265942, -29.467636, 1.500000, 0.966243, 0.000000, -0.038076, -0.999275,
+-0.000000, 4.212124, -29.503689, 2.000000, 0.966243, -0.000000, -0.038077, -0.999275,
+0.000000, 3.265942, -29.467636, 1.500000, 0.966243, 0.000000, -0.038076, -0.999275,
+-1.002737, 3.502487, -29.476650, 1.000000, 0.966243, 0.000000, -0.038077, -0.999275,
+-1.002737, 4.921762, -29.530731, 4.000000, 0.966243, 0.000000, -0.038077, -0.999275,
+-0.000000, 4.212124, -29.503689, 2.000000, 0.966243, -0.000000, -0.038077, -0.999275,
+-1.336982, 4.212124, -29.503693, 0.500000, 0.966243, 0.000000, -0.038077, -0.999275,
+0.000000, 5.158308, -29.539745, 3.500000, 0.966243, -0.000000, -0.038080, -0.999275,
+-0.000000, 4.212124, -29.503689, 2.000000, 0.966243, -0.000000, -0.038077, -0.999275,
+-1.002737, 4.921762, -29.530731, 4.000000, 0.966243, 0.000000, -0.038077, -0.999275,
+1.002737, 4.921762, -29.530731, 3.000000, 0.966243, -0.000000, -0.038080, -0.999275,
+-0.000000, 4.212124, -29.503689, 2.000000, 0.966243, -0.000000, -0.038077, -0.999275,
+0.000000, 5.158308, -29.539745, 3.500000, 0.966243, -0.000000, -0.038080, -0.999275,
+1.002737, -4.882575, -28.503754, 2.500000, 1.053028, -0.000002, -0.026493, -0.999649,
+1.336982, -5.594234, -28.484890, 2.500000, 1.119843, 0.000002, -0.026495, -0.999649,
+0.000000, -5.594234, -28.484894, 1.500000, 1.053028, -0.000000, -0.026493, -0.999649,
+0.000000, -5.594234, -28.484894, 1.500000, 1.053028, -0.000000, -0.026493, -0.999649,
+1.336982, -5.594234, -28.484890, 2.500000, 1.119843, 0.000002, -0.026495, -0.999649,
+1.002737, -6.305892, -28.466030, 1.500000, 1.053028, 0.000002, -0.026494, -0.999649,
+0.000000, -5.594234, -28.484894, 1.500000, 1.053028, -0.000000, -0.026493, -0.999649,
+1.002737, -6.305892, -28.466030, 1.500000, 1.053028, 0.000002, -0.026494, -0.999649,
+0.000000, -6.543112, -28.459743, 1.500000, 1.119843, 0.000000, -0.026496, -0.999649,
+0.000000, -5.594234, -28.484894, 1.500000, 1.053028, -0.000000, -0.026493, -0.999649,
+0.000000, -6.543112, -28.459743, 1.500000, 1.119843, 0.000000, -0.026496, -0.999649,
+-1.002737, -6.305892, -28.466030, 0.500000, 1.053028, -0.000002, -0.026494, -0.999649,
+-1.002737, -4.882575, -28.503754, 3.500000, 1.053028, -0.000001, -0.026493, -0.999649,
+0.000000, -5.594234, -28.484894, 1.500000, 1.053028, -0.000000, -0.026493, -0.999649,
+-1.336982, -5.594234, -28.484890, 0.500000, 1.119843, -0.000004, -0.026495, -0.999649,
+0.000000, -4.645356, -28.510036, 3.500000, 1.119843, 0.000000, -0.026488, -0.999649,
+0.000000, -5.594234, -28.484894, 1.500000, 1.053028, -0.000000, -0.026493, -0.999649,
+-1.002737, -4.882575, -28.503754, 3.500000, 1.053028, -0.000001, -0.026493, -0.999649,
+1.002737, -4.882575, -28.503754, 2.500000, 1.053028, -0.000002, -0.026493, -0.999649,
+0.000000, -5.594234, -28.484894, 1.500000, 1.053028, -0.000000, -0.026493, -0.999649,
+0.000000, -4.645356, -28.510036, 3.500000, 1.119843, 0.000000, -0.026488, -0.999649,
+1.002737, -1.445931, 3.440848, 2.500000, -0.500000, -0.000000, 0.500000, -0.866025,
+1.336982, -2.065033, 3.083410, 2.500000, -0.594898, 0.000000, 0.500000, -0.866025,
+0.000000, -2.065034, 3.083410, 3.000000, -1.083333, 0.000000, 0.500000, -0.866025,
+0.000000, -2.065034, 3.083410, 3.000000, -1.083333, 0.000000, 0.500000, -0.866025,
+1.336982, -2.065033, 3.083410, 2.500000, -0.594898, 0.000000, 0.500000, -0.866025,
+1.002737, -2.684134, 2.725971, 4.500000, -1.666667, -0.000000, 0.500000, -0.866025,
+0.000000, -2.065034, 3.083410, 3.000000, -1.083333, 0.000000, 0.500000, -0.866025,
+1.002737, -2.684134, 2.725971, 4.500000, -1.666667, -0.000000, 0.500000, -0.866025,
+0.000000, -2.890502, 2.606825, 4.500000, -1.833333, 0.000000, 0.500000, -0.866026,
+0.000000, -2.065034, 3.083410, 3.000000, -1.083333, 0.000000, 0.500000, -0.866025,
+0.000000, -2.890502, 2.606825, 4.500000, -1.833333, 0.000000, 0.500000, -0.866026,
+-1.002737, -2.684134, 2.725971, 3.500000, -1.666667, 0.000000, 0.500000, -0.866025,
+-1.002737, -1.445931, 3.440848, 2.500000, -1.666667, 0.000000, 0.500000, -0.866025,
+0.000000, -2.065034, 3.083410, 3.000000, -1.083333, 0.000000, 0.500000, -0.866025,
+-1.336982, -2.065033, 3.083410, 3.500000, -1.833333, 0.000000, 0.500000, -0.866025,
+0.000000, -1.239565, 3.559994, 2.500000, -1.833333, 0.000000, 0.500000, -0.866025,
+0.000000, -2.065034, 3.083410, 3.000000, -1.083333, 0.000000, 0.500000, -0.866025,
+-1.002737, -1.445931, 3.440848, 2.500000, -1.666667, 0.000000, 0.500000, -0.866025,
+1.002737, -1.445931, 3.440848, 2.500000, -0.500000, -0.000000, 0.500000, -0.866025,
+0.000000, -2.065034, 3.083410, 3.000000, -1.083333, 0.000000, 0.500000, -0.866025,
+0.000000, -1.239565, 3.559994, 2.500000, -1.833333, 0.000000, 0.500000, -0.866025,
+4.193409, -2.445326, 32.893612, 3.000000, -0.594415, 0.682263, 0.725032, 0.094055,
+0.250684, -6.277495, 43.932335, 1.687500, -0.646499, 0.009105, 0.001936, 0.999957,
+5.620958, -6.307936, 32.893612, 2.375000, -0.573582, 0.996241, -0.000983, 0.086619,
+0.250684, -6.277495, 43.932335, 1.687500, -0.646499, 0.009105, 0.001936, 0.999957,
+4.193409, -10.256766, 32.893612, 1.972222, -0.557378, 0.680284, -0.725440, 0.104643,
+5.620958, -6.307936, 32.893612, 2.375000, -0.573582, 0.996241, -0.000983, 0.086619,
+0.250684, -6.277495, 43.932335, 1.687500, -0.646499, 0.009105, 0.001936, 0.999957,
+0.000000, -11.548096, 32.893612, 1.500000, -0.573582, -0.004203, -0.998166, 0.060395,
+4.193409, -10.256766, 32.893612, 1.972222, -0.557378, 0.680284, -0.725440, 0.104643,
+0.250684, -6.277495, 43.932335, 1.687500, -0.646499, 0.009105, 0.001936, 0.999957,
+-4.193409, -10.256766, 32.893612, 1.027778, -0.557378, -0.685012, -0.716396, 0.132421,
+0.000000, -11.548096, 32.893612, 1.500000, -0.573582, -0.004203, -0.998166, 0.060395,
+-5.620958, -6.307936, 32.893612, 0.625000, -0.573582, -0.991757, -0.001005, 0.128133,
+-4.193409, -10.256766, 32.893612, 1.027778, -0.557378, -0.685012, -0.716396, 0.132421,
+0.250684, -6.277495, 43.932335, 1.687500, -0.646499, 0.009105, 0.001936, 0.999957,
+0.250684, -6.277495, 43.932335, 1.687500, -0.646499, 0.009105, 0.001936, 0.999957,
+-4.193409, -2.445326, 32.893612, 0.000000, -0.594415, -0.686924, 0.716419, 0.121978,
+-5.620958, -6.307936, 32.893612, 0.625000, -0.573582, -0.991757, -0.001005, 0.128133,
+0.250684, -6.277495, 43.932335, 1.687500, -0.646499, 0.009105, 0.001936, 0.999957,
+0.000000, -1.067776, 32.893612, 3.500000, -0.594415, -0.004492, 0.998437, 0.055707,
+-4.193409, -2.445326, 32.893612, 4.000000, -0.594415, -0.686924, 0.716419, 0.121978,
+0.250684, -6.277495, 43.932335, 1.687500, -0.646499, 0.009105, 0.001936, 0.999957,
+4.193409, -2.445326, 32.893612, 3.000000, -0.594415, 0.682263, 0.725032, 0.094055,
+0.000000, -1.067776, 32.893612, 3.500000, -0.594415, -0.004492, 0.998437, 0.055707,
+};
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderInterface.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderInterface.cpp
new file mode 100644
index 0000000..61586d8
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderInterface.cpp
@@ -0,0 +1,351 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "RenderInterface.h"
+#include "MeshShaderParam.h"
+#include "RenderPlugin.h"
+
+namespace RenderInterface
+{
+
+////////////////////////////////////////////////////////////////////////////////////////////
+bool InitDevice(int deviceID)
+{
+ if (!RenderPlugin::Instance()->InitDevice(deviceID))
+ {
+ MessageBox( 0, L"Could not create device.", L"Error", MB_ICONEXCLAMATION );
+ return false;
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool GetDeviceInfoString(wchar_t *str)
+{
+ return RenderPlugin::Instance()->GetDeviceInfoString(str);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool Initialize()
+{
+ return RenderPlugin::Instance()->Initialize();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void Shutdown()
+{
+ RenderPlugin::Instance()->Shutdown();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// gpu buffer management
+///////////////////////////////////////////////////////////////////////////////
+GPUBufferResource* CreateVertexBuffer(
+ unsigned int ByteWidth, void* pSysMem)
+{
+ return RenderPlugin::Instance()->CreateVertexBuffer(ByteWidth, pSysMem);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void CopyToDevice(
+ GPUBufferResource *pDevicePtr, void* pSysMem, unsigned int ByteWidth)
+{
+ RenderPlugin::Instance()->CopyToDevice(pDevicePtr, pSysMem, ByteWidth);
+}
+
+///////////////////////////////////////////////////////////////////
+// texture resource mangement
+///////////////////////////////////////////////////////////////////
+GPUShaderResource* CreateTextureResource(const char* filepath)
+{
+ return RenderPlugin::Instance()->CreateTextureSRV(filepath);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void RenderShadowMap(GPUShaderResource* pShadowSRV, float znear, float zfar)
+{
+ // update constant buffer
+ ShadowVizParam shaderParam;
+ {
+ shaderParam.m_zFar = zfar;
+ shaderParam.m_zNear = znear;
+ }
+ CopyShaderParam(SHADER_TYPE_VISUALIZE_SHADOW, &shaderParam, sizeof(ShadowVizParam), 0);
+
+ RenderPlugin::Instance()->BindPixelShaderResources(0, 1, &pShadowSRV);
+
+ // render states
+ RenderPlugin::Instance()->ApplySampler(0, SAMPLER_TYPE_POINTCLAMP);
+
+ RenderPlugin::Instance()->BindShaderResources(SHADER_TYPE_VISUALIZE_SHADOW, 1, &pShadowSRV);
+
+
+ RenderPlugin::Instance()->ApplyRasterizerState(RASTERIZER_STATE_FILL_CULL_NONE);
+ RenderPlugin::Instance()->ApplyDepthStencilState(DEPTH_STENCIL_DEPTH_NONE);
+
+ // set IA vars
+ RenderPlugin::Instance()->ClearInputLayout();
+
+ RenderPlugin::Instance()->SetPrimitiveTopologyTriangleStrip();
+
+ // set shader and tex resource
+ ApplyShader(SHADER_TYPE_VISUALIZE_SHADOW);
+
+ // draw quad
+ RenderPlugin::Instance()->Draw(3, 0);
+
+ // cleanup shader and its resource
+ RenderPlugin::Instance()->ClearPixelShaderResources(0, 1);
+ RenderPlugin::Instance()->DisableShader(SHADER_TYPE_VISUALIZE_SHADOW);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// render with full color shader
+void RenderScreenQuad(
+ GPUShaderResource* pTextureSRV
+ )
+{
+ RenderPlugin::Instance()->ApplyRasterizerState(RASTERIZER_STATE_FILL_CULL_NONE);
+ RenderPlugin::Instance()->ApplyDepthStencilState(DEPTH_STENCIL_DEPTH_NONE);
+
+ RenderPlugin::Instance()->ClearInputLayout();
+
+ RenderPlugin::Instance()->SetPrimitiveTopologyTriangleStrip();
+
+ if(pTextureSRV)
+ {
+ RenderPlugin::Instance()->BindShaderResources(SHADER_TYPE_SCREEN_QUAD, 1, &pTextureSRV);
+
+ ApplyShader(SHADER_TYPE_SCREEN_QUAD);
+
+ RenderPlugin::Instance()->BindPixelShaderResources(0, 1, &pTextureSRV);
+ RenderPlugin::Instance()->ApplySampler(0, SAMPLER_TYPE_POINTCLAMP);
+
+ RenderPlugin::Instance()->Draw(3,0);
+
+ RenderPlugin::Instance()->ClearPixelShaderResources(0, 1);
+ RenderPlugin::Instance()->DisableShader(SHADER_TYPE_SCREEN_QUAD);
+ }
+ else
+ {
+ ApplyShader(SHADER_TYPE_SCREEN_QUAD_COLOR);
+
+ RenderPlugin::Instance()->Draw(3,0);
+
+ RenderPlugin::Instance()->DisableShader(SHADER_TYPE_SCREEN_QUAD_COLOR);
+ }
+}
+
+
+void SubmitGpuWork()
+{
+ RenderPlugin::Instance()->SubmitGpuWork();
+}
+
+void WaitForGpu()
+{
+ RenderPlugin::Instance()->WaitForGpu();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// draw calls
+///////////////////////////////////////////////////////////////////////////////
+void DrawLineList(GPUBufferResource* pDevicePtr, unsigned int nVerts, unsigned int stride)
+{
+ RenderPlugin::Instance()->SetVertexBuffer(pDevicePtr, stride);
+ RenderPlugin::Instance()->SetPrimitiveTopologyLineList();
+ RenderPlugin::Instance()->Draw(nVerts, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// render states management
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyDepthStencilState(DEPTH_STENCIL_STATE state)
+{
+ RenderPlugin::Instance()->ApplyDepthStencilState(state);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyRasterizerState(RASTERIZER_STATE state)
+{
+ RenderPlugin::Instance()->ApplyRasterizerState(state);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplySampler(int slot, SAMPLER_TYPE st)
+{
+ RenderPlugin::Instance()->ApplySampler(slot, st);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ApplyBlendState(BLEND_STATE st)
+{
+ RenderPlugin::Instance()->ApplyBlendState(st);
+}
+
+void ApplyForShadow(int ForShadow)
+{
+ RenderPlugin::Instance()->ApplyForShadow(ForShadow);
+}
+
+void SwitchToDX11()
+{
+ RenderPlugin::Instance()->SwitchToDX11();
+}
+
+void FlushDX11()
+{
+ RenderPlugin::Instance()->FlushDX11();
+}
+
+void FlushDX12()
+{
+ RenderPlugin::Instance()->FlushDX12();
+}
+
+void ApplyPrimitiveTopologyLine()
+{
+ RenderPlugin::Instance()->ApplyPrimitiveTopologyLine();
+}
+
+void ApplyPrimitiveTopologyTriangle()
+{
+ RenderPlugin::Instance()->ApplyPrimitiveTopologyTriangle();
+}
+
+///////////////////////////////////////////////////////////////////
+// shader magement
+///////////////////////////////////////////////////////////////////
+void ApplyShader(SHADER_TYPE st)
+{
+ RenderPlugin::Instance()->ApplyShader(st);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void CopyShaderParam(SHADER_TYPE st, void* pSysMem, unsigned int bytes, unsigned int slot)
+{
+ RenderPlugin::Instance()->CopyShaderParam(st, pSysMem, bytes, slot);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Viewport magement
+/////////////////////////////////////////////////////////////////////////////////////////
+void GetViewport(Viewport& vp)
+{
+ RenderPlugin::Instance()->GetViewport(vp);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SetViewport(const Viewport& vp)
+{
+ RenderPlugin::Instance()->SetViewport(vp);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Render window interafce
+/////////////////////////////////////////////////////////////////////////////////////////
+bool CreateRenderWindow(HWND hWnd, int nSamples)
+{
+ return RenderPlugin::Instance()->CreateRenderWindow(hWnd, nSamples);
+}
+
+bool ResizeRenderWindow(int w, int h)
+{
+ return RenderPlugin::Instance()->ResizeRenderWindow(w,h);
+}
+
+void PresentRenderWindow()
+{
+ return RenderPlugin::Instance()->PresentRenderWindow();
+}
+
+void ClearRenderWindow(float r, float g, float b)
+{
+ return RenderPlugin::Instance()->ClearRenderWindow(r,g,b);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Texture resource management
+///////////////////////////////////////////////////////////////////////////////
+static GPUShaderResource* g_backgroundTextureSRV = 0;
+
+bool LoadBackgroundTexture(const char* filePath)
+{
+ ClearBackgroundTexture();
+
+ RenderPlugin::Instance()->PreRender();
+ g_backgroundTextureSRV = RenderPlugin::Instance()->CreateTextureSRV(filePath);
+ RenderPlugin::Instance()->PostRender();
+
+ return (g_backgroundTextureSRV != 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void RenderBackgroundTexture()
+{
+ RenderScreenQuad(g_backgroundTextureSRV);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void ClearBackgroundTexture()
+{
+ SAFE_RELEASE(g_backgroundTextureSRV);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Text draw helper functions (using DXUT)
+/////////////////////////////////////////////////////////////////////////////////////////
+void TxtHelperBegin()
+{
+ RenderPlugin::Instance()->TxtHelperBegin();
+}
+
+void TxtHelperEnd()
+{
+ RenderPlugin::Instance()->TxtHelperEnd();
+}
+
+void TxtHelperSetInsertionPos(int x, int y)
+{
+ RenderPlugin::Instance()->TxtHelperSetInsertionPos(x,y);
+}
+
+void TxtHelperSetForegroundColor(float r, float g, float b, float a)
+{
+ RenderPlugin::Instance()->TxtHelperSetForegroundColor(r,g,b,a);
+}
+
+void TxtHelperDrawTextLine(wchar_t* str)
+{
+ RenderPlugin::Instance()->TxtHelperDrawTextLine(str);
+}
+
+} // end namespace \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderInterface.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderInterface.h
new file mode 100644
index 0000000..9bc4036
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderInterface.h
@@ -0,0 +1,175 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "windows.h"
+
+#include "RenderResources.h"
+
+// API agnostic interface for rendering
+namespace RenderInterface
+{
+ ///////////////////////////////////////////////////////////////////
+ enum RASTERIZER_STATE
+ {
+ RASTERIZER_STATE_FILL_CULL_NONE,
+ RASTERIZER_STATE_FILL_CULL_FRONT,
+ RASTERIZER_STATE_FILL_CULL_BACK,
+ RASTERIZER_STATE_WIRE,
+ RASTERIZER_STATE_END
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ enum DEPTH_STENCIL_STATE
+ {
+ DEPTH_STENCIL_DEPTH_TEST,
+ DEPTH_STENCIL_DEPTH_NONE,
+ DEPTH_STENCIL_STATE_END
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ enum SAMPLER_TYPE
+ {
+ SAMPLER_TYPE_LINEAR,
+ SAMPLER_TYPE_POINTCLAMP,
+ SAMPLER_TYPE_END,
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ enum BLEND_STATE
+ {
+ BLEND_STATE_ALPHA,
+ BLEND_STATE_NONE,
+ BLEND_STATE_END
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ enum SHADER_TYPE
+ {
+ SHADER_TYPE_MESH_RENDERING,
+ SHADER_TYPE_MESH_SHADOW,
+ SHADER_TYPE_SCREEN_QUAD,
+ SHADER_TYPE_SCREEN_QUAD_COLOR,
+ SHADER_TYPE_VISUALIZE_SHADOW,
+ SHADER_TYPE_SIMPLE_COLOR,
+#ifndef NV_ARTISTTOOLS
+ SHADER_TYPE_HAIR_SHADER_DEFAULT,
+ SHADER_TYPE_HAIR_SHADER_SHADOW,
+#endif // NV_ARTISTTOOLS
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ // global acess for render context and device to minimize D3D entry points
+ ///////////////////////////////////////////////////////////////////
+ CORELIB_EXPORT bool InitDevice(int deviceID);
+ CORELIB_EXPORT bool Initialize();
+ CORELIB_EXPORT void Shutdown();
+
+ CORELIB_EXPORT void SubmitGpuWork();
+ CORELIB_EXPORT void WaitForGpu();
+
+ ///////////////////////////////////////////////////////////////////
+ // render window management
+ ///////////////////////////////////////////////////////////////////
+ CORELIB_EXPORT bool CreateRenderWindow(HWND hWnd, int nSamples);
+ CORELIB_EXPORT bool ResizeRenderWindow(int w, int h);
+ CORELIB_EXPORT void PresentRenderWindow();
+ CORELIB_EXPORT void ClearRenderWindow(float r, float g, float b);
+
+ ///////////////////////////////////////////////////////////////////
+ // shader magement
+ ///////////////////////////////////////////////////////////////////
+ CORELIB_EXPORT void ApplyShader(SHADER_TYPE st);
+ CORELIB_EXPORT void CopyShaderParam(SHADER_TYPE st, void* pSysMem, unsigned int bytes, unsigned int slot = 0);
+
+ ///////////////////////////////////////////////////////////////////
+ // viewport management
+ ///////////////////////////////////////////////////////////////////
+ struct Viewport
+ {
+ float TopLeftX;
+ float TopLeftY;
+ float Width;
+ float Height;
+ float MinDepth;
+ float MaxDepth;
+ };
+
+ CORELIB_EXPORT void GetViewport(Viewport& vp);
+ CORELIB_EXPORT void SetViewport(const Viewport& vp);
+
+ ///////////////////////////////////////////////////////////////////
+ // gpu buffer management
+ ///////////////////////////////////////////////////////////////////
+ CORELIB_EXPORT GPUBufferResource* CreateVertexBuffer( unsigned int ByteWidth, void* pSysMem = 0);
+ CORELIB_EXPORT void CopyToDevice(GPUBufferResource *pDevicePtr, void* pSysMem, unsigned int ByteWidth);
+
+ ///////////////////////////////////////////////////////////////////
+ // texture resource mangement
+ ///////////////////////////////////////////////////////////////////
+ CORELIB_EXPORT GPUShaderResource* CreateTextureResource(const char* filePath);
+ CORELIB_EXPORT void RenderShadowMap(GPUShaderResource* pShadowSRV, float znear, float zfar);
+
+ ///////////////////////////////////////////////////////////////////
+ // render state management
+ ///////////////////////////////////////////////////////////////////
+ CORELIB_EXPORT void ApplyDepthStencilState(DEPTH_STENCIL_STATE state);
+ CORELIB_EXPORT void ApplyRasterizerState(RASTERIZER_STATE state);
+ CORELIB_EXPORT void ApplySampler(int slot, SAMPLER_TYPE st);
+ CORELIB_EXPORT void ApplyBlendState(BLEND_STATE st);
+
+ CORELIB_EXPORT void ApplyForShadow(int ForShadow);
+ CORELIB_EXPORT void SwitchToDX11();
+ CORELIB_EXPORT void FlushDX11();
+ CORELIB_EXPORT void FlushDX12();
+ CORELIB_EXPORT void ApplyPrimitiveTopologyLine();
+ CORELIB_EXPORT void ApplyPrimitiveTopologyTriangle();
+ ///////////////////////////////////////////////////////////////////
+ // draw calls
+ ///////////////////////////////////////////////////////////////////
+ void DrawLineList(GPUBufferResource* pVertexBuffer, unsigned int nVerts, unsigned int bytesize);
+
+ ///////////////////////////////////////////////////////////////////
+ // background textures
+ ///////////////////////////////////////////////////////////////////
+ bool LoadBackgroundTexture(const char* filePath);
+ void RenderBackgroundTexture();
+ void ClearBackgroundTexture();
+
+ ///////////////////////////////////////////////////////////////////
+ CORELIB_EXPORT bool GetDeviceInfoString(wchar_t *str);
+
+ ///////////////////////////////////////////////////////////////////
+ // text helpers
+ CORELIB_EXPORT void TxtHelperBegin();
+ CORELIB_EXPORT void TxtHelperEnd();
+ CORELIB_EXPORT void TxtHelperSetInsertionPos(int x, int y);
+ CORELIB_EXPORT void TxtHelperSetForegroundColor(float r, float g, float b, float a = 1.0f);
+ CORELIB_EXPORT void TxtHelperDrawTextLine(wchar_t* str);
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderPlugin.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderPlugin.cpp
new file mode 100644
index 0000000..3df8c85
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderPlugin.cpp
@@ -0,0 +1,86 @@
+#include "RenderPlugin.h"
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+RenderPlugin* g_Plugin = nullptr;
+
+RenderPlugin::RenderPlugin()
+{
+ m_RenderApi = "";
+}
+
+typedef RenderPlugin*(*Func)(void);
+
+bool RenderPlugin::Load(std::vector<std::string>& render_plugins)
+{
+ if (render_plugins.size() == 0)
+ {
+ return false;
+ }
+
+ std::vector<std::string>::iterator it;
+ std::string pluginDll = "";
+ HMODULE module = NULL;
+ Func CreateFunc = NULL;
+ bool loaded = false;
+ for (it = render_plugins.begin(); it != render_plugins.end(); it++)
+ {
+#ifdef NV_ARTISTTOOLS
+ pluginDll = "RenderPlugin";
+#else
+ pluginDll = "FurRender";
+#endif
+
+ pluginDll.append(*it);
+
+#ifdef _WIN64
+ pluginDll.append(".win64");
+#else
+ pluginDll.append(".win32");
+#endif
+
+#ifdef _DEBUG
+ pluginDll.append(".d");
+#else
+#endif
+
+ pluginDll.append(".dll");
+
+ module = LoadLibraryA(pluginDll.c_str());
+ if (NULL == module)
+ return false;
+
+ CreateFunc = (Func)GetProcAddress(module, "CreateRenderPlugin");
+ if (NULL == CreateFunc)
+ return false;
+
+ g_Plugin = CreateFunc();
+ if (NULL != g_Plugin)
+ {
+ loaded = true;
+ break;
+ }
+ }
+ return loaded;
+}
+
+RenderPlugin::~RenderPlugin()
+{
+}
+
+
+RenderPlugin* RenderPlugin::Instance()
+{
+ return g_Plugin;
+}
+
+void RenderPlugin::Destroy()
+{
+ if (nullptr == g_Plugin)
+ return;
+
+ delete g_Plugin;
+ g_Plugin = nullptr;
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderPlugin.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderPlugin.h
new file mode 100644
index 0000000..e755aea
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderPlugin.h
@@ -0,0 +1,124 @@
+#pragma once
+
+#include "RenderInterface.h"
+using namespace RenderInterface;
+
+class NVHairReadOnlyBuffer;
+class GPUProfiler;
+class ShadowMap;
+
+class IDXGIAdapter;
+class IUnknown;
+class IDXGIFactory1;
+class IDXGISwapChain;
+
+struct D3DHandles
+{
+public:
+ IDXGIAdapter* pAdapter;
+ IDXGIFactory1* pFactory;
+ IUnknown* pDevice;
+ IUnknown* pDeviceContext;
+
+ IDXGISwapChain* pDXGISwapChain;
+ IUnknown* pD3D11BackBuffer;
+ IUnknown* pD3D11RenderTargetView;
+ IUnknown* pD3D11DepthBuffer;
+ IUnknown* pD3D11DepthStencilView;
+};
+
+#ifdef CORERENDER_LIB
+# define CORERENDER_EXPORT Q_DECL_EXPORT
+#else
+# define CORERENDER_EXPORT Q_DECL_IMPORT
+#endif
+
+class CORELIB_EXPORT RenderPlugin
+{
+public:
+ static bool Load(std::vector<std::string>& render_plugins);
+ static RenderPlugin* Instance();
+ static void Destroy();
+
+ ~RenderPlugin();
+
+ // self
+ virtual std::string GetRenderApi() { return m_RenderApi; }
+
+ // interface
+ virtual bool InitDevice(int deviceID) = 0;
+ virtual bool Initialize() = 0;
+ virtual void Shutdown() = 0;
+ virtual void CopyToDevice(GPUBufferResource *pDevicePtr, void* pSysMem, unsigned int ByteWidth) = 0;
+ virtual void ApplyDepthStencilState(DEPTH_STENCIL_STATE state) = 0;
+ virtual void ApplyRasterizerState(RASTERIZER_STATE state) = 0;
+ virtual void ApplySampler(int slot, SAMPLER_TYPE st) = 0;
+ virtual void ApplyBlendState(BLEND_STATE st) = 0;
+ virtual void GetViewport(Viewport& vp) = 0;
+ virtual void SetViewport(const Viewport& vp) = 0;
+ virtual void BindVertexShaderResources(int startSlot, int numSRVs, GPUShaderResource** ppSRVs) = 0;
+ virtual void BindPixelShaderResources(int startSlot, int numSRVs, GPUShaderResource** ppSRVs) = 0;
+ virtual void ClearVertexShaderResources(int startSlot, int numSRVs) = 0;
+ virtual void ClearPixelShaderResources(int startSlot, int numSRVs) = 0;
+ virtual void ClearInputLayout() = 0;
+ virtual void SetVertexBuffer(GPUBufferResource* pBuffer, UINT stride, UINT offset = 0) = 0;
+ virtual void SetPrimitiveTopologyTriangleStrip() = 0;
+ virtual void SetPrimitiveTopologyTriangleList() = 0;
+ virtual void SetPrimitiveTopologyLineList() = 0;
+ virtual void Draw(unsigned int vertexCount, unsigned int startCount = 0) = 0;
+ virtual GPUBufferResource* CreateVertexBuffer(unsigned int ByteWidth, void* pSysMem = 0) = 0;
+ virtual GPUShaderResource* CreateShaderResource(unsigned int stride, unsigned int numElements, void* pSysMem, NVHairReadOnlyBuffer* pReadOnlyBuffer = NULL) = 0;
+
+ // interface dx12
+ virtual void ApplyForShadow(int ForShadow) = 0;
+ virtual void SwitchToDX11() = 0;
+ virtual void FlushDX11() = 0;
+ virtual void FlushDX12() = 0;
+ virtual void ApplyPrimitiveTopologyLine() = 0;
+ virtual void ApplyPrimitiveTopologyTriangle() = 0;
+ virtual void SubmitGpuWork() = 0;
+ virtual void WaitForGpu() = 0;
+
+ // util
+ virtual bool CreateRenderWindow(HWND hWnd, int nSamples) = 0;
+ virtual bool ResizeRenderWindow(int w, int h) = 0;
+ virtual void PresentRenderWindow() = 0;
+ virtual void ClearRenderWindow(float r, float g, float b) = 0;
+ virtual bool GetDeviceInfoString(wchar_t *str) = 0;
+ virtual GPUShaderResource* CreateTextureSRV(const char* texturename) = 0;
+ virtual void TxtHelperBegin() = 0;
+ virtual void TxtHelperEnd() = 0;
+ virtual void TxtHelperSetInsertionPos(int x, int y) = 0;
+ virtual void TxtHelperSetForegroundColor(float r, float g, float b, float a = 1.0f) = 0;
+ virtual void TxtHelperDrawTextLine(wchar_t* str) = 0;
+
+ // shader
+ virtual bool InitializeShaders() = 0;
+ virtual void DestroyShaders() = 0;
+ virtual void ApplyShader(SHADER_TYPE st) = 0;
+ virtual void DisableShader(SHADER_TYPE st) = 0;
+ virtual void BindShaderResources(SHADER_TYPE st, int numSRVs, GPUShaderResource** ppSRVs) = 0;
+ virtual void CopyShaderParam(SHADER_TYPE st, void* pSysMem, unsigned int bytes, unsigned int slot = 0) = 0;
+
+ // GPUProfiler
+ virtual GPUProfiler* CreateGPUProfiler() = 0;
+
+ // ShadowMap
+ virtual ShadowMap* CreateShadowMap(int resolution) = 0;
+
+ // D3D12RenderContext
+ virtual void PreRender() = 0;
+ virtual void PostRender() = 0;
+
+ // GPUMeshResources
+ virtual GPUMeshResources* GPUMeshResourcesCreate(MeshData* pMeshData, const SkinData& skinData) = 0;
+ virtual void GPUMeshResourcesRelease(GPUMeshResources* pResource) = 0;
+
+ // Get devices related
+ virtual D3DHandles& GetDeviceHandles(D3DHandles& deviceHandles) = 0;
+
+protected:
+ RenderPlugin();
+ std::string m_RenderApi;
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderResources.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderResources.cpp
new file mode 100644
index 0000000..19863fc
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderResources.cpp
@@ -0,0 +1,47 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "RenderResources.h"
+
+// shared path
+#include "AnimUtil.h"
+#include "MeshData.h"
+
+#include "RenderPlugin.h"
+
+////////////////////////////////////////////////////////////////////////////////////////
+GPUMeshResources* GPUMeshResources::Create(MeshData* pMeshData, const SkinData& skinData)
+{
+ return RenderPlugin::Instance()->GPUMeshResourcesCreate(pMeshData, skinData);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+void GPUMeshResources::Release()
+{
+ RenderPlugin::Instance()->GPUMeshResourcesRelease(this);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderResources.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderResources.h
new file mode 100644
index 0000000..c261730
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/Interface/RenderResources.h
@@ -0,0 +1,72 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#pragma once
+
+#include "corelib_global.h"
+#include "CoreLib.h"
+
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(x) { if (x) x->Release(); x = 0; }
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////
+// API specific GPU resources (todo - add reference counting)
+//////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////
+class GPUBufferResource
+{
+public:
+ virtual ~GPUBufferResource() {}
+ virtual void Release() = 0;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////
+class GPUShaderResource
+{
+public:
+ virtual ~GPUShaderResource() {}
+ virtual void Release() = 0;
+};
+
+class MeshData;
+class SkinData;
+
+////////////////////////////////////////////////////////////////////////////////////////
+class GPUMeshResources
+{
+public:
+ GPUBufferResource* m_pVertexBuffer;
+ GPUShaderResource* m_pBoneIndicesSRV;
+ GPUShaderResource* m_pBoneWeightsSRV;
+
+ static GPUMeshResources* Create(MeshData*, const SkinData& skinData);
+ void Release();
+};
+
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/LightShaderParam.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/LightShaderParam.h
new file mode 100644
index 0000000..9935f71
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/LightShaderParam.h
@@ -0,0 +1,83 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "MathUtil.h"
+
+#define MAX_LIGHTS 4
+
+// shader parameter for light
+struct LightParam
+{
+ int m_enable;
+ atcore_float3 m_dir;
+
+ int m_useShadows;
+ atcore_float3 m_color;
+
+ atcore_float3 m_ambientColor;
+ int m_isEnvLight;
+
+ int m_lhs;
+ int _reserved1;
+ int _reserved2;
+ int _reserved3;
+
+ float m_depthBias;
+ float m_depthGain;
+ int m_useEnvMap;
+ float m_intensity;
+
+ atcore_float4x4 m_viewMatrix;
+ atcore_float4x4 m_lightMatrix;
+
+public:
+ LightParam()
+ {
+ m_dir = gfsdk_makeFloat3(-1.0f, -1.0f, -1.0f);
+ m_enable = 0;
+ m_useShadows = false;
+ m_isEnvLight = 0;
+ m_useEnvMap = 0;
+
+ m_depthBias = 1.0f;
+ m_depthGain = 1.0f;
+
+ m_color = gfsdk_makeFloat3(1.0f, 1.0f, 1.0f);
+ m_ambientColor = gfsdk_makeFloat3(0.0f, 0.0f, 0.0f);
+ }
+};
+
+
+// light shader block in c-buffer
+struct LightShaderParam
+{
+ LightParam m_lightParam[MAX_LIGHTS];
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/MeshShaderParam.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/MeshShaderParam.h
new file mode 100644
index 0000000..5dce51d
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/MeshShaderParam.h
@@ -0,0 +1,142 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "MathUtil.h"
+#include "LightShaderParam.h"
+
+// same layout as the constant buffer used in body shader
+#define MAX_BONE_MATRICES 512
+
+// shared struct for mesh shader cbuffer and material access
+struct MeshShaderParam
+{
+ atcore_float4x4 m_ViewProjection;
+ atcore_float4x4 m_BodyTransformation;
+
+ LightShaderParam m_lightParam;
+
+ atcore_float3 m_eyePosition;
+ float m_specularShininess;
+
+ int m_useDiffuseTextures;
+ int m_useSpecularTextures;
+ int m_useNormalTextures;
+ int m_useTextures;
+
+
+ atcore_float4 m_ambientColor;
+ atcore_float4 m_diffuseColor;
+ atcore_float4 m_specularColor;
+
+ int m_wireFrame;
+ int m_useLighting;
+ int m_wireFrameOver;
+ float m_unitScale;
+
+ int m_useDQs;
+ int m_diffuseChannel;
+ int m_flatNormal;
+ int m_usePinPos;
+
+ atcore_float4x4 m_boneMatrices[MAX_BONE_MATRICES];
+ atcore_dualquaternion m_boneDQs[MAX_BONE_MATRICES];
+
+ MeshShaderParam()
+ {
+ m_specularShininess = 30.0f;
+
+ m_ambientColor = gfsdk_makeFloat4(0.0f, 0.0f, 0.0f, 1.0f);
+ m_diffuseColor = gfsdk_makeFloat4(1.0f, 1.0f, 1.0f, 1.0f);
+ m_specularColor = gfsdk_makeFloat4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ m_useDiffuseTextures = true;
+ m_useSpecularTextures = true;
+ m_useNormalTextures = true;
+ m_useTextures = true;
+
+ m_wireFrame = false;
+ m_wireFrameOver = false;
+ m_useLighting = true;
+ m_unitScale = 1.0f;
+
+ m_useDQs = false;
+ m_flatNormal = false;
+
+ m_usePinPos = false;
+
+ memset(m_boneMatrices, 0, sizeof(atcore_float4x4) * MAX_BONE_MATRICES);
+ memset(m_boneDQs, 0, sizeof(atcore_dualquaternion) * MAX_BONE_MATRICES);
+ }
+};
+
+// struct for mesh shadow shader cbuffer
+struct MeshShadowShaderParam
+{
+ atcore_float4x4 m_ViewProjection;
+ atcore_float4x4 m_ViewMatrix;
+ atcore_float4x4 m_BodyTransformation;
+
+ int m_useDQs;
+ int m_usePinPos;
+ float _reserved_[2];
+
+ atcore_float4x4 m_boneMatrices[MAX_BONE_MATRICES];
+ atcore_dualquaternion m_boneDQs[MAX_BONE_MATRICES];
+
+ MeshShadowShaderParam()
+ {
+ m_useDQs = false;
+ m_usePinPos = false;
+
+ memset(m_boneMatrices, 0, sizeof(atcore_float4x4) * MAX_BONE_MATRICES);
+ memset(m_boneDQs, 0, sizeof(atcore_dualquaternion) * MAX_BONE_MATRICES);
+ }
+};
+
+struct SimpleShaderParam
+{
+ atcore_float4x4 world;
+ atcore_float4x4 view;
+ atcore_float4x4 projection;
+ atcore_float4 color;
+
+ int useVertexColor;
+ int dummy2;
+ int dummy3;
+ int dummy4;
+};
+
+struct ShadowVizParam
+{
+ float m_zNear;
+ float m_zFar;
+ float _align1;
+ float _align2;
+}; \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/ShadowMap.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/ShadowMap.cpp
new file mode 100644
index 0000000..72b90be
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/ShadowMap.cpp
@@ -0,0 +1,36 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "ShadowMap.h"
+
+#include "RenderPlugin.h"
+
+/////////////////////////////////////////////////////////////////////////
+ShadowMap* ShadowMap::Create(int resolution)
+{
+ return RenderPlugin::Instance()->CreateShadowMap(resolution);
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/ShadowMap.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/ShadowMap.h
new file mode 100644
index 0000000..9a62b06
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/ShadowMap.h
@@ -0,0 +1,48 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "d3d11.h"
+
+class GPUShaderResource;
+
+struct ShadowMap
+{
+public:
+ static ShadowMap* ShadowMap::Create(int resolution);
+ virtual ~ShadowMap() {}
+
+ virtual void Release() = 0;
+ virtual void BeginRendering(float clearDepth) = 0;
+ virtual void EndRendering() = 0;
+
+ virtual GPUShaderResource* GetShadowSRV() = 0;
+};
+
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/SimpleRenderable.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Render/SimpleRenderable.cpp
new file mode 100644
index 0000000..0dfb169
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/SimpleRenderable.cpp
@@ -0,0 +1,493 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#include "SimpleRenderable.h"
+
+#include "RenderInterface.h"
+
+#include <vector>
+
+#include "Nv.h"
+
+static std::vector<SimpleRenderable*> g_SimpleShapes;
+
+struct DefaultVertexType
+{
+ atcore_float3 pos;
+ atcore_float4 color;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+SimpleRenderable::SimpleRenderable()
+ : m_pVertexBuffer(NV_NULL)
+ , m_numIndices(0)
+ , m_numVertices(0)
+{
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+SimpleRenderable::~SimpleRenderable()
+{
+ Free();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleRenderable::Free()
+{
+ SAFE_RELEASE(m_pVertexBuffer);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleRenderable::Initialize()
+{
+ //////////////////////////////////////////////////////////////////////////////
+ // create icon shape
+ g_SimpleShapes.resize(NUM_SHAPE_TYPES);
+
+ g_SimpleShapes[GROUND_YUP] = new SimpleRenderable;
+ g_SimpleShapes[GROUND_YUP]->InitGroundGeometry(false);
+
+ g_SimpleShapes[GROUND_ZUP] = new SimpleRenderable;
+ g_SimpleShapes[GROUND_ZUP]->InitGroundGeometry(true);
+
+ g_SimpleShapes[AXIS_YUP] = new SimpleRenderable;
+ g_SimpleShapes[AXIS_YUP]->InitAxisGeometry(false);
+
+ g_SimpleShapes[AXIS_ZUP] = new SimpleRenderable;
+ g_SimpleShapes[AXIS_ZUP]->InitAxisGeometry(true);
+
+ g_SimpleShapes[WIND_YUP] = new SimpleRenderable;
+ g_SimpleShapes[WIND_YUP]->InitWindGeometry();
+
+ g_SimpleShapes[WIND_ZUP] = new SimpleRenderable;
+ g_SimpleShapes[WIND_ZUP]->InitWindGeometry();
+
+ g_SimpleShapes[LIGHT] = new SimpleRenderable;
+ g_SimpleShapes[LIGHT]->InitLightGeometry();
+
+ g_SimpleShapes[LIGHT_RAY] = new SimpleRenderable;
+ g_SimpleShapes[LIGHT_RAY]->InitLightRayGeometry();
+
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+void SimpleRenderable::Draw(SHAPE_TYPE t, bool depthTest)
+{
+ if (t >= g_SimpleShapes.size())
+ return;
+
+ g_SimpleShapes[t]->Draw(depthTest);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void SimpleRenderable::Shutdown()
+{
+ for (int i = 0; i < g_SimpleShapes.size(); i++)
+ {
+ if (g_SimpleShapes[i])
+ {
+ g_SimpleShapes[i]->Free();
+ delete g_SimpleShapes[i];
+ }
+ }
+
+ g_SimpleShapes.clear();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleRenderable::InitGroundGeometry(bool zUP)
+{
+ const int nSeed = 10;
+ const int nRow = nSeed * 2 + 1;
+ const int nLines = nRow * 2;
+ const float fLen = 25.0f;
+ const float fSpace = fLen/nSeed;
+ float groundHeight = 0.0f;
+
+ const atcore_float4 color1 = gfsdk_makeFloat4(0.65, 0.65, 0.65, 1.0f);
+ const atcore_float4 color2 = gfsdk_makeFloat4(0.1f, 0.1f, 0.1f, 1.0f);
+
+ DWORD offset;
+
+ const int numVerts = nLines * 2;
+ DefaultVertexType* buf = new DefaultVertexType[numVerts];
+ DefaultVertexType* pData = buf;
+
+ //build ground lines/verts
+ for(int i = 0; i < nSeed; i++)
+ {
+ if ( zUP )
+ {
+ // lines parallel to y
+ pData->pos = gfsdk_makeFloat3(-fSpace * (i+1), -fLen, groundHeight);
+ pData->color = color1;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(-fSpace * (i+1), fLen, groundHeight);
+ pData->color = color1;
+ pData++;
+
+ // lines parallel to y
+ pData->pos = gfsdk_makeFloat3(fSpace * (i+1), -fLen, groundHeight);
+ pData->color = color1;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(fSpace * (i+1), fLen, groundHeight);
+ pData->color = color1;
+ pData++;
+
+ // line x
+ pData->pos = gfsdk_makeFloat3(-fLen, -fSpace * (i+1), groundHeight);
+ pData->color = color1;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(fLen, -fSpace * (i+1), groundHeight);
+ pData->color = color1;
+ pData++;
+
+ // line x
+ pData->pos = gfsdk_makeFloat3(-fLen, fSpace * (i+1), groundHeight);
+ pData->color = color1;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(fLen, fSpace * (i+1), groundHeight);
+ pData->color = color1;
+ pData++;
+ }
+ else
+ {
+ // lines parallel to z
+ pData->pos = gfsdk_makeFloat3(-fSpace * (i+1), groundHeight, -fLen);
+ pData->color = color1;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(-fSpace * (i+1), groundHeight, fLen);
+ pData->color = color1;
+ pData++;
+
+ // lines parallel to z
+ pData->pos = gfsdk_makeFloat3(fSpace * (i+1), groundHeight, -fLen);
+ pData->color = color1;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(fSpace * (i+1), groundHeight, fLen);
+ pData->color = color1;
+ pData++;
+
+ // line x
+ pData->pos = gfsdk_makeFloat3(-fLen, groundHeight, -fSpace * (i+1));
+ pData->color = color1;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(fLen, groundHeight, -fSpace * (i+1));
+ pData->color = color1;
+ pData++;
+
+ // line x
+ pData->pos = gfsdk_makeFloat3(-fLen, groundHeight, fSpace * (i+1));
+ pData->color = color1;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(fLen, groundHeight, fSpace * (i+1));
+ pData->color = color1;
+ pData++;
+ }
+ }
+
+ if ( zUP )
+ {
+ // line y
+ pData->pos = gfsdk_makeFloat3(-fLen, 0.0f, groundHeight);
+ pData->color = color2;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(fLen, 0.0f, groundHeight);
+ pData->color = color2;
+ pData++;
+
+ // line x
+ pData->pos = gfsdk_makeFloat3(0.0f, -fLen, groundHeight);
+ pData->color = color2;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(0.0f, fLen, groundHeight);
+ pData->color = color2;
+ pData++;
+ }
+ else
+ {
+ // line z
+ pData->pos = gfsdk_makeFloat3(-fLen, groundHeight, 0.0f);
+ pData->color = color2;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(fLen, groundHeight, 0.0f);
+ pData->color = color2;
+ pData++;
+
+ // line x
+ pData->pos = gfsdk_makeFloat3(0.0f, groundHeight, -fLen);
+ pData->color = color2;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(0.0f, groundHeight, fLen);
+ pData->color = color2;
+ pData++;
+ }
+
+ int bufBytes = sizeof(DefaultVertexType) * numVerts;
+
+ m_pVertexBuffer = RenderInterface::CreateVertexBuffer(bufBytes, buf);
+
+ m_numVertices = numVerts;
+
+ return (NV_NULL != m_pVertexBuffer);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleRenderable::InitAxisGeometry(bool zUP)
+{
+ const atcore_float4 colorRed = gfsdk_makeFloat4(1.0f, 0, 0, 1.0f);
+ const atcore_float4 colorGreen = gfsdk_makeFloat4(0, 1.0f, 0, 1.0f);
+ const atcore_float4 colorBlue = gfsdk_makeFloat4(0, 0, 1.0f, 1.0f);
+ const float dist = 1.0f;
+ const int numVerts = 3 * 2;
+ DefaultVertexType* buf = new DefaultVertexType[numVerts];
+ DefaultVertexType* pData = buf;
+
+ {
+ // x axis
+ pData->pos = gfsdk_makeFloat3(0, 0, 0);
+ pData->color = colorRed;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(dist, 0, 0);
+ pData->color = colorRed;
+ pData++;
+
+ // y axis
+ pData->pos = gfsdk_makeFloat3(0, 0, 0);
+ pData->color = colorGreen;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(0, dist, 0);
+ pData->color = colorGreen;
+ pData++;
+
+ // z axis
+ pData->pos = gfsdk_makeFloat3(0, 0, 0);
+ pData->color = colorBlue;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(0, 0, dist);
+ pData->color = colorBlue;
+ pData++;
+ }
+
+ int bufBytes = sizeof(DefaultVertexType) * numVerts;
+
+ m_pVertexBuffer = RenderInterface::CreateVertexBuffer(bufBytes, buf);
+
+ m_numVertices = numVerts;
+
+ return (NV_NULL != m_pVertexBuffer);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleRenderable::InitLightGeometry()
+{
+ // The following geometry data are generated by external/ObjLoad tool
+#include "GeometryData/LightGeometryData.h"
+ const atcore_float4 colorYellow = gfsdk_makeFloat4(1.0f, 1.0f, 0, 1.0f);
+ const int numVerts = num_faces*3*2;
+ DefaultVertexType* buf = new DefaultVertexType[numVerts];
+ DefaultVertexType* pData = buf;
+
+ const float modelScale = 0.25f;
+ for (int fi = 0; fi < num_faces; ++fi)
+ {
+ float* v0 = &vertices[(fi*3+0)*8];
+ float* v1 = &vertices[(fi*3+1)*8];
+ float* v2 = &vertices[(fi*3+2)*8];
+
+ // flip Y
+ v0[2] *= -1;
+ v1[2] *= -1;
+ v2[2] *= -1;
+
+ // line 0
+ pData->pos = modelScale * gfsdk_makeFloat3(v0[0], v0[1], v0[2]);
+ pData->color = colorYellow;
+ pData++;
+
+ pData->pos = modelScale * gfsdk_makeFloat3(v1[0], v1[1], v1[2]);
+ pData->color = colorYellow;
+ pData++;
+
+ // line 1
+ pData->pos = modelScale * gfsdk_makeFloat3(v1[0], v1[1], v1[2]);
+ pData->color = colorYellow;
+ pData++;
+
+ pData->pos = modelScale * gfsdk_makeFloat3(v2[0], v2[1], v2[2]);
+ pData->color = colorYellow;
+ pData++;
+
+ // line 2
+ pData->pos = modelScale * gfsdk_makeFloat3(v2[0], v2[1], v2[2]);
+ pData->color = colorYellow;
+ pData++;
+
+ pData->pos = modelScale * gfsdk_makeFloat3(v0[0], v0[1], v0[2]);
+ pData->color = colorYellow;
+ pData++;
+ }
+
+ int bufBytes = sizeof(DefaultVertexType) * numVerts;
+
+ m_pVertexBuffer = RenderInterface::CreateVertexBuffer(bufBytes, buf);
+
+ m_numVertices = numVerts;
+
+ return (NV_NULL != m_pVertexBuffer);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleRenderable::InitLightRayGeometry()
+{
+ const atcore_float4 colorRed = gfsdk_makeFloat4(1.0f, 0, 0, 1.0f);
+ const int numVerts = 2;
+ DefaultVertexType* buf = new DefaultVertexType[numVerts];
+ DefaultVertexType* pData = buf;
+
+ pData->pos = gfsdk_makeFloat3(0, 0, 0);
+ pData->color = colorRed;
+ pData++;
+
+ pData->pos = gfsdk_makeFloat3(0, 0, 0);
+ pData->color = colorRed;
+ pData++;
+
+ int bufBytes = sizeof(DefaultVertexType) * numVerts;
+
+ m_pVertexBuffer = RenderInterface::CreateVertexBuffer(bufBytes, buf);
+
+ m_numVertices = numVerts;
+
+ return (NV_NULL != m_pVertexBuffer);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleRenderable::InitWindGeometry()
+{
+ // The following geometry data are generated by external/ObjLoad tool
+#include "GeometryData/WindGeometryData.h"
+ const atcore_float4 colorBlue = gfsdk_makeFloat4(0, 0, 1.0f, 1.0f);
+ const int numVerts = num_faces*3*2;
+ DefaultVertexType* buf = new DefaultVertexType[numVerts];
+ DefaultVertexType* pData = buf;
+
+ const float modelScale = 0.5f;
+ for (int fi = 0; fi < num_faces; ++fi)
+ {
+ float* v0 = &vertices[(fi*3+0)*8];
+ float* v1 = &vertices[(fi*3+1)*8];
+ float* v2 = &vertices[(fi*3+2)*8];
+
+ pData->pos = modelScale * gfsdk_makeFloat3(v0[0], v0[1], v0[2]);
+ pData->color = colorBlue;
+ pData++;
+
+ pData->pos = modelScale * gfsdk_makeFloat3(v1[0], v1[1], v1[2]);
+ pData->color = colorBlue;
+ pData++;
+
+ pData->pos = modelScale * gfsdk_makeFloat3(v1[0], v1[1], v1[2]);
+ pData->color = colorBlue;
+ pData++;
+
+ pData->pos = modelScale * gfsdk_makeFloat3(v2[0], v2[1], v2[2]);
+ pData->color = colorBlue;
+ pData++;
+
+ pData->pos = modelScale * gfsdk_makeFloat3(v2[0], v2[1], v2[2]);
+ pData->color = colorBlue;
+ pData++;
+
+ pData->pos = modelScale * gfsdk_makeFloat3(v0[0], v0[1], v0[2]);
+ pData->color = colorBlue;
+ pData++;
+ }
+
+ int bufBytes = sizeof(DefaultVertexType) * numVerts;
+
+ m_pVertexBuffer = RenderInterface::CreateVertexBuffer(bufBytes, buf);
+
+ m_numVertices = numVerts;
+
+ return (NV_NULL != m_pVertexBuffer);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleRenderable::Draw(bool depthTest)
+{
+ RenderInterface::ApplyPrimitiveTopologyLine();
+
+ RenderInterface::ApplyShader(RenderInterface::SHADER_TYPE_SIMPLE_COLOR);
+ RenderInterface::DrawLineList(m_pVertexBuffer, m_numVertices, sizeof(DefaultVertexType));
+
+ RenderInterface::FlushDX12();
+ RenderInterface::ApplyPrimitiveTopologyTriangle();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleRenderable::DrawLine(const atcore_float3& from, const atcore_float3& to)
+{
+ SimpleRenderable* pShape = g_SimpleShapes[LIGHT_RAY];
+
+ DefaultVertexType buf[2];
+ DefaultVertexType* pData = buf;
+
+ // start position
+ pData->pos = from;
+ pData->color = gfsdk_makeFloat4(1.0f, 1.0f, 0, 1.0f);
+ pData++;
+
+ // end position
+ pData->pos = to;
+ pData->color = gfsdk_makeFloat4(1.0f, 1.0f, 0, 1.0f);
+ pData++;
+
+ RenderInterface::CopyToDevice(pShape->m_pVertexBuffer, buf, 2 * sizeof(DefaultVertexType));
+
+ pShape->Draw(true);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Render/SimpleRenderable.h b/NvBlast/tools/ArtistTools/source/CoreLib/Render/SimpleRenderable.h
new file mode 100644
index 0000000..c43c07d
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Render/SimpleRenderable.h
@@ -0,0 +1,75 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#pragma once
+
+#include "MathUtil.h"
+
+class GPUBufferResource;
+
+class SimpleRenderable
+{
+public:
+ enum SHAPE_TYPE
+ {
+ GROUND_YUP,
+ GROUND_ZUP,
+ AXIS_YUP,
+ AXIS_ZUP,
+ WIND_YUP,
+ WIND_ZUP,
+ LIGHT,
+ LIGHT_RAY,
+ NUM_SHAPE_TYPES
+ };
+
+ static bool Initialize();
+ static void Shutdown();
+ static void Draw(SHAPE_TYPE t, bool depthTest = true);
+ static void DrawLine(const atcore_float3& from, const atcore_float3& to);
+
+protected:
+ GPUBufferResource* m_pVertexBuffer;
+
+ unsigned int m_numVertices;
+ unsigned int m_numIndices;
+
+ SimpleRenderable();
+ ~SimpleRenderable();
+
+ bool InitGroundGeometry(bool zUp);
+ bool InitAxisGeometry(bool zUp);
+ bool InitLightGeometry();
+ bool InitLightRayGeometry();
+ bool InitWindGeometry();
+
+ void Draw(bool depthTest = true);
+
+ void Free();
+
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Camera.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Camera.cpp
new file mode 100644
index 0000000..74d93f4
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Camera.cpp
@@ -0,0 +1,867 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#include "Camera.h"
+
+//#define USE_D3DX9MATH
+#ifdef USE_D3DX9MATH
+#include <d3dx9math.h> // TODO - remove d3dx reference (quaternion funcs)
+
+#pragma comment(lib, "d3dx9.lib")
+#define MAKEVECTOR3 D3DXVECTOR3
+#else
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#define FLOAT float
+#define D3DXVECTOR3 atcore_float3
+#define D3DXMATRIX atcore_float4x4
+#define D3DXQUATERNION atcore_float4
+
+#define MAKEVECTOR3 gfsdk_makeFloat3
+
+#define D3DXToRadian( degree ) ((degree) * 0.01745329251994329547)
+
+D3DXQUATERNION * D3DXQuaternionIdentity(
+ __inout D3DXQUATERNION *pOut
+ )
+{
+ *pOut = gfsdk_makeFloat4(0, 0, 0, 1);
+ return pOut;
+}
+
+D3DXQUATERNION * D3DXQuaternionNormalize(
+ __inout D3DXQUATERNION *pOut,
+ __in const D3DXQUATERNION *pQ
+ )
+{
+ gfsdk_normalize(*pOut);
+ return pOut;
+}
+
+D3DXQUATERNION * D3DXQuaternionRotationAxis(
+ __inout D3DXQUATERNION *pOut,
+ __in const D3DXVECTOR3 *pV,
+ __in FLOAT Angle
+ )
+{
+ FLOAT s = sin(Angle * 0.5);
+
+ FLOAT x = pV->x * s;
+ FLOAT y = pV->y * s;
+ FLOAT z = pV->z * s;
+ FLOAT w = cos(Angle * 0.5);
+
+ *pOut = gfsdk_makeFloat4(x, y, z, w);
+ return pOut;
+}
+
+D3DXQUATERNION * D3DXQuaternionMultiply(
+ __inout D3DXQUATERNION *pOut,
+ __in const D3DXQUATERNION *pQ1,
+ __in const D3DXQUATERNION *pQ2
+ )
+{
+ gfsdk_normalize(*pQ1);
+ gfsdk_normalize(*pQ2);
+
+ FLOAT px = pQ2->x;
+ FLOAT py = pQ2->y;
+ FLOAT pz = pQ2->z;
+ FLOAT pw = pQ2->w;
+
+ FLOAT qx = pQ1->x;
+ FLOAT qy = pQ1->y;
+ FLOAT qz = pQ1->z;
+ FLOAT qw = pQ1->w;
+
+ FLOAT x = pw * qx + px * qw + py * qz - pz * qy;
+ FLOAT y = pw * qy + py * qw + pz * qx - px * qz;
+ FLOAT z = pw * qz + pz * qw + px * qy - py * qx;
+ FLOAT w = pw * qw - px * qx - py * qy - pz * qz;
+
+ *pOut = gfsdk_makeFloat4(x, y, z, w);
+ gfsdk_normalize(*pOut);
+ return pOut;
+}
+
+D3DXMATRIX * D3DXMatrixLookAtLH(
+ __inout D3DXMATRIX *pOut,
+ __in const D3DXVECTOR3 *pEye,
+ __in const D3DXVECTOR3 *pAt,
+ __in const D3DXVECTOR3 *pUp
+ )
+{
+ /*
+ zaxis = normal(At - Eye)
+ xaxis = normal(cross(Up, zaxis))
+ yaxis = cross(zaxis, xaxis)
+
+ xaxis.x yaxis.x zaxis.x 0
+ xaxis.y yaxis.y zaxis.y 0
+ xaxis.z yaxis.z zaxis.z 0
+ -dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) 1
+ */
+
+ D3DXVECTOR3 zaxis = *pAt - *pEye;
+ gfsdk_normalize(zaxis);
+ D3DXVECTOR3 xaxis = gfsdk_cross(*pUp, zaxis);
+ gfsdk_normalize(xaxis);
+ D3DXVECTOR3 yaxis = gfsdk_cross(zaxis, xaxis);
+
+ gfsdk_makeIdentity(*pOut);
+ pOut->_11 = zaxis.x;
+ pOut->_21 = zaxis.y;
+ pOut->_31 = zaxis.z;
+ pOut->_12 = yaxis.x;
+ pOut->_22 = yaxis.y;
+ pOut->_32 = yaxis.z;
+ pOut->_13 = zaxis.x;
+ pOut->_23 = zaxis.y;
+ pOut->_33 = zaxis.z;
+ pOut->_41 = -gfsdk_dot(xaxis, *pEye);
+ pOut->_42 = -gfsdk_dot(yaxis, *pEye);
+ pOut->_43 = -gfsdk_dot(zaxis, *pEye);
+ return pOut;
+}
+
+D3DXMATRIX * D3DXMatrixLookAtRH(
+ __inout D3DXMATRIX *pOut,
+ __in const D3DXVECTOR3 *pEye,
+ __in const D3DXVECTOR3 *pAt,
+ __in const D3DXVECTOR3 *pUp
+ )
+{
+ /*
+ zaxis = normal(Eye - At)
+ xaxis = normal(cross(Up, zaxis))
+ yaxis = cross(zaxis, xaxis)
+
+ xaxis.x yaxis.x zaxis.x 0
+ xaxis.y yaxis.y zaxis.y 0
+ xaxis.z yaxis.z zaxis.z 0
+ -dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) 1
+ */
+
+ D3DXVECTOR3 zaxis = *pEye - *pAt;
+ gfsdk_normalize(zaxis);
+ D3DXVECTOR3 xaxis = gfsdk_cross(*pUp, zaxis);
+ gfsdk_normalize(xaxis);
+ D3DXVECTOR3 yaxis = gfsdk_cross(zaxis, xaxis);
+
+ gfsdk_makeIdentity(*pOut);
+ pOut->_11 = xaxis.x;
+ pOut->_21 = xaxis.y;
+ pOut->_31 = xaxis.z;
+ pOut->_12 = yaxis.x;
+ pOut->_22 = yaxis.y;
+ pOut->_32 = yaxis.z;
+ pOut->_13 = zaxis.x;
+ pOut->_23 = zaxis.y;
+ pOut->_33 = zaxis.z;
+ pOut->_41 = -gfsdk_dot(xaxis, *pEye);
+ pOut->_42 = -gfsdk_dot(yaxis, *pEye);
+ pOut->_43 = gfsdk_dot(zaxis, *pEye);
+ return pOut;
+}
+
+D3DXMATRIX * D3DXMatrixPerspectiveFovLH(
+ __inout D3DXMATRIX *pOut,
+ __in FLOAT fovy,
+ __in FLOAT Aspect,
+ __in FLOAT zn,
+ __in FLOAT zf
+ )
+{
+ /*
+ cot(fovY/2) 0 0 0
+ 0 cot(fovY/2)/aspect 0 0
+ 0 0 zf/(zf-zn) 1
+ 0 0 -zn*zf/(zf-zn) 0
+ */
+
+ memset(pOut, 0, sizeof(D3DXMATRIX));
+ FLOAT cosHalfFovy = 1 / tan(fovy * 0.5);
+ pOut->_11 = cosHalfFovy;
+ pOut->_22 = cosHalfFovy / Aspect;
+ pOut->_33 = zf / (zf - zn);
+ pOut->_34 = 1;
+ pOut->_43 = -zn*zf / (zf - zn);
+ return pOut;
+}
+
+D3DXMATRIX * D3DXMatrixPerspectiveFovRH(
+ __inout D3DXMATRIX *pOut,
+ __in FLOAT fovy,
+ __in FLOAT Aspect,
+ __in FLOAT zn,
+ __in FLOAT zf
+ )
+{
+ /*
+ cot(fovY/2)/aspect 0 0 0
+ 0 cot(fovY/2) 0 0
+ 0 0 zf/(zn-zf) -1
+ 0 0 zn*zf/(zn-zf) 0
+ */
+
+ memset(pOut, 0, sizeof(D3DXMATRIX));
+ FLOAT cosHalfFovy = 1 / tan(fovy * 0.5);
+ pOut->_11 = cosHalfFovy / Aspect;
+ pOut->_22 = cosHalfFovy;
+ pOut->_33 = zf / (zn - zf);
+ pOut->_34 = -1;
+ pOut->_43 = zn*zf / (zn - zf);
+ return pOut;
+}
+
+D3DXMATRIX * D3DXMatrixOrthoLH(
+ __inout D3DXMATRIX *pOut,
+ __in FLOAT w,
+ __in FLOAT h,
+ __in FLOAT zn,
+ __in FLOAT zf
+ )
+{
+ /*
+ 2/w 0 0 0
+ 0 2/h 0 0
+ 0 0 1/(zf-zn) 0
+ 0 0 zn/(zn-zf) 1
+ */
+
+ gfsdk_makeIdentity(*pOut);
+ pOut->_11 = 2 / w;
+ pOut->_22 = 2 / h;
+ pOut->_33 = 1 / (zf - zn);
+ pOut->_43 = zn / (zn - zf);
+ return pOut;
+}
+
+D3DXMATRIX * D3DXMatrixOrthoRH(
+ __inout D3DXMATRIX *pOut,
+ __in FLOAT w,
+ __in FLOAT h,
+ __in FLOAT zn,
+ __in FLOAT zf
+ )
+{
+ /*
+ 2/w 0 0 0
+ 0 2/h 0 0
+ 0 0 1/(zn-zf) 0
+ 0 0 zn/(zn-zf) 1
+ */
+
+ gfsdk_makeIdentity(*pOut);
+ pOut->_11 = 2 / w;
+ pOut->_22 = 2 / h;
+ pOut->_33 = 1 / (zn - zf);
+ pOut->_43 = zn / (zn - zf);
+ return pOut;
+}
+
+D3DXQUATERNION * D3DXQuaternionRotationMatrix(
+ __inout D3DXQUATERNION *pOut,
+ __in const D3DXMATRIX *pM
+ )
+{
+ FLOAT fourXSquaredMinus1 = pM->_11 - pM->_22 - pM->_33;
+ FLOAT fourYSquaredMinus1 = pM->_22 - pM->_11 - pM->_33;
+ FLOAT fourZSquaredMinus1 = pM->_33 - pM->_11 - pM->_22;
+ FLOAT fourWSquaredMinus1 = pM->_11 + pM->_22 + pM->_33;
+
+ int biggestIndex = 0;
+ FLOAT fourBiggestSquaredMinus1 = fourWSquaredMinus1;
+ if (fourXSquaredMinus1 > fourBiggestSquaredMinus1)
+ {
+ fourBiggestSquaredMinus1 = fourXSquaredMinus1;
+ biggestIndex = 1;
+ }
+ if (fourYSquaredMinus1 > fourBiggestSquaredMinus1)
+ {
+ fourBiggestSquaredMinus1 = fourYSquaredMinus1;
+ biggestIndex = 2;
+ }
+ if (fourZSquaredMinus1 > fourBiggestSquaredMinus1)
+ {
+ fourBiggestSquaredMinus1 = fourZSquaredMinus1;
+ biggestIndex = 3;
+ }
+
+ FLOAT biggestVal = sqrt(fourBiggestSquaredMinus1 + 1) * 0.5;
+ FLOAT mult = 0.25 / biggestVal;
+
+ D3DXQuaternionIdentity(pOut);
+ switch (biggestIndex)
+ {
+ case 0:
+ pOut->w = biggestVal;
+ pOut->x = (pM->_23 - pM->_32) * mult;
+ pOut->y = (pM->_31 - pM->_13) * mult;
+ pOut->z = (pM->_12 - pM->_21) * mult;
+ break;
+ case 1:
+ pOut->w = (pM->_23 - pM->_32) * mult;
+ pOut->x = biggestVal;
+ pOut->y = (pM->_12 + pM->_21) * mult;
+ pOut->z = (pM->_31 + pM->_13) * mult;
+ break;
+ case 2:
+ pOut->w = (pM->_31 - pM->_13) * mult;
+ pOut->x = (pM->_12 + pM->_21) * mult;
+ pOut->y = biggestVal;
+ pOut->z = (pM->_23 + pM->_32) * mult;
+ break;
+ case 3:
+ pOut->w = (pM->_12 - pM->_21) * mult;
+ pOut->x = (pM->_31 + pM->_13) * mult;
+ pOut->y = (pM->_23 + pM->_32) * mult;
+ pOut->z = biggestVal;
+ break;
+ default:
+ break;
+ }
+ return pOut;
+}
+
+D3DXMATRIX * D3DXMatrixRotationQuaternion(
+ __inout D3DXMATRIX *pOut,
+ __in const D3DXQUATERNION *pQ
+ )
+{
+ gfsdk_makeIdentity(*pOut);
+ FLOAT qxx = (pQ->x * pQ->x);
+ FLOAT qyy = (pQ->y * pQ->y);
+ FLOAT qzz = (pQ->z * pQ->z);
+ FLOAT qxz = (pQ->x * pQ->z);
+ FLOAT qxy = (pQ->x * pQ->y);
+ FLOAT qyz = (pQ->y * pQ->z);
+ FLOAT qwx = (pQ->w * pQ->x);
+ FLOAT qwy = (pQ->w * pQ->y);
+ FLOAT qwz = (pQ->w * pQ->z);
+ pOut->_11 = 1 - 2 * (qyy + qzz);
+ pOut->_12 = 2 * (qxy + qwz);
+ pOut->_13 = 2 * (qxz - qwy);
+ pOut->_21 = 2 * (qxy - qwz);
+ pOut->_22 = 1 - 2 * (qxx + qzz);
+ pOut->_23 = 2 * (qyz + qwx);
+ pOut->_31 = 2 * (qxz + qwy);
+ pOut->_32 = 2 * (qyz - qwx);
+ pOut->_33 = 1 - 2 * (qxx + qyy);
+ return pOut;
+}
+#endif // USE_D3DX9MATH
+
+Camera::Camera(bool zup, bool lhs)
+ :
+ _zup(zup),
+ _lhs(lhs),
+ _isPerspective(true)
+{
+
+ D3DXQuaternionIdentity((D3DXQUATERNION*)&_orientation);
+
+ gfsdk_makeIdentity(_viewMatrix);
+ gfsdk_makeIdentity(_projectionMatrix);
+
+ _fov = (75.0f / 360.0f) * 3.141592653589793;
+}
+
+Camera::~Camera()
+{
+}
+
+void
+Camera::Init(bool zup, bool lhs)
+{
+ _lhs = lhs;
+ _zup = zup;
+}
+
+atcore_float3 Camera::GetUp() const
+{
+ atcore_float3 up;
+
+ if (IsYUp())
+ up = gfsdk_makeFloat3(0.0f, 1.0f, 0.0f);
+ else
+ up = gfsdk_makeFloat3(0.0f, 0.0f, 1.0f);
+
+ return up;
+}
+
+void Camera::SetDefaults()
+{
+ atcore_float3 eye;
+ atcore_float3 at = gfsdk_makeFloat3(0.0f, 0.0f, 0.0f);
+
+ if (IsYUp())
+ {
+ if (_lhs)
+ eye = gfsdk_makeFloat3(0.0f, 60.0f, -120.0f);
+ else
+ eye = gfsdk_makeFloat3(0.0f, 60.0f, 120.0f);
+ }
+ else // zup
+ {
+ if (_lhs)
+ eye = gfsdk_makeFloat3(0.0f, 120.0f, 60.0f);
+ else
+ eye = gfsdk_makeFloat3(0.0f, -120.0f, 60.0f);
+ }
+
+ atcore_float3 up = GetUp();
+
+ LookAt(eye, at, up);
+}
+
+// Build a look at matrix, and calculate the major axis and rotation component.
+void Camera::LookAt(const atcore_float3& eye, const atcore_float3& at, const atcore_float3& up)
+{
+ if (_lhs)
+ D3DXMatrixLookAtLH((D3DXMATRIX*)&_viewMatrix, (D3DXVECTOR3*)&eye, (D3DXVECTOR3*)&at, (D3DXVECTOR3*)&up);
+ else
+ D3DXMatrixLookAtRH((D3DXMATRIX*)&_viewMatrix, (D3DXVECTOR3*)&eye, (D3DXVECTOR3*)&at, (D3DXVECTOR3*)&up);
+
+ _eye = eye;
+ _at = at;
+
+ atcore_float3 dir = at - eye;
+ _lookDistance = gfsdk_length(dir);
+
+ D3DXQuaternionRotationMatrix((D3DXQUATERNION*)&_orientation, (D3DXMATRIX*)&_viewMatrix);
+ BuildViewMatrix();
+}
+
+void Camera::SetEye(const atcore_float3& eye)
+{
+ _eye = eye;
+ _lookDistance = gfsdk_distance(_eye, _at);
+}
+
+void Camera::SetAt(const atcore_float3& at)
+{
+ _at = at;
+ _lookDistance = gfsdk_distance(_eye, _at);
+}
+
+void Camera::SetViewMatrix(const atcore_float3& xAxis, const atcore_float3& yAxis, const atcore_float3& zAxis)
+{
+ _viewMatrix._11 = xAxis.x; _viewMatrix._21 = xAxis.y; _viewMatrix._31 = xAxis.z;
+ _viewMatrix._12 = yAxis.x; _viewMatrix._22 = yAxis.y; _viewMatrix._32 = yAxis.z;
+ _viewMatrix._13 = zAxis.x; _viewMatrix._23 = zAxis.y; _viewMatrix._33 = zAxis.z;
+
+ D3DXQuaternionRotationMatrix((D3DXQUATERNION*)&_orientation, (D3DXMATRIX*)&_viewMatrix);
+ D3DXQuaternionNormalize((D3DXQUATERNION*)&_orientation, (D3DXQUATERNION*)&_orientation);
+
+ atcore_float3 _viewDirection = _lhs ? -1.0f * zAxis : zAxis;
+
+ _eye = _at + _viewDirection * _lookDistance;
+
+ _viewMatrix._41 = - gfsdk_dot(xAxis,_eye);
+ _viewMatrix._42 = - gfsdk_dot(yAxis,_eye);
+ _viewMatrix._43 = - gfsdk_dot(zAxis,_eye);
+}
+
+// Build a perspective matrix
+void Camera::Perspective()
+{
+ _isPerspective = true;
+
+ if (_lhs)
+ D3DXMatrixPerspectiveFovLH( (D3DXMATRIX*)&_projectionMatrix, _fov, _aspectRatio, _znear, _zfar);
+ else
+ D3DXMatrixPerspectiveFovRH( (D3DXMATRIX*)&_projectionMatrix, _fov, _aspectRatio, _znear, _zfar);
+
+}
+
+void Camera::Ortho(float width, float height, float znear, float zfar)
+{
+ if (_lhs)
+ D3DXMatrixOrthoLH( (D3DXMATRIX*)&_projectionMatrix, width, height, znear, zfar);
+ else
+ D3DXMatrixOrthoRH( (D3DXMATRIX*)&_projectionMatrix, width, height, znear, zfar);
+
+ _znear = znear;
+ _zfar = zfar;
+ _width = width;
+ _height = height;
+ _isPerspective = false;
+}
+
+// Dolly towards the viewpoint
+void Camera::Dolly(float zoom)
+{
+ if (_isPerspective)
+ {
+ atcore_float3 offset = _eye - _at;
+
+ _lookDistance = gfsdk_length(offset);
+
+ gfsdk_normalize(offset);
+
+ float zoomFactor = zoom * _lookDistance;
+
+ _lookDistance += zoomFactor;
+
+ _eye = _lookDistance * offset + _at;
+
+ BuildViewMatrix();
+ }
+ else
+ {
+ _width += zoom * 4.0f;
+ _height += zoom * 4.0f;
+
+ D3DXMatrixOrthoRH( (D3DXMATRIX*)&_projectionMatrix, _width, _height, _znear, _zfar);
+
+ }
+}
+
+// Orbit around the viewpoint
+void Camera::Orbit(const atcore_float2& delta)
+{
+
+ float heading = D3DXToRadian(delta.x);
+ float pitch = D3DXToRadian(delta.y);
+
+ if (_lhs)
+ {
+ heading *= -1.0f;
+ pitch *= -1.0f;
+ }
+
+ D3DXQUATERNION rot;
+
+ D3DXVECTOR3 yAxis = MAKEVECTOR3(0.0f, 0.0f, 1.0f);
+ if (IsYUp()) // change up axis if Y is the up axis (for maya)
+ {
+ yAxis = MAKEVECTOR3( 0.0f, 1.0f, 0.0f );
+ }
+
+ D3DXVECTOR3 xAxis = MAKEVECTOR3(1.0f, 0.0f, 0.0f);
+ if (heading != 0.0f)
+ {
+ D3DXQuaternionRotationAxis(&rot, &yAxis, heading);
+ D3DXQuaternionMultiply((D3DXQUATERNION*)&_orientation, &rot, (D3DXQUATERNION*)&_orientation);
+ }
+
+ if (pitch != 0.0f)
+ {
+ D3DXQuaternionRotationAxis(&rot, &xAxis, pitch);
+ D3DXQuaternionMultiply((D3DXQUATERNION*)&_orientation, (D3DXQUATERNION*)&_orientation, &rot);
+ }
+ BuildViewMatrix();
+
+}
+
+// Orbit around the model's center for HAIR-188
+void Camera::OrbitLight(const atcore_float2& delta)
+{
+
+ float heading = D3DXToRadian(delta.x);
+ float pitch = D3DXToRadian(delta.y);
+
+ if (_lhs)
+ {
+ heading *= -1.0f;
+ pitch *= -1.0f;
+ }
+
+ D3DXQUATERNION rot;
+
+ D3DXVECTOR3 yAxis = MAKEVECTOR3(0.0f, 0.0f, 1.0f);
+ if (IsYUp()) // change up axis if Y is the up axis (for maya)
+ {
+ yAxis = MAKEVECTOR3( 0.0f, 1.0f, 0.0f );
+ }
+
+ D3DXVECTOR3 xAxis = MAKEVECTOR3(1.0f, 0.0f, 0.0f);
+ if (heading != 0.0f)
+ {
+ D3DXQuaternionRotationAxis(&rot, &yAxis, heading);
+ D3DXQuaternionMultiply((D3DXQUATERNION*)&_orientation, &rot, (D3DXQUATERNION*)&_orientation);
+ }
+
+ if (pitch != 0.0f)
+ {
+ D3DXQuaternionRotationAxis(&rot, &xAxis, pitch);
+ D3DXQuaternionMultiply((D3DXQUATERNION*)&_orientation, &rot, (D3DXQUATERNION*)&_orientation);
+ }
+ BuildViewMatrix();
+
+}
+
+void Camera::Pan(const atcore_float2& delta)
+{
+ //Scale the movement by the current view
+ //float depth = depthRange.y - depthRange.x;
+
+ atcore_float3 viewDir = GetEye() - GetAt();
+ float depth = gfsdk_length(viewDir);
+ if (depth <= 0.0f)
+ depth = 1.0f;
+
+ atcore_float3 xAxis = GetXAxis();
+ atcore_float3 yAxis = GetYAxis();
+
+ if (_isPerspective)
+ {
+ float fov2 = ((float)-tan(0.5 * _fov) * (depth));
+ atcore_float2 newDelta = fov2 * delta;
+
+ _at = _at + (-1.0f * yAxis * newDelta.y) + (xAxis * newDelta.x);
+ }
+ else
+ {
+ atcore_float2 newDelta = depth * delta;
+ _at = _at + (yAxis * newDelta.y) + (-1.0f * xAxis * newDelta.x);
+ }
+
+
+ BuildViewMatrix();
+}
+
+atcore_float3 Camera::GetXAxis() const
+{
+ return gfsdk_makeFloat3(_viewMatrix._11, _viewMatrix._21, _viewMatrix._31);
+
+}
+
+atcore_float3 Camera::GetYAxis() const
+{
+ return gfsdk_makeFloat3(_viewMatrix._12, _viewMatrix._22, _viewMatrix._32);
+}
+
+atcore_float3 Camera::GetZAxis() const
+{
+ return gfsdk_makeFloat3(_viewMatrix._13, _viewMatrix._23, _viewMatrix._33);
+}
+
+atcore_float3 Camera::GetViewDirection() const
+{
+ atcore_float3 zAxis = GetZAxis();
+ return _lhs ? -1.0f * zAxis : zAxis;
+}
+
+// Reconstruct the view matrix from the current orientation and eye/look direction.
+void Camera::BuildViewMatrix()
+{
+ // Reconstruct the view matrix.
+ D3DXQuaternionNormalize((D3DXQUATERNION*)&_orientation, (D3DXQUATERNION*)&_orientation);
+ D3DXMatrixRotationQuaternion((D3DXMATRIX*)&_viewMatrix, (D3DXQUATERNION*)&_orientation);
+
+ atcore_float3 xAxis = GetXAxis();
+ atcore_float3 yAxis = GetYAxis();
+ atcore_float3 zAxis = GetZAxis();
+
+ atcore_float3 viewDirection = GetViewDirection();
+
+ _eye = _at + viewDirection * _lookDistance;
+
+ _viewMatrix._41 = - gfsdk_dot(xAxis,_eye);
+ _viewMatrix._42 = - gfsdk_dot(yAxis,_eye);
+ _viewMatrix._43 = - gfsdk_dot(zAxis,_eye);
+}
+
+// Set Z Up or Y Up.
+void Camera::ResetUpDir(bool zup)
+{
+ if (zup == _zup)
+ return;
+
+ _zup = zup;
+
+ atcore_float3 eye = GetEye();
+ atcore_float3 at = GetAt();
+ atcore_float3 up;
+
+ if (IsYUp())
+ {
+ // Swap eye z and y
+ float temp = eye.y;
+ eye.y = eye.z;
+ eye.z = -temp;
+ // Swap at z and y
+ temp = at.y;
+ at.y = at.z;
+ at.z = -temp;
+
+ // Set up dir
+ up = gfsdk_makeFloat3(0.0f, 1.0f, 0.0f);
+ }
+ else
+ {
+ // Swap eye z and y
+ float temp = eye.y;
+ eye.y = -eye.z;
+ eye.z = temp;
+ // Swap at z and y
+ temp = at.y;
+ at.y = -at.z;
+ at.z = temp;
+
+ // Set up dir
+ up = gfsdk_makeFloat3(0.0f, 0.0f, 1.0f);
+ }
+ LookAt(eye, at, up);
+ BuildViewMatrix();
+}
+
+// Set Z Up or Y Up.
+void Camera::ResetLhs(bool lhs)
+{
+ if (lhs == _lhs)
+ return;
+
+ _lhs = lhs;
+
+ atcore_float3 eye = GetEye();
+ atcore_float3 at = GetAt();
+
+ if (_zup)
+ {
+ eye.y *= -1;
+ at.y *= -1;
+ }
+ else
+ {
+ eye.z *= -1;
+ at.z *= -1;
+ }
+
+ if (_isPerspective)
+ Perspective();
+ else
+ Ortho(_width, _height, _znear, _zfar);
+
+ atcore_float3 up = GetUp();
+
+ LookAt(eye, at, up);
+ BuildViewMatrix();
+}
+
+void Camera::FitBounds(const atcore_float3& center, const atcore_float3& extents)
+{
+ SetAt(center);
+ // set center first to get eye
+ BuildViewMatrix();
+ if (_isPerspective)
+ {
+ float size = extents.x;
+ size = max(size, extents.y);
+ size = max(size, extents.z);
+ atcore_float3 eye = GetEye();
+
+ atcore_float3 dir = eye - center;
+ gfsdk_normalize(dir);
+ float distance = size / tanf(_fov/2.f);
+
+ eye = center + distance * dir;
+
+ SetEye(eye);
+ BuildViewMatrix();
+ }
+}
+
+#ifndef NV_ARTISTTOOLS
+#include "ProjectParams.h"
+#endif // NV_ARTISTTOOLS
+
+bool Camera::LoadParameters(void* ptr)
+{
+#ifndef NV_ARTISTTOOLS
+ nvidia::parameterized::HairProjectParametersNS::Camera_Type* param =
+ static_cast<nvidia::parameterized::HairProjectParametersNS::Camera_Type*>(ptr);
+
+ _zup = param->flags == 1;
+ _fov = param->fov;
+ _aspectRatio = param->aspectRatio;
+ _znear = param->znear;
+ _zfar = param->zfar;
+ _isPerspective = param->isPerspective;
+ memcpy(&_eye, &param->eye, sizeof(_eye));
+ memcpy(&_at, &param->at, sizeof(_at));
+ _lookDistance = param->lookDistance;
+ memcpy(&_orientation, &param->orientation, sizeof(_orientation));
+ memcpy(&_viewMatrix, &param->viewMatrix, sizeof(_viewMatrix));
+ memcpy(&_projectionMatrix, &param->projectionMatrix, sizeof(_projectionMatrix));
+#else
+ CoreLib::Inst()->Camera_LoadParameters(ptr, this);
+#endif // NV_ARTISTTOOLS
+ return true;
+}
+
+bool Camera::SaveParameters(void *ptr)
+{
+#ifndef NV_ARTISTTOOLS
+ nvidia::parameterized::HairProjectParametersNS::Camera_Type* outParam =
+ static_cast<nvidia::parameterized::HairProjectParametersNS::Camera_Type*>(ptr);
+
+ outParam->flags = (_zup ? 1 : 2);
+ outParam->fov = _fov;
+ outParam->aspectRatio = _aspectRatio;
+ outParam->znear = _znear;
+ outParam->zfar = _zfar;
+ outParam->width = 0;
+ outParam->height = 0;
+ outParam->isPerspective = _isPerspective;
+ memcpy(&outParam->eye, &_eye, sizeof(outParam->eye));
+ memcpy(&outParam->at, &_at, sizeof(outParam->at));
+ outParam->lookDistance = _lookDistance;
+ memcpy(&outParam->orientation, &_orientation, sizeof(outParam->orientation));
+ memcpy(&outParam->viewMatrix, &_viewMatrix, sizeof(outParam->viewMatrix));
+ memcpy(&outParam->projectionMatrix, &_projectionMatrix, sizeof(outParam->projectionMatrix));
+#else
+ CoreLib::Inst()->Camera_SaveParameters(ptr, this);
+#endif // NV_ARTISTTOOLS
+ return true;
+}
+
+void Camera::getScreenCoord(float x, float y, float z, int &sx, int &sy)
+{
+ atcore_float4x4 view = (atcore_float4x4&)GetViewMatrix();
+ atcore_float4x4 projection = (atcore_float4x4&)GetProjectionMatrix();
+
+ atcore_float4x4 viewProjection = view * projection;
+
+ atcore_float4 vp = gfsdk_transform(viewProjection, gfsdk_makeFloat4(x, y, z, 1.0f));
+
+ float nx = vp.x / vp.w;
+ float ny = vp.y / vp.w;
+
+ float w = GetWidth();
+ float h = GetHeight();
+
+ sx = w * (0.5f + 0.5f * nx);
+ sy = h * (0.5f - 0.5f * ny);
+
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Camera.h b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Camera.h
new file mode 100644
index 0000000..23fb0c6
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Camera.h
@@ -0,0 +1,128 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "MathUtil.h"
+
+class CORELIB_EXPORT Camera
+{
+public:
+
+ // YUp default
+ Camera(bool zUp = false, bool lhs = false);
+ ~Camera();
+
+ void Init(bool zup, bool lhs);
+ void LookAt(const atcore_float3& eye, const atcore_float3& target, const atcore_float3& up);
+ void Perspective();
+ void Ortho(float width, float height, float znear, float zfar);
+ void Dolly(float zoom);
+ void Orbit(const atcore_float2& delta);
+ void OrbitLight(const atcore_float2& delta); // special for HAIR-188
+ void Pan(const atcore_float2& delta);
+
+ void getScreenCoord(float x, float y, float z, int &sx, int &sy);
+
+ float GetZNear() { return _znear; }
+ float GetZFar() { return _zfar; }
+
+ const atcore_float3& GetAt() const { return _at; }
+ const atcore_float3& GetEye() const { return _eye; }
+
+ float GetWidth() const { return _width; }
+ float GetHeight() const { return _height; }
+
+ void SetFOV(float fov) { _fov = fov; }
+ void SetAspetRatio(float aspect) { _aspectRatio = aspect; }
+ void SetZNear(float znear) { _znear = znear; }
+ void SetZFar(float zfar) { _zfar = zfar; }
+
+ void SetSize(int w, int h) { _width = w; _height = h; }
+
+ atcore_float3 GetXAxis() const;
+ atcore_float3 GetYAxis() const;
+ atcore_float3 GetZAxis() const;
+
+ atcore_float3 GetViewDirection() const;
+
+ void SetViewMatrix(const atcore_float3& xAxis, const atcore_float3& yAxis, const atcore_float3& zAxis);
+
+ float GetLookDistance() const { return _lookDistance; }
+ atcore_float3 GetUp() const;
+
+ void SetEye(const atcore_float3& eye);
+ void SetAt(const atcore_float3& at);
+
+ atcore_float2 GetZRange() const { return gfsdk_makeFloat2(_znear, _zfar); }
+
+ const atcore_float4x4& GetProjectionMatrix() const { return _projectionMatrix; }
+ const atcore_float4x4& GetViewMatrix() const { return _viewMatrix; }
+
+ // Change Up Dir and reset internal eye and at.
+ void ResetUpDir(bool zup);
+ void ResetLhs(bool lhs);
+
+ bool IsYUp() const { return _zup == false; }
+ bool UseLHS() const { return _lhs; }
+
+ bool LoadParameters(void* param);
+ bool SaveParameters(void* outParam);
+
+ void BuildViewMatrix();
+
+ void SetDefaults();
+
+ void FitBounds(const atcore_float3& center, const atcore_float3& extents);
+
+
+//private:
+ // coordinate axis
+ bool _zup;
+ bool _lhs;
+
+ // Perspective
+ bool _isPerspective;
+ float _fov;
+ float _aspectRatio;
+
+ float _znear;
+ float _zfar;
+ float _width;
+ float _height;
+
+ float _lookDistance;
+
+ atcore_float3 _eye;
+ atcore_float3 _at;
+
+ atcore_float4 _orientation;
+ atcore_float4x4 _viewMatrix;
+ atcore_float4x4 _projectionMatrix;
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Gamepad.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Gamepad.cpp
new file mode 100644
index 0000000..01e3323
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Gamepad.cpp
@@ -0,0 +1,1310 @@
+#include <windows.h>
+#include <SDL.h>
+#include <QtWidgets/QApplication>
+#include <QtCore/QDir>
+#include <QtCore/QDirIterator>
+#include <QtCore/QString>
+#include <QtCore/QList>
+
+#include "Gamepad.h"
+
+#include "Camera.h"
+#include "SimpleScene.h"
+#include "AppMainWindow.h"
+#include "DisplayLightPanel.h"
+#include "DisplayScenePanel.h"
+
+#include "DXUT.h"
+//#include "D3D11RendererWindow.h"
+#include "sdkmisc.h"
+#include "GlobalSettings.h"
+#include "Light.h"
+#include "DisplayPreferencesPanel.h"
+#include "ViewerOutput.h"
+#include "D3DWidget.h"
+#include <stdarg.h>
+#include <vector>
+#include <string>
+
+#ifndef NV_ARTISTTOOLS
+#include "BlastToolbar.h"
+#include "DisplayVisualizersPanel.h"
+#include "FurCharacter.h"
+#include "HairParams.h"
+#endif // NV_ARTISTTOOLS
+
+const bool bSaveLogToDisk = true;
+bool bDefaultDemoMode = false;
+
+static QList<QString> demoProjects;
+
+static int curentPrjIdx = -1;
+static int iQuitState = 0;
+
+static std::string strAppDir;
+
+SimpleScene* theScene = NV_NULL;
+
+bool bUseOldLightCam = false, bUseOldSceneCam = false;
+
+enum ButtonState
+{
+ BUTTON_NOTHING,
+ BUTTON_DOWN,
+ BUTTON_HOLDING,
+ BUTTON_UP,
+};
+
+class GamepadHandler
+{
+public:
+ GamepadHandler()
+ :joystick(0)
+ {
+ }
+
+ ~GamepadHandler()
+ {
+ DisConnect();
+ }
+
+ void DisConnect()
+ {
+ if(joystick)
+ {
+ SDL_JoystickClose(joystick);
+ joystick = NV_NULL;
+ }
+ }
+
+ void Process();
+
+ inline ButtonState ButtonState(int button)
+ {
+ if (button >= 0 && button < iButtonState.size())
+ {
+ if (iButtonState[button] && iButtonStateOld[button] == 0)
+ return BUTTON_DOWN;
+ else if (iButtonState[button] && iButtonStateOld[button])
+ return BUTTON_HOLDING;
+ else if (iButtonState[button] == 0 && iButtonStateOld[button])
+ return BUTTON_UP;
+ }
+ return BUTTON_NOTHING;
+ }
+
+ inline int AxisChange(int idx)
+ {
+ if (idx >= 0 && idx < iAxisState.size())
+ {
+ return (iAxisState[idx] - iAxisStateAtBegin[idx]);
+ }
+ return 0;
+ }
+
+ const char* pjsName;
+ int numAxis;
+ int numTrackballs;
+ int numPov;
+ int numButtons;
+
+ std::vector<int> bKeyHolding;
+ std::vector<int> iAxisStateAtBegin;
+ std::vector<int> iAxisStateOld;
+ std::vector<int> iAxisState;
+ std::vector<int> iButtonStateOld;
+ std::vector<int> iButtonState;
+
+ SDL_Joystick* joystick;
+ SDL_JoystickGUID jsGuid;
+};
+
+std::vector<GamepadHandler> gHandlers;
+
+//
+// Gamepad thresholds taken from XINPUT API
+//
+//#define GAMEPAD_LEFT_THUMB_DEADZONE 7849
+//#define GAMEPAD_RIGHT_THUMB_DEADZONE 8689
+//#define GAMEPAD_TRIGGER_THRESHOLD 30
+
+#define GAMEPAD_BUMPER_DEADZONE 9000
+inline int ClampAxis(int value)
+{
+ if((value>GAMEPAD_BUMPER_DEADZONE) || (value<-GAMEPAD_BUMPER_DEADZONE))
+ return value;
+ return 0;
+}
+
+std::vector<std::string> keylog;
+
+void LogAdd(const char *fmt,...)
+{
+ if(bSaveLogToDisk)
+ {
+ static char logBuf[2048];
+ va_list arg;
+ va_start( arg, fmt );
+ vsprintf(logBuf, fmt, arg);
+ va_end(arg);
+ keylog.push_back(logBuf);
+ }
+}
+
+void SaveLog()
+{
+ if(keylog.size())
+ {
+ std::string fn = strAppDir + "\\buttonLog.txt";
+ FILE* fp = fopen(fn.c_str(), "w+");
+ if(fp)
+ {
+ for(int i = 0; i < keylog.size(); ++i)
+ {
+ std::string& info = keylog[i];
+ fputs(info.c_str(), fp);
+ fputs("\n", fp);
+ }
+ fclose(fp);
+ }
+ }
+}
+
+//XBOX 360 AXIS
+static int AXIS_LS_X = 0;
+static int AXIS_LS_Y = 1;
+static int AXIS_RS_X = 2;
+static int AXIS_RS_Y = 3;
+static int AXIS_LT = 4;
+static int AXIS_RT = 5;
+
+// XBox 360 Key codes
+static int GAMEPAD_KEY_DPAD_UP = 0;
+static int GAMEPAD_KEY_DPAD_DOWN = 1;
+static int GAMEPAD_KEY_DPAD_LEFT = 2;
+static int GAMEPAD_KEY_DPAD_RIGHT = 3;
+static int GAMEPAD_KEY_START = 4;
+static int GAMEPAD_KEY_BACK = 5;
+static int GAMEPAD_KEY_LS = 6;
+static int GAMEPAD_KEY_RS = 7;
+static int GAMEPAD_KEY_LEFT_BUMP = 8;
+static int GAMEPAD_KEY_RIGHT_BUMP = 9;
+static int GAMEPAD_KEY_A = 10;
+static int GAMEPAD_KEY_B = 11;
+static int GAMEPAD_KEY_X = 12;
+static int GAMEPAD_KEY_Y = 13;
+
+double GetSeconds()
+{
+ static LARGE_INTEGER lastTime;
+ static LARGE_INTEGER freq;
+ static bool first = true;
+
+ if (first)
+ {
+ QueryPerformanceCounter(&lastTime);
+ QueryPerformanceFrequency(&freq);
+
+ first = false;
+ }
+
+ static double time = 0.0;
+
+ LARGE_INTEGER t;
+ QueryPerformanceCounter(&t);
+
+ __int64 delta = t.QuadPart-lastTime.QuadPart;
+ double deltaSeconds = double(delta) / double(freq.QuadPart);
+
+ time += deltaSeconds;
+
+ lastTime = t;
+
+ return time;
+
+}
+
+Gamepad::Gamepad()
+{
+}
+
+Gamepad::~Gamepad()
+{
+}
+
+Gamepad& Gamepad::Instance()
+{
+ static Gamepad gmpad;
+ return gmpad;
+}
+
+void ChangeMode()
+{
+ AppMainWindow::Inst().shortcut_expert();
+}
+
+void ToggleSimulation()
+{
+#ifndef NV_ARTISTTOOLS
+ BlastToolbar* toolbar = AppMainWindow::Inst().GetMainToolbar();
+ toolbar->on_btnEnableSimulation_clicked();
+ // read simulation state; have to call it twice to avoid change it.
+ GlobalSettings::Inst().toggleSimulation();
+
+ bool anim = GlobalSettings::Inst().toggleSimulation();
+ DisplayFurVisualizersPanel* furPanel = AppMainWindow::Inst().GetFurVisualizersPanel();
+ if(furPanel)
+ {
+ furPanel->on_btnShowHair_stateChanged(anim);
+ furPanel->updateValues();
+ }
+#else
+ CoreLib::Inst()->Gamepad_ToggleSimulation();
+#endif // NV_ARTISTTOOLS
+}
+
+void StartAnimation()
+{
+#ifndef NV_ARTISTTOOLS
+ GlobalSettings::Inst().toggleSimulation();
+ bool simulating = GlobalSettings::Inst().toggleSimulation(); // call it twice to get right state
+
+ GlobalSettings::Inst().toggleAnimation();
+ bool animating = GlobalSettings::Inst().toggleAnimation(); // call it twice to get right state
+
+ BlastToolbar* toolbar = AppMainWindow::Inst().GetMainToolbar();
+ if(!simulating)
+ toolbar->on_btnEnableSimulation_clicked();
+
+ if(!animating)
+ toolbar->on_btnPlayAnimation_clicked();
+
+ // reset animation
+ //toolbar->on_btnResetAnimation_clicked();
+#else
+ CoreLib::Inst()->Gamepad_StartAnimation();
+#endif // NV_ARTISTTOOLS
+}
+
+void ButtonAPressed()
+{
+ // Play/Pause the animation
+ Gamepad::PlayPauseAnimation();
+}
+
+void ButtonBPressed()
+{
+ // Stops and re-starts animation
+ Gamepad::ResetAnimation();
+}
+
+void Gamepad::ShowProjectName()
+{
+ bool bExpertMode = AppMainWindow::IsExpertMode();
+ // need change title
+ char msg[1024];
+ // show title
+ if(curentPrjIdx != -1)
+ {
+ QString fn = demoProjects.at(curentPrjIdx);
+ sprintf(msg, "Blast Viewer - %s %s", fn.toUtf8().data(), (bExpertMode ? "Demo Mode" : ""));
+ AppMainWindow::Inst().setWindowTitle(msg);
+ }
+ else
+ {
+ if (bExpertMode)
+ {
+ sprintf(msg, "Blast Viewer - Expert Mode");
+ }
+ else
+ {
+ sprintf(msg, "Blast Viewer");
+ }
+ AppMainWindow::Inst().setWindowTitle(msg);
+ }
+}
+
+void LoadSamples(bool bNext)
+{
+ bUseOldLightCam = bUseOldSceneCam = false;
+ int prjCount = demoProjects.size();
+ if(prjCount==0)
+ {
+ DisplayPreferencesPanel* pPanel = AppMainWindow::Inst().GetDisplayPreferencesPanel();
+ if (pPanel)
+ {
+ pPanel->assignPlayPlaylistToGamepad();
+ }
+ if (0)
+ {
+ static int iLimitSampleCount = 20;
+ QString appDir = strAppDir.c_str();
+ QString projectPath;
+ // load from a specific file first
+ QString fn = appDir + "\\samples.txt";
+ FILE* fp = fopen(fn.toUtf8().data(), "r");
+ if (fp)
+ {
+ char Line[1024], FileName[2014];
+ while (fgets(Line, sizeof(Line), fp) != NV_NULL)
+ {
+ QString t = QString(Line).trimmed();
+ if (t.length() == 0)
+ continue;
+ QString fn = t.toLower();
+ std::string strFN = fn.toUtf8().data();
+ const char* ptest = strstr(strFN.c_str(), ".furproj");
+ if (ptest)
+ {
+ const char* pchar = strchr(strFN.c_str(), ':');
+ if (pchar)
+ {
+ demoProjects.append(fn);
+ }
+ else
+ {
+ const char* pFirst = strFN.c_str();
+ if (pFirst[0] == '/' || pFirst[0] == '\\')
+ {
+ fn = appDir + fn;
+ demoProjects.append(fn);
+ }
+ else
+ {
+ fn = appDir + QString("/") + fn;
+ demoProjects.append(fn);
+ }
+ }
+ }
+ }
+ fclose(fp);
+ }
+ }
+ if(0)
+ {
+ QString appDir = strAppDir.c_str();
+ QString projectPath;
+ // search some relative folders
+ QDir dirTmp(appDir);
+ if(dirTmp.cd("./media"))
+ projectPath = dirTmp.absolutePath();
+ else if(dirTmp.cd("../media"))
+ projectPath = dirTmp.absolutePath();
+ else if(dirTmp.cd("../../media"))
+ projectPath = dirTmp.absolutePath();
+ else if(dirTmp.cd("../../media"))
+ projectPath = dirTmp.absolutePath();
+ if(!projectPath.isEmpty())
+ {
+ QStringList filters;
+ filters<<QString("*.furproj");
+ QDirIterator dir_iterator(projectPath, filters, QDir::Files | QDir::NoSymLinks,QDirIterator::Subdirectories);
+ while(dir_iterator.hasNext())
+ {
+ dir_iterator.next();
+ QFileInfo file_info = dir_iterator.fileInfo();
+ QString absolute_file_path = file_info.absoluteFilePath();
+ demoProjects.append(absolute_file_path);
+ //if(demoProjects.size()>iLimitSampleCount)
+ // break;
+ }
+ }
+ else
+ {
+ const char* msg = "Fail to find any Blast projects!";
+ viewer_msg(msg);
+ }
+ }
+ prjCount = demoProjects.size();
+ }
+ if(prjCount)
+ {
+ if (bNext)
+ {
+ ++curentPrjIdx;
+ if (curentPrjIdx >= prjCount)
+ curentPrjIdx = 0;
+ }
+ else
+ {
+ --curentPrjIdx;
+ if (curentPrjIdx < 0)
+ curentPrjIdx = prjCount - 1;
+ }
+ // load sample
+ QString fn = demoProjects[curentPrjIdx];
+ AppMainWindow::Inst().openProject(fn);
+ }
+ Gamepad::ShowProjectName();
+}
+
+void StartButtonPressed()
+{
+ Gamepad& gp = Gamepad::Instance();
+ gp.ShowUsage();
+}
+
+void BackButtonPressed()
+{
+ Gamepad::DemoEscape();
+ return;
+
+ ++iQuitState;
+ switch(iQuitState)
+ {
+ case 0:
+ // do nothing
+ break;
+ case 1:
+ {
+ AppMainWindow::Inst().startProgress();
+ AppMainWindow::Inst().setProgressMaximum(2);
+ AppMainWindow::Inst().setProgress("Press Back again to quit. Press other buttons to cancel it.", 1);
+ }
+ break;
+ case 2:
+ {
+ AppMainWindow::Inst().setProgress("Quitting...", 2);
+ //AppMainWindow::Inst().close();
+ Gamepad::DemoEscape();
+ }
+ break;
+ default:
+ iQuitState = 0;
+ break;
+ }
+}
+
+void Gamepad::HandleJoySticks()
+{
+ int numJoysticks = SDL_NumJoysticks();
+ int numUsedJoysticks = gHandlers.size();
+ if (numUsedJoysticks != numJoysticks)
+ {
+ gHandlers.clear();
+ }
+ if(numUsedJoysticks < 1)
+ {
+ //static int iSkipCount = 0;
+ //if (++iSkipCount >= 60)
+ //{
+ // iSkipCount = 0;
+ static int iDoOnce = 1;
+ if (iDoOnce)
+ {
+ iDoOnce = 0;
+
+ Initialize();
+ numJoysticks = SDL_NumJoysticks();
+ for (int i = 0; i < numJoysticks; ++i)
+ {
+ SDL_Joystick* joystick = SDL_JoystickOpen(i);
+ if (joystick)
+ {
+ numUsedJoysticks = gHandlers.size();
+ gHandlers.resize(numUsedJoysticks + 1);
+ GamepadHandler& handler = gHandlers[numUsedJoysticks];
+ handler.joystick = joystick;
+ handler.pjsName = SDL_JoystickName(joystick);
+ handler.numAxis = SDL_JoystickNumAxes(joystick);
+ handler.numTrackballs = SDL_JoystickNumBalls(joystick);
+ handler.numPov = SDL_JoystickNumHats(joystick);
+ handler.numButtons = SDL_JoystickNumButtons(joystick);
+ handler.jsGuid = SDL_JoystickGetGUID(joystick);
+
+ LogAdd("Device Name: %s", handler.pjsName);
+ LogAdd("Num of Axis: %d", handler.numAxis);
+ LogAdd("Num of Trackballs: %d", handler.numTrackballs);
+ LogAdd("Num of POV: %d", handler.numPov);
+ LogAdd("Num of Buttons: %d", handler.numButtons);
+ LogAdd("Initial Axis States:");
+
+ handler.iAxisState.resize(handler.numAxis);
+ handler.iAxisStateAtBegin.resize(handler.numAxis);
+ handler.iAxisStateOld.resize(handler.numAxis);
+
+ handler.iButtonState.resize(handler.numButtons);
+ handler.iButtonStateOld.resize(handler.numButtons);
+
+ if (handler.numAxis == 6)
+ {
+ // XBOX 360 has 6 axis
+ AXIS_LS_X = 0;
+ AXIS_LS_Y = 1;
+ AXIS_RS_X = 2;
+ AXIS_RS_Y = 3;
+ AXIS_LT = 4;
+ AXIS_RT = 5;
+
+ GAMEPAD_KEY_DPAD_UP = 0;
+ GAMEPAD_KEY_DPAD_DOWN = 1;
+ GAMEPAD_KEY_DPAD_LEFT = 2;
+ GAMEPAD_KEY_DPAD_RIGHT = 3;
+ GAMEPAD_KEY_START = 4;
+ GAMEPAD_KEY_BACK = 5;
+ GAMEPAD_KEY_LS = 6;
+ GAMEPAD_KEY_RS = 7;
+ GAMEPAD_KEY_LEFT_BUMP = 8;
+ GAMEPAD_KEY_RIGHT_BUMP = 9;
+ GAMEPAD_KEY_A = 10;
+ GAMEPAD_KEY_B = 11;
+ GAMEPAD_KEY_X = 12;
+ GAMEPAD_KEY_Y = 13;
+ }
+ else if (handler.numAxis == 5)
+ {
+ // Betop has 5 axis when xbox mode
+ AXIS_LS_X = 0;
+ AXIS_LS_Y = 1;
+ AXIS_RS_X = 3;
+ AXIS_RS_Y = 4;
+ AXIS_LT = 2;
+ AXIS_RT = 2;
+
+ GAMEPAD_KEY_DPAD_UP = 10; // POV
+ GAMEPAD_KEY_DPAD_DOWN = 11; // POV
+ GAMEPAD_KEY_DPAD_LEFT = 12; // POV
+ GAMEPAD_KEY_DPAD_RIGHT = 13; // POV
+ GAMEPAD_KEY_START = 7;
+ GAMEPAD_KEY_BACK = 6;
+ GAMEPAD_KEY_LS = 8;
+ GAMEPAD_KEY_RS = 9;
+ GAMEPAD_KEY_LEFT_BUMP = 4;
+ GAMEPAD_KEY_RIGHT_BUMP = 5;
+ GAMEPAD_KEY_A = 0;
+ GAMEPAD_KEY_B = 1;
+ GAMEPAD_KEY_X = 2;
+ GAMEPAD_KEY_Y = 3;
+
+ if (handler.numPov == 1)
+ {
+ // BETOP xbox mode
+ handler.iButtonState.resize(handler.numButtons + 4); // POV fake buttons
+ handler.iButtonStateOld.resize(handler.numButtons + 4);
+ for (int i = GAMEPAD_KEY_DPAD_UP; i <= GAMEPAD_KEY_DPAD_RIGHT; ++i)
+ {
+ handler.iButtonStateOld[i] = handler.iButtonState[i] = 0;
+ }
+ }
+ }
+ for (int i = 0; i < handler.numAxis; ++i)
+ {
+ int value = ClampAxis(SDL_JoystickGetAxis(handler.joystick, i));
+ handler.iAxisStateAtBegin[i] = handler.iAxisStateOld[i] = handler.iAxisState[i] = value;
+ LogAdd("Axis %d State %d", i, value);
+ }
+ LogAdd("Initial Button States:");
+ for (int i = 0; i < handler.numButtons; ++i)
+ {
+ int state = SDL_JoystickGetButton(handler.joystick, i);
+ handler.iButtonStateOld[i] = handler.iButtonState[i] = state;
+ LogAdd("Button %d State %d", i, state);
+ }
+ if (handler.numPov == 1)
+ {
+ LogAdd("Initial POV Button States:");
+ Uint8 pov = SDL_JoystickGetHat(joystick, 0);
+ char msg[512];
+ sprintf(msg, "POV State: %d", pov);
+ viewer_msg(msg);
+ LogAdd(msg);
+ // BETOP xbox mode
+ handler.iButtonState.resize(handler.numButtons + 4); // POV fake buttons
+ handler.iButtonStateOld.resize(handler.numButtons + 4);
+ for (int i = GAMEPAD_KEY_DPAD_UP; i <= GAMEPAD_KEY_DPAD_RIGHT; ++i)
+ {
+ handler.iButtonStateOld[i] = handler.iButtonState[i] = 0;
+ LogAdd("POV Button %d State %d", i, 0);
+ }
+ }
+ SDL_JoystickEventState(SDL_IGNORE);
+ }
+ }
+ }
+ }
+ else
+ {
+ ManualReadGamepad();
+ }
+}
+
+bool Gamepad::Initialize()
+{
+ if (strAppDir.size() < 1)
+ {
+ strAppDir = qApp->applicationDirPath().toUtf8().data();
+ }
+
+ SDL_Quit();
+ // init SDL
+ // my Gamepad does not work with SDL_INIT_EVERYTHING. Just init the ones we use.
+ int ret = SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS);
+ return (ret == 0);
+}
+
+void Gamepad::Free()
+{
+ if (bSaveLogToDisk)
+ {
+ SaveLog();
+ }
+
+ if(int count = gHandlers.size())
+ {
+ for(int i = 0; i<count; ++i)
+ gHandlers[i].DisConnect();
+ }
+ SDL_Quit();
+}
+
+void ShowUsageInViewport()
+{
+ bool bDemoMode = AppMainWindow::IsExpertMode();
+ if(bDemoMode && bDefaultDemoMode)
+ {
+ int w = theScene->GetCamera()->GetWidth();
+ int h = theScene->GetCamera()->GetHeight();
+ //CDXUTTextHelper* pTxtHelper = theScene->GetRenderWindow()->GetTextHelper();
+
+ //pTxtHelper->Begin();
+ //pTxtHelper->SetInsertionPos(w/5, h-80);
+ //pTxtHelper->SetForegroundColor(D3DXCOLOR(1.0f, 1.0f, 0.0f, 0.8f));
+
+ //pTxtHelper->DrawTextLine(L"Start: Load a sample Back: Quit Demo");
+ //pTxtHelper->DrawTextLine(L"A: Stop/Restart Animation B: Pause/Continue Animation X: Start/Pause Simulation Y: Demo/Export Switch");
+ //pTxtHelper->DrawTextLine(L"Left Stick: Zoom In/Out Right Stick: Control Camera Cross/Trigger: Scene HUD and Stats On/Off");
+ //pTxtHelper->DrawTextLine(L"RB & LS: Wind Direction RB & RS: Wind Strength LB & LS: Light Control");
+ //pTxtHelper->End();
+ }
+}
+
+void Gamepad::ShowUsage()
+{
+ viewer_msg("Start: Show Gamepad Usage");
+ viewer_msg("Back: Quit the Blast Viewer");
+ viewer_msg("LBump: Load previous demo RBump: Load next sample");
+ viewer_msg("B: Reset Animation A: Play/Pause Animation");
+ viewer_msg("Y: Demo View On/Off X: Show/Hide the selected Hair");
+ viewer_msg("LStick: Zoom in and out RStick: Rotate the camera");
+ viewer_msg("D-Pad Up: Show/Hide HUD D-Pad Left: Show/Hide Stats");
+ viewer_msg("RTrigger & LStick: Wind Direction RTrigger & RStick: Wind Strength");
+ viewer_msg("LTrigger & LStick: Move Light");
+}
+
+
+void Gamepad::ResetScene()
+{
+#ifndef NV_ARTISTTOOLS
+ BlastToolbar* toolbar = AppMainWindow::Inst().GetMainToolbar();
+
+ GlobalSettings::Inst().toggleSimulation();
+ bool bSimulating = GlobalSettings::Inst().toggleSimulation(); // call it twice to get right state
+ if(bSimulating)
+ {
+ toolbar->on_btnEnableSimulation_clicked(); // stop simulation when stop animation
+ }
+
+ DisplayFurVisualizersPanel* furPanel = AppMainWindow::Inst().GetFurVisualizersPanel();
+ if(furPanel)
+ {
+ furPanel->on_btnShowHair_stateChanged(true); // show hair
+ furPanel->updateValues();
+ }
+
+ GlobalSettings::Inst().toggleAnimation();
+ bool anim = GlobalSettings::Inst().toggleAnimation(); // call it twice to get right state
+ if(anim)
+ {
+ toolbar->on_btnPlayAnimation_clicked(); // stop animation
+ }
+
+ toolbar->on_btnResetAnimation_clicked(); // reset animation
+
+ toolbar->on_spinWindStrength_valueChanged(0.0f);
+ toolbar->updateValues();
+#else
+ CoreLib::Inst()->Gamepad_ResetScene();
+#endif // NV_ARTISTTOOLS
+
+ Light* pLight = NV_NULL;
+ pLight = Light::GetFirstSelectedLight();
+
+ static Camera oldLightCam, oldSceneCam;
+ // restore old camera
+ if(bUseOldSceneCam)
+ {
+ *(theScene->GetCamera()) = oldSceneCam;
+ //theScene->FitCamera();
+ }
+ else
+ {
+ oldSceneCam = *theScene->GetCamera();
+ bUseOldSceneCam = true;
+ }
+ // restore light camera
+ if(pLight)
+ {
+ //pLight->FitBounds(true);
+ if(bUseOldLightCam)
+ {
+// pLight->getCamera() = oldLightCam;
+ }
+ else
+ {
+// oldLightCam = pLight->getCamera();
+// pLight->FitBounds();
+ bUseOldLightCam = true;
+ }
+ }
+ theScene->SetProjectModified(true);
+}
+
+bool Gamepad::IsDemoMode()
+{
+ return AppMainWindow::IsExpertMode();
+}
+
+void Gamepad::SetDemoProjects(QList<QString>& projects)
+{
+ demoProjects = projects;
+}
+
+void Gamepad::Process()
+{
+ if (AppMainWindow::IsExpertMode() == false)
+ {
+ static bool bFirstTime = true;
+ if (bFirstTime)
+ {
+ bFirstTime = false;
+ DisplayPreferencesPanel* pPanel = AppMainWindow::Inst().GetDisplayPreferencesPanel();
+ if (pPanel)
+ {
+ pPanel->runDemoCommandline();
+ return;
+ }
+ }
+ }
+
+ HandleJoySticks();
+
+ if (theScene == 0)
+ {
+ theScene = SimpleScene::Inst();
+ return;
+ }
+
+ //ShowUsageInViewport();
+}
+
+
+void Gamepad::ManualReadGamepad()
+{
+ SDL_JoystickUpdate();
+ if(int count = gHandlers.size())
+ {
+ for(int i = 0; i < count; ++i)
+ gHandlers[i].Process();
+ }
+}
+
+void GamepadHandler::Process()
+{
+ for(int i = 0; i < numAxis; ++i)
+ {
+ int value = ClampAxis(SDL_JoystickGetAxis(joystick, i));
+ iAxisState[i] = value;
+ if(iAxisStateOld[i] != value)
+ {
+ char msg[512];
+ sprintf(msg, "Axis changes: %d %d", i, value);
+#ifdef _DEBUG
+ viewer_msg(msg);
+#endif
+ LogAdd(msg);
+ }
+ }
+
+ bool bCancelQuit = false;
+ for(int i = 0; i < numButtons; ++i)
+ {
+ int state = SDL_JoystickGetButton(joystick, i);
+ iButtonState[i] = state;
+ if(iButtonStateOld[i] != state)
+ {
+ char msg[512];
+ sprintf(msg, "Button changes: %d %d (%d)", i, state, iButtonStateOld[i]);
+#ifdef _DEBUG
+ viewer_msg(msg);
+#endif
+ LogAdd(msg);
+ }
+ if(i != GAMEPAD_KEY_BACK && ButtonState(i) == BUTTON_UP)
+ {
+ //bCancelQuit = true;
+ }
+ }
+
+ if (numPov == 1)
+ {
+ // BETOP xbox mode
+ Uint8 pov = SDL_JoystickGetHat(joystick, 0);
+ switch (pov)
+ {
+ case SDL_HAT_UP:
+ iButtonState[GAMEPAD_KEY_DPAD_UP] = 1;
+ break;
+ case SDL_HAT_RIGHT:
+ iButtonState[GAMEPAD_KEY_DPAD_RIGHT] = 1;
+ break;
+ case SDL_HAT_DOWN:
+ iButtonState[GAMEPAD_KEY_DPAD_DOWN] = 1;
+ break;
+ case SDL_HAT_LEFT:
+ iButtonState[GAMEPAD_KEY_DPAD_LEFT] = 1;
+ break;
+ case SDL_HAT_RIGHTUP:
+ iButtonState[GAMEPAD_KEY_DPAD_RIGHT] = 1;
+ iButtonState[GAMEPAD_KEY_DPAD_UP] = 1;
+ break;
+ case SDL_HAT_RIGHTDOWN:
+ iButtonState[GAMEPAD_KEY_DPAD_RIGHT] = 1;
+ iButtonState[GAMEPAD_KEY_DPAD_DOWN] = 1;
+ break;
+ case SDL_HAT_LEFTUP:
+ iButtonState[GAMEPAD_KEY_DPAD_LEFT] = 1;
+ iButtonState[GAMEPAD_KEY_DPAD_UP] = 1;
+ break;
+ case SDL_HAT_LEFTDOWN:
+ iButtonState[GAMEPAD_KEY_DPAD_LEFT] = 1;
+ iButtonState[GAMEPAD_KEY_DPAD_DOWN] = 1;
+ break;
+ default:
+ for (int i = GAMEPAD_KEY_DPAD_UP; i <= GAMEPAD_KEY_DPAD_RIGHT; ++i)
+ {
+ iButtonState[i] = 0;
+ }
+ }
+ if (pov != SDL_HAT_CENTERED)
+ {
+ char msg[512];
+ sprintf(msg, "POV State: %d", pov);
+ viewer_msg(msg);
+ LogAdd(msg);
+ for (int i = GAMEPAD_KEY_DPAD_UP; i <= GAMEPAD_KEY_DPAD_RIGHT; ++i)
+ {
+ if (ButtonState(i) == BUTTON_DOWN)
+ {
+ sprintf(msg, "POV Button Down: %d", i);
+ viewer_msg(msg);
+ LogAdd(msg);
+ }
+ }
+ }
+ }
+
+ //bool bLeftBump = iButtonState[GAMEPAD_KEY_LEFT_BUMP], bRightBump = iButtonState[GAMEPAD_KEY_RIGHT_BUMP];
+ bool bLeftTrigger = false, bRightTrigger = false;
+ double currentTime = GetSeconds(); // real elapsed frame time
+ static double lastJoyTime = currentTime;
+
+ if(ButtonState(GAMEPAD_KEY_BACK) == BUTTON_UP)
+ {
+ BackButtonPressed();
+ }
+ if(iQuitState && bCancelQuit)
+ {
+ AppMainWindow::Inst().setProgress("Cancel quitting.", 2);
+ iQuitState = 0;
+ }
+ else
+ {
+ bCancelQuit = false;
+ }
+
+ if(!bCancelQuit)
+ {
+ if(ButtonState(GAMEPAD_KEY_START) == BUTTON_UP)
+ {
+ StartButtonPressed();
+ }
+ if (ButtonState(GAMEPAD_KEY_RIGHT_BUMP) == BUTTON_UP)
+ {
+ // next proj
+ Gamepad::DemoNext();
+ }
+ if (ButtonState(GAMEPAD_KEY_LEFT_BUMP) == BUTTON_UP)
+ {
+ // prev proj
+ Gamepad::DemoPrev();
+ }
+ if (ButtonState(GAMEPAD_KEY_B) == BUTTON_UP)
+ {
+ viewer_msg("B Pressed");
+ ButtonBPressed();
+ }
+ if(ButtonState(GAMEPAD_KEY_A) == BUTTON_UP)
+ {
+ viewer_msg("A Pressed");
+ ButtonAPressed();
+ }
+ if (ButtonState(GAMEPAD_KEY_Y) == BUTTON_UP)
+ {
+ viewer_msg("Y Pressed");
+ ChangeMode();
+ }
+ if(ButtonState(GAMEPAD_KEY_X) == BUTTON_UP)
+ {
+ viewer_msg("X Pressed");
+#ifndef NV_ARTISTTOOLS
+ // Show/hide selected hair
+ bool v = false;
+ theScene->GetFurCharacter().GetHairParam(HAIR_PARAMS_DRAW_RENDER_HAIRS, &v);
+ DisplayFurVisualizersPanel* furPanel = AppMainWindow::Inst().GetFurVisualizersPanel();
+ if (furPanel)
+ {
+ furPanel->on_btnShowHair_stateChanged(!v);
+ }
+#else
+ CoreLib::Inst()->GamepadHandler_ShowHair();
+#endif // NV_ARTISTTOOLS
+ }
+ if(ButtonState(GAMEPAD_KEY_DPAD_LEFT) == BUTTON_DOWN)
+ {
+ // Show/Hide Stats
+ Gamepad::ShowHideStats();
+ }
+ if(ButtonState(GAMEPAD_KEY_DPAD_RIGHT) == BUTTON_DOWN)
+ {
+ }
+ if(ButtonState(GAMEPAD_KEY_DPAD_UP) == BUTTON_DOWN)
+ {
+ // show/hide HUD
+ Gamepad::ShowHideHud();
+ }
+ if(ButtonState(GAMEPAD_KEY_DPAD_DOWN) == BUTTON_DOWN)
+ {
+ }
+ }
+
+ //const float g_dt = 1.0f/120.0f; // the time delta used for simulation
+ if (numAxis == 6)
+ {
+ // XBOX 360 has 6 axis
+ int iLTChange = AxisChange(AXIS_LT);
+ int iRTChange = AxisChange(AXIS_RT);
+ if (iLTChange > 30000)
+ {
+ bLeftTrigger = true;
+ }
+ if (iRTChange > 30000)
+ {
+ bRightTrigger = true;
+ }
+ }
+ else if(numAxis == 5)
+ {
+ // Betop has 5 axis when x360 mode
+ int iLTChange = AxisChange(AXIS_LT);
+ int iRTChange = AxisChange(AXIS_RT);
+ if (iLTChange>15000)
+ {
+ bLeftTrigger = true;
+ }
+ if (iRTChange < -15000)
+ {
+ bRightTrigger = true;
+ }
+ }
+ if (1)
+ {
+ static float zoomSpeed = 0.1f;
+ static float rotateSpeed = 2.5f;
+
+ float deltaTime = (currentTime - lastJoyTime);
+ lastJoyTime = currentTime;
+
+ const float jsFactor = 1.0f/32768.0f;
+ int iLSX = AxisChange(AXIS_LS_X);
+ int iLSY = AxisChange(AXIS_LS_Y);
+ if(iLSX != 0 || iLSY != 0)
+ {
+ // left stick
+ float forceLSX = iLSX * jsFactor;
+ float forceLSY = iLSY * jsFactor;
+ if(bLeftTrigger || bRightTrigger)
+ {
+ if(bRightTrigger)
+ {
+ // wind direction
+ atcore_float3 direct = gfsdk_makeFloat3(forceLSX, forceLSY, 0.1f);
+ gfsdk_normalize(direct);
+
+ GlobalSettings::Inst().m_windDir = direct;
+ theScene->SetProjectModified(true);
+ }
+ if(bLeftTrigger)
+ {
+ // light direction
+ {
+ Light* pLight = Light::GetFirstSelectedLight();
+ if (pLight)
+ {
+ atcore_float2 delta = gfsdk_makeFloat2(forceLSX, forceLSY);
+ delta = 10.0f * delta;
+ pLight->Orbit(delta); // unit is in degree(s)
+ theScene->SetProjectModified(true);
+ }
+ }
+ }
+ }
+ else
+ {
+ if(iLSY != 0)
+ {
+ // zoom in/out
+ theScene->GetCamera()->Dolly(zoomSpeed * forceLSY);
+ theScene->SetProjectModified(true);
+ }
+ }
+ }
+ int iRSX = AxisChange(AXIS_RS_X);
+ int iRSY = AxisChange(AXIS_RS_Y);
+ if(iRSX != 0 || iRSY != 0)
+ {
+ float forceX = iRSX * jsFactor;
+ float forceY = iRSY * jsFactor;
+ if(bRightTrigger)
+ {
+ if (iRSX != 0)
+ {
+ // wind strength, Press right to increase. Press left to decrease
+ static float windStrength = 0.0f;
+ static float fStep = 0.1f;
+ if (iRSX > 0)
+ windStrength += fStep;
+ else
+ windStrength -= fStep;
+ if (windStrength > 10.0f)
+ windStrength = 10.0f;
+ if (windStrength < 0.0f)
+ windStrength = 0.0f;
+
+#ifndef NV_ARTISTTOOLS
+ BlastToolbar* toolbar = AppMainWindow::Inst().GetMainToolbar();
+ toolbar->on_spinWindStrength_valueChanged(windStrength);
+ toolbar->updateValues();
+#else
+ CoreLib::Inst()->GamepadHandler_SpinWindStrength(windStrength);
+#endif // NV_ARTISTTOOLS
+ }
+ }
+ else
+ {
+ // rotate camera
+ atcore_float2 moveRightStick = gfsdk_makeFloat2(forceX, forceY);
+ theScene->GetCamera()->Orbit(moveRightStick*rotateSpeed);
+ theScene->SetProjectModified(true);
+ }
+ }
+ }
+ //if(numAxis>5)
+ //{
+ //// XBOX 360 has 6 axis
+ //if((iAxisState[4]>=0) && (iAxisStateOld[4]<0))
+ //{
+ // bool bShow = ! GlobalSettings::Inst().m_showHUD;
+ // DisplayScenePanel* pspanel = AppMainWindow::Inst().GetDisplayScenePanel();
+ // if(pspanel)
+ // {
+ // pspanel->on_btnShowHUD_stateChanged(bShow);
+ // pspanel->on_btnComputeStats_stateChanged(false);
+ // }
+ //}
+ //if((iAxisState[5]>=0) && (iAxisStateOld[5]<0))
+ //{
+ // bool bShow = ! GlobalSettings::Inst().m_computeStatistics;
+ // DisplayScenePanel* pspanel = AppMainWindow::Inst().GetDisplayScenePanel();
+ // if(pspanel)
+ // {
+ // DisplayScenePanel* pspanel = AppMainWindow::Inst().GetDisplayScenePanel();
+ // if(pspanel)
+ // {
+ // // HUD controls stats
+ // pspanel->on_btnComputeStats_stateChanged(bShow);
+ // pspanel->on_btnShowHUD_stateChanged(bShow);
+ // }
+ // }
+ //}
+ //}
+ for(int i = 0; i < numAxis; ++i)
+ {
+ //if(iAxisStateOld[i] != iAxisState[i])
+ //{
+ // char msg[512];
+ // sprintf(msg, "Axis: %d %d", i, iAxisState[i]);
+ // viewer_msg(msg);
+ //}
+ iAxisStateOld[i] = iAxisState[i];
+ }
+
+ for(int i = 0; i < numButtons; ++i)
+ {
+ iButtonStateOld[i] = iButtonState[i];
+ }
+
+ if (numPov == 1)
+ {
+ for (int i = GAMEPAD_KEY_DPAD_UP; i <= GAMEPAD_KEY_DPAD_RIGHT; ++i)
+ {
+ iButtonStateOld[i] = iButtonState[i];
+ }
+ }
+}
+
+//void Gamepad::ClearStates()
+//{
+// for(int i = 0; i < iStateSize; ++i)
+// {
+// bKeyHolding[i] = 0;
+//
+// iAxisStateOld[i] = 0;
+// iAxisState[i] = 0;
+// iButtonStateOld[i] = 0;
+// iButtonState[i] = 0;
+// }
+//}
+
+void Gamepad::ShowHideHud()
+{
+ static bool bShowHud = true;
+ DisplayScenePanel* pspanel = AppMainWindow::Inst().GetDisplayScenePanel();
+ if (pspanel)
+ {
+ // HUD controls stats
+ pspanel->on_btnShowHUD_stateChanged(bShowHud);
+ pspanel->on_btnComputeStats_stateChanged(false);
+ bShowHud = !bShowHud;
+ }
+}
+
+void Gamepad::ShowHideStats()
+{
+ static bool bShowStats = true;
+ DisplayScenePanel* pspanel = AppMainWindow::Inst().GetDisplayScenePanel();
+ if (pspanel)
+ {
+ // HUD controls stats
+ pspanel->on_btnComputeStats_stateChanged(bShowStats);
+ pspanel->on_btnShowHUD_stateChanged(bShowStats);
+ bShowStats = !bShowStats;
+ }
+}
+
+void Gamepad::QuitApp()
+{
+ AppMainWindow::Inst().close();
+}
+
+void Gamepad::ResetAnimation()
+{
+#ifndef NV_ARTISTTOOLS
+ GlobalSettings::Inst().toggleSimulation();
+ bool simulating = GlobalSettings::Inst().toggleSimulation(); // call it twice to get right state
+
+ GlobalSettings::Inst().toggleAnimation();
+ bool animating = GlobalSettings::Inst().toggleAnimation(); // call it twice to get right state
+
+ BlastToolbar* toolbar = AppMainWindow::Inst().GetMainToolbar();
+ if (!simulating)
+ {
+ toolbar->on_btnEnableSimulation_clicked();
+ }
+ if (!animating)
+ {
+ toolbar->on_btnPlayAnimation_clicked();
+ }
+ toolbar->on_btnResetAnimation_clicked();
+#else
+ CoreLib::Inst()->Gamepad_ResetAnimation();
+#endif // NV_ARTISTTOOLS
+}
+
+void Gamepad::PlayPauseAnimation()
+{
+#ifndef NV_ARTISTTOOLS
+ GlobalSettings::Inst().toggleSimulation();
+ bool simulating = GlobalSettings::Inst().toggleSimulation(); // call it twice to get right state
+
+ GlobalSettings::Inst().toggleAnimation();
+ bool animating = GlobalSettings::Inst().toggleAnimation(); // call it twice to get right state
+
+ BlastToolbar* toolbar = AppMainWindow::Inst().GetMainToolbar();
+ if (simulating != animating)
+ {
+ toolbar->on_btnEnableSimulation_clicked();
+ }
+ toolbar->on_btnEnableSimulation_clicked();
+ toolbar->on_btnPlayAnimation_clicked();
+#else
+ CoreLib::Inst()->Gamepad_PlayPauseAnimation();
+#endif // NV_ARTISTTOOLS
+}
+
+void Gamepad::DemoModeOnOff()
+{
+ ChangeMode();
+}
+
+void Gamepad::DemoNext()
+{
+ LoadSamples(true);
+ StartAnimation();
+}
+
+void Gamepad::DemoPrev()
+{
+ LoadSamples(false);
+ StartAnimation();
+}
+
+void Gamepad::SetDemoMode(bool onOff)
+{
+ //if (AppMainWindow::IsExpertMode() != onOff)
+ //{
+ // ChangeMode();
+ //}
+ if (onOff)
+ {
+ curentPrjIdx = -1; // make it start from first demo
+ DemoNext();
+
+ // turn off FPS display
+ GlobalSettings::Inst().m_showFPS = false;
+ }
+ else
+ {
+ ShowUsage();
+ }
+ ChangeMode();
+}
+
+void Gamepad::DemoEscape()
+{
+ if (AppMainWindow::IsExpertMode())
+ {
+ ChangeMode();
+ // hide HUD if it is on. for GWDCC - 393 Blast Viewer - play list stats
+ DisplayScenePanel* pspanel = AppMainWindow::Inst().GetDisplayScenePanel();
+ if (pspanel)
+ {
+ // HUD controls stats
+ pspanel->on_btnShowHUD_stateChanged(false);
+ pspanel->on_btnComputeStats_stateChanged(false);
+ }
+ }
+ //else
+ //{
+ // QuitApp();
+ //}
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Gamepad.h b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Gamepad.h
new file mode 100644
index 0000000..46d45ba
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Gamepad.h
@@ -0,0 +1,68 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+class SimpleScene;
+
+class Gamepad
+{
+public:
+ Gamepad();
+ ~Gamepad();
+
+ static Gamepad& Instance();
+
+ void Process();
+ bool Initialize();
+ void Free();
+
+ bool IsDemoMode();
+
+ void SetDemoProjects(QList<QString>& projects);
+
+ static void DemoNext();
+ static void DemoPrev();
+ static void ShowProjectName();
+ static void ShowHideHud();
+ static void ShowHideStats();
+ static void QuitApp();
+ static void ResetAnimation();
+ static void PlayPauseAnimation();
+ static void DemoModeOnOff();
+ static void DemoEscape();
+ static void SetDemoMode(bool onOff);
+ static void ShowUsage();
+
+private:
+ void ResetScene();
+ void ManualReadGamepad();
+
+ void HandleJoySticks();
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/GlobalSettings.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/GlobalSettings.cpp
new file mode 100644
index 0000000..42febc1
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/GlobalSettings.cpp
@@ -0,0 +1,310 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#include "GlobalSettings.h"
+#include <QtCore/QTimer>
+#include "Settings.h"
+
+static GlobalSettings g_settings;
+static QTimer g_frameTimer(NV_NULL);
+
+////////////////////////////////////////////////////////////////////////////////////////////
+GlobalSettings::GlobalSettings()
+{
+ Init();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+GlobalSettings& GlobalSettings::Inst()
+{
+ return g_settings;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+QTimer& GlobalSettings::GetFrameTimer()
+{
+ return g_frameTimer;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+void
+GlobalSettings::Init()
+{
+ m_animate = false;
+ m_simulate = true;
+ m_simulateStep = false;
+ m_firstFrame = true;
+ m_resetAnimationOnLoop = true;
+
+ m_animationFps = 24.0f;
+ m_repeatAnimation = true;
+ m_frameTime = 0.0f;
+ m_animationSpeed = 1.0f;
+ m_playStopped = false;
+ m_currentBoneIndex = 0;
+
+ m_simulationFrameCalc.init(0, 1.0f / 60.0f);
+ m_simulationFps = 60.0f;
+ m_timeStep = 0.0f;
+
+ m_visualizeWind = false;
+ m_showGraphicsMesh = true;
+ m_showWireframe = false;
+ m_showHUD = false;
+ m_visualizeBoneNames = false;
+
+ m_computeStatistics = false;
+ m_computeProfile = false;
+ m_previewLOD = false;
+ m_renderStyle = MESH_RENDER_TEXTURED;
+
+ m_sceneLoaded = false;
+ m_useDQ = false;
+ m_zup = false;
+ m_lhs = false;
+
+ m_sceneUnitIndex = SCENE_UNIT_CENTIMETER; // default to use cm
+
+ m_showGrid = true;
+ m_showAxis = true;
+
+ m_fovAngle = 75.0f;
+
+ m_loadTextures = true;
+ m_loadMaterials = true;
+ m_loadGroom = true;
+ m_loadCollision = true;
+ m_loadConstraints = true;
+
+ m_msaaOption = 0;
+
+ m_windDir.x = 0;
+ m_windDir.y = -1.0f;
+ m_windDir.z = 0.5f;
+ m_windStrength = 0.0f;
+ m_windNoise = 0.0f;
+
+ m_frameStartTime = 0.0f;
+ m_frameEndTime = 100.0f;
+
+ m_animationIndex = 0;
+
+ m_lockRootBone = false;
+
+ m_controlTextureOption = 0;
+ m_showSkinnedMeshOnly = false;
+
+ m_useLighting = true;
+ m_showFPS = true;
+
+ m_renderFrameCnt = 0;
+ m_renderFps = 60.0f;
+
+ m_projectFileDir = "";
+ m_projectFileName = "";
+ m_backgroundTextureFilePath = "";
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool GlobalSettings::toggleSimulation()
+{
+ m_simulate = !m_simulate;
+ m_simulateStep = false;
+
+ return m_simulate;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void GlobalSettings::stepSimulation()
+{
+ m_simulateStep = true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void GlobalSettings::setRenderFps(float fps)
+{
+ m_renderFps = fps;
+
+ OptionValue* option = nullptr;
+
+ option = AppSettings::Inst().GetOptionValue("User/PerfMode");
+ if (option)
+ {
+ if (option->Value.Bool == OA_TRUE)
+ {
+ g_frameTimer.setInterval(0);
+ }
+ else
+ g_frameTimer.setInterval((int)(1000 / fps));
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void GlobalSettings::setSimulationFps(float fps)
+{
+ m_simulationFps = fps;
+ m_simulationFrameCalc.setTimeStep(1.0f/ fps);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void GlobalSettings::resetAnimation()
+{
+ m_frameTime = m_frameStartTime;
+ m_firstFrame = m_resetAnimationOnLoop ? true : false;
+ m_playStopped = false;
+ m_simulateStep = true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void GlobalSettings::toggleAnimationRepeat()
+{
+ m_repeatAnimation = !m_repeatAnimation;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool GlobalSettings::toggleAnimation()
+{
+ m_animate = !m_animate;
+
+ if (m_animate && m_playStopped)
+ resetAnimation();
+
+ return m_animate;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void GlobalSettings::stepAnimation()
+{
+ if (!m_sceneLoaded)
+ return;
+
+ if (m_repeatAnimation)
+ m_playStopped = false;
+
+ if (!m_playStopped)
+ m_frameTime += m_animationSpeed * m_animationFps * m_timeStep;
+
+ if (m_frameTime > m_frameEndTime)
+ {
+ if (m_repeatAnimation)
+ resetAnimation();
+ else
+ {
+ m_frameTime = m_frameEndTime;
+ m_playStopped = true;
+ m_animate = false;
+ }
+ }
+
+ if (!m_animate)
+ {
+ stepSimulation();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void GlobalSettings::setSceneUnitIndex(int i)
+{
+ if (i < 0)
+ return;
+
+ if (i >= SCENE_UNIT_END)
+ return;
+
+ m_sceneUnitIndex = i;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+float GlobalSettings::getSceneUnitInCentimeters()
+{
+ float unit = 1.0f;
+
+ switch (m_sceneUnitIndex)
+ {
+ case SCENE_UNIT_CENTIMETER:
+ unit = 1.0f;
+ break;
+ case SCENE_UNIT_METER:
+ unit = 100.0f;
+ break;
+ case SCENE_UNIT_INCH:
+ unit = 2.54f;
+ break;
+ case SCENE_UNIT_DECIMETER:
+ unit = 10.0f;
+ break;
+ }
+
+ return unit;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+atcore_float3 GlobalSettings::getGravityDir()
+{
+ atcore_float3 gravityDir;
+
+ if (m_zup)
+ {
+ gravityDir.x = 0.0f;
+ gravityDir.y = 0.0f;
+ gravityDir.z = -1.0f;
+ }
+ else
+ {
+ gravityDir.x = 0.0f;
+ gravityDir.y = -1.0f;
+ gravityDir.z = 0.0f;
+ }
+
+ return gravityDir;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+std::string GlobalSettings::getAbsoluteFilePath()
+{
+ return m_projectFileDir + "\\" + m_projectFileName;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+std::string GlobalSettings::getAbsoluteFilePath(const char* fileName)
+{
+ return m_projectFileDir + "\\" + fileName;
+}
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+
+///////////////////////////////////////////////////////////////////////////////
+std::string GlobalSettings::getRelativePath(const char* filePath)
+{
+ QDir projectDir(m_projectFileDir.c_str());
+ QByteArray relPath = projectDir.relativeFilePath(filePath).toLocal8Bit();
+
+ return (const char*)relPath;
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/GlobalSettings.h b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/GlobalSettings.h
new file mode 100644
index 0000000..8a1ddec
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/GlobalSettings.h
@@ -0,0 +1,172 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "MathUtil.h"
+#include <string>
+
+#include <Nv/Common/Animation/NvCoFrameCalculator.h>
+
+class QTimer;
+
+enum
+{
+ MESH_RENDER_WIREFRAME,
+ MESH_RENDER_FLAT,
+ MESH_RENDER_SHADED,
+ MESH_RENDER_TEXTURED,
+ MESH_RENDER_END,
+};
+
+enum
+{
+ SCENE_UNIT_UNKNOWN,
+ SCENE_UNIT_CENTIMETER,
+ SCENE_UNIT_METER,
+ SCENE_UNIT_INCH,
+ SCENE_UNIT_DECIMETER,
+ SCENE_UNIT_END,
+};
+
+//////////////////////////////////////////////////////////////////////////////////////
+// Placeholder for all the global settings used in hairworks viewer.
+// This stores all simple options that are not part of hair instance descriptor
+// such as animation logic in UI, scene settings, scene visualization options etc.
+//////////////////////////////////////////////////////////////////////////////////////
+class CORELIB_EXPORT GlobalSettings
+{
+public:
+ GlobalSettings();
+
+ void Init();
+ static GlobalSettings& Inst();
+ static QTimer& GetFrameTimer();
+
+public:
+
+ // animation settings
+ bool m_animate;
+ float m_animationFps;
+ int m_animationIndex;
+ float m_animationSpeed;
+ int m_currentBoneIndex;
+ bool m_firstFrame;
+ float m_frameTime;
+ float m_frameStartTime;
+ float m_frameEndTime;
+ bool m_lockRootBone;
+ bool m_playStopped;
+ bool m_repeatAnimation;
+ bool m_resetAnimationOnLoop;
+
+ bool m_simulate;
+ bool m_simulateStep;
+
+ float m_timeStep;
+ NvCo::FrameCalculator m_simulationFrameCalc;
+ float m_simulationFps;
+
+ // scene settings
+ bool m_useDQ;
+ bool m_zup;
+ bool m_lhs;
+ bool m_sceneLoaded;
+ int m_sceneUnitIndex;
+ std::string m_backgroundTextureFilePath;
+
+ // statistics and profiling
+ bool m_computeStatistics;
+ bool m_computeProfile;
+
+ // render option
+ float m_fovAngle;
+ bool m_useLighting;
+ int m_msaaOption;
+ int m_renderFrameCnt;
+ float m_renderFps;
+
+ // viusialization
+ int m_controlTextureOption;
+ bool m_previewLOD;
+ int m_renderStyle;
+ bool m_showAxis;
+ bool m_showHUD;
+ bool m_showFPS;
+ bool m_showGraphicsMesh;
+ bool m_showGrid;
+ bool m_showWireframe;
+ bool m_showSkinnedMeshOnly;
+ bool m_visualizeShadowMap;
+ bool m_visualizeWind;
+ bool m_visualizeBoneNames;
+
+ // global wind
+ atcore_float3 m_windDir;
+ float m_windStrength;
+ float m_windNoise;
+
+ // import settings
+ bool m_loadTextures;
+ bool m_loadMaterials;
+ bool m_loadGroom;
+ bool m_loadCollision;
+ bool m_loadConstraints;
+
+ // file path
+ std::string m_projectFileDir;
+ std::string m_projectFileName;
+
+ // convenience access functions
+public:
+
+ bool isBindPose() { return m_animationIndex == 0; }
+ float getSceneUnitInCentimeters();
+ void setSceneUnitIndex(int i);
+
+ void setTimeStep(float timeStep) { m_timeStep = timeStep; }
+
+ bool toggleSimulation();
+ void stepSimulation();
+
+ void setRenderFps(float fps);
+ void setSimulationFps(float fps);
+
+ void resetAnimation();
+ void stepAnimation();
+ bool toggleAnimation();
+ void toggleAnimationRepeat();
+ void getAnimationRange( float& start, float& end);
+
+ std::string getAbsoluteFilePath();
+ std::string getAbsoluteFilePath(const char* fileName);
+ std::string getRelativePath(const char* filePath);
+
+ atcore_float3 getGravityDir();
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Light.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Light.cpp
new file mode 100644
index 0000000..e18314e
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Light.cpp
@@ -0,0 +1,744 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "Light.h"
+
+#include "GlobalSettings.h"
+#include "ShadowMap.h"
+#include "SimpleRenderable.h"
+#include "MeshShaderParam.h"
+
+#include "RenderInterface.h"
+
+//////////////////////////////////////////////////////////////////////////////
+inline int GetShadowMapResolution(int index)
+{
+ switch (index)
+ {
+ case 0: // default
+ return 2048;
+ break;
+ case 1:
+ return 4096;
+ break;
+ case 2:
+ return 1024;
+ break;
+ case 3:
+ return 512;
+ break;
+ case 4:
+ return 8192;
+ break;
+ case 5:
+ return 16384;
+ break;
+ }
+
+ return 1024;
+}
+
+namespace
+{
+ std::vector<Light> g_Lights;
+ static bool g_LinkLightOption = false;
+ std::string m_envTextureFilePath;
+ GPUShaderResource* m_pEnvTextureSRV;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+Light::Light()
+{
+ m_enable = true;
+ m_useShadows = false;
+ m_visualize = false;
+ m_isEnvLight = false;
+ m_useEnvMap = false;
+
+ m_selected = false;
+
+ m_color = gfsdk_makeFloat3(1.0f, 1.0f, 1.0f);
+ m_intensity = 1.0f;
+
+ m_pShadowMap = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+Light::~Light()
+{
+ if (m_pShadowMap)
+ {
+ delete m_pShadowMap;
+ m_pShadowMap = 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool Light::UseLHS() const {
+ return m_lightCamera.UseLHS();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+GPUShaderResource* Light::GetShadowSRV()
+{
+ if (!m_pShadowMap)
+ return 0;
+
+ return m_pShadowMap->GetShadowSRV();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::SetShadowMapResolution(int index)
+{
+ if (m_shadowMapResolutionIndex == index)
+ return;
+
+ m_lightMapResolution = GetShadowMapResolution(index);
+
+ if (m_pShadowMap)
+ {
+ m_pShadowMap->Release();
+ delete m_pShadowMap;
+ }
+
+ m_pShadowMap = ShadowMap::Create(m_lightMapResolution);
+
+ float minZ = 1.0f;
+ float maxZ = 10000.0f; // should calculate dynamically
+
+ m_lightCamera.Ortho(m_lightMapResolution, m_lightMapResolution, minZ, maxZ);
+
+ m_shadowMapResolutionIndex = index;
+
+ FitBounds();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::Init()
+{
+ m_shadowMapResolutionIndex = 2;
+ m_lightMapResolution = GetShadowMapResolution(m_shadowMapResolutionIndex);
+
+ m_pShadowMap = ShadowMap::Create(m_lightMapResolution);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::Release()
+{
+ if (m_pShadowMap)
+ {
+ delete m_pShadowMap;
+ m_pShadowMap = 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::InitCamera(const atcore_float3& from, const atcore_float3& lookAt)
+{
+ m_lightCamera.Init(false, false);
+
+// atcore_float3 up = gfsdk_makeFloat3(0.0f, 1.0f, 0.0f);
+ atcore_float3 up = gfsdk_makeFloat3(0.0f, 0.0f, 1.0f);
+
+ m_lightCamera.LookAt(from, lookAt, up);
+
+ float minZ = 1.0f;
+ float maxZ = 10000.0f; // should calculate dynamically
+
+ m_lightCamera.Ortho(m_lightMapResolution, m_lightMapResolution, minZ, maxZ);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+atcore_float3
+Light::getLightDirection() const
+{
+ return (atcore_float3&)m_lightCamera.GetViewDirection();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::SetBounds(atcore_float3* bbCenter, atcore_float3* bbExtents)
+{
+ if (bbCenter)
+ m_bbCenter = *bbCenter;
+ if (bbExtents)
+ m_bbExtent = *bbExtents;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::FitBounds(bool updateCenter)
+{
+ ////////////////////////////////////////////////////////
+ atcore_float3 bbCenter = m_bbCenter;
+ atcore_float3 bbExtents =m_bbExtent;
+
+ ////////////////////////////////////////////////////////////////////////
+ if (updateCenter)
+ {
+ atcore_float3 lightPos = m_lightCamera.GetEye();
+ atcore_float3 lightAt = m_lightCamera.GetAt();
+
+ atcore_float3 disp = bbCenter - lightAt;
+
+ lightAt = lightAt + disp;
+ lightPos = lightPos + disp;
+
+ m_lightCamera.SetEye(lightPos);
+ m_lightCamera.SetAt(lightAt);
+ m_lightCamera.BuildViewMatrix();
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ float size = bbExtents.x;
+
+ size = max(size, bbExtents.y);
+ size = max(size, bbExtents.z);
+
+ atcore_float4x4 view = m_lightCamera.GetViewMatrix();
+
+ atcore_float3 c = gfsdk_transformCoord(view, bbCenter);
+
+ size *= 3.0f;
+
+ float minZ = c.z - size;
+ float maxZ = c.z + size;
+
+ float orthoW = size;
+ float orthoH = size;
+
+ if (m_lightCamera.UseLHS())
+ m_lightCamera.Ortho(orthoW, orthoH, minZ, maxZ);
+ else // rhs camera flips Z
+ m_lightCamera.Ortho(orthoW, orthoH, -maxZ, -minZ);
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::resetUpDir(bool zup)
+{
+ m_lightCamera.ResetUpDir(zup);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::resetLhs(bool lhs)
+{
+ m_lightCamera.ResetLhs(lhs);
+ FitBounds();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::Orbit(const atcore_float2& delta)
+{
+ m_lightCamera.OrbitLight(gfsdk_makeFloat2(-delta.x, delta.y));
+
+ FitBounds();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::Pan(const atcore_float2& delta, const atcore_float3& axisX, const atcore_float3& axisY)
+{
+ atcore_float3 lightPos = m_lightCamera.GetEye();
+ atcore_float3 lightAt = m_lightCamera.GetAt();
+ atcore_float3 lightDir = m_lightCamera.GetZAxis();
+
+ float depth = GetDistance();
+
+ atcore_float2 newDelta = depth * delta;
+
+ atcore_float3 disp = -1.0f * axisY * newDelta.y + axisX * newDelta.x;
+
+ lightAt = lightAt + disp;
+ lightPos = lightPos + disp;
+
+ m_lightCamera.SetEye(lightPos);
+ m_lightCamera.SetAt(lightAt);
+ m_lightCamera.BuildViewMatrix();
+
+ FitBounds();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+float Light::GetDistance() const
+{
+ return m_lightCamera.GetLookDistance();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool Light::SetDistance(float newdistance)
+{
+ atcore_float3 lightPos = m_lightCamera.GetEye();
+ atcore_float3 lightAt = m_lightCamera.GetAt();
+ atcore_float3 lightDir = m_lightCamera.GetZAxis();
+
+ lightPos = lightAt + newdistance * lightDir;
+
+ m_lightCamera.SetEye(lightPos);
+ m_lightCamera.BuildViewMatrix();
+
+ FitBounds();
+
+ return true;
+}
+//////////////////////////////////////////////////////////////////////////////
+void Light::BeginShadowMapRendering()
+{
+ if (!m_pShadowMap) return;
+
+ float clearDepth = m_lightCamera.UseLHS() ? FLT_MAX : -FLT_MAX;
+ m_pShadowMap->BeginRendering(clearDepth);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::EndShadowMapRendering()
+{
+ if (!m_pShadowMap) return;
+
+ m_pShadowMap->EndRendering();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+atcore_float4x4 Light::GetViewMatrix() const
+{
+ return m_lightCamera.GetViewMatrix();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+atcore_float4x4 Light::GetProjectionMatrix() const
+{
+ return m_lightCamera.GetProjectionMatrix();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+atcore_float4x4 Light::GetLightMatrix() const
+{
+ atcore_float4x4 view = m_lightCamera.GetViewMatrix();
+ atcore_float4x4 projection = m_lightCamera.GetProjectionMatrix();
+
+ float mClip2Tex[] = {
+ 0.5, 0, 0, 0,
+ 0, -0.5, 0, 0,
+ 0, 0, 1, 0,
+ 0.5, 0.5, 0, 1
+ };
+ atcore_float4x4 clip2Tex = (atcore_float4x4&)mClip2Tex;
+
+ atcore_float4x4 viewProjection = view * projection;
+
+ atcore_float4x4 lightMatrix = viewProjection * clip2Tex;
+
+ return lightMatrix;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void Light::FillLightShaderParam(LightShaderParam &param)
+{
+ const std::vector<Light> &lights = g_Lights;
+
+ for (int i = 0; i < lights.size(); i++)
+ {
+ if (i >= 4)
+ break;
+
+ LightParam& lparam = param.m_lightParam[i];
+ memset(&lparam, 0, sizeof(LightParam));
+
+ const Light& light= lights[i];
+
+ lparam.m_enable = light.m_enable;
+ lparam.m_useShadows = light.m_useShadows;
+
+ lparam.m_dir = light.getLightDirection();
+ lparam.m_intensity = light.m_intensity;
+ lparam.m_color = light.m_color;
+ lparam.m_isEnvLight = light.m_isEnvLight;
+ lparam.m_useEnvMap = light.m_isEnvLight && (m_pEnvTextureSRV != 0);
+
+ float sceneUnit = GlobalSettings::Inst().getSceneUnitInCentimeters();
+ lparam.m_depthBias = (sceneUnit > 0.0f) ? 1.0f / sceneUnit : 1.0f;
+
+ if (light.UseLHS())
+ {
+ lparam.m_depthBias *= -1.0f;
+ lparam.m_depthGain = -1.0f;
+ lparam.m_lhs = true;
+ }
+ else
+ {
+ lparam.m_depthGain = 1.0f;
+ lparam.m_lhs = false;
+ }
+
+ lparam.m_viewMatrix = light.GetViewMatrix();
+ lparam.m_lightMatrix = light.GetLightMatrix();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::draw(Camera* pCamera)
+{
+ atcore_float3 lightPos = m_lightCamera.GetEye();
+ atcore_float3 lightAt = m_lightCamera.GetAt();
+
+ atcore_float4 color = gfsdk_makeFloat4(m_color.x, m_color.y, m_color.z, 1);
+ if (m_enable == false)
+ color = gfsdk_makeFloat4(0.5, 0.5, 0.5, 1);
+
+ // draw light shape
+ atcore_float4x4 lightMat = gfsdk_transpose(m_lightCamera.GetViewMatrix());
+ gfsdk_setPosition(lightMat, lightPos);
+
+ SimpleShaderParam param;
+ {
+ param.world = lightMat;
+ param.view = pCamera->GetViewMatrix();
+ param.projection = pCamera->GetProjectionMatrix();
+ param.useVertexColor = false;
+ param.color = color;
+ }
+
+ RenderInterface::CopyShaderParam(RenderInterface::SHADER_TYPE_SIMPLE_COLOR,
+ (void*)&param, sizeof(SimpleShaderParam) );
+
+ SimpleRenderable::Draw(SimpleRenderable::LIGHT);
+
+ // draw light ray
+ gfsdk_makeIdentity(param.world);
+ RenderInterface::CopyShaderParam(RenderInterface::SHADER_TYPE_SIMPLE_COLOR,
+ (void*)&param, sizeof(SimpleShaderParam) );
+
+ SimpleRenderable::DrawLine(lightAt, lightPos);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool Light::loadParameters(NvParameterized::Handle& handle)
+{
+#ifndef NV_ARTISTTOOLS
+ NvParameterized::NvParameters* params = static_cast<NvParameterized::NvParameters*>(handle.getInterface());
+ size_t offset = 0;
+ nvidia::parameterized::HairProjectParametersNS::Light_Type* param = nullptr;
+ params->getVarPtr(handle, (void*&)param, offset);
+
+ m_enable = param->enable;
+ m_useShadows = param->useShadows;
+ m_visualize = param->visualize;
+ m_intensity = param->intensity;
+
+ memcpy(&m_color, &param->color, sizeof(atcore_float3));
+
+ atcore_float3 axisX, axisY, axisZ, lightPos;
+ memcpy(&axisX, &param->lightAxisX, sizeof(atcore_float3));
+ memcpy(&axisY, &param->lightAxisY, sizeof(atcore_float3));
+ memcpy(&axisZ, &param->lightAxisZ, sizeof(atcore_float3));
+ memcpy(&lightPos, &param->lightPos, sizeof(atcore_float3));
+
+ this->SetShadowMapResolution(param->shadowMapResolution);
+
+ m_lightCamera.SetEye(lightPos);
+ m_lightCamera.SetViewMatrix(axisX, axisY, axisZ);
+ m_lightCamera.BuildViewMatrix();
+#else
+ CoreLib::Inst()->Light_loadParameters(handle, this);
+#endif // NV_ARTISTTOOLS
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool Light::saveParameters(NvParameterized::Handle& handle)
+{
+#ifndef NV_ARTISTTOOLS
+ NvParameterized::NvParameters* params = static_cast<NvParameterized::NvParameters*>(handle.getInterface());
+ size_t offset = 0;
+ nvidia::parameterized::HairProjectParametersNS::Light_Type* param = nullptr;
+ params->getVarPtr(handle, (void*&)param, offset);
+
+ param->enable = m_enable;
+ param->useShadows = m_useShadows;
+ param->visualize = m_visualize;
+ param->intensity = m_intensity;
+
+ param->shadowMapResolution = m_shadowMapResolutionIndex;
+
+ memcpy(&param->color, &m_color, sizeof(atcore_float3));
+
+ {
+ atcore_float3 axisX = m_lightCamera.GetXAxis();
+ atcore_float3 axisY = m_lightCamera.GetYAxis();
+ atcore_float3 axisZ = m_lightCamera.GetZAxis();
+ atcore_float3 lightPos = m_lightCamera.GetEye();
+
+ memcpy(&param->lightAxisX, &axisX, sizeof(atcore_float3));
+ memcpy(&param->lightAxisY, &axisY, sizeof(atcore_float3));
+ memcpy(&param->lightAxisZ, &axisZ, sizeof(atcore_float3));
+ memcpy(&param->lightPos, &lightPos, sizeof(atcore_float3));
+ }
+#else
+ CoreLib::Inst()->Light_saveParameters(handle, this);
+#endif // NV_ARTISTTOOLS
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool Light::SetEnvTextureFromFilePath(const char* textureFilePath)
+{
+ Light* pLight = Light::GetFirstSelectedLight();
+ if (!pLight || !pLight->m_isEnvLight)
+ return false;
+
+ m_envTextureFilePath = (textureFilePath) ? textureFilePath : "";
+
+ SAFE_RELEASE(m_pEnvTextureSRV);
+ if ((!textureFilePath) && (strlen(textureFilePath) > 0))
+ m_pEnvTextureSRV = RenderInterface::CreateTextureResource(textureFilePath);
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+const std::string& Light::GetEnvTextureFilePath()
+{
+ return m_envTextureFilePath;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+GPUShaderResource* Light::GetEnvTextureSRV()
+{
+ return m_pEnvTextureSRV;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+GPUShaderResource* Light::GetShadowSRV(int i)
+{
+ if ((i >= 3) || (i < 0))
+ return 0;
+
+ return g_Lights[i].GetShadowSRV();
+}
+
+bool Light::GetLinkLightOption()
+{
+ return g_LinkLightOption;
+}
+
+void Light::SetLinkLightOption(bool val)
+{
+ g_LinkLightOption = val;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+std::vector<Light>& Light::GetDefaultLights()
+{
+ return g_Lights;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+Light* Light::GetFirstSelectedLight()
+{
+ for (int i = 0; i < g_Lights.size(); i++)
+ {
+ if (g_Lights[i].m_selected)
+ return &g_Lights[i];
+ }
+
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+Light* Light::GetLight(int index)
+{
+ if (index < 0)
+ return 0;
+ if (index >= g_Lights.size())
+ return 0;
+
+ return &g_Lights[index];
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::Initialize()
+{
+ g_Lights.resize(4);
+
+ Light& keyLight = g_Lights[0];
+ Light& fillLight = g_Lights[1];
+ Light& rimLight = g_Lights[2];
+ Light& envLight = g_Lights[3];
+
+ atcore_float3 lookAt = gfsdk_makeFloat3(0.0f, 0.0f, 0.0f);
+
+ keyLight.m_selected = true;
+ keyLight.m_enable = true;
+ keyLight.m_color = gfsdk_makeFloat3(1, 1, 1);
+ keyLight.m_useShadows = true;
+ keyLight.m_isEnvLight = false;
+ keyLight.InitCamera(gfsdk_makeFloat3(100.0f, 25.0f, 0.0f), lookAt);
+ keyLight.m_name = "Key Light";
+
+ fillLight.m_enable = false;
+ fillLight.m_color = gfsdk_makeFloat3(0.5, 0.5, 0.5);
+ fillLight.m_useShadows = false;
+ fillLight.m_isEnvLight = false;
+ fillLight.InitCamera(gfsdk_makeFloat3(-100.0f, 0.0f, 25.0f), lookAt);
+ fillLight.m_name = "Fill Light";
+
+ rimLight.m_enable = false;
+ rimLight.m_color = gfsdk_makeFloat3(0.25, 0.25, 0.25);
+ rimLight.m_useShadows = false;
+ rimLight.m_isEnvLight = false;
+ rimLight.InitCamera(gfsdk_makeFloat3(0.0f, 100.0f, -25.0f), lookAt);
+ rimLight.m_name = "Rim Light";
+
+ envLight.m_enable = false;
+ envLight.m_color = gfsdk_makeFloat3(0.25, 0.25, 0.25);
+ envLight.m_useShadows = false;
+ envLight.m_isEnvLight = true;
+ envLight.InitCamera(gfsdk_makeFloat3(0.0f, 0.0f, 0.0f), lookAt);
+ envLight.m_name = "Env Light";
+
+ for (int i = 0; i < g_Lights.size(); i++)
+ g_Lights[i].Init();
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::Shutdown()
+{
+ for (int i = 0; i < g_Lights.size(); i++)
+ g_Lights[i].Release();
+
+ g_Lights.clear();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::FitLightCameras(atcore_float3& center, atcore_float3& extent)
+{
+ for (int i = 0; i < g_Lights.size(); i++)
+ {
+ if (g_LinkLightOption && (i == FILL_LIGHT || i == RIM_LIGHT))
+ continue;
+
+ Light& light = g_Lights[i];
+ light.SetBounds(&center, &extent);
+ light.FitBounds(true);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::ResetUpDir(bool zup)
+{
+ for (int i = 0; i < g_Lights.size(); i++)
+ {
+ Light& li = g_Lights[i];
+ li.resetUpDir(zup);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::ResetLhs(bool lhs)
+{
+ for (int i = 0; i < g_Lights.size(); i++)
+ {
+ Light& li = g_Lights[i];
+ li.resetLhs(lhs);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::DrawLights(Camera* pCamera)
+{
+ for (int i = 0; i < g_Lights.size(); i++)
+ {
+ Light& light = g_Lights[i];
+ if (light.m_visualize)
+ light.draw(pCamera);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void Light::RenderShadowMap()
+{
+ Light* pLight = Light::GetFirstSelectedLight();
+ if (pLight)
+ {
+ float zNear = pLight->m_lightCamera.GetZNear();
+ float zFar = pLight->m_lightCamera.GetZFar();
+
+ if (pLight->UseLHS())
+ RenderInterface::RenderShadowMap(pLight->GetShadowSRV(), zNear, zFar);
+ else
+ RenderInterface::RenderShadowMap(pLight->GetShadowSRV(), -zFar, -zNear);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool Light::LoadParameters(NvParameterized::Handle& handle)
+{
+ // load lights
+ NvParameterized::Handle lightsHandle(handle);
+ if (handle.getChildHandle(handle.getInterface(), "lights", lightsHandle) == NvParameterized::ERROR_NONE)
+ {
+ int numLights = 0;
+ lightsHandle.getArraySize(numLights);
+ if (numLights > g_Lights.size())
+ numLights = g_Lights.size();
+
+ for (int idx = 0; idx < numLights; ++idx)
+ {
+ NvParameterized::Handle lightHandle(lightsHandle);
+ if (lightsHandle.getChildHandle(idx, lightHandle) == NvParameterized::ERROR_NONE)
+ {
+ g_Lights[idx].loadParameters(lightHandle);
+ }
+ }
+ }
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool Light::SaveParameters(NvParameterized::Handle& outHandle)
+{
+ NvParameterized::Handle lightsHandle(outHandle);
+ if (outHandle.getChildHandle(outHandle.getInterface(), "lights", lightsHandle) == NvParameterized::ERROR_NONE)
+ {
+ int numLights = (int)g_Lights.size();
+
+ lightsHandle.resizeArray(numLights);
+
+ for (int idx = 0; idx < numLights; ++idx)
+ {
+ NvParameterized::Handle lightHandle(outHandle);
+ if (lightsHandle.getChildHandle(idx, lightHandle) == NvParameterized::ERROR_NONE)
+ {
+ g_Lights[idx].saveParameters(lightHandle);
+ }
+ }
+ }
+ return true;
+}
+
+// END OF STATIC FUNCTIONS
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Light.h b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Light.h
new file mode 100644
index 0000000..bbe4ef3
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Light.h
@@ -0,0 +1,152 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "MathUtil.h"
+#ifndef NV_ARTISTTOOLS
+#include "ProjectParams.h"
+#else
+#include "NvParametersTypes.h"
+#ifndef NV_PARAMETERIZED_ONLY_LAYOUTS
+#include "NvParameterized.h"
+#include "NvParameters.h"
+#include "NvParameterizedTraits.h"
+#include "NvTraitsInternal.h"
+#endif
+#endif // NV_ARTISTTOOLS
+#include "Camera.h"
+
+#include <string>
+#include <vector>
+
+#include "LightShaderParam.h"
+
+class GPUShaderResource;
+class ShadowMap;
+
+/////////////////////////////////////////////////////////////////////////
+// Utility class for light object
+/////////////////////////////////////////////////////////////////////////
+class CORELIB_EXPORT Light
+{
+public:
+ bool m_enable;
+ bool m_useShadows;
+ bool m_visualize;
+ bool m_isEnvLight;
+ bool m_useEnvMap;
+
+ bool m_selected;
+
+ float m_intensity;
+ atcore_float3 m_color;
+
+ std::string m_name;
+ int m_shadowMapResolutionIndex;
+ int m_lightMapResolution;
+
+ // public API to access 4 lights
+ static std::vector<Light>& GetDefaultLights();
+ static Light* GetLight(int index);
+ static Light* GetFirstSelectedLight();
+
+ static void Initialize();
+ static void Shutdown();
+ static void FitLightCameras(atcore_float3& center, atcore_float3& extent);
+ static void ResetUpDir(bool zup);
+ static void ResetLhs(bool lhs);
+ static void DrawLights(Camera* pCamera);
+ static void FillLightShaderParam(LightShaderParam &param);
+ static bool LoadParameters(NvParameterized::Handle& handle);
+ static bool SaveParameters(NvParameterized::Handle& outHandle);
+ static void RenderShadowMap();
+
+ static bool SetEnvTextureFromFilePath(const char* textureFilePath);
+ static const std::string & GetEnvTextureFilePath();
+ static GPUShaderResource* GetEnvTextureSRV();
+ static GPUShaderResource* GetShadowSRV(int);
+
+ static bool GetLinkLightOption();
+ static void SetLinkLightOption(bool val);
+
+public:
+ Light();
+ ~Light();
+
+ enum
+ {
+ KEY_LIGHT,
+ FILL_LIGHT,
+ RIM_LIGHT,
+ ENV_LIGHT,
+ };
+
+ void Orbit(const atcore_float2& delta);
+ void Pan(const atcore_float2& delta, const atcore_float3& axisX, const atcore_float3& axisY);
+
+ bool UseLHS() const;
+
+ float GetDistance() const;
+ bool SetDistance(float newdistsance);
+
+ void SetShadowMapResolution(int option);
+ void BeginShadowMapRendering();
+ void EndShadowMapRendering();
+
+ GPUShaderResource* GetShadowSRV();
+
+ atcore_float4x4 GetViewMatrix() const;
+ atcore_float4x4 GetProjectionMatrix() const;
+ atcore_float4x4 GetLightMatrix() const;
+
+protected:
+ void Init();
+ void Release();
+
+ bool loadParameters(NvParameterized::Handle& handle);
+ bool saveParameters(NvParameterized::Handle& outHandle);
+
+ void SetBounds(atcore_float3* center, atcore_float3* extents = 0);
+ void FitBounds(bool updateCenter = false);
+
+ atcore_float3 getLightDirection() const;
+ void InitCamera(const atcore_float3& from, const atcore_float3& lookAt);
+
+ void draw(Camera* pCamera);
+ void resetUpDir(bool zup);
+ void resetLhs(bool zup);
+
+public:
+
+ Camera m_lightCamera;
+ ShadowMap* m_pShadowMap;
+
+ atcore_float3 m_bbCenter;
+ atcore_float3 m_bbExtent;
+};
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/MeshData.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/MeshData.cpp
new file mode 100644
index 0000000..295ac7f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/MeshData.cpp
@@ -0,0 +1,108 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "MeshData.h"
+
+#include "AnimUtil.h"
+#include "RenderResources.h"
+
+///////////////////////////////////////////////////////////////////////////////
+void CreateCPUResource(MeshData* pMeshData, const MeshDesc &meshDesc)
+{
+ if (!pMeshData)
+ return;
+
+ pMeshData->m_NumVertices = meshDesc.m_NumVertices;
+ pMeshData->m_NumIndices = meshDesc.m_NumTriangles * 3;
+
+ int numIndices = pMeshData->m_NumIndices;
+
+ pMeshData->m_pIndices = new NvUInt32[numIndices];
+ pMeshData->m_pMeshVertices = new MeshData::MeshVertex[numIndices];
+
+ NvUInt32* pVertUsed = new NvUInt32[meshDesc.m_NumVertices];
+ memset(pVertUsed, meshDesc.m_NumVertices, sizeof(NvUInt32) * meshDesc.m_NumVertices);
+ for (NvUInt32 i = 0; i < numIndices; i++)
+ {
+ NvUInt32 vidx = pMeshData->m_pIndices[i] = meshDesc.m_pIndices[i];
+
+ MeshData::MeshVertex&v = pMeshData->m_pMeshVertices[i];
+
+ v.pos = meshDesc.m_pVertices[vidx];
+ v.vertexNormal = meshDesc.m_pVertexNormals[i];
+ v.faceNormal = meshDesc.m_pFaceNormals[i];
+ v.tangent = meshDesc.m_pTangents[i];
+ v.texcoord = meshDesc.m_pTexCoords[i];
+ v.vertexId = (float)vidx;
+ pVertUsed[vidx] = i;
+ }
+ int numUniqueIndices = 0;
+ for (NvUInt32 i = 0; i < meshDesc.m_NumVertices; i++)
+ {
+ if (meshDesc.m_NumVertices != pVertUsed[i])
+ ++numUniqueIndices;
+ }
+ pMeshData->m_NumUniqueIndices = numUniqueIndices;
+ pMeshData->m_pUniqueIndices = new NvUInt32[numUniqueIndices];
+ for (NvUInt32 i = 0, idx = 0; i < meshDesc.m_NumVertices; i++)
+ {
+ if (meshDesc.m_NumVertices != pVertUsed[i])
+ {
+ pMeshData->m_pUniqueIndices[idx++] = pVertUsed[i];
+ }
+ }
+ delete[] pVertUsed;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+MeshData* MeshData::Create(MeshDesc &meshDesc, SkinData& skinData)
+{
+ MeshData* pMeshData = new MeshData;
+
+ CreateCPUResource(pMeshData, meshDesc);
+
+ pMeshData->m_GPUMeshResources = GPUMeshResources::Create(pMeshData, skinData);
+
+ return pMeshData;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void MeshData::Release()
+{
+ if (m_pMeshVertices)
+ delete [] m_pMeshVertices;
+
+ if (m_pIndices)
+ delete [] m_pIndices;
+
+ if (m_pUniqueIndices)
+ delete[] m_pUniqueIndices;
+
+ m_GPUMeshResources->Release();
+ delete m_GPUMeshResources;
+ m_GPUMeshResources = NULL;
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/MeshData.h b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/MeshData.h
new file mode 100644
index 0000000..f05207e
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/MeshData.h
@@ -0,0 +1,74 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "MathUtil.h"
+
+#include "RenderResources.h"
+
+class MeshDesc;
+class SkinData;
+
+//////////////////////////////////////////////////////////////////////////////////////
+// Helper for rendering graphics mesh
+//////////////////////////////////////////////////////////////////////////////////////
+class CORELIB_EXPORT MeshData
+{
+public:
+
+ struct MeshVertex
+ {
+ atcore_float3 pos;
+ atcore_float3 vertexNormal;
+ atcore_float3 faceNormal;
+ atcore_float3 tangent;
+ atcore_float2 texcoord;
+ float vertexId;
+ };
+
+public:
+ static MeshData* Create(MeshDesc &meshDesc, SkinData& skinData);
+ void Release();
+
+public:
+ int m_NumVertices;
+ int m_NumIndices;
+
+ MeshVertex* m_pMeshVertices;
+ NvUInt32* m_pIndices;
+
+ // m_pUniqueIndices and m_NumUniqueIndices are used to boost bounding calculation in FurMesh.cpp
+ NvUInt32* m_pUniqueIndices;
+ NvUInt32 m_NumUniqueIndices;
+
+ // gpu resources
+ GPUMeshResources* m_GPUMeshResources;
+};
+
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Mouse.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Mouse.cpp
new file mode 100644
index 0000000..f321157
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Mouse.cpp
@@ -0,0 +1,105 @@
+
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+
+#include "Mouse.h"
+
+//#include "windows.h"
+
+Mouse::Mouse()
+{
+}
+
+Mouse::~Mouse()
+{
+ Free();
+}
+
+bool Mouse::Initialize(HINSTANCE hInstance, HWND hWnd)
+{
+ /*
+ if (FAILED(DirectInput8Create(hInstance, DIRECTINPUT_VERSION,
+ IID_IDirectInput8, reinterpret_cast<void**>(&_pDirectInput), 0)))
+ return false;
+
+ if (FAILED(_pDirectInput->CreateDevice(GUID_SysMouse, &_pDevice, 0)))
+ return false;
+
+ if (FAILED(_pDevice->SetDataFormat(&c_dfDIMouse)))
+ return false;
+
+ if (FAILED(_pDevice->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)))
+ return false;
+
+ if (FAILED(_pDevice->Acquire()))
+ return false;
+ */
+ return true;
+}
+
+void Mouse::Free()
+{
+ /*
+ if (_pDevice)
+ {
+ _pDevice->Unacquire();
+ _pDevice = NULL;
+ }
+
+ _pDirectInput = NULL;
+ */
+}
+
+void Mouse::Update()
+{
+ /*
+ if (!_pDirectInput || !_pDevice)
+ {
+ return;
+ }
+
+ HRESULT hr;
+
+ while (true)
+ {
+ hr = _pDevice->GetDeviceState(sizeof(DIMOUSESTATE), &_mouseState);
+
+ if (FAILED(hr))
+ {
+ if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
+ {
+ if (FAILED(_pDevice->Acquire()))
+ return;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ */
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Mouse.h b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Mouse.h
new file mode 100644
index 0000000..3cbd598
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/Mouse.h
@@ -0,0 +1,103 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+/*
+#define DIRECTINPUT_VERSION 0x0800
+#include <dinput.h>
+*/
+#include "windows.h"
+#include "MathUtil.h"
+
+class Mouse
+{
+public:
+ Mouse();
+ ~Mouse();
+
+ /*
+ enum Button
+ {
+ LEFT = 0x00,
+ RIGHT = 0x01,
+ MIDDLE = 0x02
+ };
+
+ bool IsButtonPressed(Button button) const
+ {
+ if (_mouseState.rgbButtons[button] & 0x80)
+ return true;
+ return false;
+ }
+ */
+ void SetPosition(atcore_float2 position)
+ {
+ m_Position = position;
+ }
+
+ atcore_float2 GetDelta() const
+ {
+ return m_Delta;
+ }
+
+ void SetDelta(atcore_float2 position)
+ {
+ m_Delta = gfsdk_makeFloat2(
+ static_cast<float>(position.x - m_Position.x),
+ static_cast<float>(position.y - m_Position.y));
+ m_Position = position;
+ }
+
+ float GetDeltaWheel() const
+ {
+ if (m_DeltaWheel > 0)
+ return 1.0f;
+ else if (m_DeltaWheel < 0)
+ return -1.0f;
+ else
+ return 0.0f;
+ }
+
+ void SetDeltaWheel(float deltaWheel)
+ {
+ m_DeltaWheel = deltaWheel;
+ }
+
+ void Update();
+ bool Initialize(HINSTANCE hInstance, HWND hWnd);
+ void Free();
+ /*
+ IDirectInput8* _pDirectInput;
+ IDirectInputDevice8* _pDevice;
+ DIMOUSESTATE _mouseState;
+ */
+ atcore_float2 m_Position;
+ atcore_float2 m_Delta;
+ float m_DeltaWheel;
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/SimpleScene.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/SimpleScene.cpp
new file mode 100644
index 0000000..a633770
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/SimpleScene.cpp
@@ -0,0 +1,1312 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "SimpleScene.h"
+
+#include "AppMainWindow.h"
+#include "Automate.h"
+#include "Backdoor.h"
+#include "Gamepad.h"
+#include "GlobalSettings.h"
+#include "Light.h"
+#include "Mouse.h"
+#include "SimpleRenderable.h"
+#include "Stats.h"
+#include "CorelibUtils.h"
+//#include "Timer.h"
+#include "ViewerOutput.h"
+
+#include "FoundationHolder.h"
+
+#include <NvAllocatorCallback.h>
+#include <NvErrorCallback.h>
+#include <NsAlignedMalloc.h>
+#include <NsVersionNumber.h>
+
+#include <Nv/Common/NvCoMemoryAllocator.h>
+
+#include "RenderInterface.h"
+#include "DeviceManager.h"
+
+#ifndef NV_ARTISTTOOLS
+#include "FurCharacter.h"
+#include "FurRenderer.h"
+#include "ProjectParams.h"
+#include "HairInstance.h"
+#include "HairSDK.h"
+
+namespace { // anonymous
+
+class ErrorCallback: public nvidia::NvErrorCallback
+{
+ public:
+ void reportError(nvidia::NvErrorCode::Enum code, const char* message, const char* file, int line) NV_OVERRIDE
+ {
+ if (code & (nvidia::NvErrorCode::eDEBUG_WARNING | nvidia::NvErrorCode::ePERF_WARNING))
+ {
+ viewer_warn("%s", message);
+ return;
+ }
+ viewer_err("%s", message);
+ if (code != nvidia::NvErrorCode::eNO_ERROR)
+ {
+ viewer_err("%s", message);
+ }
+ }
+};
+
+class AllocatorCallback: public nvidia::NvAllocatorCallback
+{
+ public:
+
+ void* allocate(size_t size, const char* typeName, const char* filename, int line) NV_OVERRIDE
+ {
+ return NvCo::MemoryAllocator::getInstance()->simpleAllocate(size);
+ }
+
+ void deallocate(void* ptr) NV_OVERRIDE
+ {
+ NvCo::MemoryAllocator::getInstance()->simpleDeallocate(ptr);
+ }
+};
+
+} // namespace anonymous
+
+static AllocatorCallback s_allocator;
+static ErrorCallback s_error;
+
+// global singletons (can't create more than one instance)
+struct ProjectParamsContext* g_projectParamsContext = 0;
+
+class CustomLogger : public NvCo::Logger
+{
+public:
+ virtual void log(NvCo::LogSeverity::Enum severity, const char* message, const char* functionName, const char* file, int line) NV_OVERRIDE
+ {
+ using namespace NvCo;
+
+ switch (severity)
+ {
+ default:
+ case LogSeverity::FATAL_ERROR:
+ case LogSeverity::NON_FATAL_ERROR:
+ viewer_err("%s", message);
+ break;
+ case LogSeverity::WARNING:
+ viewer_warn("%s", message);
+ break;
+ case LogSeverity::INFO:
+ viewer_info("%s", message);
+ break;
+ case LogSeverity::DEBUG_INFO:
+ viewer_msg("%s", message);
+ break;
+ }
+ }
+ virtual void flush() NV_OVERRIDE {}
+};
+
+CustomLogger g_logHandler;
+#else
+#include "GPUProfiler.h"
+#include "MeshShaderParam.h"
+#include <Nv\Common\NvCoLogger.h>
+#endif // NV_ARTISTTOOLS
+
+Gamepad& theGamepad = Gamepad::Instance();
+Mouse g_mouse;
+Timer g_fpsTimer;
+Backdoor* g_pBackdoor;
+
+///////////////////////////////////////////////////////////////////////////////
+SimpleScene* SimpleScene::Inst()
+{
+ static SimpleScene scene;
+ return &scene;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+SimpleScene::SimpleScene()
+ :
+ m_pCamera(0),
+ m_pWindCamera(0),
+ m_isProjectModified(false),
+ m_isFurModified(false),
+ m_isSceneLoading(false)
+{
+#ifndef NV_ARTISTTOOLS
+ m_pFurCharacter = new FurCharacter;
+#endif // NV_ARTISTTOOLS
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleScene::Initialize( HWND hWnd, int backdoor)
+{
+ g_fpsTimer.Start();
+
+ if(!InitCameraMouse(hWnd))
+ return false;
+
+// if (!SimpleRenderable::Initialize())
+// return false;
+
+ Light::Initialize();
+
+ //nvidia::shdfnd::initializeSharedFoundation(NV_FOUNDATION_VERSION, s_allocator, s_error);
+
+ FoundationHolder::GetFoundation();
+
+ GPUProfiler_Initialize();
+
+
+ if (backdoor == 1) // master mode
+ g_pBackdoor = createBackdoor("BACKDOOR_SERVER","BACKDOOR_CLIENT");
+
+ SetFurModified(false);
+ SetProjectModified(false);
+
+#ifndef NV_ARTISTTOOLS
+ if (!InitializeBlastSDK(&g_logHandler, backdoor))
+ return false;
+
+ g_projectParamsContext = CreateProjectParamsContext();
+ if (!g_projectParamsContext) return false;
+
+ {
+ NvHair::Sdk* hairSdk = GetHairSDK();
+ if (hairSdk)
+ {
+ const NvHair::BuildInfo& buildInfo = GetHairSDK()->getBuildInfo();
+
+ viewer_info(GetHairSDK()->getBuildInfo().m_buildString);
+
+ char releaseVersion[100] = "Blast Release:";
+ buildInfo.m_versionToStringFunc(buildInfo.m_releaseVersion, releaseVersion + strlen(releaseVersion));
+
+ viewer_info(releaseVersion);
+ }
+ }
+#else
+ CoreLib::Inst()->SimpleScene_Initialize(backdoor);
+#endif // NV_ARTISTTOOLS
+
+ AppMainWindow::Inst().updateUI();
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::Shutdown()
+{
+#ifndef SAFE_DELETE
+#define SAFE_DELETE(x) {if(x!=NV_NULL){delete x;x=NV_NULL;}}
+#endif
+
+ SAFE_DELETE(m_pCamera);
+ SAFE_DELETE(m_pWindCamera);
+
+ GPUProfiler_Shutdown();
+
+ SimpleRenderable::Shutdown();
+ Light::Shutdown();
+
+ if (g_pBackdoor)
+ {
+ g_pBackdoor->release();
+ g_pBackdoor = nullptr;
+ }
+
+#ifndef NV_ARTISTTOOLS
+ GetFurCharacter().Clear();
+
+ ShutdownBlastSDK();
+
+ if (g_projectParamsContext)
+ {
+ ReleaseProjectParamsContext(g_projectParamsContext);
+ g_projectParamsContext = nullptr;
+ }
+#else
+ CoreLib::Inst()->SimpleScene_Shutdown();
+#endif // NV_ARTISTTOOLS
+
+ RenderInterface::Shutdown();
+
+ nvidia::shdfnd::terminateSharedFoundation();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleScene::Clear()
+{
+ GlobalSettings::Inst().m_sceneLoaded = false;
+ GlobalSettings::Inst().m_firstFrame = true;
+
+#ifndef NV_ARTISTTOOLS
+ GetFurCharacter().Clear();
+#else
+ CoreLib::Inst()->SimpleScene_Clear();
+#endif // NV_ARTISTTOOLS
+
+ m_cameraBookmarks.clear();
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleScene::InitCameraMouse(HWND hAppWnd)
+{
+ // default camera pose settings
+ m_pCamera = new Camera(GlobalSettings::Inst().m_zup, false);
+ m_pCamera->SetDefaults();
+
+ // init wind camera
+ {
+ m_pWindCamera = new Camera(false);
+ m_pWindCamera->SetDefaults();
+
+ GlobalSettings::Inst().m_windDir = m_pWindCamera->GetZAxis();
+ }
+
+ // init mouse
+ g_mouse.Initialize(::GetModuleHandle(NV_NULL), (HWND)hAppWnd/*_hWidget*/);
+
+ theGamepad.Initialize();
+ return true;
+}
+
+float SimpleScene::NextTimeStep()
+{
+ static LONGLONG g_lastRenderTicks = 0;
+
+ // Work out the timestep
+ LONGLONG ticks = g_fpsTimer.GetTicksElapsed();
+ LONGLONG deltaTicks = ticks - g_lastRenderTicks;
+ g_lastRenderTicks = ticks;
+
+ float timeStep = deltaTicks / float(g_fpsTimer.GetTicksPerSecond());
+
+ const float maxTimeStep = 0.1f;
+
+ timeStep = (timeStep < 0.0f) ? 0.0f : timeStep;
+ timeStep = (timeStep > maxTimeStep) ? maxTimeStep : timeStep;
+
+ return timeStep;
+}
+
+Timer& SimpleScene::GetTimer()
+{
+ return g_fpsTimer;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::Draw()
+{
+ CoreLib* pCore = CoreLib::Inst();
+ pCore->D3DWidget_paintEvent(NULL);
+#ifndef NV_ARTISTTOOLS
+#else
+ //pCore->SimpleScene_Draw_DX12();
+
+ //RenderInterface::SwitchToDX11();
+
+ //pCore->SimpleScene_Draw_DX11();
+
+ //RenderInterface::FlushDX11();
+#endif
+ // present current window
+ //RenderInterface::PresentRenderWindow();
+ return;
+
+ if (IsSceneLoading())
+ return;
+
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ // draw background
+ RenderInterface::ClearRenderWindow(0.35f, 0.35f, 0.35f);
+ RenderInterface::RenderBackgroundTexture();
+
+ globalSettings.setTimeStep(NextTimeStep());
+ //globalSettings.setTimeStep(1.0f/60.0f);
+
+ // increment frame timer
+ if (globalSettings.m_animate)
+ {
+ globalSettings.stepAnimation();
+ }
+
+ if (globalSettings.m_playStopped)
+ AppMainWindow::Inst().updateMainToolbar();
+
+ // update camera
+ UpdateCamera();
+
+ // draw lights
+ Light::DrawLights(m_pCamera);
+
+ // show ground grid
+ if (globalSettings.m_showGrid)
+ DrawGround();
+
+ // draw wind icon
+ if (globalSettings.m_visualizeWind)
+ DrawWind();
+
+ // draw axis lines
+ if (globalSettings.m_showAxis)
+ DrawAxis();
+
+ // handle game pad
+ theGamepad.Process();
+
+ // visualize shadow map
+ if (GlobalSettings::Inst().m_visualizeShadowMap)
+ Light::RenderShadowMap();
+
+#ifndef NV_ARTISTTOOLS
+ // init profiler stats
+ FurRenderer::ResetFrameTimer();
+ // the main loop to simulate and render hairs and meshes
+ FurRenderer::UpdateFrame();
+ FurRenderer::Render(m_pCamera);
+
+ RenderInterface::SwitchToDX11();
+ // draw bone name for first hair (hacky, needs to go into SDK)
+ HairInstance* pInstance = GetFurCharacter().GetFirstSelectedHairInstance();
+ if (pInstance && globalSettings.m_visualizeBoneNames)
+ pInstance->DrawBoneNames(m_pCamera);
+
+ // draw HUD.
+ FurRenderer::DrawHUD();
+ RenderInterface::FlushDX11();
+#else
+ CoreLib::Inst()->SimpleScene_Draw_DX12();
+
+ RenderInterface::SwitchToDX11();
+
+ CoreLib::Inst()->SimpleScene_Draw_DX11();
+
+ RenderInterface::FlushDX11();
+
+#endif // NV_ARTISTTOOLS
+
+ // present current window
+ RenderInterface::PresentRenderWindow();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::Timeout()
+{
+ if (m_pCamera == nullptr)
+ {
+ // this could be called when quiting. have to check nullptr
+ return;
+ }
+
+ g_mouse.Update();
+
+ if (IsAutomateMode())
+ {
+ AutomateRun();
+ }
+
+ Draw();
+
+ if (g_pBackdoor)
+ {
+ int argc;
+ const char **argv = g_pBackdoor->getInput(argc);
+ if (argc > 0)
+ {
+ char message[1024];
+ strcpy(message,"");
+ for (int i = 0; i < argc; i++)
+ {
+ strcat(message, argv[i]);
+ strcat(message," ");
+ }
+
+ viewer_info("Message received: %s", message);
+ }
+ }
+
+}
+
+#include <Shlwapi.h>
+#include <FbxUtil.h>
+
+///////////////////////////////////////////////////////////////////////////////
+bool
+SimpleScene::LoadSceneFromFbx(const char* dir, const char* fbxName)
+{
+ return CoreLib::Inst()->SimpleScene_LoadSceneFromFbx(dir, fbxName);
+
+ /*
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ char fbxFilePath[MAX_PATH];
+
+ float sceneUnit = globalSettings.getSceneUnitInCentimeters();
+
+ PathCombineA(fbxFilePath, dir, fbxName);
+
+ AppMainWindow::Inst().setProgress("Initializing FBX loader", 0);
+ FbxUtil::Initialize(fbxFilePath, sceneUnit);
+
+ char rootBoneName[MAX_PATH];
+ int upAxis = 0;
+
+ FbxUtil::GetGlobalSettings(
+ &globalSettings.m_frameStartTime,
+ &globalSettings.m_frameEndTime,
+ &globalSettings.m_animationFps,
+ &upAxis, rootBoneName);
+
+ if (upAxis == 1)
+ SimpleScene::Inst()->ResetUpDir(false);
+ else if (upAxis = 2)
+ SimpleScene::Inst()->ResetUpDir(true);
+
+#ifndef NV_ARTISTTOOLS
+ SimpleScene::Inst()->GetFurCharacter().LoadMeshFromFbx(dir, fbxName);
+#else
+ CoreLib::Inst()->SimpleScene_LoadSceneFromFbx(dir, fbxName);
+#endif // NV_ARTISTTOOLS
+
+ FbxUtil::Release();
+
+ globalSettings.m_sceneLoaded = true;
+ globalSettings.m_animationIndex = 1;
+ globalSettings.m_firstFrame = true;
+
+ //globalSettings.m_currentBoneIndex = findBoneByName(rootBoneName);
+ globalSettings.resetAnimation();
+
+ return true;
+ */
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleScene::LoadProject(const char* dir, const char* file)
+{
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ globalSettings.m_projectFileDir = dir;
+ globalSettings.m_projectFileName = file;
+
+#ifndef NV_ARTISTTOOLS
+ nvidia::parameterized::HairProjectParametersNS::ParametersStruct params;
+ if (!ProjectParamsLoad(g_projectParamsContext, globalSettings.getAbsoluteFilePath().c_str(), this))
+ return false;
+#else
+ CoreLib::Inst()->SimpleScene_LoadProject(dir, file);
+#endif // NV_ARTISTTOOLS
+
+ SetProjectModified(false);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleScene::LoadParameters(NvParameterized::Interface* iface)
+{
+ m_isSceneLoading = true;
+
+ AppMainWindow::Inst().startProgress();
+
+#ifndef NV_ARTISTTOOLS
+ nvidia::parameterized::HairProjectParameters* params = static_cast<nvidia::parameterized::HairProjectParameters*>(iface);
+
+ nvidia::parameterized::HairProjectParametersNS::ParametersStruct& srcDesc = params->parameters();
+
+ if (m_pCamera)
+ {
+ m_pCamera->LoadParameters(&srcDesc.camera);
+ }
+
+ LoadCameraBookmarks(iface);
+
+ if (m_pWindCamera)
+ {
+ m_pWindCamera->LoadParameters(&srcDesc.windCamera);
+ }
+
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ // Load scene settings
+ globalSettings.m_repeatAnimation = srcDesc.scene.repeatAnimation;
+ globalSettings.m_animationSpeed = srcDesc.scene.animationSpeed;
+ globalSettings.m_showGrid = srcDesc.scene.showGrid;
+ globalSettings.m_showAxis = srcDesc.scene.showAxis;
+ globalSettings.m_zup = srcDesc.scene.upAxis == 1;
+ globalSettings.m_sceneUnitIndex = srcDesc.scene.sceneUnitIndex;
+
+ // Load renderer settings
+ NvParameterized::Handle handle(iface);
+
+ // Load fbx paths
+ if (iface->getParameterHandle("fbxFilePaths", handle) == NvParameterized::ERROR_NONE)
+ {
+ int arraySize;
+ handle.getArraySize(arraySize);
+ char** strArray = new char*[arraySize];
+ handle.getParamStringArray(strArray, arraySize);
+ for (int idx = 0; idx < arraySize; ++idx)
+ {
+ LoadSceneFromFbx(
+ globalSettings.m_projectFileDir.c_str(),
+ strArray[idx]);
+ }
+ delete [] strArray;
+ }
+
+ // get general fur renderer settings
+ if (iface->getParameterHandle("renderer", handle) == NvParameterized::ERROR_NONE)
+ FurRenderer::LoadParameters(handle);
+
+ // get fur character mesh setting
+ if (false == GetFurCharacter().LoadMeshParameters(handle))
+ return false;
+
+ // Load apx paths (hair instances)
+ if (iface->getParameterHandle("apxFilePaths", handle) == NvParameterized::ERROR_NONE)
+ {
+ if (false == GetFurCharacter().LoadHairParameters(handle))
+ return false;
+ }
+#else
+ CoreLib::Inst()->SimpleScene_LoadParameters(iface);
+#endif // NV_ARTISTTOOLS
+
+ m_isSceneLoading = false;
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleScene::SaveProject(const char* dir, const char* file)
+{
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ globalSettings.m_projectFileDir = dir;
+ globalSettings.m_projectFileName = file;
+
+ std::string saveFilePath = globalSettings.getAbsoluteFilePath();
+
+ std::string tempFilePath = utils::GetTempFilePath();
+
+#ifndef NV_ARTISTTOOLS
+ if (ProjectParamsSave(g_projectParamsContext, tempFilePath.c_str(), this))
+ {
+ if (!utils::RenameFile(tempFilePath.c_str(), saveFilePath.c_str(), true /* overwrite */))
+ {
+ return false;
+ }
+ SetProjectModified(false);
+ return true;
+ }
+#else
+ return CoreLib::Inst()->SimpleScene_SaveProject(dir, file);
+#endif // NV_ARTISTTOOLS
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleScene::LoadBackgroundTextureFile()
+{
+ QString texName = AppMainWindow::Inst().OpenTextureFile();
+
+ return RenderInterface::LoadBackgroundTexture(texName.toLocal8Bit());
+}
+
+//////////////////////////////////////////////////////////////////////////
+void SimpleScene::ClearBackgroundTexture()
+{
+ RenderInterface::ClearBackgroundTexture();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// slots and handlers / mouse / camera
+
+void SimpleScene::Resize( int w, int h )
+{
+ RenderInterface::ResizeRenderWindow(w,h);
+
+ m_pCamera->SetSize(w,h);
+
+ UpdateCamera();
+
+ SetProjectModified(true);
+}
+
+void SimpleScene::onMouseDown(atcore_float2 position)
+{
+ g_mouse.SetPosition(position);
+}
+
+void SimpleScene::onMouseUp(atcore_float2 position)
+{
+}
+
+void SimpleScene::onMouseMove(atcore_float2 position)
+{
+ g_mouse.SetDelta(position);
+}
+
+void SimpleScene::onMouseWheel(float deltaWheel)
+{
+ g_mouse.SetDeltaWheel(deltaWheel);
+}
+
+QString SimpleScene::createBookmark()
+{
+ QString bookmark = _generateBookmarkName();
+ m_cameraBookmarks.append(CameraBookmark(bookmark, *m_pCamera));
+ return bookmark;
+}
+
+void SimpleScene::removeBookmark(const QString& name)
+{
+ int bookmarksCount = m_cameraBookmarks.size();
+ for (int i = 0; i < bookmarksCount; ++i)
+ {
+ const CameraBookmark& bookmark = m_cameraBookmarks[i];
+ if (bookmark.name == name)
+ {
+ m_cameraBookmarks.removeAt(i);
+ break;
+ }
+ }
+}
+
+void SimpleScene::activateBookmark(const QString& name)
+{
+ int bookmarksCount = m_cameraBookmarks.size();
+ for (int i = 0; i < bookmarksCount; ++i)
+ {
+ const CameraBookmark& bookmark = m_cameraBookmarks[i];
+ if (bookmark.name == name)
+ {
+ *m_pCamera = bookmark.camera;
+ break;
+ }
+ }
+}
+
+void SimpleScene::renameBookmark(const QString& oldName, const QString& newName)
+{
+ int bookmarksCount = m_cameraBookmarks.size();
+ for (int i = 0; i < bookmarksCount; ++i)
+ {
+ CameraBookmark& bookmark = m_cameraBookmarks[i];
+ if (bookmark.name == oldName)
+ {
+ bookmark.name = newName;
+ break;
+ }
+ }
+}
+
+QList<QString> SimpleScene::getBookmarkNames()
+{
+ QList<QString> names;
+ int bookmarksCount = m_cameraBookmarks.size();
+ for (int i = 0; i < bookmarksCount; ++i)
+ {
+ const CameraBookmark& bookmark = m_cameraBookmarks[i];
+ names.append(bookmark.name);
+ }
+
+ return names;
+}
+
+void SimpleScene::Drag( char type )
+{
+ g_mouse.Update();
+
+ switch(type)
+ {
+ case 'R': RotateCamera(); break;
+ case 'Z': ZoomCamera(); break;
+ case 'P': PanCamera(); break;
+ case 'L': RotateLightDirection(); break;
+ case 'W': RotateWindDirection(); break;
+
+ case 'K': PanLight(); break;
+ }
+ SetProjectModified(true);
+}
+
+void SimpleScene::WheelZoom()
+{
+ WheelZoomCamera();
+ SetProjectModified(true);
+}
+
+void SimpleScene::PanCamera()
+{
+ if (g_mouse.GetDelta().x != 0.0f || g_mouse.GetDelta().y != 0.0f)
+ {
+ int w = m_pCamera->GetWidth();
+ int h = m_pCamera->GetHeight();
+
+ atcore_float2 delta = g_mouse.GetDelta() * 2.0f;
+ delta.x /= (float)(w);
+ delta.y /= (float)(h);
+ m_pCamera->Pan(delta);
+ }
+ SetProjectModified(true);
+}
+
+void SimpleScene::ZoomCamera()
+{
+ float dz = (- g_mouse.GetDelta().y);
+
+ if (dz != 0.0f)
+ {
+ dz *= 5.0f / m_pCamera->GetHeight();
+
+ m_pCamera->Dolly(dz);
+ }
+ SetProjectModified(true);
+}
+
+void SimpleScene::WheelZoomCamera()
+{
+ float dz = - g_mouse.GetDeltaWheel() ;
+
+ if (dz != 0.0f)
+ {
+ dz /= 5.0f;
+
+ m_pCamera->Dolly(dz);
+ }
+ SetProjectModified(true);
+}
+
+void SimpleScene::RotateCamera()
+{
+ if (g_mouse.GetDelta().x != 0.0f || g_mouse.GetDelta().y != 0.0f)
+ {
+ m_pCamera->Orbit(g_mouse.GetDelta() * 0.125f);
+ }
+ SetProjectModified(true);
+}
+
+void SimpleScene::RotateLightDirection()
+{
+ if (g_mouse.GetDelta().x != 0.0f || g_mouse.GetDelta().y != 0.0f)
+ {
+ atcore_float2 delta = g_mouse.GetDelta() * 0.5f;
+ delta.y *= -1.0f;
+
+ if (Light::GetLinkLightOption())
+ {
+ Light* pKeyLight = Light::GetLight(Light::KEY_LIGHT);
+ Light* pFillLight = Light::GetLight(Light::FILL_LIGHT);
+ Light* pRimLight = Light::GetLight(Light::RIM_LIGHT);
+ if (pKeyLight->m_selected)
+ {
+ pKeyLight->Orbit(delta);
+ pFillLight->Orbit(delta);
+ pRimLight->Orbit(delta);
+ }
+ else
+ {
+ if (pFillLight->m_selected)
+ {
+ pFillLight->Orbit(delta);
+ }
+
+ if (pRimLight->m_selected)
+ {
+ pRimLight->Orbit(delta);
+ }
+ }
+
+ Light* pEnvLight = Light::GetLight(Light::ENV_LIGHT);
+ if (pEnvLight->m_selected)
+ {
+ pEnvLight->Orbit(delta);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight)
+ continue;
+
+ if (pLight->m_selected)
+ {
+ pLight->Orbit(delta);
+ }
+ }
+ }
+ }
+ SetProjectModified(true);
+}
+
+void SimpleScene::PanLight()
+{
+ if (g_mouse.GetDelta().x != 0.0f || g_mouse.GetDelta().y != 0.0f)
+ {
+ int w = m_pCamera->GetWidth();
+ int h = m_pCamera->GetHeight();
+
+ atcore_float2 delta = g_mouse.GetDelta() * 2.0f;
+ delta.x /= (float)(w);
+ delta.y /= (float)(h);
+
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight)
+ continue;
+
+ if (pLight->m_selected)
+ pLight->Pan(delta, m_pCamera->GetXAxis(), m_pCamera->GetYAxis());
+ }
+ }
+ SetProjectModified(true);
+}
+
+void SimpleScene::RotateWindDirection()
+{
+ if (g_mouse.GetDelta().x != 0.0f || g_mouse.GetDelta().y != 0.0f)
+ {
+ m_pWindCamera->Orbit(g_mouse.GetDelta() * 0.5f);
+
+ GlobalSettings::Inst().m_windDir = m_pWindCamera->GetZAxis();
+ }
+
+ SetProjectModified(true);
+}
+
+QString SimpleScene::_generateBookmarkName()
+{
+ QString name;
+ for (int i = 1; ; i++)
+ {
+ name = QString("View%1").arg(i, 2, 10, QChar('0'));
+ int found = -1;
+ int bookmarksCount = m_cameraBookmarks.size();
+ for (int j = 0; j < bookmarksCount; ++j)
+ {
+ const CameraBookmark& bookmark = m_cameraBookmarks[j];
+ if (bookmark.name == name)
+ {
+ found = j;
+ break;
+ }
+ }
+
+ if (-1 == found)
+ break;
+ }
+ return name;
+}
+
+void SimpleScene::UpdateCamera()
+{
+ if (!m_pCamera)
+ return;
+
+ float sceneUnit = GlobalSettings::Inst().getSceneUnitInCentimeters() ;
+ float fov = (GlobalSettings::Inst().m_fovAngle / 360.0f) * 3.141592653589793;
+
+ m_pCamera->SetFOV(fov);
+
+ int w = m_pCamera->GetWidth();
+ int h = m_pCamera->GetHeight();
+
+ float aspect = ((float)(w) / (float)(h));
+
+ float minZ = 1.0f;
+ float maxZ = 10000.0f; // should calculate dynamically
+
+ if (sceneUnit != 0.0f)
+ {
+ minZ /= sceneUnit;
+ maxZ /= sceneUnit;
+ }
+
+ m_pCamera->SetAspetRatio(aspect);
+ m_pCamera->SetZFar(maxZ);
+ m_pCamera->SetZNear(minZ);
+
+ m_pCamera->Perspective();
+}
+
+void SimpleScene::FitCamera()
+{
+ if (!m_pCamera)
+ return;
+
+ atcore_float3 center, extents;
+
+#ifndef NV_ARTISTTOOLS
+ if (m_pFurCharacter)
+ m_pFurCharacter->ComputeBounds(center, extents, false);
+#else
+ CoreLib::Inst()->SimpleScene_FitCamera(center, extents);
+#endif // NV_ARTISTTOOLS
+
+ m_pCamera->FitBounds(center, extents);
+}
+
+void SimpleScene::ResetUpDir(bool zup)
+{
+ m_pCamera->ResetUpDir(zup);
+ m_pWindCamera->ResetUpDir(zup);
+ Light::ResetUpDir(zup);
+
+ GlobalSettings::Inst().m_zup = zup;
+
+ SetProjectModified(true);
+}
+
+void SimpleScene::ResetLhs(bool lhs)
+{
+ m_pCamera->ResetLhs(lhs);
+ m_pWindCamera->ResetLhs(lhs);
+ Light::ResetLhs(lhs);
+
+ GlobalSettings::Inst().m_lhs = lhs;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleScene::SaveParameters(NvParameterized::Interface* iface)
+{
+#ifndef NV_ARTISTTOOLS
+ nvidia::parameterized::HairProjectParameters* params = static_cast<nvidia::parameterized::HairProjectParameters*>(iface);
+ nvidia::parameterized::HairProjectParametersNS::ParametersStruct& targetDesc = params->parameters();
+
+ if (m_pCamera)
+ m_pCamera->SaveParameters(&targetDesc.camera);
+
+ SaveCameraBookmarks(iface);
+
+ if (m_pWindCamera)
+ m_pWindCamera->SaveParameters(&targetDesc.windCamera);
+
+ // Save scene settings
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ targetDesc.scene.repeatAnimation = globalSettings.m_repeatAnimation;
+ targetDesc.scene.animationSpeed = globalSettings.m_animationSpeed;
+ targetDesc.scene.showGrid = globalSettings.m_showGrid;
+ targetDesc.scene.showAxis = globalSettings.m_showAxis;
+
+ targetDesc.scene.upAxis = (globalSettings.m_zup) ? 1 : 2;
+ targetDesc.scene.sceneUnitIndex = globalSettings.m_sceneUnitIndex;
+
+ FurCharacter& character = GetFurCharacter();
+ NvParameterized::Handle handle(iface);
+
+ // Save renderer settings
+ if (iface->getParameterHandle("renderer", handle) == NvParameterized::ERROR_NONE)
+ {
+ FurRenderer::SaveParameters(handle);
+ character.SaveMeshParameters(handle);
+ }
+
+ if (iface->getParameterHandle("renderer.textureFilePath", handle) == NvParameterized::ERROR_NONE)
+ {
+ std::string textureFilePath = globalSettings.getRelativePath(globalSettings.m_backgroundTextureFilePath.c_str());
+ handle.setParamString(textureFilePath.c_str());
+ }
+
+ // save hair path
+ if (iface->getParameterHandle("apxFilePaths", handle) == NvParameterized::ERROR_NONE)
+ character.SaveHairParameters(handle);
+#else
+ CoreLib::Inst()->SimpleScene_SaveParameters(iface);
+#endif // NV_ARTISTTOOLS
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleScene::LoadCameraBookmarks(NvParameterized::Interface* iface)
+{
+#ifndef NV_ARTISTTOOLS
+ nvidia::parameterized::HairProjectParameters* params = static_cast<nvidia::parameterized::HairProjectParameters*>(iface);
+ nvidia::parameterized::HairProjectParametersNS::ParametersStruct& srcDesc = params->parameters();
+ nvidia::parameterized::HairProjectParametersNS::CameraBookmark_DynamicArray1D_Type& bookmarks = srcDesc.cameraBookmarks;
+
+ NvParameterized::Handle cameraBookmarksHandle(iface);
+ if (iface->getParameterHandle("cameraBookmarks", cameraBookmarksHandle) != NvParameterized::ERROR_NONE)
+ return false;
+
+ int numCameraBookmarks = 0;
+ cameraBookmarksHandle.getArraySize(numCameraBookmarks);
+ for (int idx = 0; idx < numCameraBookmarks; ++idx)
+ {
+ NvParameterized::Handle cameraBookmarkHandle(cameraBookmarksHandle);
+ if (cameraBookmarksHandle.getChildHandle(idx, cameraBookmarkHandle) == NvParameterized::ERROR_NONE)
+ {
+ CameraBookmark cameraBookmark;
+ cameraBookmark.camera.LoadParameters((void*)&(bookmarks.buf[idx].camera));
+ cameraBookmark.camera.SetSize(m_pCamera->GetWidth(), m_pCamera->GetHeight());
+ cameraBookmark.name = bookmarks.buf[idx].name.buf;
+ m_cameraBookmarks.append(cameraBookmark);
+ }
+ }
+#else
+ CoreLib::Inst()->SimpleScene_LoadCameraBookmarks(iface);
+#endif // NV_ARTISTTOOLS
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool SimpleScene::SaveCameraBookmarks(NvParameterized::Interface* iface)
+{
+#ifndef NV_ARTISTTOOLS
+ nvidia::parameterized::HairProjectParameters* params = static_cast<nvidia::parameterized::HairProjectParameters*>(iface);
+ nvidia::parameterized::HairProjectParametersNS::ParametersStruct& srcDesc = params->parameters();
+ nvidia::parameterized::HairProjectParametersNS::CameraBookmark_DynamicArray1D_Type& bookmarks = srcDesc.cameraBookmarks;
+
+ NvParameterized::Handle cameraBookmarksHandle(iface);
+ if (iface->getParameterHandle("cameraBookmarks", cameraBookmarksHandle) != NvParameterized::ERROR_NONE)
+ return false;
+
+ int numCameraBookmarks = m_cameraBookmarks.size();
+ cameraBookmarksHandle.resizeArray(numCameraBookmarks);
+
+ for (int idx = 0; idx < numCameraBookmarks; ++idx)
+ {
+ NvParameterized::Handle cameraBookmarkHandle(cameraBookmarksHandle);
+ if (cameraBookmarksHandle.getChildHandle(idx, cameraBookmarkHandle) == NvParameterized::ERROR_NONE)
+ {
+ NvParameterized::Handle tempHandle(cameraBookmarkHandle);
+ CameraBookmark& bookmark = m_cameraBookmarks[idx];
+
+ if (ParamGetChild(cameraBookmarkHandle, tempHandle, "name"))
+ {
+ tempHandle.setParamString(bookmark.name.toStdString().c_str());
+ }
+
+ bookmark.camera.SaveParameters((void*)&(bookmarks.buf[idx].camera));
+ }
+ }
+#else
+ CoreLib::Inst()->SimpleScene_SaveCameraBookmarks(iface);
+#endif // NV_ARTISTTOOLS
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::sendParam(const char *str, NvFloat32 v)
+{
+ if (g_pBackdoor)
+ {
+ char message[1024];
+ sprintf(message, "%s %f", str, v);
+// viewer_info(message);
+ g_pBackdoor->send("%s", message);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::sendParam(const char *str, NvUInt32 v)
+{
+ if (g_pBackdoor)
+ {
+ char message[1024];
+ sprintf(message, "%s %d", str, v);
+// viewer_info(message);
+ g_pBackdoor->send("%s", message);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::sendParam(const char *str, atcore_float3 v)
+{
+ if (g_pBackdoor)
+ {
+ char message[1024];
+ sprintf(message, "%s %f %f %f", str, v.x, v.y, v.z);
+// viewer_info(message);
+ g_pBackdoor->send("%s", message);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::sendParam(const char *str, atcore_float4 v)
+{
+ if (g_pBackdoor)
+ {
+ char message[1024];
+ sprintf(message, "%s %f %f %f %f", str, v.x, v.y, v.z, v.w);
+// viewer_info(message);
+ g_pBackdoor->send("%s", message);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::sendParam(const char *str, NvBoolean v)
+{
+ if (g_pBackdoor)
+ {
+ char message[1024];
+ sprintf(message, "%s %d", str, int(v));
+// viewer_info(message);
+ g_pBackdoor->send("%s", message);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::DrawGround()
+{
+ bool zup = GlobalSettings::Inst().m_zup;
+
+ SimpleShaderParam param;
+ {
+ param.useVertexColor = true;
+ gfsdk_makeIdentity(param.world);
+ param.view = m_pCamera->GetViewMatrix();
+ param.projection = m_pCamera->GetProjectionMatrix();
+ }
+ RenderInterface::CopyShaderParam(RenderInterface::SHADER_TYPE_SIMPLE_COLOR,
+ (void*)&param, sizeof(SimpleShaderParam) );
+
+ SimpleRenderable::Draw(
+ zup ? SimpleRenderable::GROUND_ZUP :
+ SimpleRenderable::GROUND_YUP, false);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::DrawWind()
+{
+ // Convert camera axis into world matrix
+ atcore_float4x4 windMat = gfsdk_transpose(m_pWindCamera->GetViewMatrix());
+
+ // Extract rotation axis from the view matrix
+ atcore_float4x4 viewMat = m_pCamera->GetViewMatrix();
+ if (m_pCamera->UseLHS())
+ gfsdk_setPosition(viewMat, gfsdk_makeFloat3(0, 0, 80));
+ else
+ gfsdk_setPosition(viewMat, gfsdk_makeFloat3(0, 0, -80));
+
+ SimpleShaderParam param;
+ {
+ param.useVertexColor = true;
+ param.world = windMat;
+ param.view = viewMat;
+ param.projection = m_pCamera->GetProjectionMatrix();
+ }
+ RenderInterface::CopyShaderParam(RenderInterface::SHADER_TYPE_SIMPLE_COLOR,
+ (void*)&param, sizeof(SimpleShaderParam) );
+
+ int targetWidth = m_pCamera->GetWidth();
+ int targetHeight = m_pCamera->GetHeight();
+ float aspectRatio = (float)targetWidth / (float)targetHeight;
+
+ // Wind view size
+ const int srcHeight = 64;
+ const int srcWidth = aspectRatio*srcHeight;
+ const int originX = 64;
+
+ RenderInterface::Viewport savedVP, vp;
+ RenderInterface::GetViewport(savedVP);
+
+ // set the viewport transform
+ {
+ vp.TopLeftX = originX + ( (srcWidth > srcHeight) ? (srcHeight - srcWidth)/2.0f : 0);
+ vp.TopLeftY = targetHeight-srcHeight;
+ vp.Width = (float)srcWidth;
+ vp.Height = (float)srcHeight;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ }
+
+ RenderInterface::SetViewport(vp);
+
+ bool zUP = GlobalSettings::Inst().m_zup;
+ SimpleRenderable::Draw(zUP ?
+ SimpleRenderable::WIND_ZUP :
+ SimpleRenderable::WIND_YUP, false);
+
+ // Restore states
+ RenderInterface::SetViewport(savedVP);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void SimpleScene::DrawAxis()
+{
+ // Extract rotation axis from the view matrix
+ atcore_float4x4 viewMat = m_pCamera->GetViewMatrix();
+ if (m_pCamera->UseLHS())
+ gfsdk_setPosition(viewMat, gfsdk_makeFloat3(0, 0, 4));
+ else
+ gfsdk_setPosition(viewMat, gfsdk_makeFloat3(0, 0, -4));
+
+ SimpleShaderParam param;
+ {
+ param.useVertexColor = true;
+ gfsdk_makeIdentity(param.world);
+ param.view = viewMat;
+ param.projection = m_pCamera->GetProjectionMatrix();
+ }
+ RenderInterface::CopyShaderParam(RenderInterface::SHADER_TYPE_SIMPLE_COLOR,
+ (void*)&param, sizeof(SimpleShaderParam) );
+
+ int targetWidth = m_pCamera->GetWidth();
+ int targetHeight = m_pCamera->GetHeight();
+ float aspectRatio = (float)targetWidth / (float)targetHeight;
+
+ // Axis view size
+ const int srcHeight = 64;
+ const int srcWidth = aspectRatio*srcHeight;
+
+ RenderInterface::Viewport savedVP, vp;
+ RenderInterface::GetViewport(savedVP);
+
+ // set the viewport transform
+ {
+ vp.TopLeftX = (srcWidth > srcHeight) ? (srcHeight - srcWidth)/2.0f : 0; // To make it like a square view
+ vp.TopLeftY = targetHeight-srcHeight;
+ vp.Width = (float)srcWidth;
+ vp.Height = (float)srcHeight;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ }
+
+ RenderInterface::SetViewport(vp);
+
+ bool zUP = GlobalSettings::Inst().m_zup;
+ SimpleRenderable::Draw(zUP ?
+ SimpleRenderable::AXIS_ZUP :
+ SimpleRenderable::AXIS_YUP, false);
+
+ RenderInterface::SetViewport(savedVP);
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Scene/SimpleScene.h b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/SimpleScene.h
new file mode 100644
index 0000000..8d01970
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Scene/SimpleScene.h
@@ -0,0 +1,184 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include <Windows.h>
+#include "MathUtil.h"
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include "Camera.h"
+#include "Timer.h"
+class FurCharacter;
+
+class DeviceManager;
+class SampleManager;
+
+namespace NvParameterized
+{
+ class Interface;
+}
+
+struct CameraBookmark
+{
+ CameraBookmark()
+ {
+ }
+ CameraBookmark(const QString& inName, const Camera& inCamera)
+ : name(inName)
+ , camera(inCamera)
+ {
+ }
+ QString name;
+ Camera camera;
+};
+
+//////////////////////////////////////////////////////////////////////////////////////
+// This scene object does the followings
+// - handles the overall project settings load/save
+// - owns and calls FurRenderer's draw functions
+// - owns and handle main camera and mouse callbacks
+// - owns and handles backdoor communication with the SDK and game engines
+//////////////////////////////////////////////////////////////////////////////////////
+class CORELIB_EXPORT SimpleScene
+{
+public:
+ SimpleScene();
+
+ static SimpleScene* Inst();
+
+ // prepare shaders, manage objects
+ bool Initialize(HWND hWnd, int backdoor = 0);
+
+ bool LoadProject(const char* dir, const char* file);
+ bool SaveProject(const char* dir, const char* file);
+ bool LoadParameters(NvParameterized::Interface* iface);
+ bool SaveParameters(NvParameterized::Interface* iface);
+ bool LoadCameraBookmarks(NvParameterized::Interface* iface);
+ bool SaveCameraBookmarks(NvParameterized::Interface* iface);
+ bool Clear();
+
+ bool LoadSceneFromFbx(const char* dir, const char* fbxName);
+
+ bool IsUpdatingUI() { return m_isUpdatingUI; }
+ void setIsUpdatingUI(bool b) { m_isUpdatingUI = b;}
+ bool IsSceneLoading() { return m_isSceneLoading; }
+
+ Camera* GetCamera() { return m_pCamera; }
+ FurCharacter& GetFurCharacter() { return *m_pFurCharacter; }
+ void SetFurCharacter(FurCharacter* pFurCharacter) { m_pFurCharacter = pFurCharacter; }
+
+ DeviceManager& GetDeviceManager() { return *m_pDeviceManager; }
+ void SetDeviceManager(DeviceManager* pDeviceManager) { m_pDeviceManager = pDeviceManager; }
+ SampleManager& GetSampleManager() { return *m_pSampleManager; }
+ void SetSampleManager(SampleManager* pSampleManager) { m_pSampleManager = pSampleManager; }
+
+ void ResetUpDir(bool zup);
+ void ResetLhs(bool lhs);
+
+ bool LoadBackgroundTextureFile();
+ void ClearBackgroundTexture();
+
+ // backdoor
+ void sendParam(const char *str, NvFloat32 v);
+ void sendParam(const char *str, NvUInt32 v);
+ void sendParam(const char *str, atcore_float3 v);
+ void sendParam(const char *str, atcore_float4 v);
+ void sendParam(const char *str, NvBoolean v);
+
+ bool IsFurModified() const { return m_isFurModified; }
+ bool IsProjectModified() const { return m_isProjectModified; }
+ void SetFurModified(bool isModified) { m_isFurModified = isModified; }
+ void SetProjectModified(bool isModified) { m_isProjectModified = isModified; }
+
+ void UpdateCamera();
+ void FitCamera();
+
+ void Draw();
+ void Timeout();
+ void Resize(int w, int h);
+ void Drag(char type);
+ void WheelZoom();
+ void Shutdown();
+
+ void onMouseDown(atcore_float2 position);
+ void onMouseUp(atcore_float2 position);
+ void onMouseMove(atcore_float2 position);
+ void onMouseWheel(float deltaWheel);
+
+ QString createBookmark();
+ void removeBookmark(const QString& name);
+ void activateBookmark(const QString& name);
+ void renameBookmark(const QString& oldName, const QString& newName);
+ QList<QString> getBookmarkNames();
+
+ static float NextTimeStep();
+
+ Timer& GetTimer();
+
+private:
+ // initialize scene components
+ bool InitCameraMouse(HWND hAppWnd);
+ bool InitFurSDK();
+
+ void DrawGround();
+ void DrawAxis();
+ void DrawHUD();
+ void DrawWind();
+
+ // camera / mouse
+ void PanCamera();
+ void ZoomCamera();
+ void WheelZoomCamera();
+ void RotateCamera();
+
+ void RotateLightDirection();
+ void PanLight();
+
+ void RotateWindDirection();
+
+ QString _generateBookmarkName();
+
+public:
+
+ Camera* m_pCamera;
+ Camera* m_pWindCamera;
+
+ QList<CameraBookmark> m_cameraBookmarks;
+
+ FurCharacter* m_pFurCharacter;
+
+ DeviceManager* m_pDeviceManager;
+ SampleManager* m_pSampleManager;
+
+ bool m_isProjectModified;
+ bool m_isFurModified;
+ bool m_isSceneLoading;
+ bool m_isUpdatingUI;
+};
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Automate.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Automate.cpp
new file mode 100644
index 0000000..6c7d551
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Automate.cpp
@@ -0,0 +1,530 @@
+#include <windows.h>
+
+#include <QtWidgets/QApplication>
+
+#include "AppMainWindow.h"
+//#include "SimpleScene.h"
+
+#include "OpenAutomate.h"
+#include "Automate.h"
+#include "Settings.h"
+
+//#define OPEN_CONSOLE
+#ifdef OPEN_CONSOLE
+#include <Windows.h>
+#endif
+
+#include <cassert>
+#include <string>
+
+#include <Nv/Common/NvCoCommon.h>
+
+#define KEYSTR ("Software\\OpenAutomate\\RegisteredApps\\NVIDIA\\FurViewer\\v1.0\\")
+
+const oaChar *Benchmarks[] = {
+ "HairBall",
+ "Teapot",
+ "Manjaladon",
+ "WitcherHorse",
+ NV_NULL
+};
+oaInt NumBenchmarks = 1;
+
+static void ParseArgs(int argc, char *argv[]);
+
+static void OAMainLoop(const char *opt);
+static bool RegisterAppItself();
+static int RunApp(QApplication& a);
+static void GetAllOptions(void);
+static void GetCurrentOptions(void);
+
+static bool g_isAutomateMode = false;
+static int InstallModeFlag = 0;
+static char *OAOpt = NV_NULL;
+
+bool AutomateInstallApp()
+{
+ return RegisterAppItself();
+}
+
+static bool RegisterAppItself()
+{
+ char exePath[MAX_PATH];
+ if(!GetExePath(exePath))
+ {
+ fprintf(stderr, "Cannot get exe path\r\n");
+ return false;
+ }
+
+ HKEY hKey;
+ DWORD dwRes = RegOpenKeyExA(
+ HKEY_LOCAL_MACHINE,
+ KEYSTR,
+ 0,
+ KEY_WRITE | KEY_READ,
+ &hKey);
+
+ DWORD dwSize = MAX_PATH;
+ char buf[MAX_PATH];
+ if(dwRes == ERROR_SUCCESS)
+ {
+ dwRes = RegQueryValueExA(
+ hKey,
+ "INSTALL_ROOT_PATH",
+ NV_NULL,
+ NV_NULL,
+ (LPBYTE)buf,
+ &dwSize);
+ if(dwRes == ERROR_SUCCESS && !lstrcmpiA(buf, exePath))
+ {
+ RegCloseKey(hKey);
+ return true;
+ }
+ }
+ else
+ {
+ dwRes = RegCreateKeyExA(
+ HKEY_LOCAL_MACHINE,
+ KEYSTR,
+ 0,
+ NV_NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE, NV_NULL,
+ &hKey,
+ &dwSize);
+ if(ERROR_SUCCESS != dwRes)
+ {
+ RegCloseKey(hKey);
+ return false;
+ }
+ }
+
+ bool bRet = false;
+ do
+ {
+ dwRes = RegSetValueExA(
+ hKey,
+ "INSTALL_ROOT_PATH",
+ 0,
+ REG_SZ,
+ (BYTE*)exePath,
+ (DWORD)strlen(exePath));
+ if(ERROR_SUCCESS != dwRes)
+ {
+ fprintf(stderr, "Write INSTALL_ROOT_PATH Failed\r\n");
+ break;
+ }
+
+#ifdef _WIN64
+#ifdef _DEBUG
+ strcat(exePath, "FurViewer.win64.D.exe");
+#else
+ strcat(exePath, "FurViewer.win64.exe");
+#endif
+#else
+#ifdef _DEBUG
+ strcat(exePath, "FurViewer.win32.D.exe");
+#else
+ strcat(exePath, "FurViewer.win32.exe");
+#endif
+#endif
+
+ dwRes = RegSetValueExA(
+ hKey,
+ "ENTRY_EXE",
+ 0,
+ REG_SZ,
+ (BYTE*)exePath,
+ (DWORD)strlen(exePath));
+ if(ERROR_SUCCESS != dwRes)
+ {
+ fprintf(stderr, "Write ENTRY_EXE Failed\r\n");
+ break;
+ }
+
+ ZeroMemory(buf, sizeof(buf));
+ SYSTEMTIME tm;
+ GetLocalTime(&tm);
+ sprintf(
+ buf,
+ "%04d-%02d-%02d %02d:%02d:%02d",
+ tm.wYear,
+ tm.wMonth,
+ tm.wDay,
+ tm.wHour,
+ tm.wMinute,
+ tm.wSecond);
+ dwRes = RegSetValueExA(
+ hKey,
+ "INSTALL_DATETIME",
+ 0,
+ REG_SZ,
+ (BYTE*)buf,
+ (DWORD)strlen(buf));
+ if(ERROR_SUCCESS != dwRes)
+ {
+ fprintf(stderr, "Write INSTALL_DATETIME Failed\r\n");
+ break;
+ }
+
+ dwRes = RegSetValueExA(
+ hKey,
+ "REGION",
+ 0,
+ REG_SZ,
+ (BYTE*)"en_US",
+ (DWORD)strlen("en_US"));
+ if(ERROR_SUCCESS != dwRes)
+ {
+ fprintf(stderr, "Write REGION Failed\r\n");
+ break;
+ }
+
+ bRet = true;
+ } while(0);
+
+ RegCloseKey(hKey);
+ return bRet;
+}
+
+static const char *FormatDataType(oaOptionDataType value_type)
+{
+ switch(value_type)
+ {
+ case OA_TYPE_STRING:
+ return "String";
+ case OA_TYPE_INT:
+ return "Int";
+ case OA_TYPE_FLOAT:
+ return "Float";
+ case OA_TYPE_ENUM:
+ return "Enum";
+ case OA_TYPE_BOOL:
+ return "Bool";
+ default:
+ return "Unknown";
+ }
+}
+
+static const char *FormatCompareOp(oaComparisonOpType op_value)
+{
+ switch(op_value)
+ {
+ case OA_COMP_OP_EQUAL:
+ return "Equal";
+ case OA_COMP_OP_NOT_EQUAL:
+ return "NotEqual";
+ case OA_COMP_OP_GREATER:
+ return "Greater";
+ case OA_COMP_OP_LESS:
+ return "Less";
+ case OA_COMP_OP_GREATER_OR_EQUAL:
+ return "GreaterOrEqual";
+ case OA_COMP_OP_LESS_OR_EQUAL:
+ return "LessOrEqual";
+ default:
+ return "Unknown";
+ }
+}
+
+static void ConvertOAValue(oaOptionDataType value_type,
+ const oaValue *value,
+ char *result)
+{
+ switch(value_type)
+ {
+ case OA_TYPE_STRING:
+ case OA_TYPE_ENUM:
+ if (value->String) strcpy(result, value->String);
+ else result[0] = '\0';
+ break;
+ case OA_TYPE_INT:
+ sprintf(result, "%d", value->Int);
+ break;
+ case OA_TYPE_FLOAT:
+ sprintf(result, "%f", value->Float);
+ break;
+ case OA_TYPE_BOOL:
+ sprintf(result, "%1d", value->Bool);
+ break;
+ default:
+ return;
+ }
+}
+
+static void PrintOptions(const oaNamedOption *option)
+{
+ char buf[MAX_PATH];
+ ConvertOAValue(option->DataType, &option->Value, buf);
+
+ fprintf(stderr, "name=%s,type=%s,value=%s\r\n", option->Name, FormatDataType(option->DataType), buf);
+ if(option->MaxValue.Int && option->MinValue.Int)
+ {
+ fprintf(stderr," numsteps=%d", option->NumSteps);
+ ConvertOAValue(option->DataType, &option->MinValue, buf);
+ fprintf(stderr, "minvalue=%s", buf);
+ ConvertOAValue(option->DataType, &option->MaxValue, buf);
+ fprintf(stderr,"maxvalue=%s\r\n", buf);
+ }
+
+ if(option->Dependency.ParentName)
+ {
+ ConvertOAValue(option->Dependency.ComparisonValType, &option->Dependency.ComparisonVal, buf);
+ fprintf(stderr, " parentname=%s,comparisionop=%s,comparisiontype=%s,comparisionvalue=%s\r\n",
+ option->Dependency.ParentName,
+ FormatCompareOp(option->Dependency.ComparisonOp),
+ FormatDataType(option->Dependency.ComparisonValType),
+ buf);
+ }
+}
+
+#if (0) // Remove this!
+int main(int argc, char *argv[])
+{
+ SetConsoleTitleA("OA - simple application");
+ ParseArgs(argc, argv);
+
+ AppSettings::Inst().InitOptions();
+
+ if(InstallModeFlag)
+ {
+ InstallApp();
+ }
+ else if(OAModeFlag)
+ {
+ OAMainLoop(OAOpt);
+ }
+ else
+ {
+ RunApp();
+ }
+
+ return(0);
+}
+#endif
+
+void GetAllOptions(void)
+{
+ fprintf(stderr, "All Options: \r\n");
+ for(oaInt i=0; i < AppSettings::Inst().GetNumOptions(); ++i)
+ {
+ oaNamedOption* option = AppSettings::Inst().GetOption(i);
+ if (!strcmp(option->Name, "User/ProjectPath"))
+ continue;
+ if (!strcmp(option->Name, "User/FurAssetPath"))
+ continue;
+ PrintOptions(AppSettings::Inst().GetOption(i));
+ oaAddOption(AppSettings::Inst().GetOption(i));
+ }
+}
+
+void GetCurrentOptions(void)
+{
+ fprintf(stderr, "Current Options: \r\n");
+
+ std::map<std::string, OptionValue>::const_iterator Iter = AppSettings::Inst().GetCurrentOptionMap()->begin();
+
+ oaNamedOption option;
+ oaInitOption(&option);
+
+ for(; Iter != AppSettings::Inst().GetCurrentOptionMap()->end(); ++Iter)
+ {
+ if (!strcmp(Iter->second.Name, "User/ProjectPath"))
+ continue;
+ if (!strcmp(Iter->second.Name, "User/FurAssetPath"))
+ continue;
+
+ option.Name = Iter->second.Name;
+ option.Value = Iter->second.Value;
+ option.DataType = Iter->second.Type;
+ PrintOptions(&option);
+
+ oaAddOptionValue(Iter->second.Name,
+ Iter->second.Type,
+ &Iter->second.Value);
+ }
+}
+
+void SetOptions(void)
+{
+ oaNamedOption *Option;
+
+ fprintf(stderr, "Set Options: \r\n");
+ while ((Option = oaGetNextOption()) != NV_NULL)
+ {
+ /*
+ * Set option value to persist for subsequent runs of the game
+ * to the given value. Option->Name will be the name of the value,
+ * and Option->Value will contain the appropriate value.
+ */
+ PrintOptions(Option);
+ AppSettings::Inst().SetOptionValue(Option->Name, Option->DataType, &Option->Value);
+ }
+
+ AppSettings::Inst().WriteOptionsFile();
+}
+
+void GetBenchmarks(void)
+{
+ /* foreach known available benchmark call oaAddBenchmark() with a unique string identifying it */
+ for(oaInt i=0; i < NumBenchmarks; ++i)
+ oaAddBenchmark(Benchmarks[i]);
+}
+
+void RunBenchmark(const oaChar *benchmark_name)
+{
+ oaValue Val;
+ int i;
+
+ bool FoundBenchmark = false;
+ for(i=0; i < NumBenchmarks; ++i)
+ if(!strcmp(Benchmarks[i], benchmark_name))
+ {
+ FoundBenchmark = true;
+ break;
+ }
+
+ /* Check if the requested benchark is valid */
+ if(!FoundBenchmark)
+ {
+ char Msg[1024];
+ sprintf(Msg, "'%s' is not a valid benchmark.", benchmark_name);
+ OA_RAISE_ERROR(INVALID_BENCHMARK, benchmark_name);
+ }
+
+ /* Setup everything to run the benchmark */
+
+ /* oaStartBenchmark() must be called right before the first frame */
+ oaStartBenchmark();
+
+ /*
+ * Run the benchmark, and call oaDisplayFrame() right before the final
+ * present call for each frame
+ */
+ //for(i=0; i < 50; ++i)
+ //{
+ // SLEEP(20);
+
+ // oaValue FrameValue;
+ // FrameValue.Int = i;
+ // oaValue OtherInt;
+ // OtherInt.Int = i+1000;
+ // oaChar str[100];
+ // sprintf(str, "frame number: %d\00", i);
+ // oaValue Str;
+ // Str.String = str;
+
+ // oaAddFrameValue("FrameCount", OA_TYPE_INT, &FrameValue);
+ // oaAddFrameValue("OtherInt", OA_TYPE_INT, &OtherInt);
+ // oaAddFrameValue("String", OA_TYPE_STRING, &Str);
+
+ // oaDisplayFrame((oaFloat)(i * 20) / (oaFloat)1000);
+ //}
+ {
+// SimpleScene* scene = SimpleScene::Inst();
+ AppMainWindow::Inst().menu_clearScene();
+ }
+
+ /* Return some result values */
+ Val.Int = 18249;
+ oaAddResultValue("Score", OA_TYPE_INT, &Val);
+
+ Val.Float = 29.14;
+ oaAddResultValue("Some other score", OA_TYPE_FLOAT, &Val);
+
+ /* oaStartBenchmark() must be called right after the last frame */
+ oaEndBenchmark();
+}
+
+int AutomateInit(const char* opt)
+{
+ oaVersion Version;
+ if (!oaInit((const oaString)opt, &Version))
+ {
+ Error("OA did not initialize properly.");
+ return 1;
+ }
+ g_isAutomateMode = true;
+ return 0;
+}
+
+void AutomateRun()
+{
+ oaCommand Command;
+
+ oaInitCommand(&Command);
+ switch(oaGetNextCommand(&Command))
+ {
+ /* No more commands, exit program */
+ case OA_CMD_EXIT:
+ AppMainWindow::Inst().close();
+ return;
+
+ /* Run as normal */
+ case OA_CMD_RUN:
+ break;
+
+ /* Enumerate all in-game options */
+ case OA_CMD_GET_ALL_OPTIONS:
+ GetAllOptions();
+ break;
+
+ /* Return the option values currently set */
+ case OA_CMD_GET_CURRENT_OPTIONS:
+ GetCurrentOptions();
+ break;
+
+ /* Set all in-game options */
+ case OA_CMD_SET_OPTIONS:
+ SetOptions();
+ break;
+
+ /* Enumerate all known benchmarks */
+ case OA_CMD_GET_BENCHMARKS:
+ GetBenchmarks();
+ break;
+
+ /* Run benchmark */
+ case OA_CMD_RUN_BENCHMARK:
+ RunBenchmark(Command.BenchmarkName);
+ break;
+ }
+}
+
+bool IsAutomateMode()
+{
+ return g_isAutomateMode;
+}
+
+bool GetAutomateInstallModeOption(int argc, char* argv[])
+{
+ for (int idx = 1; idx < argc; ++idx)
+ {
+ if (!strcmp(argv[idx], "-install"))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+std::string GetAutomateOption(int argc, char* argv[])
+{
+ for (int idx = 1; idx < argc; ++idx)
+ {
+ if (!strcmp(argv[idx], "-openautomate"))
+ {
+ if ((idx + 1) < argc)
+ {
+ return argv[idx+1];
+ }
+ else
+ {
+ Error("-openautomate option must have an argument.");
+ return "";
+ }
+ }
+ }
+ return "";
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Automate.h b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Automate.h
new file mode 100644
index 0000000..6f5de4f
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Automate.h
@@ -0,0 +1,23 @@
+
+// Wrapper functions for OpenAutomate
+
+// Add application info into registry key for Automate
+// Return true if succeeded
+bool AutomateInstallApp();
+
+// Initialize OpenAutomate with its command line option. No need to cleanup
+int AutomateInit(const char* opt);
+
+// Call this function when the application is idle when IsAutomateMode() is true
+void AutomateRun();
+
+// Returns true if automate mode is initialized by AutomateInit() call
+bool IsAutomateMode();
+
+// Utility function to parse the command line option for OpenAutomate
+// Returns OpenAutomate option if it has. If not, returns empty string
+std::string GetAutomateOption(int argc, char* argv[]);
+
+// Returns true if it has "-install" in the command line option
+bool GetAutomateInstallModeOption(int argc, char* argv[]);
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/CoreLibUtils.h b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/CoreLibUtils.h
new file mode 100644
index 0000000..6decd0c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/CoreLibUtils.h
@@ -0,0 +1,65 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#pragma once
+
+#include <QtCore/QFile>
+#include <QtCore/QTemporaryFile>
+
+namespace utils {
+
+inline std::string GetTempFilePath()
+{
+ QByteArray tempFilePath;
+ QTemporaryFile tempFile;
+ // temp file will be automatically deleted after this function
+ tempFile.open();
+ tempFilePath = tempFile.fileName().toLocal8Bit();
+ return std::string(tempFilePath);
+}
+
+inline bool RenameFile(const char* srcFilePath, const char* targetFilePath, bool isOvewrite = false)
+{
+ if (QFile::exists(targetFilePath))
+ {
+ if (isOvewrite == false) return false;
+ if (!QFile::remove(targetFilePath)) return false;
+ }
+ return QFile::rename(srcFilePath, targetFilePath);
+}
+
+inline bool CopyFile(const char* srcFilePath, const char* targetFilePath, bool isOverwrite = false)
+{
+ if (QFile::exists(targetFilePath))
+ {
+ if (isOverwrite == false) return false;
+ if (!QFile::remove(targetFilePath)) return false;
+ }
+ return QFile::copy(srcFilePath, targetFilePath);
+}
+
+} // end of utils
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/MathUtil.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/MathUtil.cpp
new file mode 100644
index 0000000..bdb3a77
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/MathUtil.cpp
@@ -0,0 +1,327 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// This file contains wrapper functions to make hair lib easy to setup and use
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#include "MathUtil.h"
+#include <string.h>
+
+////////////////////////////////////////////////////////////////////////////////////////
+void gfsdk_makeIdentity(atcore_float4x4& transform)
+{
+ memset(&transform, 0, sizeof(atcore_float4x4));
+ transform._11 = 1.0f;
+ transform._22 = 1.0f;
+ transform._33 = 1.0f;
+ transform._44 = 1.0f;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+void gfsdk_makeTranslation(atcore_float4x4& m, const atcore_float3& t)
+{
+ gfsdk_makeIdentity(m);
+ m._41 = t.x;
+ m._42 = t.y;
+ m._43 = t.z;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+void gfsdk_makeScale(atcore_float4x4& m, const atcore_float3& s)
+{
+ gfsdk_makeIdentity(m);
+ m._11 = s.x;
+ m._12 = s.y;
+ m._13 = s.z;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void gfsdk_makeRotation(atcore_float4x4& m, const atcore_float4& q)
+{
+ gfsdk_makeIdentity(m);
+
+ const float x = q.x;
+ const float y = q.y;
+ const float z = q.z;
+ const float w = q.w;
+
+ const float x2 = x + x;
+ const float y2 = y + y;
+ const float z2 = z + z;
+
+ const float xx = x2*x;
+ const float yy = y2*y;
+ const float zz = z2*z;
+
+ const float xy = x2*y;
+ const float xz = x2*z;
+ const float xw = x2*w;
+
+ const float yz = y2*z;
+ const float yw = y2*w;
+ const float zw = z2*w;
+
+ m._11 = 1.0f - yy - zz;
+ m._12 = xy + zw;
+ m._13 = xz - yw;
+
+ m._21 = xy - zw;
+ m._22 = 1.0f - xx - zz;
+ m._23 = yz + xw;
+
+ m._31 = xz + yw;
+ m._32 = yz - xw;
+ m._33 = 1.0f - xx - yy;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+atcore_float4x4 gfsdk_makeTransform(const atcore_float4& q, const atcore_float3& t, const atcore_float3 &s)
+{
+ atcore_float4x4 m;
+
+ gfsdk_makeRotation(m, q);
+
+ m._11 *= s.x; m._12 *= s.x; m._13 *= s.x;
+ m._21 *= s.y; m._22 *= s.y; m._23 *= s.y;
+ m._31 *= s.z; m._32 *= s.z; m._33 *= s.z;
+
+ m._41 = t.x;
+ m._42 = t.y;
+ m._43 = t.z;
+
+ return m;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+atcore_float4 gfsdk_getRotation(const atcore_float4x4& sm)
+{
+ atcore_float4x4 m = sm;
+
+ gfsdk_orthonormalize(m);
+
+ atcore_float4 q;
+
+ float x,y,z,w;
+
+ float tr = m._11 + m._22 + m._33, h;
+ if(tr >= 0)
+ {
+ h = sqrt(tr +1);
+ w = float(0.5) * h;
+ h = float(0.5) / h;
+
+ x = (m._23 - m._32) * h;
+ y = (m._31 - m._13) * h;
+ z = (m._12 - m._21) * h;
+ }
+ else
+ {
+ float max = m._11;
+ int i = 0;
+ if (m._22 > m._11)
+ {
+ i = 1;
+ max = m._22;
+ }
+ if (m._33 > max)
+ i = 2;
+ switch (i)
+ {
+ case 0:
+ h = sqrt((m._11 - (m._22 + m._33)) + 1);
+ x = float(0.5) * h;
+ h = float(0.5) / h;
+
+ y = (m._21 + m._12) * h;
+ z = (m._13 + m._31) * h;
+ w = (m._23 - m._32) * h;
+ break;
+ case 1:
+ h = sqrt((m._22 - (m._33 + m._11)) + 1);
+ y = float(0.5) * h;
+ h = float(0.5) / h;
+
+ z = (m._32 + m._23) * h;
+ x = (m._21 + m._12) * h;
+ w = (m._31 - m._13) * h;
+ break;
+ case 2:
+ h = sqrt((m._33 - (m._11 + m._22)) + 1);
+ z = float(0.5) * h;
+ h = float(0.5) / h;
+
+ x = (m._13 + m._31) * h;
+ y = (m._32 + m._23) * h;
+ w = (m._12 - m._21) * h;
+ break;
+ default: // Make compiler happy
+ x = y = z = w = 0;
+ break;
+ }
+ }
+
+ return gfsdk_makeFloat4(x,y,z,w);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+atcore_float4x4 gfsdk_lerp(atcore_float4x4& start, atcore_float4x4& end, float t)
+{
+ atcore_float4 sq = gfsdk_getRotation(start);
+ atcore_float4 eq = gfsdk_getRotation(end);
+ atcore_float3 st = gfsdk_getTranslation(start);
+ atcore_float3 et = gfsdk_getTranslation(end);
+
+ atcore_float3 ss = gfsdk_getScale(start);
+ atcore_float3 es = gfsdk_getScale(end);
+ atcore_float3 s = gfsdk_lerp(ss, es, t);
+
+ atcore_dualquaternion sdq = gfsdk_makeDQ(sq, st);
+ atcore_dualquaternion edq = gfsdk_makeDQ(eq, et);
+
+ atcore_dualquaternion dq = gfsdk_lerp(sdq, edq, t);
+
+ atcore_float4 gr = getRotation(dq);
+ atcore_float3 gt = getTranslation(dq);
+
+ return gfsdk_makeTransform(gr, gt, s);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+atcore_float4x4 operator*(const atcore_float4x4& in1, const atcore_float4x4& in2)
+{
+#define MATRIX_SUM(OUT, IN1, IN2, ROW, COL) OUT._##ROW##COL = IN1._##ROW##1 * IN2._1##COL + IN1._##ROW##2 * IN2._2##COL + IN1._##ROW##3 * IN2._3##COL + IN1._##ROW##4 * IN2._4##COL;
+
+ atcore_float4x4 out;
+
+ MATRIX_SUM(out, in1, in2, 1, 1);
+ MATRIX_SUM(out, in1, in2, 1, 2);
+ MATRIX_SUM(out, in1, in2, 1, 3);
+ MATRIX_SUM(out, in1, in2, 1, 4);
+
+ MATRIX_SUM(out, in1, in2, 2, 1);
+ MATRIX_SUM(out, in1, in2, 2, 2);
+ MATRIX_SUM(out, in1, in2, 2, 3);
+ MATRIX_SUM(out, in1, in2, 2, 4);
+
+ MATRIX_SUM(out, in1, in2, 3, 1);
+ MATRIX_SUM(out, in1, in2, 3, 2);
+ MATRIX_SUM(out, in1, in2, 3, 3);
+ MATRIX_SUM(out, in1, in2, 3, 4);
+
+ MATRIX_SUM(out, in1, in2, 4, 1);
+ MATRIX_SUM(out, in1, in2, 4, 2);
+ MATRIX_SUM(out, in1, in2, 4, 3);
+ MATRIX_SUM(out, in1, in2, 4, 4);
+
+#undef MATRIX_SUM
+
+ return out;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+float
+gfsdk_getDeterminant(const atcore_float4x4& m)
+{
+ const float* matrix = (const float*)&m;
+
+ atcore_float3 p0 = gfsdk_makeFloat3(matrix[0*4+0], matrix[0*4+1], matrix[0*4+2]);
+ atcore_float3 p1 = gfsdk_makeFloat3(matrix[1*4+0], matrix[1*4+1], matrix[1*4+2]);
+ atcore_float3 p2 = gfsdk_makeFloat3(matrix[2*4+0], matrix[2*4+1], matrix[2*4+2]);
+
+ atcore_float3 tempv = gfsdk_cross(p1,p2);
+
+ return gfsdk_dot(p0, tempv);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+atcore_float4x4
+gfsdk_getSubMatrix(int ki,int kj, const atcore_float4x4& m)
+{
+ atcore_float4x4 out;
+ gfsdk_makeIdentity(out);
+
+ float* pDst = (float*)&out;
+ const float* matrix = (const float*)&m;
+
+ int row, col;
+ int dstCol = 0, dstRow = 0;
+
+ for ( col = 0; col < 4; col++ )
+ {
+ if ( col == kj )
+ {
+ continue;
+ }
+ for ( dstRow = 0, row = 0; row < 4; row++ )
+ {
+ if ( row == ki )
+ {
+ continue;
+ }
+ pDst[dstCol*4+dstRow] = matrix[col*4+row];
+ dstRow++;
+ }
+ dstCol++;
+ }
+
+ return out;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+atcore_float4x4 gfsdk_inverse(const atcore_float4x4& m)
+{
+ atcore_float4x4 im;
+
+ float* inverse_matrix = (float*)&im;
+
+ float det = gfsdk_getDeterminant(m);
+ det = 1.0f / det;
+ for (int i = 0; i < 4; i++ )
+ {
+ for (int j = 0; j < 4; j++ )
+ {
+ int sign = 1 - ( ( i + j ) % 2 ) * 2;
+
+ atcore_float4x4 subMat = gfsdk_getSubMatrix(i, j, m);
+ float subDeterminant = gfsdk_getDeterminant(subMat);
+
+ inverse_matrix[i*4+j] = ( subDeterminant * sign ) * det;
+ }
+ }
+
+ return im;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+atcore_dualquaternion gfsdk_makeDQ(const atcore_float4x4& m)
+{
+ atcore_float4 q = gfsdk_getRotation(m);
+ atcore_float3 t = gfsdk_getTranslation(m);
+
+ return gfsdk_makeDQ(q, t);
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/MathUtil.h b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/MathUtil.h
new file mode 100644
index 0000000..7b7a2a5
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/MathUtil.h
@@ -0,0 +1,557 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#pragma once
+
+#include "corelib_global.h"
+#include "CoreLib.h"
+#include "math.h"
+#include "float.h"
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline float gfsdk_lerp(float v1, float v2, float t)
+{
+ return (1.0f - t) * v1 + t * v2;
+}
+
+inline float gfsdk_min(float x, float y) {
+ return (x < y) ? x : y;
+}
+
+inline float gfsdk_max(float x, float y) {
+ return (x > y) ? x : y;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float2 gfsdk_makeFloat2(float x, float y)
+{
+ atcore_float2 v;
+ v.x = x;
+ v.y = y;
+ return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float2 operator*(float s, const atcore_float2 &p)
+{
+ return gfsdk_makeFloat2(s * p.x, s * p.y);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float2 operator*(const atcore_float2 &p, float s)
+{
+ return gfsdk_makeFloat2(s * p.x, s * p.y);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_makeFloat3(float x, float y, float z)
+{
+ atcore_float3 v;
+ v.x = x;
+ v.y = y;
+ v.z = z;
+ return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 operator+(const atcore_float3 &p0, const atcore_float3 &p1)
+{
+ return gfsdk_makeFloat3(p0.x + p1.x, p0.y + p1.y, p0.z + p1.z);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3& operator+=(atcore_float3 &v, const atcore_float3 & v1)
+{
+ v.x += v1.x; v.y += v1.y; v.z += v1.z;
+ return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 operator-(const atcore_float3 &p0, const atcore_float3 &p1)
+{
+ return gfsdk_makeFloat3(p0.x - p1.x, p0.y - p1.y, p0.z - p1.z);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3& operator-=(atcore_float3 &v, const atcore_float3 & v1)
+{
+ v.x -= v1.x; v.y -= v1.y; v.z -= v1.z;
+ return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 operator*(float s, const atcore_float3 &p)
+{
+ return gfsdk_makeFloat3(s * p.x, s * p.y, s * p.z);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 operator*(const atcore_float3 &p, float s)
+{
+ return gfsdk_makeFloat3(s * p.x, s * p.y, s * p.z);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline float gfsdk_dot(const atcore_float3& v0, const atcore_float3 &v1) {
+ return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline float gfsdk_lengthSquared(const atcore_float3& v) {
+ return gfsdk_dot(v,v);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline float gfsdk_length(const atcore_float3 &v) {
+ return sqrt(gfsdk_lengthSquared(v));
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline float gfsdk_distance(const atcore_float3 &v1, const atcore_float3 &v2) {
+ return gfsdk_length(v2-v1);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline const atcore_float3& gfsdk_normalize(atcore_float3 &v) {
+ float l = gfsdk_length(v);
+ if (l != 0) { v.x /= l; v.y /= l; v.z /= l; }
+ return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_cross(const atcore_float3& v1, const atcore_float3& v2)
+{
+ return gfsdk_makeFloat3(
+ v1.y * v2.z - v1.z * v2.y,
+ v1.z * v2.x - v1.x * v2.z,
+ v1.x * v2.y - v1.y * v2.x);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_lerp(const atcore_float3& v1, const atcore_float3& v2, float t)
+{
+ return gfsdk_makeFloat3(gfsdk_lerp(v1.x, v2.x, t), gfsdk_lerp(v1.y, v2.y, t), gfsdk_lerp(v1.z, v2.z, t));
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_min(const atcore_float3& v1, const atcore_float3 &v2)
+{
+ return gfsdk_makeFloat3(
+ gfsdk_min(v1.x, v2.x),
+ gfsdk_min(v1.y, v2.y),
+ gfsdk_min(v1.z, v2.z)
+ );
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_max(const atcore_float3& v1, const atcore_float3 &v2)
+{
+ return gfsdk_makeFloat3(
+ gfsdk_max(v1.x, v2.x),
+ gfsdk_max(v1.y, v2.y),
+ gfsdk_max(v1.z, v2.z)
+ );
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline float gfsdk_min(const atcore_float3 &v)
+{
+ return gfsdk_min(gfsdk_min(v.x, v.y), v.z);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline float gfsdk_max(const atcore_float3 &v)
+{
+ return gfsdk_max(gfsdk_max(v.x, v.y), v.z);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// float4
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4 gfsdk_makeFloat4(float x = 0.0f, float y = 0.0f, float z = 0.0f, float w = 0.0f)
+{
+ atcore_float4 v;
+ v.x = x;
+ v.y = y;
+ v.z = z;
+ v.w = w;
+ return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4 gfsdk_makeFloat4(const atcore_float3& v, float w)
+{
+ return gfsdk_makeFloat4(v.x, v.y, v.z, w);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4& operator+=(atcore_float4 &v, const atcore_float4 & v1)
+{
+ v.x += v1.x; v.y += v1.y; v.z += v1.z; v.w += v1.w;
+ return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4 operator*(float s, const atcore_float4 &p)
+{
+ return gfsdk_makeFloat4(s * p.x, s * p.y, s * p.z, s * p.w);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4 operator*(const atcore_float4 &p, float s)
+{
+ return gfsdk_makeFloat4(s * p.x, s * p.y, s * p.z, s * p.w);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline float gfsdk_dot(const atcore_float4& v0, const atcore_float4 &v1) {
+ return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z + v0.w * v1.w;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline float gfsdk_lengthSquared(const atcore_float4& v) {
+ return gfsdk_dot(v,v);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline float gfsdk_length(const atcore_float4 &v) {
+ return sqrt(gfsdk_lengthSquared(v));
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline const atcore_float4 gfsdk_normalize(const atcore_float4 &v) {
+ atcore_float4 nv = v;
+
+ float l = gfsdk_length(nv);
+ if (l > FLT_EPSILON)
+ {
+ const float s = 1.0f / l;
+
+ nv.x *= s;
+ nv.y *= s;
+ nv.z *= s;
+ nv.w *= s;
+ }
+
+ return nv;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4 gfsdk_lerp(const atcore_float4& v1, const atcore_float4& v2, float t)
+{
+ return gfsdk_makeFloat4(
+ gfsdk_lerp(v1.x, v2.x, t),
+ gfsdk_lerp(v1.y, v2.y, t),
+ gfsdk_lerp(v1.z, v2.z, t),
+ gfsdk_lerp(v1.w, v2.w, t)
+ );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// quaternion
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+inline atcore_float4 gfsdk_quaternionConjugate(const atcore_float4& in)
+{
+ return gfsdk_makeFloat4(-in.x, -in.y, -in.z, in.w);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4 gfsdk_quaternionMultiply(const atcore_float4& q0, const atcore_float4& q1)
+{
+ atcore_float4 q;
+
+ const float tx = q0.w * q1.x + q0.x * q1.w + q0.y * q1.z - q0.z * q1.y;
+ const float ty = q0.w * q1.y + q0.y * q1.w + q0.z * q1.x - q0.x * q1.z;
+ const float tz = q0.w * q1.z + q0.z * q1.w + q0.x * q1.y - q0.y * q1.x;
+
+ q.w = q0.w * q1.w - q0.x * q1.x - q0.y * q1.y - q0.z * q1.z;
+ q.x = tx;
+ q.y = ty;
+ q.z = tz;
+
+ return q;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 4x4 matrix
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////
+CORELIB_EXPORT void gfsdk_makeIdentity(atcore_float4x4& transform);
+CORELIB_EXPORT void gfsdk_makeTranslation(atcore_float4x4& m, const atcore_float3& t);
+CORELIB_EXPORT void gfsdk_makeScale(atcore_float4x4& m, const atcore_float3& s);
+CORELIB_EXPORT void gfsdk_makeRotation(atcore_float4x4& m, const atcore_float4& q);
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4x4& operator*=(atcore_float4x4& m, float s)
+{
+ float* data = (float*)&m;
+ for (int i = 0; i < 16; i++)
+ data[i] *= s;
+
+ return m;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline void gfsdk_setPosition(atcore_float4x4&m, const atcore_float3& v)
+{
+ m._41 = v.x;
+ m._42 = v.y;
+ m._43 = v.z;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4x4 gfsdk_transpose(const atcore_float4x4& m)
+{
+ atcore_float4x4 om;
+
+ om._11 = m._11; om._12 = m._21; om._13 = m._31; om._14 = m._41;
+ om._21 = m._12; om._22 = m._22; om._23 = m._32; om._24 = m._42;
+ om._31 = m._13; om._32 = m._23; om._33 = m._33; om._34 = m._43;
+ om._41 = m._14; om._42 = m._24; om._43 = m._34; om._44 = m._44;
+
+ return om;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4x4& operator+=(atcore_float4x4& m1, const atcore_float4x4& m2)
+{
+ float* data1 = (float*)&m1;
+ float* data2 = (float*)&m2;
+
+ for (int i = 0; i < 16; i++)
+ data1[i] += data2[i];
+
+ return m1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4 gfsdk_transform(const atcore_float4x4 &m, atcore_float4 op)
+{
+ atcore_float4 p;
+
+ p.x = op.x * m._11 + op.y * m._21 + op.z * m._31 + op.w * m._41;
+ p.y = op.x * m._12 + op.y * m._22 + op.z * m._32 + op.w * m._42;
+ p.z = op.x * m._13 + op.y * m._23 + op.z * m._33 + op.w * m._43;
+ p.w = op.x * m._14 + op.y * m._24 + op.z * m._34 + op.w * m._44;
+
+ return p;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_transformCoord(const atcore_float4x4 &m, atcore_float3 op)
+{
+ atcore_float3 p;
+
+ p.x = op.x * m._11 + op.y * m._21 + op.z * m._31 + m._41;
+ p.y = op.x * m._12 + op.y * m._22 + op.z * m._32 + m._42;
+ p.z = op.x * m._13 + op.y * m._23 + op.z * m._33 + m._43;
+
+ return p;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_transformVector(const atcore_float4x4 &m, atcore_float3 op)
+{
+ atcore_float3 p;
+
+ p.x = op.x * m._11 + op.y * m._21 + op.z * m._31;
+ p.y = op.x * m._12 + op.y * m._22 + op.z * m._32;
+ p.z = op.x * m._13 + op.y * m._23 + op.z * m._33;
+
+ return p;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_getScale(const atcore_float4x4& m)
+{
+ atcore_float3 ax = gfsdk_makeFloat3(m._11, m._12, m._13);
+ atcore_float3 ay = gfsdk_makeFloat3(m._21, m._22, m._23);
+ atcore_float3 az = gfsdk_makeFloat3(m._31, m._32, m._33);
+
+ return gfsdk_makeFloat3(gfsdk_length(ax), gfsdk_length(ay), gfsdk_length(az));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_getTranslation(const atcore_float4x4& m)
+{
+ return gfsdk_makeFloat3(m._41, m._42, m._43);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline void gfsdk_setTranslation(atcore_float4x4& m, const atcore_float3 &v)
+{
+ m._41 = v.x;
+ m._42 = v.y;
+ m._43 = v.z;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline const atcore_float4x4& gfsdk_orthonormalize(atcore_float4x4& m)
+{
+ atcore_float3 ax = gfsdk_makeFloat3(m._11, m._12, m._13);
+ atcore_float3 ay = gfsdk_makeFloat3(m._21, m._22, m._23);
+ atcore_float3 az = gfsdk_makeFloat3(m._31, m._32, m._33);
+
+ gfsdk_normalize(ax);
+ gfsdk_normalize(ay);
+ gfsdk_normalize(az);
+
+ m._11 = ax.x; m._12 = ax.y; m._13 = ax.z;
+ m._21 = ay.x; m._22 = ay.y; m._23 = ay.z;
+ m._31 = az.x; m._32 = az.y; m._33 = az.z;
+
+ return m;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+CORELIB_EXPORT atcore_float4x4 gfsdk_lerp(atcore_float4x4& start, atcore_float4x4& end, float t);
+
+////////////////////////////////////////////////////////////////////////////////
+CORELIB_EXPORT atcore_float4 gfsdk_getRotation(const atcore_float4x4& m);
+
+////////////////////////////////////////////////////////////////////////////////
+CORELIB_EXPORT atcore_float4x4 gfsdk_makeTransform(const atcore_float4& q, const atcore_float3& t, const atcore_float3 &s);
+
+////////////////////////////////////////////////////////////////////////////////
+CORELIB_EXPORT atcore_float4x4 operator*(const atcore_float4x4& in1, const atcore_float4x4& in2);
+
+////////////////////////////////////////////////////////////////////////////////
+CORELIB_EXPORT atcore_float4x4 gfsdk_inverse(const atcore_float4x4& m);
+
+////////////////////////////////////////////////////////////////////////////////
+// dual quaternion
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_dualquaternion gfsdk_makeDQ(const atcore_float4& q, const atcore_float3& t)
+{
+ atcore_dualquaternion dq;
+
+ dq.q0 = gfsdk_normalize(q);
+ dq.q1 = gfsdk_quaternionMultiply(gfsdk_makeFloat4(t, 0), dq.q0) * 0.5f;
+
+ return dq;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+atcore_dualquaternion gfsdk_makeDQ(const atcore_float4x4& m);
+
+////////////////////////////////////////////////////////////////////////////////
+inline const atcore_dualquaternion& gfsdk_normalize(atcore_dualquaternion & dq)
+{
+ float mag = gfsdk_dot( dq.q0, dq.q0);
+ float deLen = 1.0f / sqrt(mag+FLT_EPSILON);
+
+ dq.q0 = dq.q0 * deLen;
+ dq.q1 = dq.q1 * deLen;
+
+ return dq;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_dualquaternion operator*(float s, const atcore_dualquaternion & dq)
+{
+ return atcore_dualquaternion(s * dq.q0, s * dq.q1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_dualquaternion operator*(const atcore_dualquaternion & dq, float s)
+{
+ return atcore_dualquaternion(s * dq.q0, s * dq.q1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_dualquaternion& operator+=(atcore_dualquaternion &dq, const atcore_dualquaternion & dq2)
+{
+ // hemispherization
+ float sign = (gfsdk_dot(dq.q0, dq2.q0) < -FLT_EPSILON) ? -1.0f: 1.0f;
+
+ dq.q0 += sign * dq2.q0;
+ dq.q1 += sign * dq2.q1;
+
+ return dq;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_dualquaternion gfsdk_lerp(const atcore_dualquaternion &dq1, const atcore_dualquaternion & dq2, float t)
+{
+ atcore_dualquaternion dq = dq1 * (1.0f - t);
+
+ float sign = (gfsdk_dot(dq1.q0, dq2.q0) < -FLT_EPSILON) ? -1.0f: 1.0f;
+
+ dq += (t * sign) * dq2;
+ gfsdk_normalize(dq);
+
+ return dq;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_transformCoord(const atcore_dualquaternion& dq, const atcore_float3 &vecIn)
+{
+ atcore_float3 d0 = gfsdk_makeFloat3(dq.q0.x, dq.q0.y, dq.q0.z);
+ atcore_float3 de = gfsdk_makeFloat3(dq.q1.x, dq.q1.y, dq.q1.z);
+ float a0 = dq.q0.w;
+ float ae = dq.q1.w;
+
+ atcore_float3 temp = gfsdk_cross( d0, vecIn ) + a0 * vecIn;
+ atcore_float3 temp2 = 2.0f * (a0 * de - ae * d0 + gfsdk_cross(d0, de));
+
+ return vecIn + temp2 + 2.0f * gfsdk_cross( d0, temp);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 gfsdk_transformVector(const atcore_dualquaternion& dq, const atcore_float3 &vecIn)
+{
+ atcore_float3 d0 = gfsdk_makeFloat3(dq.q0.x, dq.q0.y, dq.q0.z);
+ atcore_float3 de = gfsdk_makeFloat3(dq.q1.x, dq.q1.y, dq.q1.z);
+ float a0 = dq.q0.w;
+ float ae = dq.q1.w;
+
+ atcore_float3 temp = gfsdk_cross( d0, vecIn ) + a0 * vecIn;
+ return vecIn + 2.0f * gfsdk_cross( d0, temp);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_float4 getRotation(const atcore_dualquaternion& dq)
+{
+ return dq.q0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+inline atcore_float3 getTranslation(const atcore_dualquaternion& dq)
+{
+ atcore_float4 dual = 2.0f * dq.q1;
+ atcore_float4 t = gfsdk_quaternionMultiply(dual, gfsdk_quaternionConjugate( dq.q0 ));
+
+ return gfsdk_makeFloat3(t.x, t.y, t.z);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Profiler.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Profiler.cpp
new file mode 100644
index 0000000..aab4de3
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Profiler.cpp
@@ -0,0 +1,82 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "nvToolsExt.h"
+#include <stdlib.h> // for rand()
+
+void ProfilerRangePush(const char* name) {
+ unsigned int color = 0xFF000000 | ((rand()%256) << 16) | ((rand()%256) << 8) | (rand()%256);
+ // Zero the structure
+ nvtxEventAttributes_t event_attrib = {0};
+ // Set the version and the size information
+ event_attrib.version = NVTX_VERSION;
+ event_attrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE;
+ // Configure the attributes. 0 is the default for all attributes
+ event_attrib.colorType = NVTX_COLOR_ARGB;
+ event_attrib.color = color;
+ event_attrib.messageType = NVTX_MESSAGE_TYPE_ASCII;
+ event_attrib.message.ascii = name;
+ nvtxRangePushEx(&event_attrib);
+}
+
+void ProfilerRangePush(const char* name, unsigned int color) {
+ // Zero the structure
+ nvtxEventAttributes_t event_attrib = {0};
+ // Set the version and the size information
+ event_attrib.version = NVTX_VERSION;
+ event_attrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE;
+ // Configure the attributes. 0 is the default for all attributes
+ event_attrib.colorType = NVTX_COLOR_ARGB;
+ event_attrib.color = color;
+ event_attrib.messageType = NVTX_MESSAGE_TYPE_ASCII;
+ event_attrib.message.ascii = name;
+ nvtxRangePushEx(&event_attrib);
+}
+
+void ProfilerRangePop() {
+ nvtxRangePop();
+}
+
+#include "Profiler.h"
+
+ScopedProfiler::ScopedProfiler(const char* name)
+{
+ ProfilerRangePush(name);
+}
+
+ScopedProfiler::ScopedProfiler(const char* name, unsigned int color)
+{
+ ProfilerRangePush(name, color);
+}
+
+ScopedProfiler::~ScopedProfiler()
+{
+ ProfilerRangePop();
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Profiler.h b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Profiler.h
new file mode 100644
index 0000000..5f00175
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Profiler.h
@@ -0,0 +1,51 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "corelib_global.h"
+
+// name - the name to be displayed
+void ProfilerRangePush(const char* name);
+
+// name - the name to be displayed
+// color - ARGB color. ex) 0xFFFF0000 = Red, 0xFF0000FF = Blue
+void ProfilerRangePush(const char* name, unsigned int color);
+
+void ProfilerRangePop();
+
+struct CORELIB_EXPORT ScopedProfiler
+{
+ ScopedProfiler(const char* name);
+
+ ScopedProfiler(const char* name, unsigned int color);
+
+ ~ScopedProfiler();
+};
+
+#define FUNCTION_PROFILER() ScopedProfiler _scoped_function_profiler(__FUNCTION__);
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Settings.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Settings.cpp
new file mode 100644
index 0000000..5445bef
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Settings.cpp
@@ -0,0 +1,767 @@
+/*******************************************************************************
+* NVIDIA Corporation
+* Software License Agreement - OpenAutomate SDK
+*
+* IMPORTANT - READ BEFORE COPYING, INSTALLING OR USING
+* Do not use or load the OpenAutomate SDK and any associated materials
+* provided by NVIDIA on NVIDIA�s website (collectively, the "Software")
+* until You have carefully read the following terms and conditions. By
+* loading or using the Software, You agree to fully comply with the terms
+* and conditions of this Software License Agreement ("Agreement") by and
+* between NVIDIA Corporation, a Delaware corporation with its principal
+* place of business at 2701 San Tomas Expressway, Santa Clara, California
+* 95050 U.S.A. ("NVIDIA"), and You. If You do not wish to so agree, do not
+* install or use the Software.
+*
+* For the purposes of this Agreement:
+*
+* "Licensee," "You" and/or "Your" shall mean, collectively and
+* individually, Original Equipment Manufacturers, Independent Hardware
+* Vendors, Independent Software Vendors, and End-Users of the Software
+* pursuant to the terms and conditions of this Agreement.
+*
+* "Derivative Works" shall mean derivatives of the Software created by You
+* or a third party on Your behalf, which term shall include: (a) for
+* copyrightable or copyrighted material, any translation, abridgement,
+* revision or other form in which an existing work may be recast,
+* transformed or adapted; (b) for work protected by topography or mask
+* right, any translation, abridgement, revision or other form in which an
+* existing work may be recast, transformed or adapted; (c) for patentable
+* or patented material, any Improvement; and (d) for material protected by
+* trade secret, any new material derived from or employing such existing
+* trade secret.
+*
+* "Excluded License" is any license that requires as a condition of use,
+* modification and/or distribution of software subject to the Excluded
+* License, that such software or other software distributed and/or
+* combined with such software be (i) disclosed or distributed in source
+* code form, (ii) licensed for the purpose of making derivative works, or
+* (iii) redistributable at no charge.
+*
+* SECTION 1 - GRANT OF LICENSE.
+* NVIDIA agrees to provide the Software and any associated materials
+* pursuant to the terms and conditions of this Agreement. Subject to the
+* terms of this Agreement, NVIDIA grants to You a nonexclusive,
+* transferable, worldwide, revocable, limited, royalty-free, fully paid-up
+* license under NVIDIA�s copyrights to
+*
+* (a) install, deploy, use, have used execute, reproduce, display,
+* perform, run, modify the source code of the Software, or to prepare and
+* have prepared Derivative Works thereof the Software for Your own
+* internal development, testing and maintenance purposes to incorporate
+* the Software or Derivative Works thereof, in part or whole, into Your
+* software applications;
+*
+* (b) to transfer, distribute and sublicense the Software (in its
+* unmodified form as delivered to You by NVIDIA pursuant to this
+* Agreement) in any medium or technology for Your sublicensees to
+* incorporate the Software or Derivative Works thereof, in part or whole,
+* into their respective software applications; and
+*
+* (c) to transfer, distribute and sublicense Derivative Works (in object
+* code only) of the Software (i)_as incorporated in Your application
+* software in any medium or technology; and (ii) certified as OpenAutomate
+* Compatible Software.
+*
+* You may exercise your license rights pursuant to Subsection 1(b) and (c)
+* above pursuant to the terms and conditions of any form of end-user
+* software license agreement of Your choice, including but not limited to
+* an Excluded License.
+*
+* In the event NVIDIA certifies Your application software, incorporating
+* the Derivative Works (in object code only) of the Software, as
+* OpenAutomate compatible ("OpenAutomate Compatible Software"), NVIDIA
+* grants You a nonexclusive, worldwide, revocable, paid-up license to use
+* the name and trademark to "OpenAutomate Compatible" solely for the
+* purposes of identifying and/or marketing Your application software as
+* OpenAutomate Compatible Software; provided that Licensee fully complies
+* with the following:
+*
+* (x) Licensee agrees that it is strictly prohibited from using the name
+* and trademark of "OpenAutomate Compatible" if Your application software
+* is not OpenAutomate Compatible Software;
+*
+* (y) if NVIDIA objects to Your improper use of the "OpenAutomate
+* Compatible" name and trademark, You will take all reasonable steps
+* necessary to resolve NVIDIA�s objections. NVIDIA may reasonably monitor
+* the quality of Your application software bearing the "OpenAutomate
+* Compatible" name or trademark pursuant to this Agreement; and
+*
+* (z) any goodwill attached to NVIDIA�s trademarks, service marks, or
+* trade names belong to NVIDIA and this Agreement does not grant You any
+* right to use them.
+*
+* If You are not the final manufacturer or vendor of a computer system or
+* software program incorporating the Software, or if Your Contractors (as
+* defined below), affiliates or subsidiaries need to exercise any, some or
+* all of the license grant described above herein to the Software on Your
+* behalf, then You may transfer a copy of the Software, (and related
+* end-user documentation) to such recipient for use in accordance with the
+* terms of this Agreement, provided such recipient agrees to be fully
+* bound by the terms hereof. Except as expressly permitted in this
+* Agreement, Unless otherwise authorized in the Agreement, You shall not
+* otherwise assign, sublicense, lease, or in any other way transfer or
+* disclose Software to any third party. Unless otherwise authorized in the
+* Agreement, You shall not reverse- compile, disassemble,
+* reverse-engineer, or in any manner attempt to derive the source code of
+* the Software from the object code portions of the Software.
+*
+* Except as expressly stated in this Agreement, no license or right is
+* granted to You directly or by implication, inducement, estoppel or
+* otherwise. NVIDIA shall have the right to inspect or have an independent
+* auditor inspect Your relevant records to verify Your compliance with the
+* terms and conditions of this Agreement.
+*
+* SECTION 2 - CONFIDENTIALITY.
+* If applicable, any exchange of Confidential Information (as defined in
+* the NDA) shall be made pursuant to the terms and conditions of a
+* separately signed Non-Disclosure Agreement ("NDA") by and between NVIDIA
+* and You. For the sake of clarity, You agree that the Software is
+* Confidential Information of NVIDIA.
+*
+* If You wish to have a third party consultant or subcontractor
+* ("Contractor") perform work on Your behalf which involves access to or
+* use of Software, You shall obtain a written confidentiality agreement
+* from the Contractor which contains terms and obligations with respect to
+* access to or use of Software no less restrictive than those set forth in
+* this Agreement and excluding any distribution or sublicense rights, and
+* use for any other purpose than permitted in this Agreement. Otherwise,
+* You shall not disclose the terms or existence of this Agreement or use
+* NVIDIA's name in any publications, advertisements, or other
+* announcements without NVIDIA's prior written consent. Unless otherwise
+* provided in this Agreement, You do not have any rights to use any NVIDIA
+* trademarks or logos.
+*
+* SECTION 3 - OWNERSHIP OF SOFTWARE AND INTELLECTUAL PROPERTY RIGHTS.
+* All rights, title and interest to all copies of the Software remain with
+* NVIDIA, subsidiaries, licensors, or its suppliers. The Software is
+* copyrighted and protected by the laws of the United States and other
+* countries, and international treaty provisions. You may not remove any
+* copyright notices from the Software. NVIDIA may make changes to the
+* Software, or to items referenced therein, at any time and without
+* notice, but is not obligated to support or update the Software. Except
+* as otherwise expressly provided, NVIDIA grants no express or implied
+* right under any NVIDIA patents, copyrights, trademarks, or other
+* intellectual property rights.
+*
+* All rights, title and interest in the Derivative Works of the Software
+* remain with You subject to the underlying license from NVIDIA to the
+* Software. In Your sole discretion, You may grant NVIDIA, upon NVIDIA�s
+* request for such a license described herein, an irrevocable, perpetual,
+* nonexclusive, worldwide, royalty-free paid-up license to make, have
+* made, use, have used, sell, license, distribute, sublicense or otherwise
+* transfer Derivative Works created by You that add functionality or
+* improvement to the Software.
+*
+* You has no obligation to give NVIDIA any suggestions, comments or other
+* feedback ("Feedback") relating to the Software. However, NVIDIA may use
+* and include any Feedback that You voluntarily provide to improve the
+* Software or other related NVIDIA technologies. Accordingly, if You
+* provide Feedback, You agree NVIDIA and its licensees may freely use,
+* reproduce, license, distribute, and otherwise commercialize the Feedback
+* in the Software or other related technologies without the payment of any
+* royalties or fees.
+*
+* You may transfer the Software only if the recipient agrees to be fully
+* bound by these terms and conditions of this Agreement.
+*
+* SECTION 4 - NO WARRANTIES.
+* THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY
+* OF ANY KIND, INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT,
+* OR FITNESS FOR A PARTICULAR PURPOSE. NVIDIA does not warrant or assume
+* responsibility for the accuracy or completeness of any information,
+* text, graphics, links or other items contained within the Software.
+* NVIDIA does not represent that errors or other defects will be
+* identified or corrected.
+*
+* SECTION 5 - LIMITATION OF LIABILITY.
+* EXCEPT WITH RESPECT TO THE MISUSE OF THE OTHER PARTY�S INTELLECTUAL
+* PROPERTY OR DISCLOSURE OF THE OTHER PARTY�S CONFIDENTIAL INFORMATION IN
+* BREACH OF THIS AGREEMENT, IN NO EVENT SHALL NVIDIA, SUBSIDIARIES,
+* LICENSORS, OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, INDIRECT, LOST PROFITS, CONSEQUENTIAL,
+* BUSINESS INTERRUPTION OR LOST INFORMATION) ARISING OUT OF THE USE OF OR
+* INABILITY TO USE THE SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS PROHIBIT EXCLUSION OR
+* LIMITATION OF LIABILITY FOR IMPLIED WARRANTIES OR CONSEQUENTIAL OR
+* INCIDENTAL DAMAGES, SO THE ABOVE LIMITATION MAY NOT APPLY TO YOU. YOU
+* MAY ALSO HAVE OTHER LEGAL RIGHTS THAT VARY FROM JURISDICTION TO
+* JURISDICTION. NOTWITHSTANDING THE FOREGOING, NVIDIA�S AGGREGATE
+* LIABILITY ARISING OUT OF THIS AGREEMENT SHALL NOT EXCEED ONE HUNDRED
+* UNITED STATES DOLLARS (USD$100).
+*
+* SECTION 6 - TERM.
+* This Agreement and the licenses granted hereunder shall be effective as
+* of the date You download the applicable Software ("Effective Date") and
+* continue for a period of one (1) year ("Initial Term") respectively,
+* unless terminated earlier in accordance with the "Termination" provision
+* of this Agreement. Unless either party notifies the other party of its
+* intent to terminate this Agreement at least three (3) months prior to
+* the end of the Initial Term or the applicable renewal period, this
+* Agreement will be automatically renewed for one (1) year renewal periods
+* thereafter, unless terminated in accordance with the "Termination"
+* provision of this Agreement.
+*
+* SECTION 7 - TERMINATION.
+* NVIDIA may terminate this Agreement at any time if You violate its
+* terms. Upon termination, You will immediately destroy the Software or
+* return all copies of the Software to NVIDIA, and certify to NVIDIA in
+* writing that such actions have been completed. Upon termination or
+* expiration of this Agreement the license grants to Licensee shall
+* terminate, except that sublicenses rightfully granted by Licensee under
+* this Agreement in connection with Section 1(b) and (c) of this Agreement
+* provided by Licensee prior to the termination or expiration of this
+* Agreement shall survive in accordance with their respective form of
+* license terms and conditions.
+*
+* SECTION 8 - MISCELLANEOUS.
+*
+* SECTION 8.1 - SURVIVAL.
+* Those provisions in this Agreement, which by their nature need to
+* survive the termination or expiration of this Agreement, shall survive
+* termination or expiration of the Agreement, including but not limited to
+* Sections 2, 3, 4, 5, 7, and 8.
+*
+* SECTION 8.2 - APPLICABLE LAWS.
+* Claims arising under this Agreement shall be governed by the laws of
+* Delaware, excluding its principles of conflict of laws and the United
+* Nations Convention on Contracts for the Sale of Goods. The state and/or
+* federal courts residing in Santa Clara County, California shall have
+* exclusive jurisdiction over any dispute or claim arising out of this
+* Agreement. You may not export the Software in violation of applicable
+* export laws and regulations.
+*
+* SECTION 8.3 - AMENDMENT.
+* The Agreement shall not be modified except by a written agreement that
+* names this Agreement and any provision to be modified, is dated
+* subsequent to the Effective Date, and is signed by duly authorized
+* representatives of both parties.
+*
+* SECTION 8.4 - NO WAIVER.
+* No failure or delay on the part of either party in the exercise of any
+* right, power or remedy under this Agreement or under law, or to insist
+* upon or enforce performance by the other party of any of the provisions
+* of this Agreement or under law, shall operate as a waiver thereof, nor
+* shall any single or partial exercise of any right, power or remedy
+* preclude other or further exercise thereof, or the exercise of any other
+* right, power or remedy; rather the provision, right, or remedy shall be
+* and remain in full force and effect.
+*
+* SECTION 8.5 - NO ASSIGNMENT.
+* This Agreement and Licensee�s rights and obligations herein, may not be
+* assigned, subcontracted, delegated, or otherwise transferred by Licensee
+* without NVIDIA�s prior written consent, and any attempted assignment,
+* subcontract, delegation, or transfer in violation of the foregoing will
+* be null and void. The terms of this Agreement shall be binding upon
+* Licensee�s assignees.
+*
+* SECTION 8.6 - GOVERNMENT RESTRICTED RIGHTS.
+* The parties acknowledge that the Software is subject to U.S. export
+* control laws and regulations. The parties agree to comply with all
+* applicable international and national laws that apply to the Software,
+* including the U.S. Export Administration Regulations, as well as
+* end-user, end-use and destination restrictions issued by U.S. and other
+* governments.
+*
+* The Software has been developed entirely at private expense and is
+* commercial computer software provided with RESTRICTED RIGHTS. Use,
+* duplication or disclosure of the Software by the U.S. Government or a
+* U.S. Government subcontractor is subject to the restrictions set forth
+* in the Agreement under which the Software was obtained pursuant to DFARS
+* 227.7202-3(a) or as set forth in subparagraphs (c)(1) and (2) of the
+* Commercial Computer Software - Restricted Rights clause at FAR
+* 52.227-19, as applicable. Contractor/manufacturer is NVIDIA, 2701 San
+* Tomas Expressway, Santa Clara, CA 95050. Use of the Software by the
+* Government constitutes acknowledgment of NVIDIA's proprietary rights
+* therein.
+*
+* SECTION 8.7 - INDEPENDENT CONTRACTORS.
+* Licensee�s relationship to NVIDIA is that of an independent contractor,
+* and neither party is an agent or partner of the other. Licensee will
+* not have, and will not represent to any third party that it has, any
+* authority to act on behalf of NVIDIA.
+*
+* SECTION 8.8 - SEVERABILITY.
+* If for any reason a court of competent jurisdiction finds any provision
+* of this Agreement, or portion thereof, to be unenforceable, that
+* provision of the Agreement will be enforced to the maximum extent
+* permissible so as to affect the intent of the parties, and the remainder
+* of this Agreement will continue in full force and effect. This Agreement
+* has been negotiated by the parties and their respective counsel and will
+* be interpreted fairly in accordance with its terms and without any
+* strict construction in favor of or against either party.
+*
+* SECTION 8.9 - ENTIRE AGREEMENT.
+* This Agreement and NDA constitute the entire agreement between the
+* parties with respect to the subject matter contemplated herein, and
+* merges all prior and contemporaneous communications.
+*
+******************************************************************************/
+
+
+#include "settings.h"
+#include "Nv.h"
+
+char OptionsFileName[] = "FurViewerOptions.txt";
+//std::vector<void *> AllocBlocks;
+
+using namespace std;
+
+void Error(const char *fmt, ...);
+static int HexCharToInt(unsigned char c);
+bool GetExePath(char* exe_path);
+static int Hex2BytesToInt(const unsigned char *buf);
+static oaFloat StrToFloat(const char *buf);
+static void WriteFloat(FILE *fp, oaFloat val);
+static void StripNewLine(char *str);
+void *Alloc(size_t n);
+char *StrDup(const char *str);
+
+bool GetExePath(char* exe_path)
+{
+#if WIN32
+ char delim = '\\';
+#else
+ char delim = '/';
+#endif
+
+ DWORD dwRet;
+ dwRet = GetModuleFileNameA(NV_NULL, exe_path, MAX_PATH);
+ if ( dwRet == 0 )
+ {
+ exe_path[0] = '\0';
+ return false;
+ }
+
+ int i;
+ for ( i = dwRet; i > 0; i-- )
+ {
+ if ( exe_path[i-1] == delim )
+ break;
+ }
+ exe_path[i] = '\0';
+
+ return true;
+}
+
+void Error(const char *fmt, ...)
+{
+ va_list AP;
+ va_start(AP, fmt);
+
+ char msg[1024];
+ //fprintf(msg, "ERROR: ");
+ //vfprintf(msg, fmt, AP);
+ //fprintf(msg, "\n");
+ sprintf(msg, fmt, AP);
+ OutputDebugStringA(msg);
+ assert(0);
+// exit(-1);
+}
+
+static int HexCharToInt(unsigned char c)
+{
+ if(c >= '0' && c <= '9')
+ return((int)(c - '0'));
+
+ c = tolower(c);
+ if(c >= 'a' && c <= 'f')
+ return((int)(c - 'a' + 10));
+
+ return(0);
+}
+
+static int Hex2BytesToInt(const unsigned char *buf)
+{
+ return(HexCharToInt(buf[0]) << 4 | HexCharToInt(buf[1]));
+}
+
+static oaFloat StrToFloat(const char *buf)
+{
+ size_t Len = strlen(buf);
+ if(Len != sizeof(oaFloat) * 2)
+ return(0.0);
+
+ oaFloat Ret;
+ unsigned char *Buf = (unsigned char *)&Ret;
+ for(int i=0; i < sizeof(oaFloat); ++i)
+ {
+ Buf[i] = Hex2BytesToInt((const unsigned char *)buf);
+ buf += 2;
+ }
+
+ return(Ret);
+}
+
+static void WriteFloat(FILE *fp, oaFloat val)
+{
+ unsigned char *Buf = (unsigned char *)&val;
+ for(int i=0; i < sizeof(oaFloat); ++i)
+ fprintf(fp, "%02x", Buf[i]);
+}
+
+static void StripNewLine(char *str)
+{
+ size_t StrLen = strlen(str);
+ if(StrLen == 0)
+ return;
+
+ for(size_t i=StrLen-1; i >= 0; --i)
+ if(str[i] == '\n')
+ {
+ str[i] = 0;
+ break;
+ }
+}
+
+void *Alloc(size_t n)
+{
+ void *Ret = malloc(n);
+ assert(n != 0);
+
+ //AllocBlocks.push_back(Ret);
+ return(Ret);
+}
+
+char *StrDup(const char *str)
+{
+ assert(str != NV_NULL);
+ char *Ret = strdup(str);
+
+ //AllocBlocks.push_back(Ret);
+ return(Ret);
+}
+
+AppSettings::AppSettings()
+{
+ int NumOptions = 0;
+}
+
+AppSettings::~AppSettings()
+{
+ Cleanup();
+}
+
+void AppSettings::InitOptions(void)
+{
+ {
+ oaNamedOption *Option;
+
+ // Resolution (enum)
+ Option = &Options[NumOptions++];
+ oaInitOption(Option);
+ Option->Name = "User/Resolution";
+ Option->DataType = OA_TYPE_ENUM;
+ Option->Value.Enum = "640x480";
+
+ Options[NumOptions] = *Option;
+ Option = &Options[NumOptions++];
+ Option->Value.Enum = "1024x768";
+
+ Options[NumOptions] = *Option;
+ Option = &Options[NumOptions++];
+ Option->Value.Enum = "1200x768";
+
+ Options[NumOptions] = *Option;
+ Option = &Options[NumOptions++];
+ Option->Value.Enum = "1600x1200";
+
+ // AA (enum)
+ Option = &Options[NumOptions++];
+ oaInitOption(Option);
+
+ Option->Name = "User/AA";
+ Option->DataType = OA_TYPE_ENUM;
+ Option->Value.Enum = "Off";
+
+ Options[NumOptions] = *Option;
+ Option = &Options[NumOptions++];
+ Option->Value.Enum = "2X";
+
+ Options[NumOptions] = *Option;
+ Option = &Options[NumOptions++];
+ Option->Value.Enum = "4X";
+
+ Options[NumOptions] = *Option;
+ Option = &Options[NumOptions++];
+ Option->Value.Enum = "8X";
+
+ // device id (int)
+ Option = &Options[NumOptions++];
+ oaInitOption(Option);
+ Option->Name = "User/Device";
+ Option->DataType = OA_TYPE_INT;
+
+ Option->Value.Int = -1; // when -1 to choose a good GPU
+
+ //Backdoor (enum)
+ Option = &Options[NumOptions++];
+ oaInitOption(Option);
+ Option->Name = "User/Backdoor";
+ Option->DataType = OA_TYPE_STRING;
+ Option->Value.String = "";
+
+ // HideUI (bool)
+ Option = &Options[NumOptions++];
+ oaInitOption(Option);
+ Option->Name = "User/HideUI";
+ Option->DataType = OA_TYPE_BOOL;
+
+ Option->Value.Bool = OA_FALSE;
+
+ // Perf mode (bool)
+ Option = &Options[NumOptions++];
+ oaInitOption(Option);
+ Option->Name = "User/PerfMode";
+ Option->DataType = OA_TYPE_BOOL;
+
+ Option->Value.Bool = OA_FALSE;
+
+ // Play (bool)
+ Option = &Options[NumOptions++];
+ oaInitOption(Option);
+ Option->Name = "User/Play";
+ Option->DataType = OA_TYPE_BOOL;
+
+ Option->Value.Bool = OA_FALSE;
+
+ // ProjectPath (string)
+ Option = &Options[NumOptions++];
+ oaInitOption(Option);
+ Option->Name = "User/ProjectPath";
+ Option->DataType = OA_TYPE_STRING;
+ Option->Value.String = "";
+
+ // FurAssetPath (string)
+ Option = &Options[NumOptions++];
+ oaInitOption(Option);
+ Option->Name = "User/FurAssetPath";
+ Option->DataType = OA_TYPE_STRING;
+ Option->Value.String = "";
+
+ // FurDemoPlaylist (string)
+ Option = &Options[NumOptions++];
+ oaInitOption(Option);
+ Option->Name = "User/FurDemoPlaylist";
+ Option->DataType = OA_TYPE_STRING;
+ Option->Value.String = "";
+
+ //Option = &Options[NumOptions++];
+ //oaInitOption(Option);
+ //Option->Name = "r2_slight_fade";
+ //Option->DataType = OA_TYPE_FLOAT;
+ //Option->MinValue.Float = 0.0;
+ //Option->MaxValue.Float = 100.0;
+ //Option->NumSteps = 200;
+ }
+
+ //****************************************************************************
+ //*** Init OptionValues
+ //****************************************************************************
+
+ // Initialize default options
+ for(int i=0; i < NumOptions; ++i)
+ {
+ string Name(Options[i].Name);
+ OptionValueMap[Name].Name = Options[i].Name;
+ OptionValueMap[Name].Type = Options[i].DataType;
+ OptionValueMap[Name].Value = Options[i].Value;
+ }
+
+ InitDefaultOptions();
+ ///////////////////////////////////////////////////////
+ // Load any persistent options if they've been previously set
+ ReadOptionsFile();
+}
+
+void AppSettings::InitDefaultOptions(void)
+{
+ oaValue Value;
+
+ Value.Enum = "1200x768";
+ SetOptionValue("User/Resolution", OA_TYPE_ENUM, &Value);
+
+ Value.Enum = "8X";
+ SetOptionValue("User/AA", OA_TYPE_ENUM, &Value);
+}
+
+void AppSettings::SetOptionValue(const char *name,
+ oaOptionDataType type,
+ const oaValue *value)
+{
+ string Name(name);
+ assert(OptionValueMap.find(Name) != OptionValueMap.end());
+ assert(OptionValueMap[Name].Type == type);
+
+ switch(type)
+ {
+ case OA_TYPE_STRING:
+ OptionValueMap[Name].Value.String = StrDup(value->String);
+ break;
+
+ case OA_TYPE_ENUM:
+ OptionValueMap[Name].Value.Enum = StrDup(value->Enum);
+ break;
+
+ default:
+ OptionValueMap[Name].Value = *value;
+ }
+}
+
+void AppSettings::ReadOptionsFile(void)
+{
+ char optionFile[MAX_PATH] = "";
+ if(!GetExePath(optionFile))
+ {
+ fprintf(stderr, "Cannot get exe path\r\n");
+ }
+ strcat(optionFile, OptionsFileName);
+
+
+ FILE *FP = fopen(optionFile, "rb");
+ if(!FP)
+ return;
+
+ fprintf(stderr, "FurViewer: Reading options file \"%s\".\n",
+ optionFile);
+ fflush(stderr);
+
+ char Line[1024] = "";
+ int LineNum = 1;
+ while (fgets(Line, sizeof(Line), FP) != NV_NULL)
+ {
+ StripNewLine(Line);
+ if(Line[0] == 0)
+ continue;
+
+ char *Name = strtok(Line, "\t");
+ char *Value = strtok(NV_NULL, "");
+
+ if(!Name || !Value)
+ {
+ //Error("Invalid format in options file \"%s\" on line %d\n",
+ //OptionsFileName,
+ //LineNum);
+ continue;
+ }
+
+ map<string, OptionValue>::const_iterator OptVal =
+ OptionValueMap.find(string(Name));
+
+ if(OptVal == OptionValueMap.end())
+ Error("Unknown option \"%s\" defined in options file \"%s\" on line %d.",
+ Name,
+ OptionsFileName,
+ LineNum);
+
+ SetOptionValue(Name, OptVal->second.Type, Value);
+
+ LineNum++;
+ }
+
+ fclose(FP);
+}
+
+void AppSettings::Cleanup(void)
+{
+ //vector<void *>::iterator Iter = AllocBlocks.begin();
+ //for(; Iter != AllocBlocks.end(); Iter++)
+ // free(*Iter);
+
+ //AllocBlocks.clear();
+}
+
+
+void AppSettings::WriteOptionsFile(FILE *fp)
+{
+ map<string, OptionValue>::const_iterator Iter = OptionValueMap.begin();
+ for(; Iter != OptionValueMap.end(); ++Iter)
+ {
+ fprintf(fp, "%s\t", Iter->second.Name);
+ switch(Iter->second.Type)
+ {
+ case OA_TYPE_INT:
+ fprintf(fp, "%d", Iter->second.Value.Int);
+ break;
+
+ case OA_TYPE_BOOL:
+ fprintf(fp, "%d", (int)Iter->second.Value.Bool);
+ break;
+
+ case OA_TYPE_FLOAT:
+ WriteFloat(fp, Iter->second.Value.Float);
+ break;
+
+ case OA_TYPE_STRING:
+ fprintf(fp, "%s", Iter->second.Value.String);
+ break;
+
+ case OA_TYPE_ENUM:
+ fprintf(fp, "%s", Iter->second.Value.Enum);
+ break;
+
+ }
+
+ fprintf(fp, "\n");
+ }
+}
+
+void AppSettings::WriteOptionsFile(void)
+{
+ char optionFile[MAX_PATH] = "";
+ if(!GetExePath(optionFile))
+ {
+ fprintf(stderr, "Cannot get exe path\r\n");
+ }
+ strcat(optionFile, OptionsFileName);
+
+ fprintf(stderr, "FurViewer: Writing options file \"%s\".\n",
+ optionFile);
+ fflush(stderr);
+
+ FILE *FP = fopen(optionFile, "wb");
+ if(!FP)
+ Error("Couldn't open \"%s\" for write.\n", optionFile);
+
+ WriteOptionsFile(FP);
+
+ fclose(FP);
+}
+
+void AppSettings::SetOptionValue(const char *name,
+ oaOptionDataType type,
+ const char *value)
+{
+ assert(name != NV_NULL);
+ assert(type != OA_TYPE_INVALID);
+ assert(value != NV_NULL);
+
+ oaValue Value;
+ switch(type)
+ {
+ case OA_TYPE_INT:
+ Value.Int = atoi(value);
+ break;
+
+ case OA_TYPE_FLOAT:
+ Value.Float = StrToFloat(value);
+ break;
+
+ case OA_TYPE_BOOL:
+ Value.Bool = atoi(value) ? OA_TRUE : OA_FALSE;
+ break;
+
+ case OA_TYPE_STRING:
+ Value.String = (oaString)value;
+ break;
+
+ case OA_TYPE_ENUM:
+ Value.Enum = (oaString)value;
+ break;
+ }
+
+ SetOptionValue(name, type, &Value);
+}
+
+
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Settings.h b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Settings.h
new file mode 100644
index 0000000..a845732
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Settings.h
@@ -0,0 +1,392 @@
+/*******************************************************************************
+* NVIDIA Corporation
+* Software License Agreement - OpenAutomate SDK
+*
+* IMPORTANT - READ BEFORE COPYING, INSTALLING OR USING
+* Do not use or load the OpenAutomate SDK and any associated materials
+* provided by NVIDIA on NVIDIA�s website (collectively, the "Software")
+* until You have carefully read the following terms and conditions. By
+* loading or using the Software, You agree to fully comply with the terms
+* and conditions of this Software License Agreement ("Agreement") by and
+* between NVIDIA Corporation, a Delaware corporation with its principal
+* place of business at 2701 San Tomas Expressway, Santa Clara, California
+* 95050 U.S.A. ("NVIDIA"), and You. If You do not wish to so agree, do not
+* install or use the Software.
+*
+* For the purposes of this Agreement:
+*
+* "Licensee," "You" and/or "Your" shall mean, collectively and
+* individually, Original Equipment Manufacturers, Independent Hardware
+* Vendors, Independent Software Vendors, and End-Users of the Software
+* pursuant to the terms and conditions of this Agreement.
+*
+* "Derivative Works" shall mean derivatives of the Software created by You
+* or a third party on Your behalf, which term shall include: (a) for
+* copyrightable or copyrighted material, any translation, abridgement,
+* revision or other form in which an existing work may be recast,
+* transformed or adapted; (b) for work protected by topography or mask
+* right, any translation, abridgement, revision or other form in which an
+* existing work may be recast, transformed or adapted; (c) for patentable
+* or patented material, any Improvement; and (d) for material protected by
+* trade secret, any new material derived from or employing such existing
+* trade secret.
+*
+* "Excluded License" is any license that requires as a condition of use,
+* modification and/or distribution of software subject to the Excluded
+* License, that such software or other software distributed and/or
+* combined with such software be (i) disclosed or distributed in source
+* code form, (ii) licensed for the purpose of making derivative works, or
+* (iii) redistributable at no charge.
+*
+* SECTION 1 - GRANT OF LICENSE.
+* NVIDIA agrees to provide the Software and any associated materials
+* pursuant to the terms and conditions of this Agreement. Subject to the
+* terms of this Agreement, NVIDIA grants to You a nonexclusive,
+* transferable, worldwide, revocable, limited, royalty-free, fully paid-up
+* license under NVIDIA�s copyrights to
+*
+* (a) install, deploy, use, have used execute, reproduce, display,
+* perform, run, modify the source code of the Software, or to prepare and
+* have prepared Derivative Works thereof the Software for Your own
+* internal development, testing and maintenance purposes to incorporate
+* the Software or Derivative Works thereof, in part or whole, into Your
+* software applications;
+*
+* (b) to transfer, distribute and sublicense the Software (in its
+* unmodified form as delivered to You by NVIDIA pursuant to this
+* Agreement) in any medium or technology for Your sublicensees to
+* incorporate the Software or Derivative Works thereof, in part or whole,
+* into their respective software applications; and
+*
+* (c) to transfer, distribute and sublicense Derivative Works (in object
+* code only) of the Software (i)_as incorporated in Your application
+* software in any medium or technology; and (ii) certified as OpenAutomate
+* Compatible Software.
+*
+* You may exercise your license rights pursuant to Subsection 1(b) and (c)
+* above pursuant to the terms and conditions of any form of end-user
+* software license agreement of Your choice, including but not limited to
+* an Excluded License.
+*
+* In the event NVIDIA certifies Your application software, incorporating
+* the Derivative Works (in object code only) of the Software, as
+* OpenAutomate compatible ("OpenAutomate Compatible Software"), NVIDIA
+* grants You a nonexclusive, worldwide, revocable, paid-up license to use
+* the name and trademark to "OpenAutomate Compatible" solely for the
+* purposes of identifying and/or marketing Your application software as
+* OpenAutomate Compatible Software; provided that Licensee fully complies
+* with the following:
+*
+* (x) Licensee agrees that it is strictly prohibited from using the name
+* and trademark of "OpenAutomate Compatible" if Your application software
+* is not OpenAutomate Compatible Software;
+*
+* (y) if NVIDIA objects to Your improper use of the "OpenAutomate
+* Compatible" name and trademark, You will take all reasonable steps
+* necessary to resolve NVIDIA�s objections. NVIDIA may reasonably monitor
+* the quality of Your application software bearing the "OpenAutomate
+* Compatible" name or trademark pursuant to this Agreement; and
+*
+* (z) any goodwill attached to NVIDIA�s trademarks, service marks, or
+* trade names belong to NVIDIA and this Agreement does not grant You any
+* right to use them.
+*
+* If You are not the final manufacturer or vendor of a computer system or
+* software program incorporating the Software, or if Your Contractors (as
+* defined below), affiliates or subsidiaries need to exercise any, some or
+* all of the license grant described above herein to the Software on Your
+* behalf, then You may transfer a copy of the Software, (and related
+* end-user documentation) to such recipient for use in accordance with the
+* terms of this Agreement, provided such recipient agrees to be fully
+* bound by the terms hereof. Except as expressly permitted in this
+* Agreement, Unless otherwise authorized in the Agreement, You shall not
+* otherwise assign, sublicense, lease, or in any other way transfer or
+* disclose Software to any third party. Unless otherwise authorized in the
+* Agreement, You shall not reverse- compile, disassemble,
+* reverse-engineer, or in any manner attempt to derive the source code of
+* the Software from the object code portions of the Software.
+*
+* Except as expressly stated in this Agreement, no license or right is
+* granted to You directly or by implication, inducement, estoppel or
+* otherwise. NVIDIA shall have the right to inspect or have an independent
+* auditor inspect Your relevant records to verify Your compliance with the
+* terms and conditions of this Agreement.
+*
+* SECTION 2 - CONFIDENTIALITY.
+* If applicable, any exchange of Confidential Information (as defined in
+* the NDA) shall be made pursuant to the terms and conditions of a
+* separately signed Non-Disclosure Agreement ("NDA") by and between NVIDIA
+* and You. For the sake of clarity, You agree that the Software is
+* Confidential Information of NVIDIA.
+*
+* If You wish to have a third party consultant or subcontractor
+* ("Contractor") perform work on Your behalf which involves access to or
+* use of Software, You shall obtain a written confidentiality agreement
+* from the Contractor which contains terms and obligations with respect to
+* access to or use of Software no less restrictive than those set forth in
+* this Agreement and excluding any distribution or sublicense rights, and
+* use for any other purpose than permitted in this Agreement. Otherwise,
+* You shall not disclose the terms or existence of this Agreement or use
+* NVIDIA's name in any publications, advertisements, or other
+* announcements without NVIDIA's prior written consent. Unless otherwise
+* provided in this Agreement, You do not have any rights to use any NVIDIA
+* trademarks or logos.
+*
+* SECTION 3 - OWNERSHIP OF SOFTWARE AND INTELLECTUAL PROPERTY RIGHTS.
+* All rights, title and interest to all copies of the Software remain with
+* NVIDIA, subsidiaries, licensors, or its suppliers. The Software is
+* copyrighted and protected by the laws of the United States and other
+* countries, and international treaty provisions. You may not remove any
+* copyright notices from the Software. NVIDIA may make changes to the
+* Software, or to items referenced therein, at any time and without
+* notice, but is not obligated to support or update the Software. Except
+* as otherwise expressly provided, NVIDIA grants no express or implied
+* right under any NVIDIA patents, copyrights, trademarks, or other
+* intellectual property rights.
+*
+* All rights, title and interest in the Derivative Works of the Software
+* remain with You subject to the underlying license from NVIDIA to the
+* Software. In Your sole discretion, You may grant NVIDIA, upon NVIDIA�s
+* request for such a license described herein, an irrevocable, perpetual,
+* nonexclusive, worldwide, royalty-free paid-up license to make, have
+* made, use, have used, sell, license, distribute, sublicense or otherwise
+* transfer Derivative Works created by You that add functionality or
+* improvement to the Software.
+*
+* You has no obligation to give NVIDIA any suggestions, comments or other
+* feedback ("Feedback") relating to the Software. However, NVIDIA may use
+* and include any Feedback that You voluntarily provide to improve the
+* Software or other related NVIDIA technologies. Accordingly, if You
+* provide Feedback, You agree NVIDIA and its licensees may freely use,
+* reproduce, license, distribute, and otherwise commercialize the Feedback
+* in the Software or other related technologies without the payment of any
+* royalties or fees.
+*
+* You may transfer the Software only if the recipient agrees to be fully
+* bound by these terms and conditions of this Agreement.
+*
+* SECTION 4 - NO WARRANTIES.
+* THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY
+* OF ANY KIND, INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT,
+* OR FITNESS FOR A PARTICULAR PURPOSE. NVIDIA does not warrant or assume
+* responsibility for the accuracy or completeness of any information,
+* text, graphics, links or other items contained within the Software.
+* NVIDIA does not represent that errors or other defects will be
+* identified or corrected.
+*
+* SECTION 5 - LIMITATION OF LIABILITY.
+* EXCEPT WITH RESPECT TO THE MISUSE OF THE OTHER PARTY�S INTELLECTUAL
+* PROPERTY OR DISCLOSURE OF THE OTHER PARTY�S CONFIDENTIAL INFORMATION IN
+* BREACH OF THIS AGREEMENT, IN NO EVENT SHALL NVIDIA, SUBSIDIARIES,
+* LICENSORS, OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, INDIRECT, LOST PROFITS, CONSEQUENTIAL,
+* BUSINESS INTERRUPTION OR LOST INFORMATION) ARISING OUT OF THE USE OF OR
+* INABILITY TO USE THE SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS PROHIBIT EXCLUSION OR
+* LIMITATION OF LIABILITY FOR IMPLIED WARRANTIES OR CONSEQUENTIAL OR
+* INCIDENTAL DAMAGES, SO THE ABOVE LIMITATION MAY NOT APPLY TO YOU. YOU
+* MAY ALSO HAVE OTHER LEGAL RIGHTS THAT VARY FROM JURISDICTION TO
+* JURISDICTION. NOTWITHSTANDING THE FOREGOING, NVIDIA�S AGGREGATE
+* LIABILITY ARISING OUT OF THIS AGREEMENT SHALL NOT EXCEED ONE HUNDRED
+* UNITED STATES DOLLARS (USD$100).
+*
+* SECTION 6 - TERM.
+* This Agreement and the licenses granted hereunder shall be effective as
+* of the date You download the applicable Software ("Effective Date") and
+* continue for a period of one (1) year ("Initial Term") respectively,
+* unless terminated earlier in accordance with the "Termination" provision
+* of this Agreement. Unless either party notifies the other party of its
+* intent to terminate this Agreement at least three (3) months prior to
+* the end of the Initial Term or the applicable renewal period, this
+* Agreement will be automatically renewed for one (1) year renewal periods
+* thereafter, unless terminated in accordance with the "Termination"
+* provision of this Agreement.
+*
+* SECTION 7 - TERMINATION.
+* NVIDIA may terminate this Agreement at any time if You violate its
+* terms. Upon termination, You will immediately destroy the Software or
+* return all copies of the Software to NVIDIA, and certify to NVIDIA in
+* writing that such actions have been completed. Upon termination or
+* expiration of this Agreement the license grants to Licensee shall
+* terminate, except that sublicenses rightfully granted by Licensee under
+* this Agreement in connection with Section 1(b) and (c) of this Agreement
+* provided by Licensee prior to the termination or expiration of this
+* Agreement shall survive in accordance with their respective form of
+* license terms and conditions.
+*
+* SECTION 8 - MISCELLANEOUS.
+*
+* SECTION 8.1 - SURVIVAL.
+* Those provisions in this Agreement, which by their nature need to
+* survive the termination or expiration of this Agreement, shall survive
+* termination or expiration of the Agreement, including but not limited to
+* Sections 2, 3, 4, 5, 7, and 8.
+*
+* SECTION 8.2 - APPLICABLE LAWS.
+* Claims arising under this Agreement shall be governed by the laws of
+* Delaware, excluding its principles of conflict of laws and the United
+* Nations Convention on Contracts for the Sale of Goods. The state and/or
+* federal courts residing in Santa Clara County, California shall have
+* exclusive jurisdiction over any dispute or claim arising out of this
+* Agreement. You may not export the Software in violation of applicable
+* export laws and regulations.
+*
+* SECTION 8.3 - AMENDMENT.
+* The Agreement shall not be modified except by a written agreement that
+* names this Agreement and any provision to be modified, is dated
+* subsequent to the Effective Date, and is signed by duly authorized
+* representatives of both parties.
+*
+* SECTION 8.4 - NO WAIVER.
+* No failure or delay on the part of either party in the exercise of any
+* right, power or remedy under this Agreement or under law, or to insist
+* upon or enforce performance by the other party of any of the provisions
+* of this Agreement or under law, shall operate as a waiver thereof, nor
+* shall any single or partial exercise of any right, power or remedy
+* preclude other or further exercise thereof, or the exercise of any other
+* right, power or remedy; rather the provision, right, or remedy shall be
+* and remain in full force and effect.
+*
+* SECTION 8.5 - NO ASSIGNMENT.
+* This Agreement and Licensee�s rights and obligations herein, may not be
+* assigned, subcontracted, delegated, or otherwise transferred by Licensee
+* without NVIDIA�s prior written consent, and any attempted assignment,
+* subcontract, delegation, or transfer in violation of the foregoing will
+* be null and void. The terms of this Agreement shall be binding upon
+* Licensee�s assignees.
+*
+* SECTION 8.6 - GOVERNMENT RESTRICTED RIGHTS.
+* The parties acknowledge that the Software is subject to U.S. export
+* control laws and regulations. The parties agree to comply with all
+* applicable international and national laws that apply to the Software,
+* including the U.S. Export Administration Regulations, as well as
+* end-user, end-use and destination restrictions issued by U.S. and other
+* governments.
+*
+* The Software has been developed entirely at private expense and is
+* commercial computer software provided with RESTRICTED RIGHTS. Use,
+* duplication or disclosure of the Software by the U.S. Government or a
+* U.S. Government subcontractor is subject to the restrictions set forth
+* in the Agreement under which the Software was obtained pursuant to DFARS
+* 227.7202-3(a) or as set forth in subparagraphs (c)(1) and (2) of the
+* Commercial Computer Software - Restricted Rights clause at FAR
+* 52.227-19, as applicable. Contractor/manufacturer is NVIDIA, 2701 San
+* Tomas Expressway, Santa Clara, CA 95050. Use of the Software by the
+* Government constitutes acknowledgment of NVIDIA's proprietary rights
+* therein.
+*
+* SECTION 8.7 - INDEPENDENT CONTRACTORS.
+* Licensee�s relationship to NVIDIA is that of an independent contractor,
+* and neither party is an agent or partner of the other. Licensee will
+* not have, and will not represent to any third party that it has, any
+* authority to act on behalf of NVIDIA.
+*
+* SECTION 8.8 - SEVERABILITY.
+* If for any reason a court of competent jurisdiction finds any provision
+* of this Agreement, or portion thereof, to be unenforceable, that
+* provision of the Agreement will be enforced to the maximum extent
+* permissible so as to affect the intent of the parties, and the remainder
+* of this Agreement will continue in full force and effect. This Agreement
+* has been negotiated by the parties and their respective counsel and will
+* be interpreted fairly in accordance with its terms and without any
+* strict construction in favor of or against either party.
+*
+* SECTION 8.9 - ENTIRE AGREEMENT.
+* This Agreement and NDA constitute the entire agreement between the
+* parties with respect to the subject matter contemplated herein, and
+* merges all prior and contemporaneous communications.
+*
+******************************************************************************/
+
+
+#ifndef _SETTINGS_H
+#define _SETTINGS_H
+
+#include <assert.h>
+#include <ctype.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <vector>
+#include <map>
+#include <string>
+#include <conio.h>
+#include <OpenAutomate.h>
+
+#include "corelib_global.h"
+
+#if WIN32
+# include <windows.h>
+# define SLEEP(ms) Sleep(ms)
+#else
+# include <unistd.h>
+# define SLEEP(ms) usleep(1000 * (ms))
+#endif
+
+void Error(const char *fmt, ...);
+bool GetExePath(char* exe_path);
+
+struct OptionValue
+{
+ const char *Name;
+ oaOptionDataType Type;
+ oaValue Value;
+};
+
+class CORELIB_EXPORT AppSettings
+{
+public:
+ AppSettings();
+ ~AppSettings();
+
+ static AppSettings& Inst()
+ {
+ static AppSettings s_inst;
+ return s_inst;
+ }
+
+ void InitOptions();
+
+ void WriteOptionsFile();
+
+ void SetOptionValue(const char *name,
+ oaOptionDataType type,
+ const oaValue *value);
+
+ int GetNumOptions(){return NumOptions;}
+
+ oaNamedOption* GetOption(int i){return &Options[i];}
+
+ OptionValue* GetOptionValue(char* opt_name)
+ {
+ return &OptionValueMap[opt_name];
+ }
+
+ std::map<std::string, OptionValue>* GetCurrentOptionMap()
+ {
+ return &OptionValueMap;
+ }
+
+private:
+
+ void Cleanup();
+
+ void InitDefaultOptions();
+
+ void ReadOptionsFile();
+
+ void WriteOptionsFile(FILE *fp);
+
+ void SetOptionValue(const char *name,
+ oaOptionDataType type,
+ const char *value);
+
+ oaNamedOption Options[128];
+ std::map<std::string, OptionValue> OptionValueMap;
+
+ int NumOptions;
+};
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Stats.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Stats.cpp
new file mode 100644
index 0000000..d52aa14
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Stats.cpp
@@ -0,0 +1,76 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+///////////////////////////////////////////////////////////////////////////////
+#include "Stats.h"
+
+void Stats::reset()
+{
+ m_totalRenderTime = 0.0f;
+ m_shadowRenderTime = 0.0f;
+ m_meshRenderTime = 0.0f;
+ m_hairRenderTime = 0.0f;
+ m_hairStatsTime = 0.0f;
+ m_totalUpdateTime = 0.0f;
+ m_meshSkinningTime = 0.0f;
+ m_hairSkinningTime = 0.0f;
+ m_hairSimulationTime = 0.0f;
+ m_queryTime = 0.0f;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void Stats::add(const Stats& toAdd)
+{
+ m_totalRenderTime += toAdd.m_totalRenderTime;
+ m_shadowRenderTime += toAdd.m_shadowRenderTime;
+ m_meshRenderTime += toAdd.m_meshRenderTime;
+ m_hairRenderTime += toAdd.m_hairRenderTime;
+ m_hairStatsTime += toAdd.m_hairStatsTime;
+
+ m_totalUpdateTime += toAdd.m_totalUpdateTime;
+ m_meshSkinningTime += toAdd.m_meshSkinningTime;
+ m_hairSkinningTime += toAdd.m_hairSkinningTime;
+ m_hairSimulationTime += toAdd.m_hairSimulationTime;
+
+ m_queryTime += toAdd.m_queryTime;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void Stats::average(float numFrames)
+{
+ m_totalRenderTime /= numFrames;
+ m_shadowRenderTime /= numFrames;
+ m_meshRenderTime /= numFrames;
+ m_hairRenderTime /= numFrames;
+ m_hairStatsTime /= numFrames;
+ m_totalUpdateTime /= numFrames;
+ m_meshSkinningTime /= numFrames;
+ m_hairSkinningTime /= numFrames;
+ m_hairSimulationTime /= numFrames;
+ m_queryTime /= numFrames;
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Stats.h b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Stats.h
new file mode 100644
index 0000000..fb22e57
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Stats.h
@@ -0,0 +1,54 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include "corelib_global.h"
+
+// scene statistics
+struct CORELIB_EXPORT Stats
+{
+ double m_totalRenderTime;
+ double m_shadowRenderTime;
+ double m_meshRenderTime;
+ double m_hairRenderTime;
+ double m_hairStatsTime;
+
+ double m_totalUpdateTime;
+ double m_meshSkinningTime;
+ double m_hairSkinningTime;
+ double m_hairSimulationTime;
+
+ double m_queryTime;
+
+ Stats() { reset(); }
+
+ void reset();
+ void add(const Stats& toAdd);
+ void average(float numFrames);
+}; \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Timer.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Timer.cpp
new file mode 100644
index 0000000..2161989
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Timer.cpp
@@ -0,0 +1,80 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#include "Timer.h"
+
+Timer::Timer(bool isStartNow)
+{
+ ::QueryPerformanceFrequency(&m_ticksPerSecond);
+ Reset(isStartNow);
+}
+
+void Timer::Reset(bool isStartNow)
+{
+ m_isPaused = true;
+ m_totalPausedTime.QuadPart = 0;
+ m_lastPausedTime.QuadPart = 0;
+ if (isStartNow)
+ {
+ Start();
+ }
+}
+
+void Timer::Start()
+{
+ if (m_isPaused)
+ {
+ LARGE_INTEGER timeNow;
+ ::QueryPerformanceCounter(&timeNow);
+ m_totalPausedTime.QuadPart += timeNow.QuadPart - m_lastPausedTime.QuadPart;
+ m_isPaused = false;
+ }
+}
+
+void Timer::Pause()
+{
+ if (!m_isPaused)
+ {
+ m_isPaused = true;
+ ::QueryPerformanceCounter(&m_lastPausedTime);
+ }
+}
+
+LONGLONG Timer::GetTicksElapsed() const
+{
+ LARGE_INTEGER timeNow;
+ if (m_isPaused)
+ {
+ timeNow = m_lastPausedTime;
+ }
+ else
+ {
+ ::QueryPerformanceCounter(&timeNow);
+ }
+ return (timeNow.QuadPart - m_totalPausedTime.QuadPart);
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Timer.h b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Timer.h
new file mode 100644
index 0000000..c14ff97
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/Timer.h
@@ -0,0 +1,68 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+
+#include "corelib_global.h"
+
+class CORELIB_EXPORT Timer
+{
+public:
+ Timer(bool isStartNow = false);
+ void Start();
+ void Reset(bool isStartNow = false);
+ void Pause();
+ bool IsRunning() const
+ {
+ return !m_isPaused;
+ }
+ double GetTimeInMilliSeconds() const
+ {
+ return double(GetTicksElapsed()*1000.0) / GetTicksPerSecond();
+ }
+ double GetTimeInSeconds() const
+ {
+ return double(GetTicksElapsed()) / GetTicksPerSecond();
+ }
+
+public:
+ bool m_isPaused;
+
+ // Get time ticks elapsed
+ LONGLONG GetTicksElapsed() const;
+ // Get the timer frequency. Time tick count per second
+ LONGLONG GetTicksPerSecond() const {
+ return m_ticksPerSecond.QuadPart;
+ }
+ LARGE_INTEGER m_ticksPerSecond;
+ LARGE_INTEGER m_lastPausedTime;
+ LARGE_INTEGER m_totalPausedTime;
+};
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/ViewerOutput.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/ViewerOutput.cpp
new file mode 100644
index 0000000..d5486bc
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/ViewerOutput.cpp
@@ -0,0 +1,75 @@
+#include <windows.h>
+#include "ViewerOutput.h"
+
+ViewerOutput& ViewerOutput::Inst()
+{
+ static ViewerOutput inst;
+ return inst;
+}
+
+void ViewerOutput::RegisterPrinter( FrontPrinter* printer )
+{
+ if(!printer) return;
+
+ _printers.insert(printer);
+}
+
+void ViewerOutput::UnRegisterPrinter( FrontPrinter* printer )
+{
+ if(!printer) return;
+
+ auto itr = _printers.find(printer);
+ if(itr != _printers.end())
+ _printers.erase(itr);
+}
+
+void ViewerOutput::print( FrontPrinter::Effect e, unsigned long color, const char* fmt, ... )
+{
+ va_list args;
+ va_start(args, fmt);
+
+ vsprintf_s(_buf, MAX_BUFFER_SIZE, fmt, args);
+
+ va_end(args);
+
+ for (auto itr = _printers.begin(); itr != _printers.end(); ++itr)
+ {
+ (*itr)->print(_buf, color, e);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+ViewerStream::~ViewerStream()
+{
+ flush();
+}
+
+ViewerStream& ViewerStream::flush()
+{
+ this->std::ostream::flush();
+
+ if(_buffer.size() == 0)
+ return (*this);
+
+ ViewerOutput::Inst().print(_effect, _color, _buffer.buf);
+ _buffer.reset();
+
+ return (*this);
+}
+
+ViewerStream::ViewerStreamBuf::ViewerStreamBuf()
+{
+ reset();
+}
+
+std::streamsize ViewerStream::ViewerStreamBuf::size()
+{
+ return (pptr() - pbase());
+}
+
+void ViewerStream::ViewerStreamBuf::reset()
+{
+ memset(buf, 0, sizeof(buf));
+ setp(buf, buf + FURVIEWER_MAX_OUTPUT_CHAR);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Utils/ViewerOutput.h b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/ViewerOutput.h
new file mode 100644
index 0000000..b1fb9f7
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Utils/ViewerOutput.h
@@ -0,0 +1,136 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#include <set>
+
+#include "corelib_global.h"
+
+/*
+ * !! CAUSION:
+ * Not thread safe, should only output messages in the MAIN thread!
+ * Otherwise, cannot guarantee the Qt Gui behavior.
+ */
+
+// DON'T TRY TO WRITE CHARS MORE THAN THE FURVIEWER_MAX_OUTPUT_CHAR
+#define FURVIEWER_MAX_OUTPUT_CHAR 2048
+
+// c-style print
+#define viewer_msg(fmt, ...) ViewerOutput::Inst().print(FrontPrinter::NONE, 0, fmt, ##__VA_ARGS__)
+#define viewer_warn(fmt, ...) ViewerOutput::Inst().print(FrontPrinter::NONE, RGB(255,200,020), fmt, ##__VA_ARGS__)
+#define viewer_info(fmt, ...) ViewerOutput::Inst().print(FrontPrinter::NONE, RGB(118,185,000), fmt, ##__VA_ARGS__)
+#define viewer_err(fmt, ...) ViewerOutput::Inst().print(FrontPrinter::NONE, RGB(255,000,000), fmt, ##__VA_ARGS__)
+#define viewer_fatal(fmt, ...) ViewerOutput::Inst().print(FrontPrinter::BOLD, RGB(255,000,000), fmt, ##__VA_ARGS__)
+
+// c++ style output stream
+#define viewer_stream_msg ViewerStream(FrontPrinter::NONE, 0)
+#define viewer_stream_warn ViewerStream(FrontPrinter::NONE, RGB(255,200,020))
+#define viewer_stream_info ViewerStream(FrontPrinter::NONE, RGB(118,185,000))
+#define viewer_stream_err ViewerStream(FrontPrinter::NONE, RGB(255,000,000))
+#define viewer_stream_fatal ViewerStream(FrontPrinter::NONE, RGB(255,000,000))
+
+
+//////////////////////////////////////////////////////////////////////////
+// implementation
+//////////////////////////////////////////////////////////////////////////
+class FrontPrinter
+{
+public:
+ enum Effect
+ {
+ NONE = 0x0,
+ BOLD = 0x1,
+ ITALIC = 0x2,
+ UNDERLINE = 0x4
+ };
+
+ virtual void print(const char* txt, unsigned long color = 0, Effect e = NONE) = 0;
+};
+
+class CORELIB_EXPORT ViewerOutput
+{
+public:
+ static ViewerOutput& Inst();
+
+ void RegisterPrinter(FrontPrinter* printer);
+ void UnRegisterPrinter(FrontPrinter* printer);
+
+ void print(FrontPrinter::Effect e, unsigned long color, const char* fmt, ...);
+
+private:
+ enum {MAX_BUFFER_SIZE = FURVIEWER_MAX_OUTPUT_CHAR + 1};
+
+ char _buf[MAX_BUFFER_SIZE];
+
+ std::set<FrontPrinter*> _printers;
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+// stream to support c++ style output
+
+#include <streambuf>
+#include <sstream>
+
+class ViewerStream : public std::ostream
+{
+public:
+ explicit ViewerStream(FrontPrinter::Effect e, unsigned long color)
+ : std::ostream(&_buffer)
+ , _effect(e)
+ , _color(color)
+ {}
+
+ ~ViewerStream();
+
+ ViewerStream& flush();
+
+private:
+
+ class ViewerStreamBuf : public std::streambuf
+ {
+ public:
+ enum
+ {
+ STATIC_BUFFER_SIZE = FURVIEWER_MAX_OUTPUT_CHAR + 1,
+ };
+
+ ViewerStreamBuf();
+
+ void reset();
+ std::streamsize size();
+
+ // fixed stack buffer
+ char buf[STATIC_BUFFER_SIZE];
+ };
+
+ ViewerStreamBuf _buffer;
+ FrontPrinter::Effect _effect;
+ unsigned long _color;
+};
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.cpp
new file mode 100644
index 0000000..3a85d8b
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.cpp
@@ -0,0 +1,1448 @@
+#include <QtWidgets/QShortcut>
+#include <QtWidgets/QAction>
+#include <QtWidgets/QMenu>
+#include <QtWidgets/QFileDialog>
+#include <QtWidgets/QMessageBox>
+#include <QtGui/QDesktopServices>
+#include <QtWidgets/QScrollBar>
+#include <QtWidgets/QGraphicsEllipseItem>
+#include <QtWidgets/QGraphicsView>
+#include <QtWidgets/QProgressDialog>
+
+#include <Windows.h>
+
+#include "AppMainWindow.h"
+#include "ExpandablePanel.h"
+
+#include "D3DWidget.h"
+
+#include "DisplayMeshesPanel.h"
+
+#include "DisplayPreferencesPanel.h"
+#include "DisplayScenePanel.h"
+#include "DisplayLightPanel.h"
+#include "ui_DisplayPreferencesPanel.h"
+#include "ui_DisplayScenePanel.h"
+#include "ui_DisplayLightPanel.h"
+#include "CameraBookmarksDialog.h"
+
+#include "SimpleScene.h"
+#include "GlobalSettings.h"
+
+#include "ViewerOutput.h"
+#include "Gamepad.h"
+#if USE_CURVE_EDITOR
+#include "CurveEditorMainWindow.h"
+#endif
+#ifndef NV_ARTISTTOOLS
+#include "ui_AppMainToolbar.h"
+#include "ui_AssetControlPanel.h"
+#include "ui_GeneralAttributesPanel.h"
+#include "ui_PhysicalMaterialsPanel.h"
+#include "ui_StyleMaterialsPanel.h"
+#include "ui_GraphicalMaterialsPanel.h"
+#include "BlastToolbar.h"
+#include "AssetControlPanel.h"
+#include "GraphicalMaterialPanel.h"
+#include "PhysicalMaterialPanel.h"
+#include "StyleMaterialPanel.h"
+#include "GeneralAttributePanel.h"
+#include "MaterialSetPanel.h"
+#include "LodPanel.h"
+#include "DisplayVisualizersPanel.h"
+#include "ui_DisplayVisualizersPanel.h"
+#include "DisplayMeshMaterialsPanel.h"
+#include "FurCharacter.h"
+#include "HairParams.h"
+#include "AboutDialog.h"
+#else
+#endif // NV_ARTISTTOOLS
+
+class MsgPrinter : public FrontPrinter
+{
+public:
+ MsgPrinter(QTextBrowser* browser):_browser(browser)
+ {
+
+ }
+
+ void print(const char* txt, unsigned long color /* = 0 */, Effect e /* = NONE */)
+ {
+ if(color == 0 && e == FrontPrinter::NONE)
+ {
+ _browser->insertPlainText(QString(txt)+"\n");
+ }
+ else
+ {
+ // output html text
+ QString surfix;
+ QString postfix;
+ surfix.reserve(64);
+ postfix.reserve(64);
+ if(e & FrontPrinter::BOLD)
+ {
+ surfix = surfix + "<b>";
+ postfix= postfix + "</b>";
+ }
+ else if(e & FrontPrinter::UNDERLINE)
+ {
+ surfix = surfix + "<u>";
+ postfix= QString("</u>") + postfix;
+ }
+ else if(e & FrontPrinter::ITALIC)
+ {
+ surfix = surfix + "<i>";
+ postfix= QString("</i>") + postfix;
+ }
+
+ if(color != 0)
+ {
+ int r = GetRValue(color);
+ int g = GetGValue(color);
+ int b = GetBValue(color);
+
+ surfix = QString("<div style=\"color:rgb(%1,%2,%3);\">").arg(r).arg(g).arg(b) + surfix;
+ postfix= postfix + QString("</div><br />");
+ }
+
+ QString html = surfix + QString(txt) + postfix;
+ _browser->insertHtml(html);
+ }
+ // auto scroll to the bottom
+ QScrollBar *sb = _browser->verticalScrollBar();
+ if (sb) sb->setValue(sb->maximum());
+ }
+
+private:
+ QTextBrowser* _browser;
+};
+
+int AppMainWindow::_connectionMode = 0;
+bool AppMainWindow::_expertMode = false;
+AppMainWindow* gAppMainWindow = NV_NULL;
+
+void CreateAppMainWindow()
+{
+ gAppMainWindow = new AppMainWindow;
+}
+
+void ReleaseAppMainWindow()
+{
+ delete gAppMainWindow;
+ gAppMainWindow = NV_NULL;
+}
+
+AppMainWindow& AppMainWindow::Inst()
+{
+ return *gAppMainWindow;
+}
+
+AppMainWindow::AppMainWindow(QWidget *parent, Qt::WindowFlags flags)
+ : QMainWindow(parent, flags)
+ , _bookmarksMenu(0)
+ ,_displayMeshesPanel(0)
+ , _displayPreferencesPanel(0)
+ , _displayScenePanel(0)
+ ,_displayLightPanel(0)
+#if USE_CURVE_EDITOR
+ ,_curveEditorInitizlized(false)
+ , _curveEditorMainWindow(nullptr)
+#endif
+ ,_bookmarkActionGroup(0)
+ ,_actionAddBookmark(0)
+ ,_actionEditBookmarks(0)
+{
+ setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+ setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+
+ ui.setupUi(this);
+ //ui.dockOutputWindow->hide();
+
+#ifndef NV_ARTISTTOOLS
+ _mainToolbar = 0;
+ _physicalMaterialPanel = 0;
+ _styleMaterialPanel = 0;
+ _graphicalMaterialPanel = 0;
+ _displayFurVisualizersPanel = 0;
+ _assetControlPanel = 0;
+ _generalAttributePanel = 0;
+ _lodPanel = 0;
+ _displayMeshMaterialsPanel;
+#if USE_MATERIAL_SET
+ _materialSetPanel = 0;
+#endif
+#else
+ CoreLib::Inst()->AppMainWindow_AppMainWindow();
+#endif // NV_ARTISTTOOLS
+
+ _progressDialog.close(); // prevent show one empty progress dialog when it runs.
+
+ m_bGizmoWithLocal = false;
+}
+
+void AppMainWindow::InitUI()
+{
+ _d3dWidget = new D3DWidget(this);
+ _d3dWidget->setMinimumSize(200, 200);
+ ui.renderLayout->addWidget(_d3dWidget);
+
+ InitShortCuts();
+ InitMenuItems();
+ InitToolbar();
+ InitPluginTab();
+ InitMainTab();
+
+ InitMouseSchemes();
+
+ updateUI();
+
+ if (_connectionMode == 1) // master mode
+ ui.sideBarTab->removeTab(1);
+
+ if (_connectionMode == 2)
+ ui.sideBarTab->removeTab(0);
+
+
+ QString defFilePath;
+
+ QString appDir = qApp->applicationDirPath();
+ QDir dir(appDir);
+ if (dir.cd("../../media"))
+ defFilePath = dir.absolutePath();
+
+ _lastFilePath = defFilePath;
+
+ _navigationStyle = 0;
+
+ // initialize the message printer
+ _printer = new MsgPrinter(this->ui.outputWindow);
+ ViewerOutput::Inst().RegisterPrinter(_printer);
+
+#ifndef NV_ARTISTTOOLS
+
+ viewer_info(
+ "<a href=\"https://developer.nvidia.com/hairworks\" style=\"color:rgb(118,180,0);\">NVIDIA Blast Version v"
+ NV_HAIR_RELEASE_VERSION_STRING
+ "</a>");
+
+#else
+ CoreLib::Inst()->AppMainWindow_InitUI();
+#endif // NV_ARTISTTOOLS
+}
+
+AppMainWindow::~AppMainWindow()
+{
+}
+
+void AppMainWindow::setConnectionMode(int m)
+{
+ _connectionMode = m;
+}
+
+void AppMainWindow::startProgress()
+{
+ _progressDialog.setWindowModality(Qt::WindowModal);
+ _progressDialog.show();
+}
+
+void AppMainWindow::setProgress(const char* label, int progress)
+{
+ _progressDialog.setLabelText(label);
+ if (progress >= 0)
+ _progressDialog.setValue(progress);
+
+ _progressDialog.update();
+}
+
+void AppMainWindow::endProgress()
+{
+ _progressDialog.close();
+}
+
+void AppMainWindow::quit()
+{
+ emit aboutToQuit();
+}
+
+void AppMainWindow::setProgressMaximum(int m)
+{
+ _progressDialog.setMaximum(m);
+}
+
+void AppMainWindow::InitMenuItems()
+{
+ QMenuBar* menu = ui.menuBar;
+ QAction* act = NV_NULL;
+
+ // file sub-menu
+ QMenu* fileMenu = menu->addMenu("&File");
+
+ if (_connectionMode != 1)
+ {
+ act = new QAction("Clear scene", this);
+ act->setShortcut(QKeySequence::New);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_clearScene()));
+ fileMenu->addAction(act);
+
+ fileMenu->addSeparator();
+
+ act = new QAction("Open fbx file", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_openfbx()));
+ fileMenu->addAction(act);
+
+ fileMenu->addSeparator();
+
+#ifndef NV_ARTISTTOOLS
+ fileMenu->addSeparator();
+ act = new QAction("Open project file", this);
+ act->setShortcut(QKeySequence::Open);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_openProject()));
+ fileMenu->addAction(act);
+
+ act = new QAction("Save project file", this);
+ act->setShortcut(QKeySequence::Save);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveProject()));
+ fileMenu->addAction(act);
+
+ act = new QAction("Save project file as...", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveProjectAs()));
+ fileMenu->addAction(act);
+
+ fileMenu->addSeparator();
+
+ act = new QAction("&Open hair file", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_openHair()));
+ fileMenu->addAction(act);
+
+ act = new QAction("&Save hair file", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveHair()));
+ fileMenu->addAction(act);
+
+ act = new QAction("Save hair file as...", this);
+ act->setShortcut(QKeySequence::SaveAs);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveHairAs()));
+ fileMenu->addAction(act);
+
+ act = new QAction("Save all hairs...", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveAllHairs()));
+ fileMenu->addAction(act);
+
+ fileMenu->addSeparator();
+#else
+ CoreLib::Inst()->AppMainWindow_InitMenuItems(ui.menuBar);
+#endif // NV_ARTISTTOOLS
+ }
+
+ act = new QAction("E&xit", this);
+ act->setShortcut(QKeySequence::Quit);
+ connect(act, SIGNAL(triggered()), this, SLOT(close()));
+ fileMenu->addAction(act);
+
+ // view submenu
+ QMenu* viewMenu = menu->addMenu("&View");
+ act = new QAction("Bookmarks", this);
+ //connect(act, SIGNAL(triggered()), this, SLOT(menu_showOutput()));
+ viewMenu->addAction(act);
+ _bookmarksMenu = new QMenu("Bookmarks", this);
+ connect(_bookmarksMenu, SIGNAL(triggered(QAction*)), this, SLOT(menu_bookmarkTriggered(QAction*)));
+ act->setMenu(_bookmarksMenu);
+ act = new QAction("Add Bookmark", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_addBookmark()));
+ _bookmarksMenu->addAction(act);
+ _actionAddBookmark = act;
+ act = new QAction("Edit Bookmarks", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_editBookmarks()));
+ _bookmarksMenu->addAction(act);
+ _actionEditBookmarks = act;
+ _bookmarksMenu->addSeparator();
+ _bookmarkActionGroup = new QActionGroup(this);
+
+ // window submenu
+ QMenu* windowMenu = menu->addMenu("&Window");
+ act = new QAction("Output", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_showOutput()));
+ windowMenu->addAction(act);
+
+ act = new QAction("Attribute Editor", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_showAttributeEditor()));
+ windowMenu->addAction(act);
+
+#if USE_CURVE_EDITOR
+ act = new QAction("Curve Editor", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_showCurveEditor()));
+ windowMenu->addAction(act);
+#endif
+
+ // help submenu
+ QMenu* helpMenu = menu->addMenu("&Help");
+
+ act = new QAction("Documentation", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_opendoc()));
+ helpMenu->addAction(act);
+
+ act = new QAction("&About", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_about()));
+ helpMenu->addAction(act);
+}
+
+void AppMainWindow::InitToolbar()
+{
+ if (_connectionMode != 1)
+ {
+#ifndef NV_ARTISTTOOLS
+ _mainToolbar = new BlastToolbar(ui.centralWidget);
+ ui.verticalLayout->insertWidget(0, _mainToolbar);
+ connect(_mainToolbar->getUI().btnFileOpen, SIGNAL(clicked()), this, SLOT(menu_openProject()));
+#else
+ CoreLib::Inst()->AppMainWindow_InitToolbar(ui.centralWidget, ui.verticalLayout);
+#endif // NV_ARTISTTOOLS
+ }
+}
+
+void AppMainWindow::InitPluginTab()
+{
+#ifndef NV_ARTISTTOOLS
+ QWidget *tabFur;
+ QGridLayout *gridLayout;
+ QFrame *furMaterialEditorArea;
+ QVBoxLayout *furMaterialEditorAreaLayout;
+ QScrollArea *furScrollArea;
+ QWidget *furScrollAreaContents;
+ QVBoxLayout *furScrollAreaLayout;
+ QSpacerItem *verticalSpacer;
+
+ tabFur = new QWidget();
+ tabFur->setObjectName(QStringLiteral("tabFur"));
+ gridLayout = new QGridLayout(tabFur);
+ gridLayout->setSpacing(6);
+ gridLayout->setContentsMargins(11, 11, 11, 11);
+ gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setContentsMargins(0, 0, 0, 0);
+ furMaterialEditorArea = new QFrame(tabFur);
+ furMaterialEditorArea->setObjectName(QStringLiteral("furMaterialEditorArea"));
+ furMaterialEditorAreaLayout = new QVBoxLayout(furMaterialEditorArea);
+ furMaterialEditorAreaLayout->setSpacing(6);
+ furMaterialEditorAreaLayout->setContentsMargins(11, 11, 11, 11);
+ furMaterialEditorAreaLayout->setObjectName(QStringLiteral("furMaterialEditorAreaLayout"));
+ furMaterialEditorAreaLayout->setContentsMargins(2, 2, 2, 2);
+
+ gridLayout->addWidget(furMaterialEditorArea, 1, 0, 1, 1);
+
+ furScrollArea = new QScrollArea(tabFur);
+ furScrollArea->setObjectName(QStringLiteral("furScrollArea"));
+ furScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ furScrollArea->setWidgetResizable(true);
+ furScrollAreaContents = new QWidget();
+ furScrollAreaContents->setObjectName(QStringLiteral("furScrollAreaContents"));
+ furScrollAreaContents->setGeometry(QRect(0, 0, 359, 481));
+ furScrollAreaLayout = new QVBoxLayout(furScrollAreaContents);
+ furScrollAreaLayout->setSpacing(3);
+ furScrollAreaLayout->setContentsMargins(11, 11, 11, 11);
+ furScrollAreaLayout->setObjectName(QStringLiteral("furScrollAreaLayout"));
+ furScrollAreaLayout->setContentsMargins(2, 2, 2, 2);
+ verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ furScrollAreaLayout->addItem(verticalSpacer);
+
+ furScrollArea->setWidget(furScrollAreaContents);
+
+ gridLayout->addWidget(furScrollArea, 0, 0, 1, 1);
+
+ ui.sideBarTab->addTab(tabFur, QString());
+
+ ui.sideBarTab->setTabText(ui.sideBarTab->indexOf(tabFur), QApplication::translate("AppMainWindowClass", "Hair", 0));
+
+ ExpandablePanel* panel = 0;
+ int pannelCnt = 0;
+
+ if (_connectionMode == 0)
+ {
+ panel = new ExpandablePanel(furScrollAreaContents, false);
+ _generalAttributePanel = new GeneralAttributePanel(panel);
+ panel->AddContent(_generalAttributePanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Asset Selection");
+
+ panel = new ExpandablePanel(furScrollAreaContents, false);
+ _assetControlPanel = new AssetControlPanel(panel);
+ panel->AddContent(_assetControlPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("General Settings");
+
+ }
+
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _displayFurVisualizersPanel = new DisplayFurVisualizersPanel(panel);
+ panel->AddContent(_displayFurVisualizersPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Visualization");
+
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _physicalMaterialPanel = new PhysicalMaterialPanel(panel);
+ panel->AddContent(_physicalMaterialPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Physical");
+
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _styleMaterialPanel = new StyleMaterialPanel(panel);
+ panel->AddContent(_styleMaterialPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Style");
+
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _graphicalMaterialPanel = new GraphicalMaterialPanel(panel);
+ panel->AddContent(_graphicalMaterialPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Graphics");
+
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _lodPanel = new LodPanel(panel);
+ panel->AddContent(_lodPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Level Of Detail");
+
+#if USE_MATERIAL_SET
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _materialSetPanel = new MaterialSetPanel(panel);
+ panel->AddContent(_materialSetPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Control Texture Channels");
+ //_materialSetPanel->hide();
+ //panel->SetCollapsed(true);
+#else
+ ui.furMaterialEditorAreaLayout->setEnabled(false);
+#endif
+#else
+ CoreLib::Inst()->AppMainWindow_InitPluginTab(ui.sideBarTab);
+#endif // NV_ARTISTTOOLS
+
+#if USE_CURVE_EDITOR
+ _curveEditorMainWindow = new nvidia::CurveEditor::CurveEditorMainWindow( this);//nullptr);
+ _curveEditorMainWindow->setResampleEnabled(false);
+ ui.dockWidgetCurveEditor->setWidget(_curveEditorMainWindow);
+ ui.dockWidgetCurveEditor->setWindowTitle(tr("Curve Editor"));
+
+ connect(_curveEditorMainWindow, SIGNAL(CurveAttributeChanged(nvidia::CurveEditor::CurveAttribute*)), this, SLOT(onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute*)));
+ connect(_curveEditorMainWindow, SIGNAL(ColorAttributeChanged(nvidia::CurveEditor::ColorAttribute*)), this, SLOT(onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute*)));
+ connect(_curveEditorMainWindow, SIGNAL(ReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute*, bool, int)), this, SLOT(onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute*, bool, int)));
+//#else
+// ui.furCurveEditorAreaLayout->setEnabled(false);
+#endif
+}
+
+void AppMainWindow::InitMainTab()
+{
+ int idx = 0;
+
+ if (_connectionMode != 1)
+ {
+ ExpandablePanel* panel = new ExpandablePanel(ui.displayScrollAreaContents);
+ _displayPreferencesPanel = new DisplayPreferencesPanel(panel);
+ panel->AddContent(_displayPreferencesPanel);
+ ui.displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Preferences");
+
+ panel = new ExpandablePanel(ui.displayScrollAreaContents);
+ _displayScenePanel = new DisplayScenePanel(panel);
+ panel->AddContent(_displayScenePanel);
+ ui.displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Scene");
+
+ panel = new ExpandablePanel(ui.displayScrollAreaContents);
+ _displayLightPanel = new DisplayLightPanel(panel);
+ panel->AddContent(_displayLightPanel);
+ ui.displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Light");
+
+ panel = new ExpandablePanel(ui.displayScrollAreaContents);
+ _displayMeshesPanel = new DisplayMeshesPanel(panel);
+ panel->AddContent(_displayMeshesPanel);
+ ui.displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Display Meshes");
+ }
+
+ if (_connectionMode != 1)
+ {
+#ifndef NV_ARTISTTOOLS
+ ExpandablePanel* panel = new ExpandablePanel(ui.displayScrollAreaContents);
+ _displayMeshMaterialsPanel = new DisplayMeshMaterialsPanel(panel);
+ panel->AddContent(_displayMeshMaterialsPanel);
+ ui.displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Display Mesh Materials");
+#else
+ CoreLib::Inst()->AppMainWindow_InitMainTab(ui.displayScrollAreaContents, ui.displayScrollAreaLayout, idx);
+#endif // NV_ARTISTTOOLS
+ }
+}
+
+void AppMainWindow::InitShortCuts()
+{
+ QShortcut* shortCut;
+ shortCut = new QShortcut(QKeySequence(Qt::Key_F), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_frameall()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_H), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_hud()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_G), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_statistics()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_Space), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_pause()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_B), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_reset()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_Escape), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_escape()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_V), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_expert()));
+
+ shortCut = new QShortcut(QKeySequence("Ctrl+X"), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_expert()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_D), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(demo_next()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_Right), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(demo_next()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_A), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(demo_prev()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_Left), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(demo_prev()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_F2), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_output()));
+
+ shortCut = new QShortcut(QKeySequence("Ctrl+F"), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_fitcamera()));
+}
+
+//////////////////////////////////////////////////////////////////////////
+void AppMainWindow::updateBookmarkMenu()
+{
+ // clear old menu items of camera bookmarks
+ while (_bookmarkActionGroup->actions().size() > 0)
+ {
+ QAction* act = _bookmarkActionGroup->actions()[0];
+ _bookmarkActionGroup->removeAction(act);
+ delete act;
+ }
+ _bookmarksMenu->clear();
+ _bookmarksMenu->addAction(_actionAddBookmark);
+ _bookmarksMenu->addAction(_actionEditBookmarks);
+ _bookmarksMenu->addSeparator();
+
+ QList<QString> bookmarks = SimpleScene::Inst()->getBookmarkNames();
+ int numBookmarks = bookmarks.size();
+ for (int i = 0; i < numBookmarks; ++i)
+ {
+ QString bookmark = bookmarks[i];
+
+ QAction* act = new QAction(bookmark, this);
+ act->setCheckable(true);
+ _bookmarksMenu->addAction(act);
+ _bookmarkActionGroup->addAction(act);
+ }
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+void AppMainWindow::updateUI()
+{
+ if (_bookmarksMenu && _bookmarkActionGroup)
+ {
+ updateBookmarkMenu();
+ }
+
+#ifndef NV_ARTISTTOOLS
+ if (_mainToolbar)
+ _mainToolbar->updateValues();
+
+ if (_graphicalMaterialPanel)
+ _graphicalMaterialPanel->updateValues();
+
+ if (_physicalMaterialPanel)
+ _physicalMaterialPanel->updateValues();
+
+ if (_styleMaterialPanel)
+ _styleMaterialPanel->updateValues();
+
+ if (_displayFurVisualizersPanel)
+ _displayFurVisualizersPanel->updateValues();
+
+ if (_lodPanel)
+ _lodPanel->updateValues();
+
+ if (_generalAttributePanel)
+ _generalAttributePanel->updateValues();
+
+ if (_assetControlPanel)
+ _assetControlPanel->updateValues();
+
+ if (_displayMeshMaterialsPanel)
+ _displayMeshMaterialsPanel->updateValues();
+
+#if USE_MATERIAL_SET
+ if (_materialSetPanel)
+ _materialSetPanel->updateValues();
+#endif
+#else
+ CoreLib::Inst()->AppMainWindow_updateUI();
+#endif // NV_ARTISTTOOLS
+
+ if (_displayPreferencesPanel)
+ _displayPreferencesPanel->updateValues();
+
+ if (_displayScenePanel)
+ _displayScenePanel->updateValues();
+
+ if (_displayLightPanel)
+ _displayLightPanel->updateValues();
+
+ if (_displayMeshesPanel)
+ _displayMeshesPanel->updateValues();
+
+#if USE_CURVE_EDITOR
+ if (_curveEditorMainWindow)
+ UpdateCurveEditor();
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////
+void AppMainWindow::updatePluginUI()
+{
+ SimpleScene::Inst()->setIsUpdatingUI(true);
+
+#ifndef NV_ARTISTTOOLS
+ if (_graphicalMaterialPanel)
+ _graphicalMaterialPanel->updateValues();
+
+ if (_physicalMaterialPanel)
+ _physicalMaterialPanel->updateValues();
+
+ if (_styleMaterialPanel)
+ _styleMaterialPanel->updateValues();
+
+ if (_lodPanel)
+ _lodPanel->updateValues();
+
+ if (_displayFurVisualizersPanel)
+ _displayFurVisualizersPanel->updateValues();
+
+ if (_generalAttributePanel)
+ _generalAttributePanel->updateValues();
+
+ if (_assetControlPanel)
+ _assetControlPanel->updateValues();
+
+#if USE_MATERIAL_SET
+ if (_materialSetPanel)
+ _materialSetPanel->updateValues();
+#endif
+#else
+ CoreLib::Inst()->AppMainWindow_updatePluginUI();
+#endif // NV_ARTISTTOOLS
+
+#if USE_CURVE_EDITOR
+ if (_curveEditorMainWindow)
+ UpdateCurveEditor();
+#endif
+
+ SimpleScene::Inst()->setIsUpdatingUI(false);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// event handlers
+
+
+//////////////////////////////////////////////////////////////////////////
+// event handlers
+bool AppMainWindow::openProject(QString fileName)
+{
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file= fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->LoadProject(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ messageBox.critical(0,"Error","File open error!");
+ messageBox.setFixedSize(500,200);
+
+ AppMainWindow::Inst().endProgress();
+ char message[1024];
+ sprintf(message, "Failed to open project file(\"%s\")", (const char*)file);
+ viewer_err(message);
+ return false;
+ }
+
+ AppMainWindow::Inst().endProgress();
+ _lastFilePath = fileInfo.absoluteDir().absolutePath();
+
+ updateUI();
+ return true;
+ }
+ return false;
+}
+
+void AppMainWindow::processDragAndDrop(QString fname)
+{
+ openProject(fname);
+}
+
+void AppMainWindow::removeBookmark(const QString& name)
+{
+ QList<QAction*> bookmarks = _bookmarkActionGroup->actions();
+ int bookmarkCount = bookmarks.size();
+ for (int i = 0; i < bookmarkCount; ++i)
+ {
+ QAction* act = bookmarks.at(i);
+ if (act->text() == name)
+ {
+ _bookmarkActionGroup->removeAction(act);
+ _bookmarksMenu->removeAction(act);
+ delete act;
+ }
+ }
+}
+
+void AppMainWindow::renameBookmark(const QString& oldName, const QString& newName)
+{
+ QList<QAction*> bookmarks = _bookmarkActionGroup->actions();
+ int bookmarkCount = bookmarks.size();
+ for (int i = 0; i < bookmarkCount; ++i)
+ {
+ QAction* act = bookmarks.at(i);
+ if (act->text() == oldName)
+ {
+ act->setText(newName);
+ }
+ }
+}
+
+#if USE_CURVE_EDITOR
+void AppMainWindow::UpdateCurveEditor()
+{
+#ifndef NV_ARTISTTOOLS
+ _curveEditorMainWindow->setCurveAttributes(SimpleScene::Inst()->GetFurCharacter().GetCurveAttributes());
+ _curveEditorMainWindow->setColorCurveAttributes(SimpleScene::Inst()->GetFurCharacter().GetColorAttributes());
+#else
+ CoreLib::Inst()->AppMainWindow_UpdateCurveEditor();
+#endif // NV_ARTISTTOOLS
+
+ _curveEditorMainWindow->update();
+}
+
+void AppMainWindow::ShowCurveEditor(int paramId)
+{
+#ifndef NV_ARTISTTOOLS
+ _curveEditorMainWindow->setCurveAttributes(SimpleScene::Inst()->GetFurCharacter().GetCurveAttributes());
+ _curveEditorMainWindow->setColorCurveAttributes(SimpleScene::Inst()->GetFurCharacter().GetColorAttributes());
+ if (HAIR_PARAMS_ROOT_COLOR == paramId || HAIR_PARAMS_TIP_COLOR == paramId)
+ {
+ std::vector<nvidia::CurveEditor::ColorAttribute*> attributes = SimpleScene::Inst()->GetFurCharacter().GetColorAttributesByParamId(paramId);
+ _curveEditorMainWindow->setSelectedColorAttribute(attributes.size() > 0 ? attributes[0] : nullptr);
+ }
+ else
+ _curveEditorMainWindow->setSelectedCurveAttributes(SimpleScene::Inst()->GetFurCharacter().GetCurveAttributesByParamId(paramId));
+
+#else
+ CoreLib::Inst()->AppMainWindow_ShowCurveEditor(paramId);
+#endif // NV_ARTISTTOOLS
+
+ _curveEditorMainWindow->update();
+}
+#endif
+
+void AppMainWindow::menu_clearScene()
+{
+ SimpleScene::Inst()->Clear();
+ updateUI();
+}
+
+bool AppMainWindow::menu_openfbx()
+{
+ /*
+ QString lastDir = _lastFilePath;
+ QString fileName = QFileDialog::getOpenFileName(this, "Open FBX File", lastDir, "FBX File (*.fbx)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file= fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->LoadSceneFromFbx(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ messageBox.critical(0,"Error","File open error!");
+ messageBox.setFixedSize(500,200);
+
+ AppMainWindow::Inst().endProgress();
+
+ char message[1024];
+ sprintf(message, "Failed to open fbx file(\"%s\")", (const char*)file);
+ viewer_err(message);
+
+ return false;
+ }
+
+ AppMainWindow::Inst().endProgress();
+
+ _lastFilePath = fileInfo.absoluteDir().absolutePath();
+
+ updateUI();
+
+ return true;
+ }
+ return true;
+ */
+
+ // dir and file will get in blast open asset dialog
+ return SimpleScene::Inst()->LoadSceneFromFbx("", "");
+}
+
+void AppMainWindow::menu_addBookmark()
+{
+ QString bookmark = SimpleScene::Inst()->createBookmark();
+
+ QAction* act = new QAction(bookmark, this);
+ act->setCheckable(true);
+ _bookmarksMenu->addAction(act);
+ _bookmarkActionGroup->addAction(act);
+ act->setChecked(true);
+}
+
+void AppMainWindow::menu_editBookmarks()
+{
+ CameraBookmarksDialog dlg(this);
+ dlg.exec();
+}
+
+void AppMainWindow::menu_bookmarkTriggered(QAction* act)
+{
+ if (_actionAddBookmark != act && _actionEditBookmarks != act)
+ {
+ SimpleScene::Inst()->activateBookmark(act->text());
+ }
+}
+
+void AppMainWindow::menu_showOutput()
+{
+ bool bVisibal = ui.dockOutputWindow->isVisible();
+ ui.dockOutputWindow->setVisible(!bVisibal);
+}
+
+void AppMainWindow::menu_showAttributeEditor()
+{
+ bool bVisibal = ui.dockWidget->isVisible();
+ ui.dockWidget->setVisible(!bVisibal);
+}
+#if USE_CURVE_EDITOR
+void AppMainWindow::menu_showCurveEditor()
+{
+ bool bVisibal = ui.dockWidgetCurveEditor->isVisible();
+ ui.dockWidgetCurveEditor->setVisible(!bVisibal);
+}
+#endif
+void AppMainWindow::menu_about()
+{
+ qDebug("%s", __FUNCTION__);
+#ifndef NV_ARTISTTOOLS
+ AboutDialog::ShowAboutDialog();
+#else
+ CoreLib::Inst()->AppMainWindow_menu_about();
+#endif // NV_ARTISTTOOLS
+}
+
+void AppMainWindow::menu_opendoc()
+{
+ qDebug("%s", __FUNCTION__);
+
+#ifndef NV_ARTISTTOOLS
+ QString appDir = QApplication::applicationDirPath();
+ QString docsFile = QFileInfo(appDir + "/../../docs/User_Guide/Nvidia Blast.chm").absoluteFilePath();
+
+ QUrl docsUrl = QUrl::fromLocalFile(docsFile);
+ QUrl url = QUrl::fromUserInput(QString("http://docs.nvidia.com/gameworks/content/artisttools/hairworks/index.html"));
+ QDesktopServices::openUrl(url);
+#else
+ CoreLib::Inst()->AppMainWindow_menu_opendoc();
+#endif // NV_ARTISTTOOLS
+}
+
+void AppMainWindow::shortcut_frameall()
+{
+ qDebug("ShortCut_F: frame all");
+}
+
+void AppMainWindow::shortcut_hud()
+{
+ Gamepad::ShowHideHud();
+ qDebug("ShortCut_S: statistics on/off");
+}
+
+void AppMainWindow::shortcut_statistics()
+{
+ Gamepad::ShowHideStats();
+ qDebug("ShortCut_S: statistics on/off");
+}
+
+void AppMainWindow::shortcut_reset()
+{
+ Gamepad::ResetAnimation();
+}
+
+void AppMainWindow::shortcut_pause()
+{
+ //_mainToolbar->on_btnPlayAnimation_clicked(); // this one has some delay
+ //qDebug("ShortCut_Space: play/pause simualtion");
+ Gamepad::PlayPauseAnimation();
+}
+
+bool AppMainWindow::IsExpertMode()
+{
+ return _expertMode;
+}
+
+void AppMainWindow::demo_next()
+{
+ Gamepad::DemoNext();
+}
+
+void AppMainWindow::demo_prev()
+{
+ Gamepad::DemoPrev();
+}
+
+void AppMainWindow::shortcut_escape()
+{
+ Gamepad::DemoEscape();
+}
+
+void AppMainWindow::shortcut_expert()
+{
+ qDebug("ShortCut_F: expert mode on/off");
+
+ _expertMode = !_expertMode;
+ bool mode = !_expertMode;
+
+ ui.menuBar->setVisible(mode);
+ ui.dockWidget->setVisible(mode);
+ ui.dockOutputWindow->setVisible(mode);
+#if USE_CURVE_EDITOR
+ ui.dockWidgetCurveEditor->setVisible(mode);
+#endif
+ ui.statusBar->setVisible(mode);
+
+#ifndef NV_ARTISTTOOLS
+ if (_mainToolbar)
+ _mainToolbar->setVisible(mode);
+#else
+ CoreLib::Inst()->AppMainWindow_shortcut_expert(mode);
+#endif // NV_ARTISTTOOLS
+
+ //bool bDemoMode = AppMainWindow::IsExpertMode();
+ bool bMaxSized = AppMainWindow::Inst().isMaximized();
+ if (!bMaxSized)
+ {
+ // resize before change to demo mode
+ AppMainWindow::Inst().showMaximized();
+ }
+
+ _d3dWidget->update();
+ Gamepad::ShowProjectName();
+}
+
+void AppMainWindow::shortcut_output()
+{
+ ui.dockOutputWindow->show();
+ _d3dWidget->update();
+}
+
+void AppMainWindow::shortcut_meshmat()
+{
+}
+
+void AppMainWindow::shortcut_fitcamera()
+{
+ qDebug("ShortCut_Ctrl+F: fit camera");
+ SimpleScene::Inst()->FitCamera();
+}
+
+#if USE_CURVE_EDITOR
+void AppMainWindow::onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute)
+{
+#ifndef NV_ARTISTTOOLS
+ SimpleScene::Inst()->GetFurCharacter().updateCurveAttribute(attribute);
+#else
+ CoreLib::Inst()->AppMainWindow_onCurveAttributeChanged(attribute);
+#endif // NV_ARTISTTOOLS
+}
+
+void AppMainWindow::onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute)
+{
+#ifndef NV_ARTISTTOOLS
+ SimpleScene::Inst()->GetFurCharacter().updateColorAttribute(attribute);
+ _graphicalMaterialPanel->updateValues();
+#else
+ CoreLib::Inst()->AppMainWindow_onColorAttributeChanged(attribute);
+#endif // NV_ARTISTTOOLS
+}
+
+void AppMainWindow::onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex)
+{
+#ifndef NV_ARTISTTOOLS
+ SimpleScene::Inst()->GetFurCharacter().reloadColorAttributeTexture(attribute, reloadColorTex, selectedCtrlPntIndex);
+#else
+ CoreLib::Inst()->AppMainWindow_onReloadColorAttributeTexture(attribute, reloadColorTex, selectedCtrlPntIndex);
+#endif // NV_ARTISTTOOLS
+}
+#endif
+
+/*
+ Maya Scheme:
+ ALT + LMB -> Rotate
+ ALT + MMB -> Pan
+ ALT + RMB -> Zoom
+
+ M-wheel -> Zoom
+
+ 3dsMax Scheme:
+ ALT + MMB -> Rotate
+ N/A + MMB -> Pan
+ ALT + SHFT + MMB -> Zoom
+
+ M-wheel -> Zoom
+*/
+
+void AppMainWindow::InitMouseSchemes()
+{
+ ShortCut alt_lmb = qMakePair(Qt::KeyboardModifiers(Qt::AltModifier), Qt::MouseButtons(Qt::LeftButton));
+ ShortCut alt_mmb = qMakePair(Qt::KeyboardModifiers(Qt::AltModifier), Qt::MouseButtons(Qt::MiddleButton));
+ ShortCut alt_rmb = qMakePair(Qt::KeyboardModifiers(Qt::AltModifier), Qt::MouseButtons(Qt::RightButton));
+ ShortCut non_mmb = qMakePair(Qt::KeyboardModifiers(Qt::NoModifier), Qt::MouseButtons(Qt::MiddleButton));
+ ShortCut alt_shft_mmb = qMakePair(Qt::KeyboardModifiers(Qt::AltModifier|Qt::ShiftModifier), Qt::MouseButtons(Qt::MiddleButton));
+
+ _mayaScheme[alt_lmb] = 'R';
+ _mayaScheme[alt_mmb] = 'P';
+ _mayaScheme[alt_rmb] = 'Z';
+
+ _maxScheme[alt_mmb] = 'R';
+ _maxScheme[non_mmb] = 'P';
+ _maxScheme[alt_shft_mmb] = 'Z';
+}
+
+char AppMainWindow::TestMouseScheme( Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons )
+{
+ char op = TestDragCamera(modifiers, buttons);
+
+ if (op != 0)
+ return op;
+
+ if (modifiers == Qt::KeyboardModifier(Qt::ControlModifier))
+ {
+ if (buttons == Qt::MouseButton(Qt::LeftButton))
+ return 'L';
+ else if (buttons == Qt::MouseButton(Qt::MiddleButton))
+ return 'K';
+ }
+
+ if (modifiers == Qt::KeyboardModifier(Qt::ShiftModifier))
+ return 'W';
+
+ return 0;
+}
+
+char AppMainWindow::TestDragCamera( Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons )
+{
+ if(modifiers != Qt::NoModifier && modifiers != Qt::AltModifier) return 0;
+
+ ShortCut input = qMakePair(modifiers, buttons);
+
+ int scheme = _navigationStyle;
+
+ // !! MUST MATCH THE ORDER OF ITEMS IN 'cbNavigationStyle'
+ const int MAYA_SCHEME = 0;
+ const int MAX_SCHEME = 1;
+ if(scheme == MAYA_SCHEME)
+ {
+ auto itr = _mayaScheme.find(input);
+ if(itr != _mayaScheme.end()) return itr.value();
+ }
+ else
+ {
+ auto itr = _maxScheme.find(input);
+ if(itr != _maxScheme.end()) return itr.value();
+ }
+ return 0;
+}
+
+QString AppMainWindow::OpenTextureFile(QString title)
+{
+ QString lastDir = _lastFilePath;
+ QString titleStr = "Open Texture File";
+ if(!title.isEmpty())
+ titleStr = title;
+
+ QString fileName = QFileDialog::getOpenFileName(this, titleStr, lastDir, "Images (*.dds *.png *.bmp *.jpg *.tga)");
+ if(!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ _lastFilePath = fileInfo.absoluteDir().absolutePath();
+ }
+
+ return fileName;
+}
+
+void AppMainWindow::closeEvent (QCloseEvent *event)
+{
+ ViewerOutput::Inst().UnRegisterPrinter(_printer);
+
+ if (1)
+ {
+#if USE_CURVE_EDITOR
+ _curveEditorMainWindow->setParent(NULL);
+#endif
+ event->accept();
+ emit aboutToQuit();
+ return;
+ }
+ if (SimpleScene::Inst()->IsProjectModified() || SimpleScene::Inst()->IsFurModified())
+ {
+ QMessageBox::StandardButton resBtn = QMessageBox::warning(
+ this, tr("Blast Viewer"),
+ tr("Save changes?\n"),
+ QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
+ QMessageBox::Yes);
+ switch (resBtn)
+ {
+ case QMessageBox::Yes:
+#ifndef NV_ARTISTTOOLS
+ if (!menu_saveHair())
+ {
+ event->ignore();
+ return;
+ }
+ if (!menu_saveProject())
+ {
+ event->ignore();
+ return;
+ }
+#else
+ if (!CoreLib::Inst()->AppMainWindow_closeEvent(event))
+ {
+ event->ignore();
+ return;
+ }
+#endif // NV_ARTISTTOOLS
+ break;
+ case QMessageBox::No:
+ break;
+ default:
+ event->ignore();
+ return;
+ }
+ }
+ event->accept();
+ emit aboutToQuit();
+}
+
+void AppMainWindow::updateMainToolbar()
+{
+#ifndef NV_ARTISTTOOLS
+ if (_mainToolbar)
+ _mainToolbar->updateValues();
+#else
+ CoreLib::Inst()->AppMainWindow_updateMainToolbar();
+#endif // NV_ARTISTTOOLS
+}
+
+#ifndef NV_ARTISTTOOLS
+bool AppMainWindow::menu_openProject()
+{
+ QString lastDir = _lastFilePath;
+ QString fileName = QFileDialog::getOpenFileName(this, "Open Hair Project File", lastDir, "Hair Project File (*.furproj)");
+
+ return openProject(fileName);
+}
+
+bool AppMainWindow::menu_saveProject()
+{
+ char message[1024];
+
+ std::string projectFilePath = GlobalSettings::Inst().getAbsoluteFilePath();
+ if (projectFilePath != "")
+ {
+ if (SimpleScene::Inst()->SaveProject(
+ GlobalSettings::Inst().m_projectFileDir.c_str(),
+ GlobalSettings::Inst().m_projectFileName.c_str()
+ ) == false)
+ {
+ QMessageBox messageBox;
+
+ sprintf(message, "Project file %s could not be saved!", (const char*)projectFilePath.c_str());
+ messageBox.critical(0, "Error", message);
+ messageBox.setFixedSize(500, 200);
+ char message[1024];
+ sprintf(message, "Failed to save project file(\"%s\")", (const char*)projectFilePath.c_str());
+ viewer_err(message);
+ return false;
+ }
+
+ sprintf(message, "Project file %s was saved.", (const char*)projectFilePath.c_str());
+
+ /*
+ QMessageBox messageBox;
+ messageBox.information(0, "Info", message);
+ messageBox.setFixedSize(500,200);
+ */
+ viewer_msg(message);
+ return true;
+ }
+ else
+ {
+ return menu_saveProjectAs();
+ }
+ return false;
+}
+
+bool AppMainWindow::menu_saveProjectAs()
+{
+ char message[1024];
+
+ QString lastDir = _lastFilePath;
+ QString fileName = QFileDialog::getSaveFileName(this, "Save Hair Project File", lastDir, "Hair Project File (*.furproj)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->SaveProject(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ sprintf(message, "Project file %s could not be saved!", (const char*)file);
+ messageBox.critical(0, "Error", message);
+ messageBox.setFixedSize(500, 200);
+ return false;
+ }
+
+ sprintf(message, "Project file %s was saved.", (const char*)file);
+
+ /*
+ QMessageBox messageBox;
+ messageBox.information(0, "Info", message);
+ messageBox.setFixedSize(500,200);
+ */
+
+ viewer_msg(message);
+
+ _lastFilePath = fileInfo.absoluteDir().absolutePath();
+ return true;
+ }
+ return false;
+}
+
+bool AppMainWindow::menu_openHair()
+{
+ AppMainWindow& window = AppMainWindow::Inst();
+ QString lastDir = window._lastFilePath;
+ QString fileName = QFileDialog::getOpenFileName(&window, "Open Hair File", lastDir, "Apex Hair File (*.apx;*.apb)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->GetFurCharacter().LoadHairAsset(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ messageBox.critical(0, "Error", "File open error!");
+ messageBox.setFixedSize(500, 200);
+ char message[1024];
+ sprintf(message, "Failed to open hair file(\"%s\")", (const char*)file);
+ viewer_err(message);
+ return false;
+ }
+
+ window._lastFilePath = fileInfo.absoluteDir().absolutePath();
+
+ window.updateUI();
+ return true;
+ }
+
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// event handlers
+bool AppMainWindow::menu_importHair()
+{
+ AppMainWindow& window = AppMainWindow::Inst();
+ QString lastDir = window._lastFilePath;
+ QString fileName = QFileDialog::getOpenFileName(&window, "Import Hair File", lastDir, "Apex Hair File (*.apx;*.apb)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->GetFurCharacter().ImportSelectedHairAsset(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ messageBox.critical(0, "Error", "File open error!");
+ messageBox.setFixedSize(500, 200);
+ char message[1024];
+ sprintf(message, "Failed to import hair file(\"%s\")", (const char*)file);
+ viewer_err(message);
+ return false;
+ }
+
+ window._lastFilePath = fileInfo.absoluteDir().absolutePath();
+
+ window.updateUI();
+ return true;
+ }
+ return false;
+}
+
+
+bool AppMainWindow::menu_saveHair()
+{
+ return SimpleScene::Inst()->GetFurCharacter().SaveHairAsset();
+}
+
+bool AppMainWindow::menu_saveHairAs()
+{
+ AppMainWindow& window = AppMainWindow::Inst();
+ QString lastDir = window._lastFilePath;
+ QString fileName = QFileDialog::getSaveFileName(&window, "Save as", lastDir, "Apex Hair File (*.apx;*.apb)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->GetFurCharacter().SaveHairAssetAs(dir, file))
+ {
+ window.updateUI();
+ }
+
+ window._lastFilePath = fileInfo.absoluteDir().absolutePath();
+ return true;
+ }
+ return false;
+}
+
+bool AppMainWindow::menu_saveAllHairs()
+{
+ return SimpleScene::Inst()->GetFurCharacter().SaveAllHairs();
+}
+#endif // NV_ARTISTTOOLS \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.h
new file mode 100644
index 0000000..4183fc2
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.h
@@ -0,0 +1,208 @@
+#ifndef APPMAINWINDOW_H
+#define APPMAINWINDOW_H
+
+#include <QtWidgets/QMainWindow>
+#include <QtWidgets/QProgressDialog>
+
+#include "ui_AppMainWindow.h"
+#include "UIGlobal.h"
+
+class StyleMaterialPanel;
+class AssetControlPanel;
+class PhysicalMaterialPanel;
+class GraphicalMaterialPanel;
+class DisplayFurVisualizersPanel;
+class GeneralAttributePanel;
+class BlastToolbar;
+class LodPanel;
+class DisplayMeshesPanel;
+class DisplayPreferencesPanel;
+class DisplayScenePanel;
+class DisplayLightPanel;
+class DisplayMeshMaterialsPanel;
+
+#if USE_CURVE_EDITOR
+namespace nvidia {
+namespace CurveEditor {
+
+class CurveEditorMainWindow;
+class CurveAttribute;
+class ColorAttribute;
+
+} // namespace CurveEditor
+} // namespace nvidia
+#endif
+
+#if USE_MATERIAL_SET
+class MaterialSetPanel;
+#endif
+
+class D3DWidget;
+class MsgPrinter;
+class AppMainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ AppMainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ ~AppMainWindow();
+
+ CORELIB_EXPORT static AppMainWindow& Inst();
+
+ CORELIB_EXPORT void InitUI();
+ CORELIB_EXPORT void updateUI();
+ CORELIB_EXPORT void updatePluginUI();
+
+ static bool IsExpertMode();
+
+ D3DWidget* GetRenderWidget() {return _d3dWidget;}
+ char TestMouseScheme(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons);
+
+ CORELIB_EXPORT QString OpenTextureFile(QString title = "");
+
+ void setNavigationStyle(int index) { _navigationStyle = index; }
+ int getNavigationStyle() { return _navigationStyle; }
+
+ void closeEvent (QCloseEvent *event);
+
+ CORELIB_EXPORT void startProgress();
+ CORELIB_EXPORT void setProgressMaximum(int m);
+ CORELIB_EXPORT void setProgress(const char* label, int progress = -1);
+ CORELIB_EXPORT void endProgress();
+ CORELIB_EXPORT void quit();
+
+ CORELIB_EXPORT void updateMainToolbar();
+ CORELIB_EXPORT void processDragAndDrop(QString fname);
+ CORELIB_EXPORT bool openProject(QString fileName);
+
+ CORELIB_EXPORT static void setConnectionMode(int);
+
+ DisplayMeshesPanel* GetDisplayMeshesPanel() { return _displayMeshesPanel; }
+ DisplayPreferencesPanel* GetDisplayPreferencesPanel() { return _displayPreferencesPanel; }
+ DisplayScenePanel* GetDisplayScenePanel() { return _displayScenePanel; }
+ DisplayLightPanel* GetDisplayLightPanel() { return _displayLightPanel; }
+
+ void removeBookmark(const QString& name);
+ void renameBookmark(const QString& oldName, const QString& newName);
+
+#if USE_CURVE_EDITOR
+ CORELIB_EXPORT nvidia::CurveEditor::CurveEditorMainWindow* GetCurveEditorMainWindow() { return _curveEditorMainWindow; }
+ CORELIB_EXPORT void UpdateCurveEditor();
+ CORELIB_EXPORT void ShowCurveEditor(int paramId);
+#endif
+
+ inline QString GetFilePath() { return _lastFilePath; }
+signals:
+ void aboutToQuit();
+
+ public slots:
+ CORELIB_EXPORT void menu_clearScene();
+ CORELIB_EXPORT bool menu_openfbx();
+ CORELIB_EXPORT void menu_addBookmark();
+ CORELIB_EXPORT void menu_editBookmarks();
+ CORELIB_EXPORT void menu_bookmarkTriggered(QAction* act);
+ CORELIB_EXPORT void menu_showOutput();
+ CORELIB_EXPORT void menu_showAttributeEditor();
+ CORELIB_EXPORT void menu_about();
+ CORELIB_EXPORT void menu_opendoc();
+ CORELIB_EXPORT void shortcut_frameall();
+ CORELIB_EXPORT void shortcut_hud();
+ CORELIB_EXPORT void shortcut_statistics();
+ CORELIB_EXPORT void shortcut_pause();
+ CORELIB_EXPORT void shortcut_reset();
+ CORELIB_EXPORT void shortcut_escape();
+ CORELIB_EXPORT void shortcut_expert();
+ CORELIB_EXPORT void demo_next();
+ CORELIB_EXPORT void demo_prev();
+ CORELIB_EXPORT void shortcut_output();
+ CORELIB_EXPORT void shortcut_meshmat();
+ CORELIB_EXPORT void shortcut_fitcamera();
+
+#if USE_CURVE_EDITOR
+ CORELIB_EXPORT void menu_showCurveEditor();
+ CORELIB_EXPORT void onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute);
+ CORELIB_EXPORT void onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute);
+ CORELIB_EXPORT void onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex);
+#endif
+
+private:
+ char TestDragCamera(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons);
+
+public:
+ void InitMenuItems();
+ void InitToolbar();
+ void InitPluginTab();
+ void InitMainTab();
+ void InitMouseSchemes();
+ void InitShortCuts();
+ void updateBookmarkMenu();
+
+ Ui::AppMainWindowClass ui;
+
+ D3DWidget* _d3dWidget;
+ QMenu* _bookmarksMenu;
+
+ DisplayMeshesPanel* _displayMeshesPanel;
+ DisplayPreferencesPanel* _displayPreferencesPanel;
+ DisplayScenePanel* _displayScenePanel;
+ DisplayLightPanel* _displayLightPanel;
+
+
+#if USE_CURVE_EDITOR
+ bool _curveEditorInitizlized;
+ nvidia::CurveEditor::CurveEditorMainWindow* _curveEditorMainWindow;
+#endif
+
+ typedef QPair<Qt::KeyboardModifiers, Qt::MouseButtons> ShortCut;
+ QMap<ShortCut, char> _mayaScheme;
+ QMap<ShortCut, char> _maxScheme;
+ QActionGroup* _bookmarkActionGroup;
+ QAction* _actionAddBookmark;
+ QAction* _actionEditBookmarks;
+
+ QString _lastFilePath;
+
+ int _navigationStyle;
+
+ MsgPrinter* _printer;
+
+ QProgressDialog _progressDialog;
+
+
+ static bool _expertMode;
+
+ CORELIB_EXPORT static int _connectionMode;
+
+#ifndef NV_ARTISTTOOLS
+ BlastToolbar* GetMainToolbar() { return _mainToolbar; }
+ DisplayFurVisualizersPanel* GetFurVisualizersPanel() { return _displayFurVisualizersPanel; }
+
+public slots:
+ bool menu_openProject();
+ bool menu_saveProject();
+ bool menu_saveProjectAs();
+ bool menu_openHair();
+ bool menu_importHair();
+ bool menu_saveHair();
+ bool menu_saveHairAs();
+ bool menu_saveAllHairs();
+
+private:
+ BlastToolbar* _mainToolbar;
+ AssetControlPanel* _assetControlPanel;
+ GeneralAttributePanel* _generalAttributePanel;
+ DisplayFurVisualizersPanel* _displayFurVisualizersPanel;
+ StyleMaterialPanel* _styleMaterialPanel;
+ PhysicalMaterialPanel* _physicalMaterialPanel;
+ GraphicalMaterialPanel* _graphicalMaterialPanel;
+ LodPanel* _lodPanel;
+ DisplayMeshMaterialsPanel* _displayMeshMaterialsPanel;
+#if USE_MATERIAL_SET
+ MaterialSetPanel* _materialSetPanel;
+#endif
+#endif // NV_ARTISTTOOLS
+
+ bool m_bGizmoWithLocal;
+};
+
+#endif // APPMAINWINDOW_H
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.cpp
new file mode 100644
index 0000000..445067a
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.cpp
@@ -0,0 +1,106 @@
+#include "CameraBookmarksDialog.h"
+#include "SimpleScene.h"
+#include "AppMainWindow.h"
+#include <QtWidgets/QMessageBox>
+
+CameraBookmarksDialog::CameraBookmarksDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+
+ ui.buttonBox->button(QDialogButtonBox::Ok)->setFixedWidth(64);
+ ui.buttonBox->button(QDialogButtonBox::Cancel)->setFixedWidth(64);
+ ui.buttonBox->button(QDialogButtonBox::Ok)->setFixedHeight(23);
+ ui.buttonBox->button(QDialogButtonBox::Cancel)->setFixedHeight(23);
+ setWindowFlags(windowFlags()&~Qt::WindowContextHelpButtonHint);
+
+ QObject::connect(ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept()));
+ QObject::connect(ui.buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject()));
+
+ ui.editBookmarkName->setEnabled(false);
+ ui.btnRename->setEnabled(false);
+ ui.btnDelete->setEnabled(false);
+
+ _fillListWidget();
+}
+
+CameraBookmarksDialog::~CameraBookmarksDialog()
+{
+
+}
+
+void CameraBookmarksDialog::on_listWidgetBookmarks_itemSelectionChanged()
+{
+ if (ui.listWidgetBookmarks->selectedItems().size() == 0)
+ {
+ ui.editBookmarkName->setEnabled(false);
+ ui.btnRename->setEnabled(false);
+ ui.btnDelete->setEnabled(false);
+ }
+ else
+ {
+ QListWidgetItem* item = ui.listWidgetBookmarks->selectedItems().at(0);
+ ui.editBookmarkName->setEnabled(true);
+ ui.btnRename->setEnabled(true);
+ ui.btnDelete->setEnabled(true);
+
+ ui.editBookmarkName->setText(item->text());
+ }
+}
+
+void CameraBookmarksDialog::on_editBookmarkName_textChanged(QString val)
+{
+
+}
+
+void CameraBookmarksDialog::on_btnRename_clicked()
+{
+ if (ui.editBookmarkName->text().isEmpty())
+ {
+ QListWidgetItem* item = ui.listWidgetBookmarks->selectedItems().at(0);
+ ui.editBookmarkName->setText(item->text());
+ }
+ else
+ {
+ if (_isNameConflict(ui.editBookmarkName->text()))
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("The new name is conflict with name of other camera bookmark!"));
+ return;
+ }
+
+ QListWidgetItem* item = ui.listWidgetBookmarks->selectedItems().at(0);
+ SimpleScene::Inst()->renameBookmark(item->text(), ui.editBookmarkName->text());
+ AppMainWindow::Inst().renameBookmark(item->text(), ui.editBookmarkName->text());
+ item->setText(ui.editBookmarkName->text());
+ }
+
+}
+
+void CameraBookmarksDialog::on_btnDelete_clicked()
+{
+ QListWidgetItem* item = ui.listWidgetBookmarks->selectedItems().at(0);
+ SimpleScene::Inst()->removeBookmark(item->text());
+ AppMainWindow::Inst().removeBookmark(item->text());
+ ui.listWidgetBookmarks->takeItem(ui.listWidgetBookmarks->row(item));
+ delete item;
+
+}
+
+void CameraBookmarksDialog::_fillListWidget()
+{
+ QList<QString> bookmarks = SimpleScene::Inst()->getBookmarkNames();
+ ui.listWidgetBookmarks->addItems(bookmarks);
+}
+
+bool CameraBookmarksDialog::_isNameConflict(const QString& name)
+{
+ QList<QString> bookmarks = SimpleScene::Inst()->getBookmarkNames();
+ int bookmarkCount = bookmarks.size();
+ for (int i = 0; i < bookmarkCount; ++i)
+ {
+ if (bookmarks.at(i) == name)
+ return true;
+ }
+
+ return false;
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.h
new file mode 100644
index 0000000..13caa42
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.h
@@ -0,0 +1,31 @@
+#ifndef CAMERABOOKMARKSDIALOG_H
+#define CAMERABOOKMARKSDIALOG_H
+
+#include <QtWidgets/QDialog>
+#include "ui_CameraBookmarksDialog.h"
+
+#include "corelib_global.h"
+
+class CameraBookmarksDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ CameraBookmarksDialog(QWidget *parent = 0);
+ ~CameraBookmarksDialog();
+
+private slots:
+CORELIB_EXPORT void on_listWidgetBookmarks_itemSelectionChanged();
+CORELIB_EXPORT void on_editBookmarkName_textChanged(QString val);
+CORELIB_EXPORT void on_btnRename_clicked();
+CORELIB_EXPORT void on_btnDelete_clicked();
+
+private:
+ void _fillListWidget();
+ bool _isNameConflict(const QString& name);
+
+private:
+ Ui::CameraBookmarksDialog ui;
+};
+
+#endif // CAMERABOOKMARKSDIALOG_H
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/D3DWidget.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/D3DWidget.cpp
new file mode 100644
index 0000000..69be706
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/D3DWidget.cpp
@@ -0,0 +1,151 @@
+#include <QtGui/QResizeEvent>
+#include <QtGui/QMouseEvent>
+#include <QtCore/QTimer>
+#include <QtCore/QMimeData>
+
+#include "D3DWidget.h"
+#include "AppMainWindow.h"
+#include "SimpleScene.h"
+
+D3DWidget::D3DWidget( QWidget* parent )
+ : QWidget(parent, Qt::MSWindowsOwnDC) // Same settings as used in Qt's QGLWidget
+{
+ // same settings as used in QGLWidget to avoid 'white flickering'
+ setAttribute(Qt::WA_PaintOnScreen);
+ setAttribute(Qt::WA_NoSystemBackground);
+
+ // to get rid of 'black flickering'
+ setAttribute(Qt::WA_OpaquePaintEvent, true);
+
+ QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ sizePolicy.setHorizontalStretch(0);
+ sizePolicy.setVerticalStretch(0);
+ setSizePolicy(sizePolicy);
+
+ _appWindow = qobject_cast<AppMainWindow*>(parent);
+ this->setAcceptDrops(true);
+
+ setMouseTracking(true);
+}
+
+void D3DWidget::dragEnterEvent(QDragEnterEvent *e)
+{
+ CoreLib::Inst()->D3DWidget_dragEnterEvent(e);
+ e->acceptProposedAction();
+}
+
+void D3DWidget::dragMoveEvent(QDragMoveEvent *e)
+{
+ CoreLib::Inst()->D3DWidget_dragMoveEvent(e);
+ e->acceptProposedAction();
+}
+
+void D3DWidget::dragLeaveEvent(QDragLeaveEvent *e)
+{
+ CoreLib::Inst()->D3DWidget_dragLeaveEvent(e);
+ //e->acceptProposedAction();
+}
+
+void D3DWidget::dropEvent(QDropEvent *e)
+{
+ CoreLib::Inst()->D3DWidget_dropEvent(e);
+
+ const QMimeData* data = e->mimeData();
+ QString name = data->objectName();
+
+ bool hasUrls = data->hasUrls();
+ if (!hasUrls)
+ return;
+
+ QList<QUrl> urlList = data->urls();
+ QString text;
+ for (int i = 0; i < urlList.size() && i < 32; ++i) {
+ QString url = urlList.at(i).toLocalFile();
+ text += url;
+ }
+
+ e->acceptProposedAction();
+
+ AppMainWindow::Inst().processDragAndDrop(text);
+}
+
+void D3DWidget::paintEvent( QPaintEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_paintEvent(e);
+
+ SimpleScene::Inst()->Draw();
+}
+
+void D3DWidget::Shutdown()
+{
+ SimpleScene::Inst()->Shutdown();
+}
+
+void D3DWidget::Timeout()
+{
+ SimpleScene::Inst()->Timeout();
+}
+
+void D3DWidget::resizeEvent( QResizeEvent* e )
+{
+ int w = e->size().width();
+ int h = e->size().height();
+ // resize calls D3D11RenderWindow::Resize
+ SimpleScene::Inst()->Resize(w,h);
+ // D3DWidget_resizeEvent calls resize in DeviceManager
+ CoreLib::Inst()->D3DWidget_resizeEvent(e);
+}
+
+void D3DWidget::mouseMoveEvent( QMouseEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_mouseMoveEvent(e);
+
+ atcore_float2 pos = gfsdk_makeFloat2(e->x(), e->y());
+ SimpleScene::Inst()->onMouseMove(pos);
+
+ Q_ASSERT(_appWindow != NV_NULL);
+ char mode = _appWindow->TestMouseScheme(e->modifiers(), e->buttons());
+
+ if(mode == 0) return;
+ SimpleScene::Inst()->Drag(mode);
+}
+
+void D3DWidget::wheelEvent(QWheelEvent* e)
+{
+ CoreLib::Inst()->D3DWidget_wheelEvent(e);
+
+ SimpleScene::Inst()->onMouseWheel(e->delta());
+ SimpleScene::Inst()->WheelZoom();
+}
+
+void D3DWidget::mousePressEvent( QMouseEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_mousePressEvent(e);
+
+ atcore_float2 pos = gfsdk_makeFloat2(e->x(), e->y());
+ SimpleScene::Inst()->onMouseDown(pos);
+}
+
+void D3DWidget::mouseReleaseEvent( QMouseEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_mouseReleaseEvent(e);
+
+ atcore_float2 pos = gfsdk_makeFloat2(e->x(), e->y());
+ SimpleScene::Inst()->onMouseUp(pos);
+}
+
+void D3DWidget::keyPressEvent( QKeyEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_keyPressEvent(e);
+}
+
+void D3DWidget::keyReleaseEvent( QKeyEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_keyReleaseEvent(e);
+}
+
+void D3DWidget::contextMenuEvent(QContextMenuEvent *e)
+{
+ CoreLib::Inst()->D3DWidget_contextMenuEvent(e);
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/D3DWidget.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/D3DWidget.h
new file mode 100644
index 0000000..0de9a1e
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/D3DWidget.h
@@ -0,0 +1,51 @@
+#ifndef D3DWidget_h__
+#define D3DWidget_h__
+
+#include <QtWidgets/QWidget>
+#include "Nv.h"
+
+#include "corelib_global.h"
+
+class AppMainWindow;
+class D3DWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ D3DWidget(QWidget* parent);
+ virtual ~D3DWidget(){}
+
+signals:
+ void DropSignal();
+
+public slots:
+CORELIB_EXPORT void Timeout();
+CORELIB_EXPORT void Shutdown();
+
+protected:
+ // return NULL to ignore system painter
+ virtual QPaintEngine *paintEngine() const { return NV_NULL; }
+
+ // QWidget events
+ virtual void resizeEvent(QResizeEvent* e);
+ virtual void paintEvent(QPaintEvent* e);
+ virtual void mousePressEvent(QMouseEvent* e);
+ virtual void mouseReleaseEvent(QMouseEvent* e);
+ virtual void mouseMoveEvent(QMouseEvent* e);
+ virtual void wheelEvent ( QWheelEvent * e);
+ virtual void keyPressEvent(QKeyEvent* e);
+ virtual void keyReleaseEvent(QKeyEvent* e);
+
+ virtual void dragEnterEvent(QDragEnterEvent *e);
+ virtual void dragMoveEvent(QDragMoveEvent *e);
+ virtual void dragLeaveEvent(QDragLeaveEvent *e);
+ virtual void dropEvent(QDropEvent *e);
+
+ virtual void contextMenuEvent(QContextMenuEvent *e);
+
+private:
+ AppMainWindow* _appWindow;
+};
+
+#endif // D3DWidget_h__
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.cpp
new file mode 100644
index 0000000..ec267a3
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.cpp
@@ -0,0 +1,263 @@
+#include "AppMainWindow.h"
+#include "DisplayLightPanel.h"
+
+#include "Light.h"
+#include "GlobalSettings.h"
+
+#include <QtWidgets/QColorDialog>
+#include <QtCore/QFileInfo>
+
+DisplayLightPanel::DisplayLightPanel(QWidget* parent)
+ :
+ QWidget(parent)
+{
+ ui.setupUi(this);
+ _isUpdatingUI = false;
+
+ ConfigSpinBox<SlideSpinBoxF>(ui.spinLightDistance, 0.0, 1000.0, 0.1);
+ ConfigSpinBox<SlideSpinBoxF>(ui.spinLightIntensity, 0.0, 5.0, 0.01);
+
+ ui.btnLightColorTex->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ ui.btnLightColorTex->setIconSize(QSize(12,12));
+ ui.btnLightColorTexReload->setIcon(QIcon(":/AppMainWindow/images/Refresh_icon.png"));
+ ui.btnLightColorTexClear->setIcon(QIcon(":/AppMainWindow/images/Remove_icon.png"));
+
+ connect(ui.listSelectedLight, SIGNAL(itemSelectionChanged()), this, SLOT(onListSelectionChanged()));
+}
+
+void DisplayLightPanel::onListSelectionChanged()
+{
+ if (_isUpdatingUI)
+ return;
+
+ int numSelected = ui.listSelectedLight->selectedItems().count();
+
+ // change selection only when there is something selected
+ if (numSelected > 0)
+ {
+ int numItems = ui.listSelectedLight->count();
+ {
+ for (int i = 0; i < numItems; i++)
+ {
+ bool selected = ui.listSelectedLight->item(i)->isSelected();
+ Light::GetLight(i)->m_selected = selected;
+ }
+ }
+ }
+
+ updateUI();
+}
+
+void DisplayLightPanel::on_cbShadowMapResolution_currentIndexChanged( int index )
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->SetShadowMapResolution(index);
+ }
+}
+
+void DisplayLightPanel::on_btnLightUseShadow_stateChanged(int state)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->m_useShadows = state;
+ }
+}
+
+void DisplayLightPanel::on_btnVisualizeLight_stateChanged(int state)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->m_visualize = state;
+ }
+}
+
+void DisplayLightPanel::on_btnLightEnable_stateChanged(int state)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->m_enable = state;
+ }
+}
+
+void DisplayLightPanel::on_btnLinkLightEnable_stateChanged(int state)
+{
+ Light::SetLinkLightOption(state != 0 ? true : false);
+}
+
+void DisplayLightPanel::on_spinLightDistance_valueChanged(double v)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->SetDistance(v);
+ }
+}
+
+void DisplayLightPanel::on_spinLightIntensity_valueChanged(double v)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->m_intensity = v;
+ }
+}
+
+void DisplayLightPanel::on_btnVisualizeShadowMap_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_visualizeShadowMap = state;
+}
+
+void DisplayLightPanel::setButtonColor(QPushButton *button, float r, float g, float b)
+{
+ QColor specColor;
+ specColor.setRgbF(r,g,b);
+ QString specBtnStyle = QString("background-color: rgb(%1,%2,%3);")
+ .arg(specColor.red())
+ .arg(specColor.green())
+ .arg(specColor.blue());
+ button->setStyleSheet(specBtnStyle);
+}
+
+
+static bool getNewColor(atcore_float3& color)
+{
+ QColor currentColor;
+ currentColor.setRgbF(color.x, color.y, color.z);
+
+ QColor newColor = QColorDialog::getColor(currentColor, NV_NULL);
+ if(newColor.isValid())
+ {
+ qreal r,g,b;
+ newColor.getRgbF(&r, &g, &b);
+
+ color.x = r;
+ color.y = g;
+ color.z = b;
+ return true;
+ }
+
+ return false;
+}
+
+void DisplayLightPanel::on_btnLightColor_clicked()
+{
+ Light* pLight = Light::GetFirstSelectedLight();
+
+ atcore_float3 color = pLight->m_color;
+
+ if (getNewColor(color))
+ setButtonColor(ui.btnLightColor, color.x, color.y, color.z);
+
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->m_color = color;
+ }
+}
+
+inline void SetTextureIcon(QPushButton* pButton, bool enabled)
+{
+ if (enabled)
+ pButton->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ else
+ pButton->setIcon(QIcon(":/AppMainWindow/images/TextureIsUsed_icon.png"));
+}
+
+void DisplayLightPanel::on_btnLightColorTex_clicked()
+{
+ QString texName = AppMainWindow::Inst().OpenTextureFile();
+ QFileInfo fileInfo(texName);
+ QByteArray ba = fileInfo.absoluteFilePath().toLocal8Bit();
+
+ if (Light::SetEnvTextureFromFilePath((const char*)ba))
+ SetTextureIcon(ui.btnLightColorTex, Light::GetEnvTextureFilePath().empty());
+}
+
+void DisplayLightPanel::on_btnLightColorTexReload_clicked()
+{
+ std::string path = Light::GetEnvTextureFilePath();
+ if (Light::SetEnvTextureFromFilePath(path.c_str()))
+ SetTextureIcon(ui.btnLightColorTex, Light::GetEnvTextureFilePath().empty());
+}
+
+void DisplayLightPanel::on_btnLightColorTexClear_clicked()
+{
+ Light::SetEnvTextureFromFilePath(nullptr);
+ SetTextureIcon(ui.btnLightColorTex, Light::GetEnvTextureFilePath().empty());
+}
+
+void DisplayLightPanel::updateUI()
+{
+ Light* pLight = Light::GetFirstSelectedLight();
+ if (!pLight)
+ return;
+
+ atcore_float3& color = pLight->m_color;
+ setButtonColor(ui.btnLightColor, color.x, color.y, color.z);
+
+ ui.btnVisualizeLight->setChecked(pLight->m_visualize);
+
+ ui.spinLightDistance->setValue(pLight->GetDistance());
+ ui.spinLightIntensity->setValue(pLight->m_intensity);
+
+ ui.btnLightUseShadow->setChecked(pLight->m_useShadows);
+ ui.btnLightEnable->setChecked(pLight->m_enable);
+
+ ui.btnVisualizeShadowMap->setChecked(GlobalSettings::Inst().m_visualizeShadowMap);
+
+ ui.cbShadowMapResolution->setCurrentIndex(pLight->m_shadowMapResolutionIndex);
+
+ ui.btnLinkLightEnable->setChecked(Light::GetLinkLightOption());
+
+ SetTextureIcon(ui.btnLightColorTex, Light::GetEnvTextureFilePath().empty());
+}
+
+void DisplayLightPanel::updateValues()
+{
+ _isUpdatingUI = true;
+
+ ui.listSelectedLight->clear();
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight)
+ continue;
+
+ const char* lightName = pLight->m_name.c_str();
+ bool selected = pLight->m_selected;
+
+ ui.listSelectedLight->addItem(lightName);
+ ui.listSelectedLight->item(i)->setSelected(selected);
+ }
+ ui.listSelectedLight->setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+ updateUI();
+
+ _isUpdatingUI = false;
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.h
new file mode 100644
index 0000000..e22eae4
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.h
@@ -0,0 +1,47 @@
+#ifndef DisplayLightPanel_h__
+#define DisplayLightPanel_h__
+
+#include <QtWidgets/QWidget>
+#include "ui_DisplayLightPanel.h"
+
+#include "corelib_global.h"
+
+class DisplayLightPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DisplayLightPanel(QWidget* parent);
+
+ public:
+ CORELIB_EXPORT void updateValues();
+
+ public slots:
+ CORELIB_EXPORT void onListSelectionChanged();
+
+ CORELIB_EXPORT void on_spinLightDistance_valueChanged(double v);
+ CORELIB_EXPORT void on_spinLightIntensity_valueChanged(double v);
+
+ CORELIB_EXPORT void on_btnLightUseShadow_stateChanged(int state);
+ CORELIB_EXPORT void on_btnVisualizeLight_stateChanged(int state);
+ CORELIB_EXPORT void on_btnLightEnable_stateChanged(int state);
+ CORELIB_EXPORT void on_btnLinkLightEnable_stateChanged(int state);
+
+ CORELIB_EXPORT void on_btnLightColor_clicked();
+ CORELIB_EXPORT void on_btnLightColorTex_clicked();
+ CORELIB_EXPORT void on_btnLightColorTexReload_clicked();
+ CORELIB_EXPORT void on_btnLightColorTexClear_clicked();
+
+ CORELIB_EXPORT void on_btnVisualizeShadowMap_stateChanged(int state);
+
+ CORELIB_EXPORT void on_cbShadowMapResolution_currentIndexChanged(int index);
+
+private:
+ Ui::DisplayLightPanel ui;
+ bool _isUpdatingUI;
+ void setButtonColor(QPushButton *button, float r, float g, float b);
+
+ void updateUI();
+};
+
+#endif
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.cpp
new file mode 100644
index 0000000..67ca141
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.cpp
@@ -0,0 +1,177 @@
+#include "DisplayMeshesPanel.h"
+
+#include <QtWidgets/QGridLayout>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QPushButton>
+
+#include "AppMainWindow.h"
+
+#include "SimpleScene.h"
+
+#ifndef NV_ARTISTTOOLS
+#include "FurCharacter.h"
+#else
+#endif // NV_ARTISTTOOLS
+
+//////////////////////////////////////////////////////////////////////////
+// DisplayMeshItem
+
+StateViewItem::StateViewItem( QWidget* parent, unsigned int id, MeshViewState view /*= VS_VISIABLE*/ )
+ : _id(id)
+{
+ static QIcon iconVisible(":/AppMainWindow/images/visibilityToggle_visible.png");
+ static QIcon iconNotVisible(":/AppMainWindow/images/visibilityToggle_notVisible.png");
+
+ _parent = qobject_cast<DisplayMeshesPanel*>(parent);
+
+ _layout = new QHBoxLayout(this);
+ _layout->setObjectName(QString::fromUtf8("boxLayout"));
+ _layout->setMargin(0);
+
+ this->setLayout(_layout);
+
+ _btn = new QPushButton(this);
+
+ _btn->setObjectName(QString::fromUtf8("btnToggleView"));
+ QSizePolicy sizePolicy1(QSizePolicy::Ignored, QSizePolicy::Fixed);
+ sizePolicy1.setHorizontalStretch(0);
+ sizePolicy1.setVerticalStretch(0);
+ sizePolicy1.setHeightForWidth(_btn->sizePolicy().hasHeightForWidth());
+ _btn->setSizePolicy(sizePolicy1);
+ _btn->setMinimumSize(QSize(16, 16));
+ _btn->setMaximumSize(QSize(16, 16));
+ _btn->setAutoFillBackground(false);
+ _btn->setCheckable(true);
+ _btn->setChecked(view == VS_VISIABLE);
+ _btn->setIcon( (view == VS_VISIABLE) ? iconVisible : iconNotVisible);
+
+ _layout->addWidget(_btn);
+
+ _spacer = new QSpacerItem(20, 40, QSizePolicy::Expanding, QSizePolicy::Ignored);
+ _layout->addItem(_spacer);
+
+ QMetaObject::connectSlotsByName(this);
+}
+
+void StateViewItem::on_btnToggleView_clicked()
+{
+ static QIcon iconVisible(":/AppMainWindow/images/visibilityToggle_visible.png");
+ static QIcon iconNotVisible(":/AppMainWindow/images/visibilityToggle_notVisible.png");
+
+ bool bVis = _btn->isChecked();
+ _btn->setIcon(bVis ? iconVisible : iconNotVisible);
+
+ _parent->EmitToggleSignal(_id, bVis);
+
+ qDebug("%s", __FUNCTION__);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+DisplayMeshesPanel::DisplayMeshesPanel( QWidget* parent )
+ :QFrame(parent)
+{
+ _layout = new QGridLayout(this);
+ _layout->setObjectName(QString::fromUtf8("gridLayout"));
+
+ this->setLayout(_layout);
+
+ //QString styleSheet =
+ // "QPushButton#btnToggleView:checked {border:2px solid gray; background:rgb(118,180,0);} \n" \
+ // "QPushButton#btnToggleView:pressed {border:2px solid gray; background:rgb(118,180,0);}";
+ //setStyleSheet(styleSheet);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void DisplayMeshesPanel::updateValues()
+{
+ ClearItems();
+
+#ifndef NV_ARTISTTOOLS
+ FurCharacter& character = SimpleScene::Inst()->GetFurCharacter();
+ int nMesh = character.GetMeshCount();
+ for (int i = 0; i < nMesh; ++i)
+ {
+ bool used = character.GetMeshUsed(i);
+ if (!used)
+ continue;
+
+ const char* name = character.GetMeshName(i);
+ bool visible = character.GetMeshVisible(i);
+
+ StateViewItem::MeshViewState visState = visible ? StateViewItem::VS_VISIABLE : StateViewItem::VS_INVISIBLE;
+
+ AddMeshItem(QString(name), i, visState);
+ }
+#else
+ CoreLib::Inst()->DisplayMeshesPanel_updateValues();
+#endif // NV_ARTISTTOOLS
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void DisplayMeshesPanel::AddMeshItem( QString name, unsigned int id, StateViewItem::MeshViewState view )
+{
+ StateViewItem* item;
+ item = new StateViewItem(this, id, view);
+
+ QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ sizePolicy1.setHorizontalStretch(0);
+ sizePolicy1.setVerticalStretch(0);
+
+ QLabel* label = new QLabel(name, this);
+ label->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+ label->setSizePolicy(sizePolicy1);
+
+ int row = _items.size();
+ _layout->addWidget(label, row, 0, 1, 1);
+
+ _layout->addWidget(item, row, 1, 1, 1);
+
+ Q_ASSERT(_items.find(id) == _items.end());
+
+ ItemUI ui;
+ ui.label = label;
+ ui.viewItem = item;
+ _items[id] = ui;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void DisplayMeshesPanel::EmitToggleSignal( unsigned int id, bool visible )
+{
+ emit MeshViewSignal(id, visible);
+
+#ifndef NV_ARTISTTOOLS
+ FurCharacter& character = SimpleScene::Inst()->GetFurCharacter();
+ character.SetMeshVisible(id, visible);
+#else
+ CoreLib::Inst()->DisplayMeshesPanel_EmitToggleSignal(id, visible);
+#endif // NV_ARTISTTOOLS
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void DisplayMeshesPanel::RemoveMeshItem( unsigned int id )
+{
+ if(_items.find(id) != _items.end())
+ {
+ ItemUI ui = _items[id];
+ delete ui.label;
+ delete ui.viewItem;
+ _items.remove(id);
+ }
+ else
+ {
+ Q_ASSERT("Mesh item doesn't exist!!");
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void DisplayMeshesPanel::ClearItems()
+{
+ Q_FOREACH(ItemUI ui, _items)
+ {
+ delete ui.label;
+ delete ui.viewItem;
+ }
+
+ _items.clear();
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.h
new file mode 100644
index 0000000..ecc5b49
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.h
@@ -0,0 +1,80 @@
+#ifndef DisplayMeshesPanel_h__
+#define DisplayMeshesPanel_h__
+
+#include <QtWidgets/QFrame>
+#include <QtCore/QMap>
+#ifndef NV_ARTISTTOOLS
+#include "ui_LodPanel.h"
+#else
+#include <QtWidgets/QLabel>
+#endif // NV_ARTISTTOOLS
+
+#include "corelib_global.h"
+
+class QPushButton;
+class QGridLayout;
+class QHBoxLayout;
+class QSpacerItem;
+
+class DisplayMeshesPanel;
+class StateViewItem : public QWidget
+{
+ Q_OBJECT
+
+public:
+ enum MeshViewState
+ {
+ VS_INVISIBLE = 0,
+ VS_VISIABLE = 1,
+ };
+
+ StateViewItem(QWidget* parent, unsigned int id, MeshViewState view = VS_VISIABLE);
+
+ public slots:
+ CORELIB_EXPORT void on_btnToggleView_clicked();
+
+private:
+ unsigned int _id;
+
+ QHBoxLayout* _layout;
+ QPushButton* _btn;
+ QSpacerItem* _spacer;
+
+ DisplayMeshesPanel* _parent;
+};
+
+class DisplayMeshesPanel : public QFrame
+{
+ Q_OBJECT
+
+public:
+ DisplayMeshesPanel(QWidget* parent);
+
+ void updateValues();
+
+ // client code should make sure the 'id' is unique!
+ CORELIB_EXPORT void AddMeshItem(QString name, unsigned int id, StateViewItem::MeshViewState view = StateViewItem::VS_VISIABLE);
+ CORELIB_EXPORT void RemoveMeshItem(unsigned int id);
+ CORELIB_EXPORT void ClearItems();
+
+signals:
+ void MeshViewSignal(unsigned int id, bool visible);
+
+protected:
+ virtual void EmitToggleSignal(unsigned int id, bool visible);
+
+private:
+ QGridLayout* _layout;
+
+ struct ItemUI
+ {
+ StateViewItem* viewItem;
+ QLabel* label;
+ };
+
+ QMap<unsigned int, ItemUI> _items;
+
+ friend class StateViewItem;
+};
+
+#endif // GraphicalMaterialPanel_h__
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.cpp
new file mode 100644
index 0000000..fe4b808
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.cpp
@@ -0,0 +1,906 @@
+#include "DisplayPreferencesPanel.h"
+
+#include "AppMainWindow.h"
+
+#include "SimpleScene.h"
+#include "GlobalSettings.h"
+#include <QtWidgets/QInputDialog>
+#include <QtWidgets/QMessageBox>
+#include <QtWidgets/QFileDialog>
+
+#include "PlaylistParams.h"
+//#include <Nv/Blast/NvHairCommon.h>
+#include "NvParameterized.h"
+#include "XmlSerializer.h"
+#include "NsFileBuffer.h"
+#include "NvTraits.h"
+#include "NsMemoryBuffer.h"
+#include "ViewerOutput.h"
+#include "Settings.h"
+
+#include "Gamepad.h"
+
+const QString sPlaylistExt = "plist";
+bool bRefreshingComboBox = false;
+
+DisplayPreferencesPanel::DisplayPreferencesPanel(QWidget* parent)
+ :
+ QWidget(parent)
+ , idxCurrentPlaylist(-1)
+ , idxCurrentProj(-1)
+ , playlistProjectsDirty(false)
+{
+ ui.setupUi(this);
+
+ ui.btnBackgroundTex->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ ui.btnBackgroundTex->setIconSize(QSize(12,12));
+ ui.btnBackgroundTexClear->setIcon(QIcon(":/AppMainWindow/images/Remove_icon.png"));
+
+ ui.btnPlaylistsRename->setIcon(QIcon(":/AppMainWindow/images/EditWrench.png"));
+ ui.btnPlaylistsAdd->setIcon(QIcon(":/AppMainWindow/images/Add.png"));
+ ui.btnPlaylistsReload->setIcon(QIcon(":/AppMainWindow/images/refreshReload.png"));
+ ui.btnPlaylistsRemove->setIcon(QIcon(":/AppMainWindow/images/Remove_icon.png"));
+
+ ui.btnPlaylistAddProj->setIcon(QIcon(":/AppMainWindow/images/Add.png"));
+ ui.btnPlaylistRemoveProj->setIcon(QIcon(":/AppMainWindow/images/Remove_icon.png"));
+ ui.btnPlaylistProjGoUp->setIcon(QIcon(":/AppMainWindow/images/Up.png"));
+ ui.btnPlaylistProjGoDown->setIcon(QIcon(":/AppMainWindow/images/Down.png"));
+
+ ui.btnPlaylistsPlay->setIcon(QIcon(":/AppMainWindow/images/playlist.png"));
+
+ //QObject::connect(ui.listWidgetPlaylist, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(playlistDoubleClicked(QListWidgetItem*)));
+
+ ConfigSpinBox<SlideSpinBoxF>(ui.spinCameraFOV, 5.0, 180.0, 1.0);
+}
+
+DisplayPreferencesPanel::~DisplayPreferencesPanel()
+{
+}
+
+void DisplayPreferencesPanel::on_spinRenderPlayRateFPS_valueChanged(double v)
+{
+ GlobalSettings::Inst().setRenderFps((float)v);
+}
+
+void DisplayPreferencesPanel::on_spinSimulationRateFPS_valueChanged(double v)
+{
+ GlobalSettings::Inst().setSimulationFps((float)v);
+}
+
+void DisplayPreferencesPanel::on_spinCameraFOV_valueChanged(double v)
+{
+ GlobalSettings::Inst().m_fovAngle = v;
+}
+
+void DisplayPreferencesPanel::on_cbAntialiasing_currentIndexChanged( int index )
+{
+ GlobalSettings::Inst().m_msaaOption = index;
+}
+
+void DisplayPreferencesPanel::on_cbUpAxis_currentIndexChanged( int index )
+{
+ switch (index)
+ {
+ case 0: // y up
+ SimpleScene::Inst()->ResetUpDir(false);
+ break;
+ case 1: // z up
+ SimpleScene::Inst()->ResetUpDir(true);
+ break;
+ }
+ SimpleScene::Inst()->SetProjectModified(true);
+}
+
+void DisplayPreferencesPanel::on_cbHandedness_currentIndexChanged( int index )
+{
+ switch (index)
+ {
+ case 0: // rhs
+ SimpleScene::Inst()->ResetLhs(false);
+ break;
+ case 1: // lhs
+ SimpleScene::Inst()->ResetLhs(true);
+ break;
+ }
+ SimpleScene::Inst()->SetProjectModified(true);
+}
+
+void DisplayPreferencesPanel::on_cbSceneUnit_currentIndexChanged( int index )
+{
+ GlobalSettings::Inst().m_sceneUnitIndex = index;
+}
+
+void DisplayPreferencesPanel::on_cbNavigationStyle_currentIndexChanged( int index )
+{
+ AppMainWindow::Inst().setNavigationStyle(index);
+}
+
+void DisplayPreferencesPanel::on_btnBackgroundTex_clicked()
+{
+ if (SimpleScene::Inst()->LoadBackgroundTextureFile())
+ ui.btnBackgroundTex->setIcon(QIcon(":/AppMainWindow/images/TextureIsUsed_icon.png"));
+ else
+ ui.btnBackgroundTex->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+
+ updateValues();
+ SimpleScene::Inst()->SetProjectModified(true);
+}
+
+void DisplayPreferencesPanel::on_btnBackgroundTexClear_clicked()
+{
+ SimpleScene::Inst()->ClearBackgroundTexture();
+ ui.btnBackgroundTex->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ updateValues();
+}
+
+void DisplayPreferencesPanel::updateValues()
+{
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ ui.spinRenderPlayRateFPS->setValue(globalSettings.m_renderFps);
+ ui.spinSimulationRateFPS->setValue(globalSettings.m_simulationFps);
+ ui.cbUpAxis->setCurrentIndex(globalSettings.m_zup);
+ ui.cbHandedness->setCurrentIndex(globalSettings.m_lhs);
+ ui.spinCameraFOV->setValue(globalSettings.m_fovAngle);
+ ui.cbSceneUnit->setCurrentIndex(globalSettings.m_sceneUnitIndex);
+ ui.cbNavigationStyle->setCurrentIndex(AppMainWindow::Inst().getNavigationStyle());
+ ui.cbAntialiasing->setCurrentIndex(globalSettings.m_msaaOption);
+
+ savePlaylistProjects();
+ reloadComboxBoxPlaylists();
+
+ //// sync playlist to gamepad
+ //static bool bOnce = true;
+ //if (bOnce)
+ //{
+ // bOnce = false;
+ // assignPlayPlaylistToGamepad(0);
+ //}
+}
+
+void DisplayPreferencesPanel::reloadComboxBoxPlaylists()
+{
+ playlistsLoader.loadPlaylistsFromMediaPath();
+ // set playlist combo box
+ //idxCurrentPlaylist = ui.cbPlaylists->currentIndex();
+ bRefreshingComboBox = true;
+ ui.cbPlaylists->clear();
+ int count = playlistsLoader.playlists.size();
+ for (int i = 0; i < count; ++i)
+ {
+ QFileInfo& fi = playlistsLoader.playlists[i];
+ std::string fn = fi.fileName().toUtf8().data();
+ ui.cbPlaylists->addItem(fi.fileName());
+ }
+ bRefreshingComboBox = false;
+ if (idxCurrentPlaylist > count || idxCurrentPlaylist < 0)
+ idxCurrentPlaylist = 0;
+
+ ui.cbPlaylists->setCurrentIndex(idxCurrentPlaylist);
+
+ // refresh project list
+ reloadListboxPorjectsFromPlayist();
+}
+
+void DisplayPreferencesPanel::runDemoCommandline()
+{
+ // run demos if command line asks
+ static bool once = true;
+ if (once)
+ {
+ once = false;
+ std::string demoPlaylist = AppSettings::Inst().GetOptionValue("User/FurDemoPlaylist")->Value.String;
+ if (demoPlaylist.size() > 1)
+ {
+ QString demoList = QString(demoPlaylist.c_str()).toUpper();
+ int count = playlistsLoader.playlists.size();
+ for (int i = 0; i < count; ++i)
+ {
+ QFileInfo& fi = playlistsLoader.playlists[i];
+ QString fname = fi.fileName().toUpper();
+ if (fname == demoList)
+ {
+ idxCurrentPlaylist = i;
+ ui.cbPlaylists->setCurrentIndex(idxCurrentPlaylist);
+ playPlaylist(idxCurrentPlaylist);
+ return;
+ }
+ }
+ viewer_msg(QString("Cannot find playlist, " + demoList).toUtf8().data());
+ }
+ }
+}
+
+void DisplayPreferencesPanel::reloadListboxPorjectsFromPlayist()
+{
+ int count = playlistsLoader.getProjectsInPlaylist(idxCurrentPlaylist, playlistProjects);
+ refreshListboxPorjects();
+}
+
+void DisplayPreferencesPanel::savePlaylistProjects()
+{
+ if (playlistProjectsDirty)
+ {
+ playlistsLoader.saveProjectsInPlaylist(idxCurrentPlaylist, playlistProjects);
+ playlistProjectsDirty = false;
+ }
+}
+
+void DisplayPreferencesPanel::refreshListboxPorjects()
+{
+ int count = playlistProjects.size();
+ ui.listWidgetPlaylist->clear();
+ ui.listWidgetPlaylist->setSortingEnabled(false);
+ ui.listWidgetPlaylist->setSelectionMode(QAbstractItemView::SingleSelection);
+ QStringList tips;
+ for (int i = 0; i < count; ++i)
+ {
+ QString fullName = playlistsLoader.convertToAbsoluteFilePath(playlistProjects[i]);
+ QFileInfo fi(fullName);
+ tips.append(fi.absoluteFilePath());
+ std::string tmp = fi.absoluteFilePath().toUtf8().data();
+ ui.listWidgetPlaylist->addItem(fi.fileName());
+ }
+ ui.listWidgetPlaylist->setTips(tips);
+ if (idxCurrentProj > count || idxCurrentProj < 0)
+ {
+ idxCurrentProj = 0;
+ }
+ ui.listWidgetPlaylist->setCurrentRow(idxCurrentProj);
+}
+
+void DisplayPreferencesPanel::SelectPlayList(QString& name)
+{
+ QString newName = name.toUpper();
+ int count = playlistsLoader.playlists.size();
+ for (int i = 0; i < count; ++i)
+ {
+ QFileInfo& fi = playlistsLoader.playlists[i];
+ if (fi.baseName().toUpper() == newName)
+ {
+ ui.cbPlaylists->setCurrentIndex(i);
+ break;
+ }
+ }
+}
+
+void DisplayPreferencesPanel::on_cbPlaylists_currentIndexChanged(int index)
+{
+ savePlaylistProjects();
+ if (!bRefreshingComboBox)
+ {
+ idxCurrentPlaylist = ui.cbPlaylists->currentIndex();
+ reloadListboxPorjectsFromPlayist();
+ }
+}
+
+void DisplayPreferencesPanel::SelectProject(QString& name)
+{
+ QString newName = name.toUpper();
+ std::string strNew = newName.toUtf8().data();
+ int count = playlistProjects.size();
+ for (int i = 0; i < count; ++i)
+ {
+ QString& str = playlistProjects[i];
+ //QFileInfo fi(str);
+ //std::string stmp = fi.absoluteFilePath().toUtf8().data();
+ //if (fi.absoluteFilePath().toUpper() == newName)
+ if (str.toUpper() == newName)
+ {
+ ui.listWidgetPlaylist->setCurrentRow(i);
+ break;
+ }
+ }
+}
+
+void DisplayPreferencesPanel::on_listWidgetPlaylist_itemSelectionChanged()
+{
+ idxCurrentProj = ui.listWidgetPlaylist->currentRow();
+}
+
+void DisplayPreferencesPanel::on_listWidgetPlaylist_itemDoubleClicked(QListWidgetItem* pItem)
+{
+ idxCurrentProj = ui.listWidgetPlaylist->currentRow();
+ if (idxCurrentProj < 0)
+ return;
+ QString fn = playlistProjects[idxCurrentProj];
+ QString fullname = PlaylistsLoader::convertToAbsoluteFilePath(fn);
+ AppMainWindow::Inst().openProject(fullname);
+ char msg[1024];
+ sprintf(msg, "Blast Viewer - %s", fullname.toUtf8().data());
+ AppMainWindow::Inst().setWindowTitle(msg);
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistsRename_clicked()
+{
+ idxCurrentPlaylist = ui.cbPlaylists->currentIndex();
+ if (idxCurrentPlaylist < 0)
+ return;
+
+ QFileInfo& fi = playlistsLoader.playlists[idxCurrentPlaylist];
+ bool isOK = false;
+ QString newBaseName = QInputDialog::getText(NULL, "Rename Playlist - " + fi.fileName(),
+ "Input a new name for the playlist, " + fi.fileName(), QLineEdit::Normal,
+ fi.baseName(), &isOK);
+ if (isOK)
+ {
+ bool ok = playlistsLoader.rename(idxCurrentPlaylist, newBaseName);
+ if (ok)
+ {
+ reloadComboxBoxPlaylists();
+ SelectPlayList(newBaseName);
+ }
+ else
+ {
+ QMessageBox::warning(this, "Fail to rename a playlist",
+ "Fail to rename a playlist. The failure could relate to name duplication or hardware failure.",
+ QMessageBox::Close);
+ }
+ }
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistsAdd_clicked()
+{
+ savePlaylistProjects();
+
+ bool isOK = false;
+ QString sInput = QInputDialog::getText(NULL, "Create New Playlist", "Input a name for the new playlist.", QLineEdit::Normal, "", &isOK);
+ if (isOK)
+ {
+ QString newName = sInput.trimmed();
+ bool ok = playlistsLoader.add(newName);
+ if (ok)
+ {
+ reloadComboxBoxPlaylists();
+ // select the new one
+ SelectPlayList(newName);
+ }
+ else
+ {
+ QMessageBox::warning(this, "Fail to add new playlist",
+ "Fail to add new playlist. The failure could relate to name duplication or hardware failure.",
+ QMessageBox::Close);
+ }
+ }
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistsReload_clicked()
+{
+ savePlaylistProjects();
+ reloadComboxBoxPlaylists();
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistsRemove_clicked()
+{
+ savePlaylistProjects();
+ idxCurrentPlaylist = ui.cbPlaylists->currentIndex();
+ if (idxCurrentPlaylist < 0)
+ return;
+
+ bool ok = playlistsLoader.remove(idxCurrentPlaylist);
+ if (ok)
+ {
+ reloadComboxBoxPlaylists();
+ }
+ else
+ {
+ QMessageBox::warning(this, "Fail to remove a playlist",
+ "Fail to remove a playlist. The failure could relate to hardware.",
+ QMessageBox::Close);
+ }
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistAddProj_clicked()
+{
+ static QString lastPath;
+ if (lastPath.size() < 1)
+ {
+ lastPath = PlaylistsLoader::mediaPath;
+ }
+ QString fileNameInput = QFileDialog::getOpenFileName(this, "Open Hair Project File", lastPath, "Hair Project File (*.furproj)");
+ if (!QFile::exists(fileNameInput))
+ return;
+ std::string tmp = fileNameInput.toUtf8().data();
+ QString fileName = PlaylistsLoader::convertToSaveingFilePath(fileNameInput);
+ if (fileName.size() < 1)
+ {
+ return;
+ }
+ lastPath = QFileInfo(fileNameInput).absolutePath();
+ std::string tmp2 = fileName.toUtf8().data();
+ playlistProjects.append(fileName);
+ refreshListboxPorjects();
+ //QFileInfo fi(fileName);
+ SelectProject(fileName);// fi.absoluteFilePath());
+ playlistProjectsDirty = true;
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistProjGoUp_clicked()
+{
+ idxCurrentProj = ui.listWidgetPlaylist->currentRow();
+ if (idxCurrentProj <= 0)
+ return;
+
+ QString tmp = playlistProjects[idxCurrentProj];
+ playlistProjects[idxCurrentProj] = playlistProjects[idxCurrentProj - 1];
+ playlistProjects[idxCurrentProj - 1] = tmp;
+
+ refreshListboxPorjects();
+ SelectProject(tmp);
+
+ playlistProjectsDirty = true;
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistProjGoDown_clicked()
+{
+ int count = playlistProjects.size();
+ idxCurrentProj = ui.listWidgetPlaylist->currentRow();
+ if (idxCurrentProj < 0 || idxCurrentProj>= count -1)
+ return;
+
+ QString tmp = playlistProjects[idxCurrentProj];
+ playlistProjects[idxCurrentProj] = playlistProjects[idxCurrentProj + 1];
+ playlistProjects[idxCurrentProj + 1] = tmp;
+
+ refreshListboxPorjects();
+ SelectProject(tmp);
+
+ playlistProjectsDirty = true;
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistRemoveProj_clicked()
+{
+ int count = playlistProjects.size();
+ idxCurrentProj = ui.listWidgetPlaylist->currentRow();
+ if (idxCurrentProj < 0 || idxCurrentProj >= count)
+ {
+ return;
+ }
+
+ playlistProjects.removeAt(idxCurrentProj);
+
+ refreshListboxPorjects();
+ playlistProjectsDirty = true;
+}
+
+void DisplayPreferencesPanel::assignPlayPlaylistToGamepad(int idx)
+{
+ if (idx == -1)
+ idx = idxCurrentPlaylist;
+ int count = playlistsLoader.getProjectsInPlaylist(idx, playlistProjects);
+ if (count < 1)
+ {
+ viewer_msg("Playlist is empty.");
+ return;
+ }
+ QList<QString> files;
+ for (int i = 0; i < count; ++i)
+ {
+ QString fname = PlaylistsLoader::convertToAbsoluteFilePath(playlistProjects[i]);
+ if (fname.size() > 0)
+ {
+ files.append(fname);
+ }
+ }
+
+ Gamepad& theGamepad = Gamepad::Instance();
+ theGamepad.SetDemoProjects(files);
+}
+
+void DisplayPreferencesPanel::playPlaylist(int idx)
+{
+ assignPlayPlaylistToGamepad(idx);
+ Gamepad& theGamepad = Gamepad::Instance();
+ theGamepad.SetDemoMode(true);
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistsPlay_clicked()
+{
+ savePlaylistProjects();
+
+ idxCurrentPlaylist = ui.cbPlaylists->currentIndex();
+ if (idxCurrentPlaylist < 0)
+ {
+ viewer_msg("No available playlists.");
+ return;
+ }
+ playPlaylist(idxCurrentPlaylist);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+using namespace nvidia;
+using namespace nvidia::parameterized;
+
+QString PlaylistsLoader::projectPath;
+QString PlaylistsLoader::mediaPath;
+
+#include "FoundationHolder.h"
+
+struct PlaylistParamsContext
+{
+ //nvidia::NvFoundation* mFoundation;
+ NvParameterized::Traits* mTraits;
+ PlaylistParamsFactory* mPlaylistParamsFactory;
+};
+
+PlaylistsLoader::PlaylistsLoader()
+ :pContext(nullptr)
+{
+}
+
+PlaylistsLoader::~PlaylistsLoader()
+{
+}
+
+void PlaylistsLoader::CreatePlaylistParamsContext()
+{
+ if (pContext)
+ return;
+
+ PlaylistParamsContext* context = new PlaylistParamsContext;
+ //context->mFoundation = FoundationHolder::GetFoundation();
+ FoundationHolder::GetFoundation();
+ //assert(context->mFoundation != NV_NULL);
+
+ context->mTraits = NvParameterized::createTraits();
+ context->mPlaylistParamsFactory = new PlaylistParamsFactory;
+ context->mTraits->registerFactory(*context->mPlaylistParamsFactory);
+ pContext = context;
+}
+
+void PlaylistsLoader::ReleasePlaylistParamsContext()
+{
+ if (pContext)
+ {
+ pContext->mTraits->release();
+ delete pContext->mPlaylistParamsFactory;
+ delete pContext;
+ pContext = nullptr;
+ }
+}
+
+void PlaylistsLoader::loadPlaylistsFromMediaPath()
+{
+ if (projectPath.isEmpty())
+ {
+ QString appDir = qApp->applicationDirPath();
+ QDir dirTmp(appDir);
+ if (dirTmp.cd("./media/playlists"))
+ projectPath = dirTmp.absolutePath();
+ else if (dirTmp.cd("../media/playlists"))
+ projectPath = dirTmp.absolutePath();
+ else if (dirTmp.cd("../../media/playlists"))
+ projectPath = dirTmp.absolutePath();
+ else if (dirTmp.cd("../../media"))
+ {
+ bool ok = dirTmp.mkdir("playlists");
+ if (dirTmp.cd("playlists"))
+ {
+ projectPath = dirTmp.absolutePath();
+ }
+ }
+ if (!projectPath.isEmpty())
+ {
+ if (dirTmp.cd(".."))
+ {
+ mediaPath = dirTmp.absolutePath();
+ }
+ else
+ {
+ mediaPath = projectPath + "/..";
+ }
+ }
+ }
+ if (!projectPath.isEmpty())
+ {
+ playlists.clear();
+
+ QStringList filters;
+ filters << (QString("*.") + sPlaylistExt);
+ QDirIterator dir_iterator(projectPath, filters, QDir::Files | QDir::NoSymLinks, QDirIterator::NoIteratorFlags); //QDirIterator::Subdirectories
+ while (dir_iterator.hasNext())
+ {
+ dir_iterator.next();
+ QFileInfo file_info = dir_iterator.fileInfo();
+ std::string absolute_file_path = file_info.absoluteFilePath().toUtf8().data();
+ playlists.append(file_info);
+ }
+ }
+}
+
+bool PlaylistsLoader::rename(int idx, QString& newBaseName)
+{
+ int count = playlists.size();
+ if (idx >= 0 && idx < count)
+ {
+ QFileInfo& finfo = playlists[idx];
+ QString fn = finfo.baseName().toUpper();
+ QString fnNew = newBaseName.toUpper();
+ if (fn != fnNew)
+ {
+ QFileInfo nfi(projectPath, newBaseName + "." + sPlaylistExt);
+ QString fullNewName = nfi.absoluteFilePath();
+ std::string fntmp = fullNewName.toUtf8().data();
+ bool exist = QFile::exists(fullNewName);
+ if (exist)
+ {
+ return false;
+ }
+ bool ok = QFile::rename(finfo.absoluteFilePath(), fullNewName);
+ if (ok)
+ {
+ finfo.setFile(fullNewName);
+ exist = QFile::exists(fullNewName);
+ if (!exist)
+ {
+ return false;
+ }
+ }
+ return ok;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool PlaylistsLoader::remove(int idx)
+{
+ int count = playlists.size();
+ if (idx >= 0 && idx < count)
+ {
+ QFileInfo& finfo = playlists[idx];
+ std::string fn = finfo.fileName().toUtf8().data();
+ bool ok = QFile::remove(finfo.absoluteFilePath());
+ if (ok)
+ {
+ playlists.removeAt(idx);
+ }
+ return ok;
+ }
+ return false;
+}
+
+bool PlaylistsLoader::saveProjectsInPlaylist(int idx, QList<QString>& projects)
+{
+ int count = playlists.size();
+ if (idx < 0 || idx >= count)
+ return false;
+
+ CreatePlaylistParamsContext();
+ if (!pContext)
+ return false;
+
+ std::string tempFilePath = playlists[idx].absoluteFilePath().toUtf8().data();
+ NvParameterized::XmlSerializer serializer(pContext->mTraits);
+ NvFileBuf* stream = new NvFileBufferBase(tempFilePath.c_str(), NvFileBuf::OPEN_WRITE_ONLY);
+ if (!stream || !stream->isOpen())
+ {
+ // file open error
+ if (stream) stream->release();
+ return false;
+ }
+ NvParameterized::Traits* traits = pContext->mTraits;
+ int numObjects = 0;
+ const int kMaxObjects = 1;
+ NvParameterized::Interface* objects[kMaxObjects];
+
+ PlaylistParams* params = new PlaylistParams(traits);
+ objects[numObjects++] = params;
+ NvParameterized::Interface* iface = static_cast<NvParameterized::Interface*>(params);
+
+ if (1)
+ {
+ nvidia::parameterized::PlaylistParams* params = static_cast<nvidia::parameterized::PlaylistParams*>(iface);
+ nvidia::parameterized::PlaylistParamsNS::ParametersStruct& targetDesc = params->parameters();
+
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle("furprojFilePaths", handle) == NvParameterized::ERROR_NONE)
+ {
+ int num = projects.size();
+
+ std::vector<std::string> strArray;
+ const char** strOutput = new const char*[num];
+
+ for (int i = 0; i < num; i++)
+ {
+ std::string proj = projects[i].toUtf8().data();
+ strArray.push_back(proj);
+ strOutput[i] = strArray[i].c_str();
+ }
+
+ handle.resizeArray(num);
+ handle.setParamStringArray(strOutput, num);
+
+ delete[] strOutput;
+ }
+ }
+
+ NV_ASSERT(numObjects <= kMaxObjects);
+ NvParameterized::Serializer::ErrorType serError = NvParameterized::Serializer::ERROR_NONE;
+ bool isUpdate = false;
+ serError = serializer.serialize(*stream, (const NvParameterized::Interface**)&objects[0], numObjects, isUpdate);
+ for (int idx = 0; idx < numObjects; ++idx)
+ {
+ delete objects[idx];
+ }
+ stream->release();
+ ReleasePlaylistParamsContext();
+ return true;
+}
+
+QString PlaylistsLoader::convertToAbsoluteFilePath(QString& filePath)
+{
+ QString fname;
+ bool bCanBeRelativePath = false;
+ bool bAbsPath = (filePath.indexOf(':') >= 0);
+ if (bAbsPath)
+ {
+ if (QFile::exists(filePath))
+ {
+ fname = filePath;
+ }
+ else
+ {
+ viewer_msg(QString(filePath + " does not exist.").toUtf8().data());
+ }
+ std::string tmp2 = fname.toUtf8().data();
+ return fname;
+ }
+ else
+ {
+ QFileInfo fi(mediaPath + "/" + filePath);
+ fname = fi.absoluteFilePath();
+ if (!QFile::exists(fname))
+ {
+ viewer_msg(QString(filePath + " does not exist.").toUtf8().data());
+ fname = "";
+ }
+ std::string tmp2 = fname.toUtf8().data();
+ return fname;
+ }
+}
+
+QString PlaylistsLoader::convertToSaveingFilePath(QString& filePath)
+{
+ QString fname;
+ bool bCanBeRelativePath = false;
+ bool bAbsPath = (filePath.indexOf(':') >= 0);
+ if (bAbsPath)
+ {
+ if (QFile::exists(filePath))
+ {
+ QFileInfo fi(filePath);
+ int pos = fi.absoluteFilePath().indexOf(mediaPath, Qt::CaseInsensitive);
+ if (pos >= 0)
+ {
+ // convert to relative path
+ fname = filePath.right(filePath.size() - (pos + mediaPath.size() + 1));
+ }
+ else
+ {
+ fname = fi.absoluteFilePath();
+ }
+ }
+ else
+ {
+ fname = "";
+ viewer_msg(QString(filePath + " does not exist.").toUtf8().data());
+ }
+ std::string tmp = fname.toUtf8().data();
+ return fname;
+ }
+ // do more try
+ QString tag = "media";
+ int pos = filePath.indexOf(tag, Qt::CaseInsensitive);
+ if (pos >= 0)
+ {
+ fname = filePath.right(filePath.size() - (pos + tag.size() + 1));
+ }
+ else
+ {
+ fname = filePath;
+ }
+ QFileInfo fi(mediaPath + "/" + fname);
+ std::string tmp = fi.absoluteFilePath().toUtf8().data();
+ if (!QFile::exists(fi.absoluteFilePath()))
+ {
+ viewer_msg(QString(filePath + " does not exist.").toUtf8().data());
+ fname = "";
+ }
+ std::string tmp2 = fname.toUtf8().data();
+ return fname;
+}
+
+int PlaylistsLoader::getProjectsInPlaylist(int idx, QList<QString>& projects)
+{
+ projects.clear();
+
+ int count = playlists.size();
+ if (idx < 0 || idx >= count)
+ return 0;
+
+ CreatePlaylistParamsContext();
+ if (!pContext)
+ return 0;
+
+ std::string tempFilePath = playlists[idx].absoluteFilePath().toUtf8().data();
+ NvFileBuf* stream = new NvFileBufferBase(tempFilePath.c_str(), NvFileBuf::OPEN_READ_ONLY);
+ if (!stream || !stream->isOpen())
+ {
+ // file open error
+ if (stream)
+ stream->release();
+ return 0;
+ }
+
+ NvParameterized::Serializer::DeserializedData data;
+ NvParameterized::Serializer::ErrorType serError = NvParameterized::Serializer::ERROR_NONE;
+ NvParameterized::XmlSerializer serializer(pContext->mTraits);
+ bool isUpdated = false;
+ serError = serializer.deserialize(*stream, data, isUpdated);
+ if (data.size() < 1)
+ {
+ if (stream)
+ stream->release();
+ return 0;
+ }
+
+ for (int idx = 0; idx < (int)data.size(); ++idx)
+ {
+ NvParameterized::Interface* iface = data[idx];
+ if (::strcmp(iface->className(), PlaylistParams::staticClassName()) == 0)
+ {
+ nvidia::parameterized::PlaylistParams* params = static_cast<nvidia::parameterized::PlaylistParams*>(iface);
+ nvidia::parameterized::PlaylistParamsNS::ParametersStruct& srcDesc = params->parameters();
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle("furprojFilePaths", handle) == NvParameterized::ERROR_NONE)
+ {
+ int arraySize;
+ handle.getArraySize(arraySize);
+ char** strArray = new char*[arraySize];
+ handle.getParamStringArray(strArray, arraySize);
+ for (int idx = 0; idx < arraySize; ++idx)
+ {
+ QString fileName = PlaylistsLoader::convertToSaveingFilePath(QString(strArray[idx]));
+ if (fileName.size() > 0)
+ {
+ std::string tmp = fileName.toUtf8().data();
+ projects.append(fileName);
+ }
+ }
+ delete[] strArray;
+ }
+ }
+ }
+ stream->release();
+ ReleasePlaylistParamsContext();
+ return projects.size();
+}
+
+bool PlaylistsLoader::add(QString& name)
+{
+ int count = playlists.size();
+ for (int i = 0; i < count; ++i)
+ {
+ QFileInfo& fi = playlists[i];
+ if (fi.baseName().toUpper() == name.toUpper())
+ {
+ return false;
+ }
+ }
+ QFileInfo nfi(projectPath, name + "." + sPlaylistExt);
+ QFile newFile(nfi.absoluteFilePath());
+ if (newFile.exists())
+ {
+ return false;
+ }
+ newFile.open(QIODevice::WriteOnly);
+ newFile.close();
+ bool exist = QFile::exists(nfi.absoluteFilePath());
+ if (!exist)
+ {
+ return false;
+ }
+ playlists.append(nfi);
+ return true;
+} \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.h
new file mode 100644
index 0000000..eb57b12
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.h
@@ -0,0 +1,100 @@
+#ifndef DisplayPreferencesPanel_h__
+#define DisplayPreferencesPanel_h__
+
+#include <QtWidgets/QWidget>
+#include <QtCore/QDir>
+#include <QtCore/QDirIterator>
+#include "TipListView.h"
+#include "ui_DisplayPreferencesPanel.h"
+
+#include "corelib_global.h"
+
+struct PlaylistParamsContext;
+
+class PlaylistsLoader
+{
+public:
+ PlaylistsLoader();
+ ~PlaylistsLoader();
+
+ void loadPlaylistsFromMediaPath();
+ bool rename(int idx, QString& newName);
+ bool remove(int idx);
+ bool add(QString& name);
+ bool saveProjectsInPlaylist(int idx, QList<QString>& projects);
+ int getProjectsInPlaylist(int idx, QList<QString>& projects);
+
+ static QString convertToSaveingFilePath(QString& filePath);
+ static QString convertToAbsoluteFilePath(QString& filePath);
+
+ QList<QFileInfo> playlists;
+ static QString projectPath;
+ static QString mediaPath;
+
+private:
+ void CreatePlaylistParamsContext();
+ void ReleasePlaylistParamsContext();
+ PlaylistParamsContext* pContext;
+};
+
+class DisplayPreferencesPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DisplayPreferencesPanel(QWidget* parent);
+ ~DisplayPreferencesPanel();
+
+ public:
+ void updateValues();
+
+ public slots:
+ CORELIB_EXPORT void on_spinRenderPlayRateFPS_valueChanged(double v);
+ CORELIB_EXPORT void on_spinSimulationRateFPS_valueChanged(double v);
+ CORELIB_EXPORT void on_spinCameraFOV_valueChanged(double v);
+
+ CORELIB_EXPORT void on_cbSceneUnit_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_cbAntialiasing_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_cbUpAxis_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_cbHandedness_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_cbNavigationStyle_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_btnBackgroundTex_clicked();
+ CORELIB_EXPORT void on_btnBackgroundTexClear_clicked();
+
+ CORELIB_EXPORT void on_cbPlaylists_currentIndexChanged(int index);
+ CORELIB_EXPORT void SelectPlayList(QString& name);
+ CORELIB_EXPORT void on_listWidgetPlaylist_itemSelectionChanged();
+ CORELIB_EXPORT void on_listWidgetPlaylist_itemDoubleClicked(QListWidgetItem* pItem);
+ CORELIB_EXPORT void SelectProject(QString& name);
+
+ CORELIB_EXPORT void on_btnPlaylistsRename_clicked();
+ CORELIB_EXPORT void on_btnPlaylistsAdd_clicked();
+ CORELIB_EXPORT void on_btnPlaylistsReload_clicked();
+ CORELIB_EXPORT void on_btnPlaylistsRemove_clicked();
+
+ CORELIB_EXPORT void on_btnPlaylistAddProj_clicked();
+ CORELIB_EXPORT void on_btnPlaylistProjGoUp_clicked();
+ CORELIB_EXPORT void on_btnPlaylistProjGoDown_clicked();
+ CORELIB_EXPORT void on_btnPlaylistRemoveProj_clicked();
+
+ CORELIB_EXPORT void on_btnPlaylistsPlay_clicked();
+ CORELIB_EXPORT void assignPlayPlaylistToGamepad(int idx = -1);
+ CORELIB_EXPORT void playPlaylist(int idx);
+
+ CORELIB_EXPORT void reloadComboxBoxPlaylists();
+ CORELIB_EXPORT void refreshListboxPorjects();
+ CORELIB_EXPORT void reloadListboxPorjectsFromPlayist();
+ CORELIB_EXPORT void savePlaylistProjects();
+
+ CORELIB_EXPORT void runDemoCommandline();
+
+private:
+ Ui::DisplayPreferencesPanel ui;
+ PlaylistsLoader playlistsLoader;
+ QList<QString> playlistProjects;
+ bool playlistProjectsDirty;
+ int idxCurrentPlaylist;
+ int idxCurrentProj;
+};
+
+#endif // DisplayScene_h__
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.cpp
new file mode 100644
index 0000000..b118b6b
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.cpp
@@ -0,0 +1,93 @@
+#include "DisplayScenePanel.h"
+
+#include "AppMainWindow.h"
+
+#include "SimpleScene.h"
+#include "GlobalSettings.h"
+
+DisplayScenePanel::DisplayScenePanel(QWidget* parent)
+ :
+ QWidget(parent)
+{
+ ui.setupUi(this);
+}
+
+void DisplayScenePanel::on_btnVisualizeWind_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_visualizeWind = state;
+}
+
+void DisplayScenePanel::on_btnShowGrid_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showGrid = state;
+}
+
+void DisplayScenePanel::on_btnShowAxis_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showAxis = state;
+}
+
+void DisplayScenePanel::on_btnShowWireframe_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showWireframe = state;
+}
+
+void DisplayScenePanel::on_btnUseLighting_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_useLighting = state;
+}
+
+void DisplayScenePanel::on_cbRenderType_currentIndexChanged(int index)
+{
+ GlobalSettings::Inst().m_renderStyle = index;
+}
+
+void DisplayScenePanel::on_btnShowHUD_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showHUD = state;
+}
+
+void DisplayScenePanel::on_btnComputeStats_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_computeStatistics = state;
+}
+
+void DisplayScenePanel::on_btnComputeProfile_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_computeProfile = state;
+}
+
+void DisplayScenePanel::on_btnShowGraphicsMesh_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showGraphicsMesh = state;
+}
+
+void DisplayScenePanel::on_btnShowSkinnedOnly_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showSkinnedMeshOnly = state;
+ AppMainWindow::Inst().updateUI();
+}
+
+void DisplayScenePanel::on_btnSkinningDQ_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_useDQ = state;
+}
+
+void DisplayScenePanel::on_checkBoxGizmoWithLocal_stateChanged(int state)
+{
+ AppMainWindow::Inst().m_bGizmoWithLocal = state;
+}
+
+void DisplayScenePanel::updateValues()
+{
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ ui.btnShowGrid->setChecked(globalSettings.m_showGrid);
+ ui.btnShowAxis->setChecked(globalSettings.m_showAxis);
+ ui.cbRenderType->setCurrentIndex(globalSettings.m_renderStyle);
+ ui.btnShowHUD->setChecked(globalSettings.m_showHUD);
+ ui.btnComputeStats->setChecked(globalSettings.m_computeStatistics);
+ ui.btnUseLighting->setChecked(globalSettings.m_useLighting);
+ ui.btnShowGraphicsMesh->setChecked( globalSettings.m_showGraphicsMesh);
+ ui.btnShowSkinnedOnly->setChecked( globalSettings.m_showSkinnedMeshOnly);
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.h
new file mode 100644
index 0000000..6614eca
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.h
@@ -0,0 +1,39 @@
+#ifndef DisplayScenePanel_h__
+#define DisplayScenePanel_h__
+
+#include <QtWidgets/QWidget>
+#include "ui_DisplayScenePanel.h"
+
+#include "corelib_global.h"
+
+class DisplayScenePanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DisplayScenePanel(QWidget* parent);
+
+ public:
+ void updateValues();
+
+ public slots:
+ CORELIB_EXPORT void on_btnVisualizeWind_stateChanged(int state);
+ CORELIB_EXPORT void on_btnShowGrid_stateChanged(int state);
+ CORELIB_EXPORT void on_btnShowAxis_stateChanged(int state);
+ CORELIB_EXPORT void on_cbRenderType_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_btnShowWireframe_stateChanged(int state);
+ CORELIB_EXPORT void on_btnShowHUD_stateChanged(int state);
+ CORELIB_EXPORT void on_btnComputeStats_stateChanged(int state);
+ CORELIB_EXPORT void on_btnComputeProfile_stateChanged(int state);
+ CORELIB_EXPORT void on_btnUseLighting_stateChanged(int state);
+ CORELIB_EXPORT void on_btnShowGraphicsMesh_stateChanged(int state);
+ CORELIB_EXPORT void on_btnShowSkinnedOnly_stateChanged(int state);
+ CORELIB_EXPORT void on_btnSkinningDQ_stateChanged(int state);
+ CORELIB_EXPORT void on_checkBoxGizmoWithLocal_stateChanged(int state);
+
+
+private:
+ Ui::DisplayScenePanel ui;
+};
+
+#endif // DisplayScene_h__
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.cpp
new file mode 100644
index 0000000..0fe96d1
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.cpp
@@ -0,0 +1,190 @@
+#include <QtWidgets/QLabel>
+#include <QtGui/QImage>
+#include <QtWidgets/QVBoxLayout>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QPaintEvent>
+#include <QtGui/QPainter>
+#include <QtGui/QPainterPath>
+#include "ExpandablePanel.h"
+#include "Nv.h"
+
+static QImage S_TriangleRight;
+static QImage S_TriangleDown;
+
+void InitTriangleResources(int w, int h)
+{
+ S_TriangleRight = QImage(w, h, QImage::Format_ARGB32);
+ S_TriangleDown = QImage(w, h, QImage::Format_ARGB32);
+
+ S_TriangleRight.fill(QColor(0, 0, 0, 0));
+ S_TriangleDown.fill(QColor(0, 0, 0, 0));
+
+ QPainter painter(&S_TriangleRight);
+ painter.setRenderHints(QPainter::Antialiasing,true);
+
+ QPainterPath path;
+ path.moveTo(0, 0);
+ path.lineTo(w, h>>1);
+ path.lineTo(0, h);
+ path.lineTo(0, 0);
+ painter.setPen(Qt::NoPen);
+ painter.fillPath(path, QBrush(QColor(50, 50, 50)));
+
+ // a painter cannot switch device?
+ QPainter painter2(&S_TriangleDown);
+ painter2.setRenderHint(QPainter::Antialiasing,true);
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(0, 0);
+ path.lineTo(w, 0);
+ path.lineTo(w>>1, h);
+ path.lineTo(0, 0);
+ painter2.setPen(Qt::NoPen);
+ painter2.fillPath(path, QBrush(QColor(50, 50, 50)));
+}
+
+class TitleLabelImpl : public TitleLabel
+{
+ enum
+ {
+ IMAGE_H = 10,
+ IMAGE_W = 10,
+ FIXED_H = 20,
+ };
+
+public:
+ TitleLabelImpl(QWidget* parent, bool collapsed)
+ : TitleLabel(parent)
+ , _collapsed(collapsed)
+ {
+ QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ sizePolicy.setHorizontalStretch(0);
+ sizePolicy.setVerticalStretch(0);
+ sizePolicy.setHeightForWidth(this->sizePolicy().hasHeightForWidth());
+ this->setSizePolicy(sizePolicy);
+ this->setMinimumSize(QSize(0, FIXED_H));
+ this->setMaximumSize(QSize(16777215, FIXED_H));
+ //this->setStyleSheet(QString::fromUtf8("background:rgb(219,219,219);border:1px solid rgb(185,185,185);"));
+ this->setFrameShape(QFrame::NoFrame);
+ this->setFrameShadow(QFrame::Plain);
+ this->setTextFormat(Qt::AutoText);
+ this->setScaledContents(false);
+ this->setAlignment(Qt::AlignCenter);
+
+ if(S_TriangleDown.isNull() || S_TriangleRight.isNull())
+ InitTriangleResources(IMAGE_W, IMAGE_H);
+ }
+
+ void paintEvent(QPaintEvent * e)
+ {
+ QLabel::paintEvent(e);
+
+ QPainter painter(this);
+ painter.setRenderHints(QPainter::Antialiasing,true);
+
+ const int L = 10;
+ const int T = (FIXED_H - IMAGE_H)/2;
+ QRect rc(L, T, IMAGE_W, IMAGE_H);
+
+ // [later] transform the painter should also work;
+ // but i don't get the expected results, so have to use two images
+ if(_collapsed)
+ painter.drawImage(rc, S_TriangleRight);
+ else
+ painter.drawImage(rc, S_TriangleDown);
+
+ }
+
+ bool Collapsed() {return _collapsed;}
+ void SetCollapsed(bool b)
+ {
+ _collapsed = b;
+ this->update();
+ }
+
+protected:
+ virtual void mousePressEvent(QMouseEvent* e)
+ {
+ if(e->buttons() == Qt::LeftButton)
+ {
+ _collapsed = !_collapsed;
+ this->update();
+ emit LPressSignal();
+ }
+ }
+
+private:
+ bool _collapsed;
+};
+
+ExpandablePanel::ExpandablePanel(QWidget* parent, bool collapsed)
+ : QFrame(parent)
+ , _pContent(NV_NULL)
+{
+ //_pContent = new QWidget(this);
+ Init(collapsed);
+}
+
+ExpandablePanel::ExpandablePanel( QWidget* content, QWidget* parent /*= 0*/ )
+ : QFrame(parent)
+ , _pContent(content)
+{
+ Init();
+}
+
+ExpandablePanel::~ExpandablePanel()
+{
+
+}
+
+void ExpandablePanel::SetCollapsed(bool b)
+{
+ if (_pTitle)
+ _pTitle->SetCollapsed(b);
+}
+
+void ExpandablePanel::Init(bool collapsed)
+{
+ setAutoFillBackground(true);
+ setFrameShape(QFrame::StyledPanel);
+ setFrameShadow(QFrame::Sunken);
+ _pMainLayout = new QVBoxLayout(this);
+ _pMainLayout->setSpacing(2);
+ _pMainLayout->setContentsMargins(0, 0, 0, 0);
+ _pMainLayout->setObjectName(QString::fromUtf8("mainLayout"));
+
+ _pTitle = new TitleLabelImpl(this, collapsed);
+ _pTitle->setText("TitleLabel");
+ _pMainLayout->addWidget(_pTitle);
+
+ connect(_pTitle, SIGNAL(LPressSignal()), this, SLOT(TitlePress()));
+
+ if(_pContent)
+ _pMainLayout->addWidget(_pContent);
+}
+
+void ExpandablePanel::SetTitle( const QString& title )
+{
+ _pTitle->setText(title);
+}
+
+void ExpandablePanel::TitlePress()
+{
+ if(_pTitle->Collapsed())
+ {
+ _pContent->hide();
+ }
+ else // expanded
+ {
+ _pContent->show();
+ }
+}
+
+void ExpandablePanel::AddContent( QWidget* content )
+{
+ // only support one widget as content right now
+ if (_pContent != NV_NULL) return;
+
+ _pMainLayout->addWidget(content);
+ _pContent = content;
+}
+
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.h
new file mode 100644
index 0000000..ba3018d
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.h
@@ -0,0 +1,51 @@
+#ifndef ExpandablePanel_h__
+#define ExpandablePanel_h__
+
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QLabel>
+
+#include "corelib_global.h"
+
+class TitleLabelImpl;
+class QString;
+class QVBoxLayout;
+
+class TitleLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+ TitleLabel(QWidget* parent):QLabel(parent){}
+
+signals:
+ void LPressSignal();
+};
+
+class ExpandablePanel : public QFrame
+{
+ Q_OBJECT
+
+public:
+ CORELIB_EXPORT explicit ExpandablePanel(QWidget* parent, bool collapsed = false);
+ explicit ExpandablePanel(QWidget* content, QWidget* parent);
+ virtual ~ExpandablePanel();
+
+ CORELIB_EXPORT void SetTitle(const QString& title);
+ void SetCollapsed(bool b);
+ QWidget* Content() {return _pContent;}
+ CORELIB_EXPORT void AddContent(QWidget* content);
+
+public slots:
+CORELIB_EXPORT void TitlePress();
+
+private:
+ void Init(bool collapsed = false);
+
+private:
+ QVBoxLayout* _pMainLayout;
+ TitleLabelImpl* _pTitle;
+ QWidget* _pContent;
+};
+
+#endif // ExpandablePanel_h__
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/OutputWindow.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/OutputWindow.cpp
new file mode 100644
index 0000000..08867e3
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/OutputWindow.cpp
@@ -0,0 +1,22 @@
+#include "AppMainWindow.h"
+#include "OutputWindow.h"
+
+#include <QtGUI/QContextMenuEvent>
+
+OutputWindow::OutputWindow(QWidget* parent)
+ :
+ QTextBrowser(parent)
+{
+ ui.setupUi(this);
+}
+
+void OutputWindow::contextMenuEvent(QContextMenuEvent *event)
+{
+ QMenu *menu = createStandardContextMenu();
+
+ QAction* act = new QAction("&Clear All", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(clear()));
+ menu->addAction(act);
+ menu->exec(event->globalPos());
+ delete menu;
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/OutputWindow.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/OutputWindow.h
new file mode 100644
index 0000000..5d19bb6
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/OutputWindow.h
@@ -0,0 +1,22 @@
+#ifndef OutputWindow_h__
+#define OutputWindow_h__
+
+#include <QtWidgets/QTextBrowser>
+#include "ui_OutputWindow.h"
+
+#include "UIGlobal.h"
+
+class CORELIB_EXPORT OutputWindow : public QTextBrowser
+{
+ Q_OBJECT
+
+public:
+ OutputWindow(QWidget* parent);
+
+ void contextMenuEvent(QContextMenuEvent *event);
+
+private:
+ Ui::OutputWindow ui;
+};
+
+#endif // DisplayScene_h__
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.cpp
new file mode 100644
index 0000000..b127f1c
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.cpp
@@ -0,0 +1,17 @@
+#include "SlideSpinBox.h"
+
+void SlideSpinBoxSlots::timeout()
+{
+ //qDebug("%s", __FUNCTION__);
+ this->_cb->on_timeout();
+}
+
+void ConfigSpinBoxInt(SlideSpinBoxInt* spinBox, int minv, int maxv, int step)
+{
+ spinBox->blockSignals(true);
+ spinBox->setRange(minv, maxv);
+ spinBox->setSingleStep(step);
+ spinBox->AutoConfigDragRange();
+ spinBox->setKeyboardTracking(false);
+ spinBox->blockSignals(false);
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.h
new file mode 100644
index 0000000..eeb7626
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.h
@@ -0,0 +1,284 @@
+#ifndef SlideSpinBox_h__
+#define SlideSpinBox_h__
+
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QStyleOptionSpinBox>
+#include <QtWidgets/QAbstractSpinBox>
+#include <QtGui/QMouseEvent>
+#include <QtCore/QTimer>
+#include <QtWidgets/QDoubleSpinBox>
+#include <QtWidgets/QSpinBox>
+
+#include "corelib_global.h"
+
+/*
+ A Lesson: never use a template to sub-class QWidgets!
+ Qt doesn't moc template widget classes;
+ So we have to use a specific 'slots-callback' pair to let the moc system work...
+ */
+class SlideSpinBoxCallback
+{
+public:
+ virtual void on_timeout() = 0;
+};
+
+class SlideSpinBoxSlots : public QObject
+{
+ Q_OBJECT
+
+public:
+ SlideSpinBoxSlots(SlideSpinBoxCallback* cb)
+ : _cb (cb)
+ {}
+
+ public slots:
+ CORELIB_EXPORT void timeout();
+
+private:
+ SlideSpinBoxCallback* _cb;
+};
+
+template<typename SpinWidget, typename ValueType>
+class SlideSpinBox : public SpinWidget, public SlideSpinBoxCallback
+{
+
+public:
+ void on_timeout()
+ {
+ //qDebug("%s", __FUNCTION__);
+ EmitDragValueChanged();
+ }
+
+public:
+ typedef ValueType value_type;
+
+ SlideSpinBox(QWidget* parent = 0)
+ : SpinWidget(parent)
+ , _dragRange(DEFAULT_DRAG_RANGE)
+ {
+ setAccelerated(true);
+
+ ResetCustState();
+
+ _pSlots = new SlideSpinBoxSlots(this);
+
+ _dragTimer.setParent(this);
+ _dragTimer.setInterval(DRAG_TIMER_INTERVAL);
+ _dragTimer.setSingleShot(true);
+ connect(&_dragTimer, SIGNAL(timeout()), _pSlots, SLOT(timeout()));
+ }
+
+ ~SlideSpinBox()
+ {
+ delete _pSlots;
+ }
+
+ void SetDragRange(int range)
+ {
+ if(range < MIN_DRAG_RANGE)
+ range = MIN_DRAG_RANGE;
+ else if(range > MAX_DRAG_RANGE)
+ range = MAX_DRAG_RANGE;
+
+ _dragRange = range;
+ }
+
+ void AutoConfigDragRange()
+ {
+ ValueType minv = this->minimum();
+ ValueType maxv = this->maximum();
+
+ double vrange = maxv - minv;
+ double step = 1.0;
+
+ if(vrange <= 1.0)
+ {
+ step = 0.01;
+ }
+ else if(vrange <= 10.0)
+ {
+ step = 0.1;
+ }
+
+ double pixelError = 2.0;
+ double dragRange = vrange * pixelError / step;
+
+ SetDragRange((int)dragRange);
+ }
+
+protected:
+ void mouseMoveEvent ( QMouseEvent * event )
+ {
+ if(!_dragBegin)
+ {
+ QAbstractSpinBox::mouseMoveEvent(event);
+ return;
+ }
+
+ if(!_dragging)
+ {
+ _dragging = true;
+ _cursor = this->cursor();
+
+ this->setCursor(Qt::SizeVerCursor);
+ }
+
+ //if(_dragging)
+ //{
+ // _dragTimer.start(); // always restart, we only need the timeout event;
+ //}
+
+ event->accept();
+ DragValue(event->pos());
+ }
+
+ void mousePressEvent( QMouseEvent * event )
+ {
+ if(event->button() == Qt::LeftButton)
+ {
+ SetupCustState(event);
+ }
+
+ if(_dragging)
+ blockSignals(true);
+ QAbstractSpinBox::mousePressEvent(event);
+ if(_dragging)
+ blockSignals(false);
+ }
+
+ void mouseReleaseEvent( QMouseEvent * event )
+ {
+ if(_dragging)
+ {
+ setCursor(_cursor);
+ _dragTimer.stop();
+ }
+
+ QAbstractSpinBox::mouseReleaseEvent(event);
+ //if(_dragBegin)
+ // EmitDragValueChanged();
+
+ ResetCustState();
+ }
+
+ void timerEvent(QTimerEvent *event)
+ {
+ if(_dragging)
+ {
+ // stop timer event to disable acceleration/auto-stepping
+ event->ignore();
+ return;
+ }
+
+ event->accept();
+
+ if(_dragBegin) blockSignals(true);
+ QAbstractSpinBox::timerEvent(event);
+ if(_dragBegin) blockSignals(false);
+ }
+
+private:
+ enum
+ {
+ MIN_DRAG_RANGE = 50,
+ MAX_DRAG_RANGE = 500,
+
+ DEFAULT_DRAG_RANGE = 100,
+
+ DRAG_TIMER_INTERVAL= 30, // in msec
+ };
+
+ bool SetupCustState(QMouseEvent* event)
+ {
+ QStyleOptionSpinBox opt;
+ this->initStyleOption(&opt);
+ QStyle::SubControl hitControl = this->style()->hitTestComplexControl(QStyle::CC_SpinBox, &opt, event->pos());
+ if(hitControl != QStyle::SC_SpinBoxUp && hitControl != QStyle::SC_SpinBoxDown)
+ return false;
+
+ _pressPosition = event->pos();
+ _dragging = false;
+ _dragBegin = true;
+ _pressValue = this->value();
+ _dragValue = this->value();
+
+ return true;
+ }
+
+ void ResetCustState()
+ {
+ _dragBegin = false;
+ _dragging = false;
+ }
+
+ void DragValue(const QPoint& pos)
+ {
+ ValueType valueRange = this->maximum() - this->minimum();
+
+ double dh = (double)(_pressPosition.y() - pos.y());
+ double dv = valueRange * dh / (double)_dragRange;
+ ValueType v = _pressValue + (ValueType)dv;
+
+ //blockSignals(true);
+ setValue(v);
+ //blockSignals(false);
+ }
+
+ void EmitDragValueChanged()
+ {
+ //if(this->value() != _pressValue) // value are always bound by qt (and decimal settings)
+ if(this->value() != _dragValue)
+ {
+ _dragValue = this->value();
+ emit valueChanged(this->value());
+ }
+ }
+
+ int _dragRange;
+
+ QPoint _pressPosition;
+ ValueType _pressValue;
+ ValueType _dragValue;
+
+ bool _dragging;
+ bool _dragBegin;
+ QCursor _cursor;
+
+ QTimer _dragTimer;
+ SlideSpinBoxSlots* _pSlots;
+};
+
+typedef SlideSpinBox<QDoubleSpinBox, double> SlideSpinBoxF;
+typedef SlideSpinBox<QSpinBox, int> SlideSpinBoxInt;
+
+template<typename CustSpinBox>
+class ConfigSpinBox
+{
+public:
+ typedef typename CustSpinBox::value_type ValueType;
+
+ ConfigSpinBox(CustSpinBox* spinBox, ValueType minv, ValueType maxv, ValueType step = (ValueType)1)
+ {
+ spinBox->blockSignals(true);
+ spinBox->setRange(minv, maxv);
+ spinBox->setSingleStep(step);
+ spinBox->AutoConfigDragRange();
+ spinBox->setKeyboardTracking(false);
+ SpecificConfig<ValueType>(spinBox);
+ spinBox->blockSignals(false);
+ }
+
+ template<typename T>
+ void SpecificConfig(CustSpinBox* spinBox){}
+
+ template<>
+ void SpecificConfig<double>(CustSpinBox* spinBox)
+ {
+ spinBox->setDecimals(2.0);
+ }
+};
+
+#include "corelib_global.h"
+CORELIB_EXPORT void ConfigSpinBoxInt(SlideSpinBoxInt* spinBox, int minv, int maxv, int step = (int)1);
+
+#endif // SlideSpinBox_h__
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBoxInt.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBoxInt.h
new file mode 100644
index 0000000..393adee
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/SlideSpinBoxInt.h
@@ -0,0 +1,15 @@
+#ifndef SlideSpinBoxInt_h__
+#define SlideSpinBoxInt_h__
+
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QStyleOptionSpinBox>
+#include <QtWidgets/QAbstractSpinBox>
+#include <QtGui/QMouseEvent>
+#include <QtCore/QTimer>
+#include <QtWidgets/QDoubleSpinBox>
+#include <QtWidgets/QSpinBox>
+#include <SlideSpinBox.h>
+
+// use this header as a trick to make moc work right
+
+#endif // SlideSpinBoxInt_h__
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/TipListView.cpp b/NvBlast/tools/ArtistTools/source/CoreLib/Window/TipListView.cpp
new file mode 100644
index 0000000..b91fd3e
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/TipListView.cpp
@@ -0,0 +1,42 @@
+#include "TipListView.h"
+#include <QtWidgets/QToolTip>
+#include <QtCore/QEvent>
+#include <QtGUI/QEvent.h>
+
+
+TipListView::TipListView(QWidget* parent)
+ :QListWidget(parent)
+{
+}
+
+void TipListView::setTips(QStringList& tips)
+{
+ mTips = tips;
+}
+
+bool TipListView::event(QEvent *evt)
+{
+ if (evt->type() == QEvent::ToolTip)
+ {
+ if (mTips.size() > 0)
+ {
+ QHelpEvent *helpEvent = (QHelpEvent *)(evt);
+ const QPoint& pos = helpEvent->pos();
+ QListWidgetItem* pItem = itemAt(pos);
+ int index = 0, num = count();
+ for (int i = 0; i < num; ++i)
+ {
+ QListWidgetItem* pi = item(i);
+ if (pi == pItem && mTips.size() > i)
+ {
+ QToolTip::showText(helpEvent->globalPos(), mTips[i]);
+ return true;
+ }
+ }
+ }
+ //QToolTip::hideText();
+ //evt->ignore();
+ //return true;
+ }
+ return QListWidget::event(evt);
+}
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/TipListView.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/TipListView.h
new file mode 100644
index 0000000..6913baa
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/TipListView.h
@@ -0,0 +1,26 @@
+#ifndef TipListView_h__
+#define TipListView_h__
+
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QListWidget>
+#include <QtCore/QEvent>
+
+#include "corelib_global.h"
+
+class TipListView : public QListWidget
+{
+ Q_OBJECT
+
+public:
+ TipListView(QWidget* parent = 0);
+
+ void setTips(QStringList& tips);
+
+protected:
+ bool event(QEvent *);
+private:
+
+ QStringList mTips;
+
+};
+#endif // TipListView_h__
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/Window/UIGlobal.h b/NvBlast/tools/ArtistTools/source/CoreLib/Window/UIGlobal.h
new file mode 100644
index 0000000..3d50132
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/Window/UIGlobal.h
@@ -0,0 +1,37 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#define USE_MATERIAL_SET 1
+#define USE_CURVE_EDITOR 0
+#define USE_TEXTURE_BRIGHTNESS 0
+
+#define USE_INTERNAL_GRAPHICAL_MATERIAL 0
+
+#include "corelib_global.h" \ No newline at end of file
diff --git a/NvBlast/tools/ArtistTools/source/CoreLib/corelib_global.h b/NvBlast/tools/ArtistTools/source/CoreLib/corelib_global.h
new file mode 100644
index 0000000..b3c0016
--- /dev/null
+++ b/NvBlast/tools/ArtistTools/source/CoreLib/corelib_global.h
@@ -0,0 +1,20 @@
+#ifndef CORELIB_GLOBAL_H
+#define CORELIB_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+#include <Nv/NvBlastCommon.h>
+
+#ifdef CORELIB_LIB
+# define CORELIB_EXPORT Q_DECL_EXPORT
+#else
+# define CORELIB_EXPORT Q_DECL_IMPORT
+#endif
+
+#pragma warning(disable:4018)
+#pragma warning(disable:4099)
+#pragma warning(disable:4101)
+#pragma warning(disable:4267)
+#pragma warning(disable:4273)
+#pragma warning(disable:4996)
+
+#endif // CORELIB_GLOBAL_H
diff --git a/NvBlast/tools/AuthoringTool/src/AuthoringTool.cpp b/NvBlast/tools/AuthoringTool/src/AuthoringTool.cpp
new file mode 100644
index 0000000..4898d3b
--- /dev/null
+++ b/NvBlast/tools/AuthoringTool/src/AuthoringTool.cpp
@@ -0,0 +1,403 @@
+#include "PxPhysicsAPI.h"
+#include "PxAllocatorCallback.h"
+#include "PxErrorCallback.h"
+#include "PsFileBuffer.h"
+#include "NvBlast.h"
+#include "NvBlastExtAuthoringCollisionBuilder.h"
+#include "NvBlastExtSerializationLLInterface.h"
+#include "NvBlastExtSerializationInterface.h"
+#include "NvBlastExtAuthoringBondGenerator.h"
+#include "NvBlastExtAuthoringFractureTool.h"
+#include "NvBlastExtAuthoringMesh.h"
+#include "SimpleRandomGenerator.h"
+#include "FbxFileReader.h"
+#include "ObjFileReader.h"
+#include "FractureProcessor.h"
+#include "FbxFileWriter.h"
+#include "ObjFileWriter.h"
+#include "BlastDataExporter.h"
+#include <string>
+#include <iostream>
+#include <vector>
+#include <cctype>
+#include <fstream>
+#include <iosfwd>
+#include <Windows.h>
+#include "tclap/CmdLine.h"
+
+using physx::PxVec3;
+using physx::PxVec2;
+
+#define DEFAULT_ASSET_NAME "AuthoringTest"
+
+
+using namespace Nv::Blast;
+
+struct TCLAPint3
+{
+ int32_t x, y, z;
+ TCLAPint3(int32_t x, int32_t y, int32_t z) :x(x), y(y), z(z){};
+ TCLAPint3() :x(0), y(0), z(0){};
+ TCLAPint3& operator=(const std::string &inp)
+ {
+ std::istringstream stream(inp);
+ if (!(stream >> x >> y >> z))
+ throw TCLAP::ArgParseException(inp + " is not int3");
+ return *this;
+ }
+};
+
+namespace TCLAP {
+ template<>
+ struct ArgTraits<TCLAPint3> {
+ typedef StringLike ValueCategory;
+ };
+}
+
+bool isDirectoryExist(std::string path)
+{
+ DWORD attributes = GetFileAttributesA(path.c_str());
+ if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ return true;
+ }
+ return false;
+}
+
+bool mkDirRecursively(std::string path)
+{
+ if (isDirectoryExist(path))
+ {
+ return true;
+ }
+ auto indx = path.find_first_of("\\/");
+ while (indx != std::string::npos)
+ {
+ std::string subfolder = path.substr(0, indx);
+ CreateDirectory(subfolder.c_str(), NULL);
+ indx = path.find_first_of("\\/", indx + 1);
+ }
+ return isDirectoryExist(path);
+}
+
+int main(int argc, const char* const* argv)
+{
+ // setup cmd line
+ TCLAP::CmdLine cmd("Blast SDK: Authoring Tool", ' ', "0.1");
+
+ TCLAP::UnlabeledValueArg<std::string> infileArg("file", "File to load", true, "", "infile");
+ cmd.add(infileArg);
+
+ TCLAP::UnlabeledValueArg<std::string> outAssetName("outAssetName", "Output asset name", true, DEFAULT_ASSET_NAME, "output asset name");
+ cmd.add(outAssetName);
+
+ TCLAP::ValueArg<std::string> outDirArg("", "outputDir", "Output directory", false, ".", "by default directory of the input file");
+ cmd.add(outDirArg);
+
+ // The output modes
+ //NOTE: Fun TCLAP quirk here - if you set the default to true and specify this switch on the command line, the value will be false!
+ TCLAP::SwitchArg bpxaOutputArg("", "bpxa", "Output ExtPxAsset to the output directory (ext: bpxa)", false);
+ cmd.add(bpxaOutputArg);
+
+ TCLAP::SwitchArg tkOutputArg("", "tk", "Output TkAsset to the output directory (ext: tkasset)", false);
+ cmd.add(tkOutputArg);
+
+ TCLAP::SwitchArg llOutputArg("", "ll", "Output LL Blast asset to the output directory (ext: llasset)", false);
+ cmd.add(llOutputArg);
+
+ TCLAP::SwitchArg ue4OutputArg("", "ue4", "Output FBX with UE4 coordinate system", false);
+ cmd.add(ue4OutputArg);
+
+ TCLAP::SwitchArg fbxAsciiArg("", "fbxascii", "Output FBX as an ascii file (defaults to binary output)", false);
+ cmd.add(fbxAsciiArg);
+
+ TCLAP::SwitchArg objOutputArg("", "obj", "Output a OBJ mesh to the output directory", false);
+ cmd.add(objOutputArg);
+
+ TCLAP::SwitchArg fbxOutputArg("", "fbx", "Output a FBX mesh to the output directory", false);
+ cmd.add(fbxOutputArg);
+
+ TCLAP::SwitchArg protoSer("", "proto", "Serialize Blast data with CapnProto", false);
+ cmd.add(protoSer);
+
+ TCLAP::SwitchArg blockSer("", "block", "Serialize Blast data as block of memory", false);
+ cmd.add(blockSer);
+
+
+
+
+ TCLAP::ValueArg<unsigned char> fracturingMode("", "mode", "Fracturing mode", false, 'v', "v - voronoi, c - clustered voronoi, s - slicing.");
+ cmd.add(fracturingMode);
+ TCLAP::ValueArg<uint32_t> cellsCount("", "cells", "Voronoi cells count", false, 5, "by default 5");
+ cmd.add(cellsCount);
+ TCLAP::ValueArg<uint32_t> clusterCount("", "clusters", "Uniform Voronoi cluster count", false, 5, "by default 5");
+ cmd.add(clusterCount);
+ TCLAP::ValueArg<float> clusterRad("", "radius", "Clustered Voronoi cluster radius", false, 1.0f, "by default 1.0");
+ cmd.add(clusterRad);
+
+ TCLAP::ValueArg<TCLAPint3> slicingNumber("", "slices", "Number of slices per direction", false, TCLAPint3(1, 1, 1), "by default 1 1 1");
+ cmd.add(slicingNumber);
+
+ TCLAP::ValueArg<float> angleVariation("", "avar", "Slicing angle variation", false, 0.0, "by default 0.0");
+ cmd.add(angleVariation);
+
+ TCLAP::ValueArg<float> offsetVariation("", "ovar", "Slicing offset variation", false, 0.0, "by default 0.0");
+ cmd.add(offsetVariation);
+
+ try
+ {
+ // parse cmd input
+ cmd.parse(argc, argv);
+ }
+ catch (TCLAP::ArgException &e) // catch any exceptions
+ {
+ std::cout << "error: " << e.error() << " for arg " << e.argId() << std::endl;
+ return -1;
+ }
+
+ // get cmd parse results
+ std::string infile = infileArg.getValue();
+
+ std::string outDir;
+
+
+ if (outDirArg.isSet())
+ {
+ outDir = outDirArg.getValue();
+ std::string temp = outDir + '/';
+ if (!isDirectoryExist(outDir.data()))
+ {
+ std::cout << "Output directory doesn't exist. It will be created." << std::endl;
+ if (!mkDirRecursively(temp.data()))
+ {
+ std::cout << "Directory creation failed!" << std::endl;
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ auto idx = infile.find_last_of("/\\");
+ if (idx == 0 || idx == std::string::npos)
+ {
+ outDir = ".";
+ }
+ else
+ {
+ outDir = infile.substr(0, idx);
+ }
+ }
+ std::string assetName = outAssetName.getValue();
+
+ // Determine whether to use the obj or fbx loader
+
+ auto idx = infile.rfind('.');
+ std::string extension;
+
+
+ if (idx != std::string::npos)
+ {
+ extension = infile.substr(idx + 1);
+ std::transform(extension.begin(), extension.end(), extension.begin(), std::toupper);
+ }
+ else
+ {
+ std::cout << "Can't determine extension (and thus, loader) of input file. " << infile << std::endl;
+ return -1;
+ }
+
+ bool bOutputBPXA = bpxaOutputArg.getValue();
+ bool bOutputTK = tkOutputArg.getValue();
+ bool bOutputLL = llOutputArg.getValue();
+
+ bool bUE4CoordSystem = ue4OutputArg.getValue();
+ bool bOutputFBXAscii = fbxAsciiArg.getValue();
+
+ bool bOutputObjFile = objOutputArg.isSet();
+ bool bOutputFbxFile = fbxOutputArg.isSet();
+
+ bool bOutputProtobufSer = protoSer.isSet();
+ bool bOutputBlockSer = blockSer.isSet();
+
+
+ // Did we specify no output formats?
+ if (!bpxaOutputArg.isSet() && !tkOutputArg.isSet() && !llOutputArg.isSet())
+ {
+ std::cout << "Didn't specify an output format on the command line, so defaulting to outputting BPXA" << std::endl;
+ bOutputBPXA = true;
+ }
+ // Did we specify no geometry output formats?
+ if (!bOutputObjFile && !bOutputFbxFile)
+ {
+ std::cout << "Didn't specify an output geometry format on the command line, so defaulting to outputting .FBX" << std::endl;
+ bOutputFbxFile = true;
+ }
+ // Did we specify no serialization type?
+ if (!bOutputBlockSer && !bOutputProtobufSer)
+ {
+ std::cout << "Didn't specify an serialization type on the command line, so defaulting to block serialization type" << std::endl;
+ bOutputBlockSer = true;
+ }
+
+ std::shared_ptr<IMeshFileReader> fileReader;
+
+ if (extension.compare("FBX")==0)
+ {
+ fileReader = std::make_shared<FbxFileReader>();
+ }
+ else if (extension.compare("OBJ")==0)
+ {
+ fileReader = std::make_shared<ObjFileReader>();
+ }
+ else
+ {
+ std::cout << "Unsupported file extension " << extension << std::endl;
+ return -1;
+ }
+
+ fileReader->setConvertToUE4(bUE4CoordSystem);
+
+ // Load the asset
+ std::shared_ptr<Mesh> loadedMesh = fileReader->loadFromFile(infile);
+
+ if (loadedMesh == nullptr)
+ {
+ std::cout << "Failed to load mesh " << infile << std::endl;
+ return -1;
+ }
+
+ // Send it to the fracture processor
+ FractureProcessor processor;
+ FractureSettings settings;
+ settings.mode = fracturingMode.getValue();
+ settings.cellsCount = cellsCount.getValue();
+ settings.clusterCount = clusterCount.getValue();
+ settings.slicingX = slicingNumber.getValue().x;
+ settings.slicingY = slicingNumber.getValue().y;
+ settings.slicingZ = slicingNumber.getValue().z;
+ settings.angleVariation = angleVariation.getValue();
+ settings.offsetVariation = offsetVariation.getValue();
+ settings.clusterRadius = clusterRad.getValue();
+
+ std::shared_ptr<FractureResult> result = processor.fractureMesh(loadedMesh, settings);
+
+ // Output the results
+ // NOTE: Writing to FBX by default.
+ std::shared_ptr<IMeshFileWriter> fileWriter;
+
+
+ auto assetLL = result->resultPhysicsAsset->getTkAsset().getAssetLL();
+
+
+ if (bOutputObjFile)
+ {
+ if (bUE4CoordSystem)
+ {
+ std::cout << "OBJ output doesn't support UE4 coordinate conversion." << std::endl;
+ }
+ fileWriter = std::make_shared<ObjFileWriter>();
+ bool writeResult = fileWriter->saveToFile(assetLL, result->resultGeometry, assetName, outDir);
+ if (!writeResult)
+ {
+ std::cerr << "Can't write geometry to OBJ file." << std::endl;
+ return -1;
+ }
+ }
+ if (bOutputFbxFile)
+ {
+ fileWriter = std::make_shared<FbxFileWriter>();
+ fileWriter->setConvertToUE4(bUE4CoordSystem);
+ {
+ auto fbxWriter = static_cast<FbxFileWriter *>(fileWriter.get());
+ fbxWriter->bOutputFBXAscii = bOutputFBXAscii;
+ }
+
+ bool writeResult = fileWriter->saveToFile(assetLL, result->resultGeometry, assetName, outDir);
+ if (!writeResult)
+ {
+ std::cerr << "Can't write geometry to FBX file." << std::endl;
+ return -1;
+ }
+ }
+
+ if (bOutputProtobufSer)
+ {
+ if (bOutputBPXA)
+ {
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << "/" << assetName << ".pbpxa";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+
+ std::ofstream myFile(outBlastFilePath, std::ios::out | std::ios::binary);
+
+ setPhysXSDK(processor.getPhysics());
+
+ serializeExtPxAssetIntoStream(result->resultPhysicsAsset.get(), myFile);
+
+ myFile.flush();
+
+ std::cout << "Wrote ExtPxAsset to " << outBlastFilePath << std::endl;
+ }
+
+ if (bOutputTK)
+ {
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << "/" << assetName << ".ptkasset";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+
+ std::ofstream myFile(outBlastFilePath, std::ios::out | std::ios::binary);
+
+ serializeTkAssetIntoStream(&result->resultPhysicsAsset->getTkAsset(), myFile);
+
+ myFile.flush();
+
+ std::cout << "Wrote TkAsset to " << outBlastFilePath << std::endl;
+ }
+
+ if (bOutputLL)
+ {
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << "/" << assetName << ".pllasset";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+
+ std::ofstream myFile(outBlastFilePath, std::ios::out | std::ios::binary);
+
+ serializeAssetIntoStream(result->resultPhysicsAsset->getTkAsset().getAssetLL(), myFile);
+
+ myFile.flush();
+
+ std::cout << "Wrote NvBlastAsset to " << outBlastFilePath << std::endl;
+ }
+ }
+
+ if (bOutputBlockSer)
+ {
+ BlastDataExporter blExpr(NvBlastTkFrameworkGet(), processor.getCooking(), NvBlastTkFrameworkGet()->getLogFn());
+ if (bOutputLL)
+ {
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << "/" << assetName << ".llasset";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+ blExpr.saveBlastLLAsset(outBlastFilePath, result->resultPhysicsAsset->getTkAsset().getAssetLL());
+ std::cout << "Wrote NvBlastAsset to " << outBlastFilePath << std::endl;
+ }
+ if (bOutputTK)
+ {
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << "/" << assetName << ".tkasset";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+ blExpr.saveBlastTkAsset(outBlastFilePath, &result->resultPhysicsAsset->getTkAsset());
+ std::cout << "Wrote TkAsset to " << outBlastFilePath << std::endl;
+ }
+ if (bOutputBPXA)
+ {
+ std::ostringstream outBlastFilePathStream;
+ outBlastFilePathStream << outDir << "/" << assetName << ".bpxa";
+ std::string outBlastFilePath = outBlastFilePathStream.str();
+ blExpr.saveBlastExtAsset(outBlastFilePath, result->resultPhysicsAsset.get());
+ std::cout << "Wrote ExtPxAsset to " << outBlastFilePath << std::endl;
+ }
+ }
+
+ return 0;
+}
diff --git a/NvBlast/tools/AuthoringTool/src/FractureProcessor.cpp b/NvBlast/tools/AuthoringTool/src/FractureProcessor.cpp
new file mode 100644
index 0000000..75307d9
--- /dev/null
+++ b/NvBlast/tools/AuthoringTool/src/FractureProcessor.cpp
@@ -0,0 +1,264 @@
+#include "FractureProcessor.h"
+#include "NvBlastExtAuthoringCollisionBuilder.h"
+#include <iostream>
+#include "PxPhysicsAPI.h"
+#include "NvBlastTkFramework.h"
+#include "NvBlastExtAuthoringFractureTool.h"
+#include "SimpleRandomGenerator.h"
+#include "NvBlastExtAuthoringBondGenerator.h"
+#include "NvBlastTypes.h"
+#include "NvBlastIndexFns.h"
+#include "NvBlast.h"
+#include <ctime>
+using namespace Nv::Blast;
+
+void loggingCallback(int type, const char* msg, const char* file, int line)
+{
+ (void)type;
+
+ std::cout << msg << " FILE:" << file << " Line: " << line << "\n";
+}
+
+
+FractureProcessor::FractureProcessor()
+{
+ initPhysX();
+
+ Nv::Blast::TkFrameworkDesc frameworkDesc =
+ {
+ &g_errorCallback,
+ &g_allocator
+ };
+
+ framework = NvBlastTkFrameworkCreate(frameworkDesc);
+ if (framework == nullptr)
+ {
+ std::cout << "Failed to create TkFramework" << std::endl;
+ return;
+ }
+}
+
+FractureProcessor::~FractureProcessor()
+{
+ releasePhysX();
+
+ if (framework != nullptr)
+ {
+ framework->release();
+ }
+}
+
+void FractureProcessor::buildPhysicsChunks(const std::vector<std::vector<Nv::Blast::Triangle>>& chunkGeometry, std::vector<Nv::Blast::ExtPxAssetDesc::ChunkDesc>& outPhysicsChunks, std::vector<Nv::Blast::ExtPxAssetDesc::SubchunkDesc>& outPhysicsSubchunks)
+{
+ Nv::Blast::ConvexMeshBuilder collisionBuilder(cooking, &physics->getPhysicsInsertionCallback());
+
+ outPhysicsChunks.resize(chunkGeometry.size());
+ outPhysicsSubchunks.resize(chunkGeometry.size());
+
+ for (uint32_t i = 0; i < chunkGeometry.size(); ++i)
+ {
+ std::vector<physx::PxVec3> vertices;
+ for (uint32_t p = 0; p < chunkGeometry[i].size(); ++p)
+ {
+ vertices.push_back(chunkGeometry[i][p].a.p);
+ vertices.push_back(chunkGeometry[i][p].b.p);
+ vertices.push_back(chunkGeometry[i][p].c.p);
+ }
+ outPhysicsSubchunks[i].transform = physx::PxTransform(physx::PxIdentity);
+ outPhysicsSubchunks[i].geometry = physx::PxConvexMeshGeometry(collisionBuilder.buildConvexMesh(vertices));
+ outPhysicsChunks[i].isStatic = false;
+ outPhysicsChunks[i].subchunkCount = 1;
+ outPhysicsChunks[i].subchunks = &outPhysicsSubchunks[i];
+ }
+
+}
+
+std::shared_ptr<FractureResult> FractureProcessor::fractureMesh(std::shared_ptr<Nv::Blast::Mesh> sourceMesh, const FractureSettings &settings)
+{
+ // Create FractureTool
+
+ std::cout << "Fracture tool initialization" << std::endl;
+
+ std::vector<NvBlastChunkDesc> chunkDesc;
+ std::vector<NvBlastBondDesc> bondDescs;
+ std::vector<std::vector<Nv::Blast::Triangle> > chunkMeshes;
+ std::vector<bool> isSupport;
+
+ Nv::Blast::FractureTool fTool(loggingCallback);
+
+ fTool.setSourceMesh(sourceMesh.get());
+ SimpleRandomGenerator rnd;
+ rnd.seed((int32_t)time(nullptr)); // Keep the same seed to have reproducible results.
+
+ std::cout << "Fracturing..." << std::endl;
+ VoronoiSitesGenerator stGenerator(sourceMesh.get(), &rnd);
+ switch (settings.mode)
+ {
+ case 'c':
+ stGenerator.clusteredSitesGeneration(settings.clusterCount, settings.cellsCount, settings.clusterRadius);
+ fTool.voronoiFracturing(0, stGenerator.getVoronoiSites(), false);
+ break;
+ case 's':
+ {
+ SlicingConfiguration slConfig;
+ slConfig.x_slices = settings.slicingX;
+ slConfig.y_slices = settings.slicingY;
+ slConfig.z_slices = settings.slicingZ;
+ slConfig.angle_variations = settings.angleVariation;
+ slConfig.offset_variations = settings.offsetVariation;
+ fTool.slicing(0, slConfig, false, &rnd);
+ break;
+ }
+ case 'v':
+ stGenerator.uniformlyGenerateSitesInMesh(settings.cellsCount);
+ fTool.voronoiFracturing(0, stGenerator.getVoronoiSites(), false);
+ break;
+ default:
+ std::cout << "Not supported mode" << std::endl;
+ return nullptr;
+ }
+ std::cout << "Creating geometry" << std::endl;
+ fTool.finalizeFracturing();
+
+ chunkMeshes.resize(fTool.getChunkList().size());
+ isSupport.resize(fTool.getChunkList().size());
+ for (uint32_t i = 0; i < fTool.getChunkList().size(); ++i)
+ {
+ fTool.getBaseMesh(i, chunkMeshes[i]);
+ isSupport[i] = fTool.getChunkList()[i].isLeaf;
+
+ }
+
+
+ BlastBondGenerator bondGenerator(cooking, &physics->getPhysicsInsertionCallback());
+
+ BondGenerationConfig cnf;
+ cnf.bondMode = BondGenerationConfig::EXACT;
+
+ bondGenerator.buildDescFromInternalFracture(&fTool, isSupport, bondDescs, chunkDesc);
+
+// const uint32_t chunkCount = static_cast<uint32_t>(chunkDesc.size());
+ const uint32_t bondCount = static_cast<uint32_t>(bondDescs.size());
+ if (bondCount == 0)
+ {
+ std::cout << "Can't create bonds descriptors..." << std::endl;
+ return nullptr;
+ }
+
+ return finalizeMeshProcessing(chunkDesc, bondDescs, chunkMeshes);
+}
+
+std::shared_ptr<FractureResult> FractureProcessor::finalizeMeshProcessing(std::vector<NvBlastChunkDesc> chunkDesc, std::vector<NvBlastBondDesc> bondDescs, std::vector<std::vector<Nv::Blast::Triangle> > chunkMeshes)
+{
+ const uint32_t chunkCount = static_cast<uint32_t>(chunkDesc.size());
+ const uint32_t bondCount = static_cast<uint32_t>(bondDescs.size());
+
+ // order chunks, build map
+ std::vector<uint32_t> chunkReorderInvMap;
+ {
+ std::vector<uint32_t> chunkReorderMap(chunkCount);
+ std::vector<char> scratch(chunkCount * sizeof(NvBlastChunkDesc));
+ NvBlastEnsureAssetExactSupportCoverage(chunkDesc.data(), chunkCount, scratch.data(), loggingCallback);
+ NvBlastBuildAssetDescChunkReorderMap(chunkReorderMap.data(), chunkDesc.data(), chunkCount, scratch.data(), loggingCallback);
+ NvBlastApplyAssetDescChunkReorderMapInplace(chunkDesc.data(), chunkCount, bondDescs.data(), bondCount, chunkReorderMap.data(), scratch.data(), loggingCallback);
+ chunkReorderInvMap.resize(chunkReorderMap.size());
+ Nv::Blast::invertMap(chunkReorderInvMap.data(), chunkReorderMap.data(), static_cast<unsigned int>(chunkReorderMap.size()));
+ }
+
+ std::shared_ptr<FractureResult> result = std::make_shared<FractureResult>();
+
+ // get result geometry
+
+ result->resultGeometry.resize(chunkMeshes.size());
+ //std::vector<std::vector<Triangle>> resultGeometry(chunkMeshes.size());
+ for (uint32_t i = 0; i < chunkMeshes.size(); ++i)
+ {
+ uint32_t chunkIndex = chunkReorderInvMap[i];
+ result->resultGeometry[i] = chunkMeshes[chunkIndex];
+ }
+
+ float maxX = INT32_MIN;
+ float maxY = INT32_MIN;
+ float maxZ = INT32_MIN;
+
+ float minX = INT32_MAX;
+ float minY = INT32_MAX;
+ float minZ = INT32_MAX;
+
+ for (uint32_t i = 0; i < bondDescs.size(); i++)
+ {
+ NvBlastBondDesc bondDesc = bondDescs[i];
+
+ minX = std::min(minX, bondDesc.bond.centroid[0]);
+ maxX = std::max(maxX, bondDesc.bond.centroid[0]);
+
+ minY = std::min(minY, bondDesc.bond.centroid[1]);
+ maxY = std::max(maxY, bondDesc.bond.centroid[1]);
+
+ minZ = std::min(minZ, bondDesc.bond.centroid[2]);
+ maxZ = std::max(maxZ, bondDesc.bond.centroid[2]);
+ }
+
+ std::cout << "Bond bounds: " << std::endl;
+ std::cout << "MIN: " << minX << ", " << minY << ", " << minZ << std::endl;
+ std::cout << "MAX: " << maxX << ", " << maxY << ", " << maxZ << std::endl;
+
+ // prepare physics data (convexes)
+ std::vector<Nv::Blast::ExtPxAssetDesc::ChunkDesc> physicsChunks(chunkCount);
+ std::vector<Nv::Blast::ExtPxAssetDesc::SubchunkDesc> physicsSubchunks;
+ buildPhysicsChunks(result->resultGeometry, physicsChunks, physicsSubchunks);
+
+ // build and serialize ExtPhysicsAsset
+ Nv::Blast::ExtPxAssetDesc descriptor;
+ descriptor.bondCount = bondCount;
+ descriptor.bondDescs = bondDescs.data();
+ descriptor.chunkCount = chunkCount;
+ descriptor.chunkDescs = chunkDesc.data();
+ descriptor.bondFlags = nullptr;
+ descriptor.pxChunks = physicsChunks.data();
+
+ result->resultPhysicsAsset = std::shared_ptr<Nv::Blast::ExtPxAsset>(Nv::Blast::ExtPxAsset::create(descriptor, *framework), [=](Nv::Blast::ExtPxAsset* asset)
+ {
+ asset->release();
+ });
+
+ std::cout << "Done" << std::endl;
+
+ return result;
+}
+
+bool FractureProcessor::initPhysX()
+{
+ foundation = PxCreateFoundation(PX_FOUNDATION_VERSION, g_allocator, g_errorCallback);
+ if (!foundation)
+ {
+ std::cout << "Can't init PhysX foundation" << std::endl;
+ return false;
+ }
+ physx::PxTolerancesScale scale;
+ physics = PxCreatePhysics(PX_PHYSICS_VERSION, *foundation, scale, true);
+ if (!physics)
+ {
+ std::cout << "Can't create Physics" << std::endl;
+ return false;
+ }
+ physx::PxCookingParams cookingParams(scale);
+ cookingParams.buildGPUData = true;
+ cooking = PxCreateCooking(PX_PHYSICS_VERSION, physics->getFoundation(), cookingParams);
+ if (!cooking)
+ {
+ std::cout << "Can't create Cooking" << std::endl;
+ return false;
+ }
+ return true;
+}
+
+void FractureProcessor::releasePhysX()
+{
+ cooking->release();
+ cooking = 0;
+ physics->release();
+ physics = 0;
+ foundation->release();
+ foundation = 0;
+}
diff --git a/NvBlast/tools/AuthoringTool/src/FractureProcessor.h b/NvBlast/tools/AuthoringTool/src/FractureProcessor.h
new file mode 100644
index 0000000..8b8fefe
--- /dev/null
+++ b/NvBlast/tools/AuthoringTool/src/FractureProcessor.h
@@ -0,0 +1,64 @@
+#pragma once
+#include <vector>
+#include "NvBlastExtAuthoringTypes.h"
+#include "PxFoundation.h"
+#include "PxPhysics.h"
+#include "PxCooking.h"
+#include "PxDefaultAllocator.h"
+#include "PxDefaultErrorCallback.h"
+#include <memory>
+#include "NvBlastExtAuthoringMesh.h"
+#include "NvBlastExtAuthoringBondGenerator.h"
+#include "NvBlastTypes.h"
+#include "NvBlastExtPxAsset.h"
+
+struct FractureResult
+{
+ std::vector<std::vector<Nv::Blast::Triangle>> resultGeometry;
+ std::shared_ptr<Nv::Blast::ExtPxAsset> resultPhysicsAsset;
+};
+
+struct FractureSettings
+{
+ unsigned char mode;
+ uint32_t cellsCount;
+ uint32_t clusterCount;
+ float clusterRadius;
+ int32_t slicingX;
+ int32_t slicingY;
+ int32_t slicingZ;
+ float angleVariation;
+ float offsetVariation;
+};
+
+class FractureProcessor
+{
+public:
+ FractureProcessor();
+ ~FractureProcessor();
+
+
+ std::shared_ptr<FractureResult> fractureMesh(std::shared_ptr<Nv::Blast::Mesh> sourceMesh, const FractureSettings &settings);
+
+
+ physx::PxPhysics* getPhysics() { return physics; }
+ physx::PxCooking* getCooking() { return cooking; }
+private:
+ physx::PxFoundation* foundation = nullptr;
+ physx::PxPhysics* physics = nullptr;
+ physx::PxCooking* cooking = nullptr;
+
+ Nv::Blast::TkFramework* framework = nullptr;
+
+ physx::PxDefaultAllocator g_allocator;
+ physx::PxDefaultErrorCallback g_errorCallback;
+
+
+ void buildPhysicsChunks(const std::vector<std::vector<Nv::Blast::Triangle>>& chunkGeometry, std::vector<Nv::Blast::ExtPxAssetDesc::ChunkDesc>& outPhysicsChunks,
+ std::vector<Nv::Blast::ExtPxAssetDesc::SubchunkDesc>& outPhysicsSubchunks);
+
+ std::shared_ptr<FractureResult> finalizeMeshProcessing(std::vector<NvBlastChunkDesc> chunkDesc, std::vector<NvBlastBondDesc> bondDescs, std::vector<std::vector<Nv::Blast::Triangle> > chunkMeshes);
+
+ bool initPhysX();
+ void releasePhysX();
+};
diff --git a/NvBlast/tools/AuthoringTool/src/SimpleRandomGenerator.h b/NvBlast/tools/AuthoringTool/src/SimpleRandomGenerator.h
new file mode 100644
index 0000000..63e2d45
--- /dev/null
+++ b/NvBlast/tools/AuthoringTool/src/SimpleRandomGenerator.h
@@ -0,0 +1,27 @@
+#pragma once
+#include "NvBlastExtAuthoringTypes.h"
+
+
+class SimpleRandomGenerator : public Nv::Blast::RandomGeneratorBase
+{
+public:
+ SimpleRandomGenerator() {
+ remember = false;
+ };
+
+ virtual float getRandomValue()
+ {
+ float r = (float)rand();
+ r = r / RAND_MAX;
+ return r;
+ }
+ virtual void seed(int32_t seed)
+ {
+ srand(seed);
+ }
+
+ virtual ~SimpleRandomGenerator() {};
+
+private:
+ bool remember;
+}; \ No newline at end of file
diff --git a/NvBlast/tools/CMakeLists.txt b/NvBlast/tools/CMakeLists.txt
new file mode 100644
index 0000000..39894ae
--- /dev/null
+++ b/NvBlast/tools/CMakeLists.txt
@@ -0,0 +1,95 @@
+cmake_minimum_required(VERSION 3.3)
+
+project(BlastTools CXX)
+
+CMAKE_POLICY(SET CMP0057 NEW) # Enable IN_LIST
+
+IF(NOT DEFINED BLAST_ROOT_DIR)
+
+ STRING(REPLACE "\\" "/" BRD_TEMP $ENV{BLAST_ROOT_DIR})
+
+ # This env variable is set by GenerateProjects.bat, and is no longer available when CMake rebuilds, so this stores it in the cache
+ SET(BLAST_ROOT_DIR ${BRD_TEMP} CACHE INTERNAL "Root of the Blast source tree")
+
+ENDIF()
+
+IF(NOT EXISTS ${BLAST_ROOT_DIR})
+ MESSAGE(FATAL_ERROR "BLAST_ROOT_DIR environment variable wasn't set or was invalid.")
+ENDIF()
+
+
+SET(GW_DEPS_ROOT $ENV{PM_PACKAGES_ROOT})
+
+# Add the project specific CMake modules to the module path
+LIST(APPEND CMAKE_MODULE_PATH ${BLAST_ROOT_DIR}/sdk/compiler/cmake/modules/)
+
+IF(NOT DEFINED CMAKEMODULES_VERSION)
+ SET(CMAKEMODULES_VERSION $ENV{PM_CMakeModules_VERSION} CACHE INTERNAL "CMakeModules version from generation batch")
+ENDIF()
+
+#TODO: More elegance
+IF(NOT EXISTS ${GW_DEPS_ROOT}/CMakeModules/${CMAKEMODULES_VERSION})
+ MESSAGE(FATAL_ERROR "Could not find CMakeModules at ${GW_DEPS_ROOT}")
+ENDIF()
+
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${GW_DEPS_ROOT}/CMakeModules/${CMAKEMODULES_VERSION}")
+
+MESSAGE("Module path:" ${CMAKE_MODULE_PATH})
+
+
+IF(CMAKE_CONFIGURATION_TYPES)
+ SET(CMAKE_CONFIGURATION_TYPES debug profile checked release)
+ SET(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
+ "Reset config to what we need"
+ FORCE)
+
+ SET(CMAKE_SHARED_LINKER_FLAGS_CHECKED "")
+ SET(CMAKE_SHARED_LINKER_FLAGS_PROFILE "")
+
+ SET(CMAKE_EXE_LINKER_FLAGS_CHECKED "")
+ SET(CMAKE_EXE_LINKER_FLAGS_PROFILE "")
+
+ENDIF()
+
+# Default to appending "DEBUG", "PROFILE", etc to produced artifacts
+IF(NOT DEFINED APPEND_CONFIG_NAME)
+ SET(APPEND_CONFIG_NAME ON)
+ENDIF()
+
+IF (APPEND_CONFIG_NAME)
+ MESSAGE("Appending config to output names")
+
+ SET(CMAKE_DEBUG_POSTFIX "DEBUG")
+ SET(CMAKE_PROFILE_POSTFIX "PROFILE")
+ SET(CMAKE_CHECKED_POSTFIX "CHECKED")
+ SET(CMAKE_RELEASE_POSTFIX "")
+ENDIF()
+
+INCLUDE(SetOutputPaths)
+
+# Either have to define a single output path, or each one.
+
+IF(NOT DEFINED BL_OUTPUT_DIR)
+ IF (NOT DEFINED BL_LIB_OUTPUT_DIR)
+ MESSAGE(FATAL_ERROR "BL_LIB_OUTPUT_DIR not defined - Define either BL_OUTPUT_DIR or BL_LIB_OUTPUT_DIR and BL_DLL_OUTPUT_DIR and BL_EXE_OUTPUT_DIR")
+ ENDIF()
+
+ IF (NOT DEFINED BL_DLL_OUTPUT_DIR)
+ MESSAGE(FATAL_ERROR "BL_DLL_OUTPUT_DIR not defined - Define either BL_OUTPUT_DIR or BL_LIB_OUTPUT_DIR and BL_DLL_OUTPUT_DIR and BL_EXE_OUTPUT_DIR")
+ ENDIF()
+
+ IF (NOT DEFINED BL_EXE_OUTPUT_DIR)
+ MESSAGE(FATAL_ERROR "BL_EXE_OUTPUT_DIR not defined - Define either BL_OUTPUT_DIR or BL_LIB_OUTPUT_DIR and BL_DLL_OUTPUT_DIR and BL_EXE_OUTPUT_DIR")
+ ENDIF()
+
+ SetLibOutputPath(${BL_LIB_OUTPUT_DIR})
+ SetDllOutputPath(${BL_DLL_OUTPUT_DIR})
+ SetExeOutputPath(${BL_EXE_OUTPUT_DIR})
+ELSE()
+ SetSingleOutputPath(${BL_OUTPUT_DIR})
+ENDIF()
+
+SET(PROJECT_CMAKE_FILES_DIR compiler/cmake/)
+
+# Include the platform specific configuration
+INCLUDE(${PROJECT_CMAKE_FILES_DIR}${TARGET_BUILD_PLATFORM}/CMakeLists.txt OPTIONAL)
diff --git a/NvBlast/tools/CurveEditor/source/Attribute.h b/NvBlast/tools/CurveEditor/source/Attribute.h
new file mode 100644
index 0000000..c8af7f7
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Attribute.h
@@ -0,0 +1,109 @@
+#ifndef ATTRIBUTE_H__
+#define ATTRIBUTE_H__
+
+#include "Curve.h"
+#include <vector>
+
+namespace nvidia {
+namespace CurveEditor {
+
+class CurveEditorMainWindow;
+
+enum CurveAttributeType
+{
+ eSingleAttr,
+ eGroupAttr,
+ eColorAttr,
+};
+
+class CURVEEDITOR_EXPORT CurveAttributeBase
+{
+ friend class CurveEditorMainWindow;
+public:
+ std::string getName() const { return _name; }
+ CurveAttributeType getType() const { return _type; }
+
+ inline bool canMoveControlPointHorizontally() { return _canMoveControlPointHorizontally; }
+ inline bool canAddRemoveControlPoint() { return _canAddRemoveControlPoint; }
+ inline bool canChangeTangentType() { return _canChangeTangentType; }
+
+protected:
+ CurveAttributeBase(const std::string& name, CurveAttributeType type, bool canMoveControlPointHorizontally = false, bool canAddRemoveControlPoint = false, bool canChangeTangentType = false)
+ : _name(name)
+ , _type(type)
+ , _canMoveControlPointHorizontally(canMoveControlPointHorizontally)
+ , _canAddRemoveControlPoint(canAddRemoveControlPoint)
+ , _canChangeTangentType(canChangeTangentType)
+ {
+ }
+
+protected:
+ std::string _name;
+ CurveAttributeType _type;
+ bool _canMoveControlPointHorizontally;
+ bool _canAddRemoveControlPoint;
+ bool _canChangeTangentType;
+};
+
+class CURVEEDITOR_EXPORT CurveAttribute : public CurveAttributeBase
+{
+public:
+ CurveAttribute()
+ : CurveAttributeBase("", eSingleAttr)
+ {
+ }
+
+ CurveAttribute(const std::string& name, bool canMoveControlPointHorizontally = false, bool canAddRemoveControlPoint = false, bool canChangeTangentType = false)
+ : CurveAttributeBase(name, eSingleAttr, canMoveControlPointHorizontally, canAddRemoveControlPoint, canChangeTangentType)
+ {
+ }
+
+ CurveAttribute(const CurveAttribute& attr)
+ : CurveAttributeBase(attr._name, eSingleAttr)
+ {
+ }
+
+ ~CurveAttribute()
+ {
+ }
+
+ QColor color;
+ Curve curve;
+};
+
+class CURVEEDITOR_EXPORT CurveAttributeGroup : public CurveAttributeBase
+{
+public:
+ CurveAttributeGroup(std::string name, bool canMoveControlPointHorizontally = false, bool canAddRemoveControlPoint = false, bool canChangeTangentType = false)
+ : CurveAttributeBase(name, eGroupAttr, canMoveControlPointHorizontally, canAddRemoveControlPoint, canChangeTangentType)
+ {
+ }
+
+ std::vector<CurveAttribute*> attributes;
+};
+
+class CURVEEDITOR_EXPORT ColorAttribute : public CurveAttributeBase
+{
+ friend class CurveEditor;
+public:
+ ColorAttribute()
+ : CurveAttributeBase("", eSingleAttr)
+ , useAlphaFromColor(false)
+ {
+ }
+
+ ColorAttribute(const std::string& name, bool canMoveControlPointHorizontally = false, bool canAddRemoveControlPoint = false, bool canChangeTangentType = false)
+ : CurveAttributeBase(name, eColorAttr, canMoveControlPointHorizontally, canAddRemoveControlPoint, canChangeTangentType)
+ , useAlphaFromColor(false)
+ {
+ }
+
+ ColorCurve colorCurve;
+ ColorCurve alphaCurve;
+ bool useAlphaFromColor;
+};
+
+} // namespace CurveEditor
+} // namespace nvidia
+
+#endif // ATTRIBUTE_H__
diff --git a/NvBlast/tools/CurveEditor/source/Common.h b/NvBlast/tools/CurveEditor/source/Common.h
new file mode 100644
index 0000000..43038fd
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Common.h
@@ -0,0 +1,10 @@
+#ifndef CURVEEDITOR_COMMON_H
+#define CURVEEDITOR_COMMON_H
+
+#ifdef CURVEEDITOR_LIB
+# define CURVEEDITOR_EXPORT Q_DECL_EXPORT
+#else
+# define CURVEEDITOR_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif
diff --git a/NvBlast/tools/CurveEditor/source/Curve.h b/NvBlast/tools/CurveEditor/source/Curve.h
new file mode 100644
index 0000000..a070fb5
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Curve.h
@@ -0,0 +1,204 @@
+#ifndef CURVE_H
+#define CURVE_H
+#include <QtCore/QPointF>
+#include <QtGui/QColor>
+#include <vector>
+#include "Common.h"
+
+namespace nvidia {
+namespace CurveEditor {
+
+enum InterpolateMode
+{
+ eDiscret,
+ eLinear,
+ eBezierSpline,
+ eCatmullRomSpline,
+};
+
+struct BezierSplineData
+{
+ float inTan;
+ float inLen;
+ float outTan;
+ float outLen;
+};
+
+struct ControlPoint
+{
+ ControlPoint()
+ : value(0, 0)
+ , mode (eDiscret)
+ {
+ memset( &splineData, 0, sizeof(BezierSplineData));
+ }
+
+ ControlPoint(float inX, float inY, InterpolateMode inMode)
+ : value(inX, inY)
+ , mode(inMode)
+ {
+ memset( &splineData, 0, sizeof(BezierSplineData));
+ }
+
+ ControlPoint(float inX, float inY, InterpolateMode inMode, BezierSplineData& inSplineData)
+ : value(inX, inY)
+ , mode(inMode)
+ , splineData(inSplineData)
+ {
+
+ }
+
+ QPointF value;
+ InterpolateMode mode;
+ BezierSplineData splineData;
+};
+
+class CURVEEDITOR_EXPORT Curve
+{
+ friend class CurveWidget;
+ friend class CurveEntity;
+public:
+ Curve(long segmentCount = 100);
+
+ void initValueRange(const QPointF& min, const QPointF& max);
+ QPointF getMinValue();
+ QPointF getMaxValue();
+
+ int getControlPointCount() { return (int) _controlPoints.size(); }
+ const ControlPoint& getControlPoint(int index) { return _controlPoints[index]; }
+ void appendControlPoint(ControlPoint& controlPoint, bool asDefaultToo = true);
+ int appendControlPoint(float x);
+ void setControlPoint(int index, const ControlPoint& point);
+ void reset(void);
+ void insertControlPointAt(int index);
+ void removeControlPoint(int index);
+ void removeControlPoints(std::vector<int>& indexes);
+
+ QPointF getPointByX(float x);
+ std::vector<QPointF> getSamplePoints();
+ Curve resampleCurve(int resamplePnts, long segmentCount = 100);
+
+ Curve& operator = (const Curve& right);
+
+private:
+ void _sample();
+ ControlPoint& _getNearCtrlPnt(float x);
+
+private:
+ bool _needSample;
+ bool _initValueRange;
+ QPointF _minValue;
+ QPointF _maxValue;
+ long _segmentCount;
+ std::vector<QPointF> _samplePoints;
+ std::vector<ControlPoint> _controlPoints;
+ std::vector<ControlPoint> _defaultControlPoints;
+};
+
+struct ColorControlPoint
+{
+ ColorControlPoint()
+ : x(0.0)
+ , color()
+ , mode (eDiscret)
+ , weight(0.5f)
+ , fallOff(0.5f)
+ , texturePath()
+ {
+ memset( &splineData, 0, sizeof(BezierSplineData));
+ }
+
+ ColorControlPoint(float inX, const QColor& inColor, InterpolateMode inMode, float inWeight = 0.5f, float inFallOff = 0.5f)
+ : x(inX)
+ , color(inColor)
+ , mode(inMode)
+ , weight(inWeight)
+ , fallOff(inFallOff)
+ , texturePath()
+ {
+ memset( &splineData, 0, sizeof(BezierSplineData));
+ }
+
+ ColorControlPoint(float inX, const QColor& inColor, InterpolateMode inMode, const BezierSplineData& inSplineData, float inWeight = 0.5f, float inFallOff = 0.5f)
+ : x(inX)
+ , color(inColor)
+ , mode(inMode)
+ , splineData(inSplineData)
+ , weight(inWeight)
+ , fallOff(inFallOff)
+ , texturePath()
+ {
+
+ }
+
+ float x;
+ QColor color;
+ InterpolateMode mode;
+ BezierSplineData splineData;
+ float weight; // if it's less than 0, the segememnt between this control point and next control point won't use weight algorithm
+ float fallOff;
+ std::string texturePath;
+ QColor textureAverageColor;
+};
+
+struct ColorPoint
+{
+ ColorPoint()
+ : x(0.0)
+ , color()
+ {
+ }
+
+ ColorPoint(float inX, const QColor& inColor)
+ : x(inX)
+ , color(inColor)
+ {
+ }
+
+ float x;
+ QColor color;
+};
+
+class ColorWidget;
+class CURVEEDITOR_EXPORT ColorCurve
+{
+ friend class ColorWidget;
+public:
+ ColorCurve(long segmentCount = 100);
+
+ void initValueRange(float min, float max);
+ float getMinValue();
+ float getMaxValue();
+
+ int getControlPointCount() { return (int) _controlPoints.size(); }
+ const ColorControlPoint& getControlPoint(int index) { return _controlPoints[index]; }
+ void appendControlPoint(ColorControlPoint& controlPoint, bool asDefaultToo = true);
+ void setControlPoint(int index, const ColorControlPoint& point);
+ void reset(void);
+ void insertControlPointAt(int index);
+ void removeControlPoint(int index);
+
+ QColor getColorByX(float x);
+
+ ColorCurve& operator = (const ColorCurve& right);
+
+private:
+ void _doSamplePoints();
+ void _reOrderControlPoints(int& pickedPoint);
+ QColor _calcTextureAverageColor(const char* texturePath);
+
+private:
+ bool _needSample;
+ bool _initValueRange;
+ float _minValue;
+ float _maxValue;
+ long _segmentCount;
+ std::vector<ColorPoint> _colorSamplePnts;
+ std::vector<ColorControlPoint> _controlPoints;
+ std::vector<ColorControlPoint> _defaultControlPoints;
+};
+
+} // namespace CurveEditor
+} // namespace nvidia
+
+#endif // CURVE_H
diff --git a/NvBlast/tools/CurveEditor/source/CurveEditorMainWindow.h b/NvBlast/tools/CurveEditor/source/CurveEditorMainWindow.h
new file mode 100644
index 0000000..1ae9092
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/CurveEditorMainWindow.h
@@ -0,0 +1,217 @@
+#ifndef CURVEEDITOR_H
+#define CURVEEDITOR_H
+
+#include <QtWidgets/QMainWindow>
+#include <QtWidgets/QTreeWidget>
+#include <QtXml\QtXml>
+#include "Attribute.h"
+
+namespace Ui {
+ class CurveEditorMainWindow;
+}
+
+namespace nvidia {
+namespace CurveEditor {
+
+class CurveWidget;
+class CurveEntity;
+class ColorWidget;
+
+class CURVEEDITOR_EXPORT CurveEditorMainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+ friend class CurveWidget;
+ friend class CurveEntity;
+ friend class ColorWidget;
+
+public:
+ explicit CurveEditorMainWindow(QWidget *parent = 0);
+ ~CurveEditorMainWindow();
+
+ void setCurveAttributes(const std::vector<CurveAttributeBase*>& attributes);
+ void setColorCurveAttributes(const std::vector<ColorAttribute*>& attributes);
+ // if this method is called, tab widget switch to curve attribute tab
+ void setSelectedCurveAttributes(const std::vector<CurveAttributeBase*>& attributes);
+ // if this method is called, tab widget switch to color attribute tab
+ void setSelectedColorAttribute(const ColorAttribute* attribute);
+ void setResampleEnabled(bool enable);
+
+signals:
+ void CurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute);
+ void ColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute);
+ // if reloadColorTex is true, reload texture of the selected control point of the color curve of the color attribute
+ // if reloadColorTex is false, reload texture of the selected control point of the alpha curve of the color attribute
+ // selectedCtrlPntIndex index of the selected control point
+ void ReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex);
+
+private slots:
+ /////////////////////////slots for signals of standard QT controls//////////////////////////////////////////////////////
+ void on_actionCopy_triggered();
+
+ void on_actionPaste_triggered();
+
+ void on_actionSave_Selected_as_Preset_triggered();
+
+ void on_actionLoad_Preset_to_Copy_Buffer_triggered();
+
+ void on_actionImport_Preset_onto_Selected_triggered();
+
+ void on_actionReset_Curve_triggered();
+
+ void on_actionAdd_Before_Selected_triggered();
+
+ void on_actionAdd_After_Selected_triggered();
+
+ void on_actionRemove_Selected_triggered();
+
+ void on_actionTangent_Stepped_triggered();
+
+ void on_actionTangent_Linear_triggered();
+
+ void on_actionTangent_Smooth_triggered();
+
+ void on_actionTangent_Ease_Out_triggered();
+
+ void on_actionTangent_Ease_In_triggered();
+
+ void on_actionTangent_Spline_triggered();
+
+ void on_actionSnap_All_triggered();
+
+ void on_actionSnap_Horizontal_triggered();
+
+ void on_actionSnap_Vertical_triggered();
+
+ void on_actionContract_Horizontally_triggered();
+
+ void on_actionExpand_Horizontally_triggered();
+
+ void on_actionContract_Vertically_triggered();
+
+ void on_actionExpand_Vertically_triggered();
+
+ void on_actionFrame_Horizontally_triggered();
+
+ void on_actionFrame_Vertically_triggered();
+
+ void on_actionFrame_All_triggered();
+
+ void on_spinBoxLocation_valueChanged(double value);
+
+ void on_spinBoxValue_valueChanged(double value);
+
+ void on_btnColor_clicked();
+
+ void on_btnColorTex_clicked();
+
+ void on_btnColorReload_clicked();
+
+ void on_btnColorClear_clicked();
+
+ void on_btnAlpha_clicked();
+
+ void on_btnAlphaTex_clicked();
+
+ void on_btnAlphaReload_clicked();
+
+ void on_btnAlphaClear_clicked();
+
+ void on_checkBoxUseAlphaChannellFromColor_stateChanged(int val);
+
+ void on_treeWidgetCurveAttributes_itemSelectionChanged();
+
+ void on_treeWidgetColorAttributes_itemSelectionChanged();
+
+ void on_tabWidgetAttributes_currentChanged(int index);
+
+ void on_sliderColorFallOff_sliderMoved(int value);
+
+ void on_sliderAlphaFallOff_sliderMoved(int value);
+
+ void on_actionAdd_Control_Point_By_Click_triggered(bool val);
+
+ void on_actionRemove_Control_Point_By_Click_triggered(bool val);
+
+ /////////////////////////slots for inside signals//////////////////////////////////////////////////////
+ void onCurvePickedControlPointChanged(const std::vector<CurveEntity*>& pickedCurves);
+
+ void onCurvePickedControlPointValueChanged(QPointF& value);
+
+ void onColorPickedControlPointChanged(bool isColorCtrlPnt);
+
+private:
+ class CurveAttributeTreeItem : public QTreeWidgetItem
+ {
+ public:
+ explicit CurveAttributeTreeItem(QTreeWidget *view, CurveAttributeBase* attribute)
+ : QTreeWidgetItem(view)
+ , _attribute(attribute)
+ {
+
+ }
+ explicit CurveAttributeTreeItem(QTreeWidgetItem *parent, CurveAttributeBase* attribute)
+ : QTreeWidgetItem(parent)
+ , _attribute(attribute)
+ {
+
+ }
+
+ CurveAttributeBase* _attribute;
+ };
+
+ class ColorAttributeTreeItem : public QTreeWidgetItem
+ {
+ public:
+ explicit ColorAttributeTreeItem(QTreeWidget *view, ColorAttribute* attribute)
+ : QTreeWidgetItem(view)
+ , _attribute(attribute)
+ {
+
+ }
+
+ ColorAttribute* _attribute;
+ };
+
+private:
+ void _fillCurveAttributesTree();
+ void _fillColorAttributesTree();
+ void _syncUIStatusWithSelectedAttribute(bool canAddRemoveControlPoint, bool canChangeTangentType);
+ void _setCurveExclusiveUIEnable(bool enable);
+ void _setColorUIEnable(bool enable);
+ void _setAlphaUIEnable(bool enable);
+ void _saveAttributeGroup(QDomElement& parentElm, CurveAttributeGroup* attributeGroup);
+ void _saveAttribute(QDomElement& parentElm, CurveAttribute* attribute);
+ void _saveAttribute(QDomElement& parentElm, ColorAttribute* attribute);
+ void _saveCurve(QDomElement& parentElm, Curve& curve);
+ void _saveCurve(QDomElement& parentElm, ColorCurve& curve, const QString& curveName);
+ void _saveCtrlPnt(QDomElement& parentElm, const ControlPoint& ctrlPnt);
+ void _saveCtrlPnt(QDomElement& parentElm, const ColorControlPoint& ctrlPnt);
+ CurveAttributeBase* _loadAttribute(QDomElement& elm);
+ void _loadCurve(QDomElement& elm, Curve& curve);
+ void _loadCurve(QDomElement& elm, ColorCurve& curve);
+ void _loadCtrlPnt(QDomElement& elm, ControlPoint& ctrlPnt);
+ void _loadCtrlPnt(QDomElement& elm, ColorControlPoint& ctrlPnt);
+
+ void _setTangentTypeUIStatus(bool enable);
+ void _setAddRemoveCtrlPntUIStatus(bool enable);
+
+ Ui::CurveEditorMainWindow* ui;
+ std::vector<CurveAttributeBase*> _curveAttributes;
+ std::vector<ColorAttribute*> _colorAttributes;
+ CurveWidget* _curveWidget;
+ ColorWidget* _colorWidget;
+ CurveAttribute* _curveAttributeCache; // for copy operation of curve attribute
+ ColorAttribute* _colorAttributeCache; // for copy operation of color attribute
+ bool _updateUIFromData;
+ bool _canMoveCurveControlPointHorizontally;
+ bool _canAddRemoveCurveControlPoint;
+ bool _canChangeCurveTangentType;
+ QString _lastFilePath;
+ QString _presetPath;
+};
+
+} // namespace CurveEditor
+} // namespace nvidia
+
+#endif // CURVEEDITOR_H
diff --git a/NvBlast/tools/CurveEditor/source/GraphEditorTestApp/CurveEditorTestApp.cpp b/NvBlast/tools/CurveEditor/source/GraphEditorTestApp/CurveEditorTestApp.cpp
new file mode 100644
index 0000000..9aa42bd
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/GraphEditorTestApp/CurveEditorTestApp.cpp
@@ -0,0 +1,342 @@
+#include "CurveEditorTestApp.h"
+#include "ui_CurveEditorTestApp.h"
+#include "CurveEditorMainWindow.h"
+#include <QtCore/QDebug>
+
+CurveEditorTestApp::CurveEditorTestApp(QWidget *parent, Qt::WindowFlags flags)
+ : QWidget(parent, flags)
+ , ui(new Ui::CurveEditorTestAppClass())
+ , _curveEditor(new CurveEditorMainWindow(this))
+{
+ ui->setupUi(this);
+
+ bool val = connect(_curveEditor, SIGNAL(CurveAttributeChanged(nvidia::CurveEditor::CurveAttribute*)), this, SLOT(onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute*)));
+ val = connect(_curveEditor, SIGNAL(ColorAttributeChanged(nvidia::CurveEditor::ColorAttribute*)), this, SLOT(onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute*)) );
+ val = connect(_curveEditor, SIGNAL(ReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute*, bool, int)), this, SLOT(onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute*, bool, int)) );
+
+ _curveEditor->hide();
+
+ _fillCurveAttributes();
+ _fillColorAttributes();
+}
+
+CurveEditorTestApp::~CurveEditorTestApp()
+{
+
+}
+
+void CurveEditorTestApp::on_btnCurveEditor_clicked(void)
+{
+ _curveEditor->show();
+}
+
+void CurveEditorTestApp::onCurveAttributeChanged(CurveAttribute* attribute)
+{
+ if (attribute)
+ {
+ qDebug()<<"-------------------------onCurveAttributeChanged---------------------------------";
+ qDebug()<< attribute->getName().c_str() <<": changed";
+
+ size_t count = attribute->curve.getControlPointCount();
+ for (int i = 0; i < count; ++i)
+ {
+ const ControlPoint& ctrlPnt = attribute->curve.getControlPoint(i);
+ if (attribute->getName() == "Y" && i == 9 && ctrlPnt.value.y() > 2.5)
+ {
+ int j = 0;
+ ++j;
+ }
+ qDebug()<< ctrlPnt.value;
+ }
+ }
+}
+
+void CurveEditorTestApp::onColorAttributeChanged(ColorAttribute* attribute)
+{
+ if (attribute)
+ {
+ qDebug()<<"----------------------------------------------------------";
+ qDebug()<< attribute->getName().c_str() <<": changed";
+ }
+}
+
+void CurveEditorTestApp::onReloadColorAttributeTexture(ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex)
+{
+ if (attribute)
+ {
+ qDebug()<<"----------------------------------------------------------";
+ qDebug()<< attribute->getName().c_str() <<": reloadColorTex" << reloadColorTex<< " selectedCtrlPntIndex: "<< selectedCtrlPntIndex;
+ }
+}
+
+void CurveEditorTestApp::_fillCurveAttributes()
+{
+ {
+ std::vector<CurveAttributeBase*> attributes;
+
+ CurveAttributeGroup* attrGroup = new CurveAttributeGroup("Position");
+ attributes.push_back(attrGroup);
+
+ CurveAttribute* attribute = new CurveAttribute("X", false, true, true);
+ //attribute->color = QColor(0x11, 0x22, 0x33, 0x44);//
+ attribute->color = QColor("#FF0000");
+ attrGroup->attributes.push_back(attribute);
+
+ {
+ Curve& curve = attribute->curve;
+ curve.initValueRange(QPointF(-1, 0), QPointF(6, 1));
+ curve.appendControlPoint(ControlPoint(-1, 1, eDiscret));
+ curve.appendControlPoint(ControlPoint(0, 0, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(0.25, 0.5, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(0.5, 0, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(0.75, 0.5, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(1, 0, eCatmullRomSpline));
+ {
+ BezierSplineData splineData;
+ splineData.inLen = 0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ControlPoint(2, 1, eBezierSpline, splineData));
+ splineData.inLen = 0.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ControlPoint(3, 0, eBezierSpline, splineData));
+ splineData.inLen = 1.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ControlPoint(4, 1, eBezierSpline, splineData));
+ }
+ curve.appendControlPoint(ControlPoint(5, 0, eLinear));
+ curve.appendControlPoint(ControlPoint(6, 1, eLinear));
+ }
+
+ attribute = new CurveAttribute("Y", true);
+ attribute->color = QColor("#FFFF00");
+ attrGroup->attributes.push_back(attribute);
+ {
+ Curve& curve = attribute->curve;
+ curve.initValueRange(QPointF(-2, 0), QPointF(8, 2));
+ curve.appendControlPoint(ControlPoint(-2, 2, eDiscret));
+ curve.appendControlPoint(ControlPoint(1, 0, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(1.25, 0.5, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(1.5, 0, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(1.75, 0.5, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(2, 0, eCatmullRomSpline));
+ {
+ BezierSplineData splineData;
+ splineData.inLen = 0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ControlPoint(3, 1, eBezierSpline, splineData));
+ splineData.inLen = 0.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ControlPoint(4, 0, eBezierSpline, splineData));
+ splineData.inLen = 1.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ControlPoint(5, 1, eBezierSpline, splineData));
+ }
+ curve.appendControlPoint(ControlPoint(6, 0, eLinear));
+ curve.appendControlPoint(ControlPoint(8, 2, eLinear));
+ }
+
+ attribute = new CurveAttribute("Z", true);
+ attribute->color = QColor("#00FF00");
+ attrGroup->attributes.push_back(attribute);
+ {
+ Curve& curve = attribute->curve;
+ curve.initValueRange(QPointF(-2, 0), QPointF(8, 4));
+ curve.appendControlPoint(ControlPoint(-2, 2, eDiscret));
+ curve.appendControlPoint(ControlPoint(1, 0, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(1.5, 4, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(1.75, 0.5, eCatmullRomSpline));
+ curve.appendControlPoint(ControlPoint(2, 1, eCatmullRomSpline));
+ {
+ BezierSplineData splineData;
+ splineData.inLen = 0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ControlPoint(3, 3, eBezierSpline, splineData));
+ splineData.inLen = 0.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ControlPoint(4, 0, eBezierSpline, splineData));
+ splineData.inLen = 1.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ControlPoint(5, 2, eBezierSpline, splineData));
+ }
+ curve.appendControlPoint(ControlPoint(6, 0, eLinear));
+ curve.appendControlPoint(ControlPoint(8, 4, eLinear));
+ }
+
+ attribute = new CurveAttribute("AddRemove_ChangeTangent", true, true, true);
+
+ attributes.push_back(attribute);
+
+ {
+ Curve& curve = attribute->curve;
+ curve.initValueRange(QPointF(-1, 0), QPointF(4, 255));
+ curve.appendControlPoint(ControlPoint(-1, 0, eLinear));
+ {
+ BezierSplineData splineData;
+ splineData.inLen = 1.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ControlPoint(4, 255, eBezierSpline, splineData));
+ }
+ }
+
+
+ _curveAttributes = attributes;
+ _curveEditor->setCurveAttributes(_curveAttributes);
+ }
+}
+
+void CurveEditorTestApp::_fillColorAttributes()
+{
+ {
+ std::vector<ColorAttribute*> attributes;
+
+ ColorAttribute* attribute = new ColorAttribute("Hair Color");
+ attributes.push_back(attribute);
+
+ {
+ ColorCurve& colorCurve = attribute->colorCurve;
+ colorCurve.initValueRange(0, 1);
+ ColorCurve& alphaCurve = attribute->alphaCurve;
+ alphaCurve.initValueRange(0, 1);
+
+ colorCurve.appendControlPoint(ColorControlPoint(0, QColor(255, 0, 0, 255), eLinear));
+ colorCurve.appendControlPoint(ColorControlPoint(1, QColor(0, 255, 0, 255), eLinear));
+
+ alphaCurve.appendControlPoint(ColorControlPoint(0, QColor(0, 0, 0, 0), eLinear));
+ alphaCurve.appendControlPoint(ColorControlPoint(1, QColor(0, 0, 0, 255), eLinear));
+ }
+
+ attribute = new ColorAttribute("XColor", true, true, true);
+ //attribute->color = QColor(0x11, 0x22, 0x33, 0x44);//
+ attributes.push_back(attribute);
+
+ {
+ ColorCurve& curve = attribute->colorCurve;
+ curve.initValueRange(-1, 6);
+ curve.appendControlPoint(ColorControlPoint(-1, QColor(255, 0, 0, 0), eDiscret));
+ curve.appendControlPoint(ColorControlPoint(0, QColor(0, 255, 0, 255), eCatmullRomSpline));
+ curve.appendControlPoint(ColorControlPoint(0.25, QColor(128, 0, 255, 128), eCatmullRomSpline));
+ curve.appendControlPoint(ColorControlPoint(0.5, QColor(255, 0, 0, 255), eCatmullRomSpline));
+ curve.appendControlPoint(ColorControlPoint(0.75, QColor(0, 255, 0, 128), eCatmullRomSpline));
+ curve.appendControlPoint(ColorControlPoint(1, QColor(0, 0, 255, 0), eCatmullRomSpline));
+ {
+ BezierSplineData splineData;
+ splineData.inLen = 0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ColorControlPoint(2, QColor(255, 0, 0, 255), eBezierSpline, splineData));
+ splineData.inLen = 1.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ColorControlPoint(3, QColor(0, 255, 0, 128), eBezierSpline, splineData));
+ splineData.inLen = 1.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ curve.appendControlPoint(ColorControlPoint(4, QColor(0, 0, 255, 0), eBezierSpline, splineData));
+ }
+ curve.appendControlPoint(ColorControlPoint(5, QColor(255, 0, 0, 255), eLinear));
+ curve.appendControlPoint(ColorControlPoint(6, QColor(0, 255, 0, 128), eLinear));
+ }
+
+ attribute = new ColorAttribute("Color_NoAddRemove_NotChangeTangent", true, false, false);
+
+ attributes.push_back(attribute);
+
+ {
+ ColorCurve& colorCurve = attribute->colorCurve;
+ colorCurve.initValueRange(-1, 4);
+ colorCurve.appendControlPoint(ColorControlPoint(-1, QColor(255, 0, 0, 0), eLinear));
+ colorCurve.appendControlPoint(ColorControlPoint(0, QColor(0, 255, 0, 255), eLinear));
+ colorCurve.appendControlPoint(ColorControlPoint(0.5, QColor(0, 0, 255, 255), eLinear));
+ colorCurve.appendControlPoint(ColorControlPoint(1, QColor(255, 0, 0, 0), eLinear));
+ {
+ BezierSplineData splineData;
+ splineData.inLen = 0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ colorCurve.appendControlPoint(ColorControlPoint(2, QColor(0, 255, 0, 255), eBezierSpline, splineData));
+ splineData.inLen = 1.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ colorCurve.appendControlPoint(ColorControlPoint(3, QColor(0, 0, 255, 128), eBezierSpline, splineData));
+ splineData.inLen = 1.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ colorCurve.appendControlPoint(ColorControlPoint(4, QColor(255, 0, 0, 0), eBezierSpline, splineData));
+ }
+
+ ColorCurve& alphaCurve = attribute->alphaCurve;
+ alphaCurve.initValueRange(-1, 4);
+ alphaCurve.appendControlPoint(ColorControlPoint(-1, QColor(0, 0, 0, 0), eDiscret));
+ alphaCurve.appendControlPoint(ColorControlPoint(1, QColor(0, 0, 0, 255), eLinear));
+ alphaCurve.appendControlPoint(ColorControlPoint(2, QColor(0, 0, 0, 80), eLinear));
+ alphaCurve.appendControlPoint(ColorControlPoint(4, QColor(0, 0, 0, 255), eLinear));
+ }
+
+ attribute = new ColorAttribute("Color_AddRemove_ChangeTangent", true, true, true);
+
+ attributes.push_back(attribute);
+
+ {
+ ColorCurve& colorCurve = attribute->colorCurve;
+ colorCurve.initValueRange(-1, 4);
+ colorCurve.appendControlPoint(ColorControlPoint(-1, QColor(255, 0, 0, 0), eLinear));
+ //colorCurve.appendControlPoint(ColorControlPoint(0, QColor(0, 255, 0, 255), eLinear));
+ //colorCurve.appendControlPoint(ColorControlPoint(0.5, QColor(0, 0, 255, 255), eLinear));
+ //colorCurve.appendControlPoint(ColorControlPoint(1, QColor(255, 0, 0, 0), eLinear));
+ {
+ BezierSplineData splineData;
+ //splineData.inLen = 0;
+ //splineData.inTan = 0;
+ //splineData.outLen = 1.0;
+ //splineData.outTan = 0;
+ //colorCurve.appendControlPoint(ColorControlPoint(2, QColor(0, 255, 0, 255), eBezierSpline, splineData));
+ //splineData.inLen = 1.0;
+ //splineData.inTan = 0;
+ //splineData.outLen = 1.0;
+ //splineData.outTan = 0;
+ //colorCurve.appendControlPoint(ColorControlPoint(3, QColor(0, 0, 255, 128), eBezierSpline, splineData));
+ splineData.inLen = 1.0;
+ splineData.inTan = 0;
+ splineData.outLen = 1.0;
+ splineData.outTan = 0;
+ colorCurve.appendControlPoint(ColorControlPoint(4, QColor(0, 255, 0, 0), eBezierSpline, splineData));
+ }
+
+ ColorCurve& alphaCurve = attribute->alphaCurve;
+ alphaCurve.initValueRange(-1, 4);
+ alphaCurve.appendControlPoint(ColorControlPoint(-1, QColor(0, 0, 0, 0), eDiscret));
+ //alphaCurve.appendControlPoint(ColorControlPoint(1, QColor(0, 0, 0, 255), eLinear));
+ //alphaCurve.appendControlPoint(ColorControlPoint(2, QColor(0, 0, 0, 80), eLinear));
+ alphaCurve.appendControlPoint(ColorControlPoint(4, QColor(0, 0, 0, 255), eLinear));
+ }
+
+ _colorAttributes = attributes;
+ _curveEditor->setColorCurveAttributes(_colorAttributes);
+ }
+}
diff --git a/NvBlast/tools/CurveEditor/source/GraphEditorTestApp/CurveEditorTestApp.h b/NvBlast/tools/CurveEditor/source/GraphEditorTestApp/CurveEditorTestApp.h
new file mode 100644
index 0000000..ed68141
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/GraphEditorTestApp/CurveEditorTestApp.h
@@ -0,0 +1,49 @@
+#ifndef GRAPHEDITORTESTAPP_H
+#define GRAPHEDITORTESTAPP_H
+
+#include <QtWidgets/QWidget>
+
+namespace nvidia {
+namespace CurveEditor {
+
+class CurveEditorMainWindow;
+class CurveAttributeBase;
+class CurveAttribute;
+class ColorAttribute;
+
+} // namespace CurveEditor
+} // namespace nvidia
+
+using namespace nvidia::CurveEditor;
+
+namespace Ui
+{
+ class CurveEditorTestAppClass;
+}
+
+class CurveEditorTestApp : public QWidget
+{
+ Q_OBJECT
+
+public:
+ CurveEditorTestApp(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ ~CurveEditorTestApp();
+
+private slots:
+ void on_btnCurveEditor_clicked(void);
+ void onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute);
+ void onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute);
+ void onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex);
+
+private:
+ void _fillCurveAttributes();
+ void _fillColorAttributes();
+
+private:
+ Ui::CurveEditorTestAppClass* ui;
+ CurveEditorMainWindow* _curveEditor;
+ std::vector<CurveAttributeBase*> _curveAttributes;
+ std::vector<ColorAttribute*> _colorAttributes;
+};
+
+#endif // GRAPHEDITORTESTAPP_H
diff --git a/NvBlast/tools/CurveEditor/source/GraphEditorTestApp/main.cpp b/NvBlast/tools/CurveEditor/source/GraphEditorTestApp/main.cpp
new file mode 100644
index 0000000..ecc3a75
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/GraphEditorTestApp/main.cpp
@@ -0,0 +1,10 @@
+#include "CurveEditorTestApp.h"
+#include <QtWidgets/QApplication>
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ CurveEditorTestApp w;
+ w.show();
+ return a.exec();
+}
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Curve/BezierSpline.cpp b/NvBlast/tools/CurveEditor/source/Internal/Curve/BezierSpline.cpp
new file mode 100644
index 0000000..03ab848
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Curve/BezierSpline.cpp
@@ -0,0 +1,143 @@
+#include "BezierSpline.h"
+
+namespace nvidia {
+namespace CurveEditor {
+
+std::vector<QPointF> BezierSpline::sample(const std::vector<BezierSplinePoint>& splinePoints, long segmentCount)
+{
+ std::vector<QPointF> samplePoints;
+
+ if (segmentCount < 1)
+ return samplePoints;
+
+ long lPointCount = (long)splinePoints.size();
+ float fLengthStep = 1.0 / segmentCount;
+ float ft;
+ QPointF p0;
+ QPointF p1;
+ QPointF p2;
+ QPointF p3;
+ QPointF p01;
+ QPointF p11;
+ QPointF p21;
+ QPointF p02;
+ QPointF p12;
+ QPointF p03;
+
+ for (int i = 1; i < lPointCount; i++)
+ {
+ const BezierSplinePoint& pt1 = splinePoints[i - 1];
+ const BezierSplinePoint& pt2 = splinePoints[i];
+
+ // start point of each Bezier curve segment
+ samplePoints.push_back(pt1.valuePoint);
+
+ // sample each point on each Bezier curve segment by percent value and De Casteljau algorithm
+ // the sample points are not including start point and end poit of the Bezier curve segement
+ for (int j = 1; j < segmentCount; j++)
+ {
+ ft = fLengthStep * j;
+
+ p0 = pt1.valuePoint;
+ p1 = pt1.ctrlPoint1;
+ p2 = pt2.ctrlPoint0;
+ p3 = pt2.valuePoint;
+
+ p01 = p0 + (p1 - p0) * ft;
+ p11 = p1 + (p2 - p1) * ft;
+ p21 = p2 + (p3 - p2) * ft;
+
+ p02 = p01 + (p11 - p01) * ft;\
+ p12 = p11 + (p21 - p11) * ft;
+ p03 = p02 + (p12 - p02) * ft;
+
+ samplePoints.push_back(p03);
+ }
+
+ if (i == lPointCount - 1)
+ {// end point of last Bezier curve segment
+ samplePoints.push_back(pt2.valuePoint);
+ }
+ }
+ return samplePoints;
+}
+
+BezierSpline::BezierSpline(long segmentCount)
+ : Spline(segmentCount)
+ , _controlPoints()
+{
+}
+
+bool BezierSpline::getControlPoint(int index, BezierSplinePoint &pt)
+{
+ long lPointCount = (long)_controlPoints.size();
+
+ if (lPointCount == 0)
+ {
+ return false;
+ }
+
+ index = index < 0 ? 0 : (index >= lPointCount ? lPointCount - 1: index);
+
+ pt = _controlPoints[index];
+
+ return true;
+}
+
+void BezierSpline::appendControlPoint(BezierSplinePoint pt)
+{
+ _controlPoints.push_back(pt);
+
+ _needSample = true;
+}
+
+void BezierSpline::insertControlPoint(int index, BezierSplinePoint pt)
+{
+ long lPointCount = (long)_controlPoints.size();
+
+ index = index < 0 ? 0 : (index >= lPointCount ? lPointCount: index);
+
+ _controlPoints.insert(_controlPoints.begin() + index, pt);
+
+ _needSample = true;
+}
+
+bool BezierSpline::setControlPoint(int index, BezierSplinePoint pt)
+{
+ long lPointCount = (long)_controlPoints.size();
+
+ if (0 <= index && index < lPointCount)
+ {
+ _controlPoints[index] = pt;
+ _needSample = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool BezierSpline::removeControlPoint(int index)
+{
+ long lPointCount = (long)_controlPoints.size();
+
+ if (0 <= index && index < lPointCount)
+ {
+ _controlPoints.erase(_controlPoints.begin() + index);
+ _needSample = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void BezierSpline::_doSample()
+{
+ _samplePoints = sample(_controlPoints, _segmentCount);
+}
+
+} // namespace CurveEditor
+} // namespace nvidia \ No newline at end of file
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Curve/BezierSpline.h b/NvBlast/tools/CurveEditor/source/Internal/Curve/BezierSpline.h
new file mode 100644
index 0000000..ba5da46
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Curve/BezierSpline.h
@@ -0,0 +1,57 @@
+#ifndef BEZIERSPLINE_H
+#define BEZIERSPLINE_H
+#include <vector>
+#include <QtCore/QPointF>
+#include "Spline.h"
+
+namespace nvidia {
+namespace CurveEditor {
+
+class BezierSplinePoint
+{
+public:
+ QPointF ctrlPoint0;
+ QPointF valuePoint;
+ QPointF ctrlPoint1;
+};
+
+class BezierSpline : public Spline
+{
+public:
+ static std::vector<QPointF> sample(const std::vector<BezierSplinePoint>& splinePoints, long segmentCount = 100);
+
+ BezierSpline(long segmentCount = 100);
+
+ virtual ~BezierSpline() {}
+
+ inline long getControlPointCount() { return (long)_controlPoints.size(); }
+
+ // index <= 0, return the first point;
+ // index >= point count, return the last point.
+ bool getControlPoint(int index, BezierSplinePoint &pt);
+
+ // add a spline point to last
+ void appendControlPoint(BezierSplinePoint pt);
+
+ // insert a spline point at the identified position.
+ // index <= 0, inert to fisrt;
+ // index >= point count, insert to last.
+ void insertControlPoint(int index, BezierSplinePoint pt);
+
+ // change a spline point value at the identified position.
+ bool setControlPoint(int index, BezierSplinePoint pt);
+
+ // remove the identified spline point.
+ bool removeControlPoint(int index);
+
+private:
+ virtual void _doSample();
+
+private:
+ std::vector<BezierSplinePoint> _controlPoints;
+};
+
+} // namespace CurveEditor
+} // namespace nvidia
+
+#endif // BEZIERSPLINE_H
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Curve/CatmullRomSpline.cpp b/NvBlast/tools/CurveEditor/source/Internal/Curve/CatmullRomSpline.cpp
new file mode 100644
index 0000000..abe80bb
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Curve/CatmullRomSpline.cpp
@@ -0,0 +1,205 @@
+#include "CatmullRomSpline.h"
+
+namespace nvidia {
+namespace CurveEditor {
+
+float CatmullRomSpline::splineInterpolate(float v0, float v1, float v2, float v3, float u)
+{
+ float basis[4];
+
+ {
+ _computeSplineBasis(u, basis);
+ return
+ basis[0] * v0 +
+ basis[1] * v1 +
+ basis[2] * v2 +
+ basis[3] * v3;
+ }
+}
+
+QPointF CatmullRomSpline::splineInterpolate(const QPointF& p0, const QPointF& p1, const QPointF& p2, const QPointF& p3, float u)
+{
+ float basis[4];
+
+ {
+ _computeSplineBasis(u, basis);
+ return
+ QPointF(basis[0] * p0.x() +
+ basis[1] * p1.x() +
+ basis[2] * p2.x() +
+ basis[3] * p3.x(),
+ basis[0] * p0.y() +
+ basis[1] * p1.y() +
+ basis[2] * p2.y() +
+ basis[3] * p3.y());
+ }
+}
+
+std::vector<QPointF> CatmullRomSpline::sample(const std::vector<QPointF>& inControlPoints, int numSegments)
+{
+ std::vector<QPointF> samplePoints;
+ int numPoints = (int)inControlPoints.size();
+
+ for (int i = 0; i < numPoints - 1; i++)
+ {
+ QPointF p0, p1, p2, p3;
+
+ if (i == 0)
+ {
+ p0 = inControlPoints[0], p1 = inControlPoints[0], p2 = inControlPoints[1];
+ if (2 < numPoints)
+ p3 = inControlPoints[2];
+ else
+ p3 = inControlPoints[1];
+
+ }
+ else if (0 < i && i < numPoints - 2)
+ {
+ p0 = inControlPoints[i-1], p1 = inControlPoints[i], p2 = inControlPoints[i+1], p3 = inControlPoints[i+2];
+ }
+ else
+ {
+ if (2 < numPoints)
+ p0 = inControlPoints[i-1];
+ else
+ p0 = inControlPoints[i];
+ p1 = inControlPoints[i], p2 = inControlPoints[i+1], p3 = inControlPoints[i+1];
+ }
+
+ for (int j = 0; j <= numSegments; j++)
+ {
+ float u = j / float(numSegments);
+
+ samplePoints.push_back(splineInterpolate(p0, p1, p2, p3, u));
+ }
+ }
+
+ return samplePoints;
+}
+
+void CatmullRomSpline::_computeSplineBasis(float u, float* basis)
+{
+ float u2 = u * u;
+ float u3 = u2 * u;
+
+ basis[0] = -0.5f * u3 + 1.0f * u2 - 0.5f * u + 0.0f;
+ basis[1] = 1.5f * u3 - 2.5f * u2 + 0.0f * u + 1.0f;
+ basis[2] = -1.5f * u3 + 2.0f * u2 + 0.5f * u + 0.0f;
+ basis[3] = 0.5f * u3 - 0.5f * u2 + 0.0f * u + 0.0f;
+}
+
+CatmullRomSpline::CatmullRomSpline(long segmentCount)
+ : Spline(segmentCount)
+ , _controlPoints()
+{
+ _segmentCount = segmentCount < 1 ? 1 : segmentCount;
+}
+
+CatmullRomSpline::CatmullRomSpline(int numControlPoints, long segmentCount)
+ : Spline(segmentCount)
+ , _controlPoints()
+{
+ for (int i = 0; i < numControlPoints; ++i)
+ {
+ _controlPoints.push_back(QPointF(i / float(numControlPoints - 1), 1.0f));
+ }
+}
+
+CatmullRomSpline::~CatmullRomSpline(void)
+{
+}
+
+void CatmullRomSpline::setControlPoint(int index, const QPointF& point)
+{
+ std::vector<QPointF>::iterator itr = _controlPoints.begin();
+ std::advance(itr, index);
+ *itr = point;
+}
+
+QPointF CatmullRomSpline::getControlPoint(int index)
+{
+ std::vector<QPointF>::iterator itr = _controlPoints.begin();
+ std::advance(itr, index);
+ return *itr;
+}
+
+std::vector<QPointF> CatmullRomSpline::getControlPoints()
+{
+ return _controlPoints;
+}
+
+void CatmullRomSpline::reset(void)
+{
+ int i = 0;
+ for (std::vector<QPointF>::iterator itr = _controlPoints.begin(); itr != _controlPoints.end(); ++itr, ++i)
+ {
+ itr->setX(i / float(_controlPoints.size() - 1));
+ itr->setY(1.0f);
+ }
+}
+
+void CatmullRomSpline::insertControlPointAt(int index)
+{
+ QPointF p0, p1, p2, p3;
+
+ QPointF newPoint;
+ std::vector<QPointF>::iterator itr = _controlPoints.begin();
+
+ if (index == 0)
+ {
+ return;
+ }
+ else if (index == 1)
+ {
+ p0 = _controlPoints[0], p1 = _controlPoints[0], p2 = _controlPoints[1];
+ if (_controlPoints.size() > 2)
+ p3 = _controlPoints[2];
+ else
+ p3 = _controlPoints[1];
+ newPoint = splineInterpolate(p0, p1, p2, p3, 0.5);
+ }
+ else if (index > (int)(_controlPoints.size() - 1))
+ {
+ return;
+ }
+ else if (index == (_controlPoints.size() - 1))
+ {
+ if (_controlPoints.size() > 2)
+ p0 = _controlPoints[index-2];
+ else
+ p0 = _controlPoints[index-1];
+ p1 = _controlPoints[index-1], p2 = _controlPoints[index], p3 = _controlPoints[index];
+ newPoint = splineInterpolate(p0, p1, p2, p3, 0.5);
+ }
+ else
+ {
+ p0 = _controlPoints[index - 2], p1 = _controlPoints[index - 1], p2 = _controlPoints[index], p3 = _controlPoints[index + 1];
+ newPoint = splineInterpolate(p0, p1, p2, p3, 0.5);
+ }
+
+ std::advance(itr, index);
+ _controlPoints.insert(itr, newPoint);
+}
+
+void CatmullRomSpline::removeControlPoints(std::vector<int>& points)
+{
+ for (std::vector<int>::iterator itr = points.begin(); itr != points.end(); ++itr)
+ {
+ std::vector<QPointF>::iterator itrToRemove = _controlPoints.begin();
+ std::advance(itrToRemove, *itr);
+ _controlPoints.erase(itrToRemove);
+
+ for (std::vector<int>::iterator itrRight = itr + 1; itrRight != points.end(); ++itrRight)
+ {
+ --(*itrRight);
+ }
+ }
+}
+
+void CatmullRomSpline::_doSample()
+{
+ _samplePoints = sample(_controlPoints, _segmentCount);
+}
+
+} // namespace CurveEditor
+} // namespace nvidia \ No newline at end of file
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Curve/CatmullRomSpline.h b/NvBlast/tools/CurveEditor/source/Internal/Curve/CatmullRomSpline.h
new file mode 100644
index 0000000..71573a9
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Curve/CatmullRomSpline.h
@@ -0,0 +1,44 @@
+#ifndef CatmullRomSpline_h__
+#define CatmullRomSpline_h__
+
+#include <QtCore/QPoint>
+#include <vector>
+#include "Spline.h"
+
+namespace nvidia {
+namespace CurveEditor {
+
+class CatmullRomSpline : public Spline
+{
+public:
+ static float splineInterpolate(float v0, float v1, float v2, float v3, float u);
+ static QPointF splineInterpolate(const QPointF& p0, const QPointF& p1, const QPointF& p2, const QPointF& p3, float u);
+ static std::vector<QPointF> sample(const std::vector<QPointF>& inControlPoints, int numSegments = 100);
+private:
+ static void _computeSplineBasis(float u, float* basis);
+
+public:
+ CatmullRomSpline(long segmentCount = 100);
+ CatmullRomSpline(int numControlPoints, long segmentCount = 100);
+ virtual ~CatmullRomSpline(void);
+
+ int getControlPointCount() { return (int)_controlPoints.size(); }
+ // add a spline point to last
+ void appendControlPoint(QPointF point) { _controlPoints.push_back(point); }
+ void setControlPoint(int index, const QPointF& point);
+ QPointF getControlPoint(int index);
+ std::vector<QPointF> getControlPoints();
+ void reset(void);
+ void insertControlPointAt(int index);
+ void removeControlPoints(std::vector<int>& points);
+
+private:
+ virtual void _doSample();
+private:
+ std::vector<QPointF> _controlPoints;
+};
+
+} // namespace CurveEditor
+} // namespace nvidia
+
+#endif // CatmullRomSpline_h__
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Curve/Curve.cpp b/NvBlast/tools/CurveEditor/source/Internal/Curve/Curve.cpp
new file mode 100644
index 0000000..01d6351
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Curve/Curve.cpp
@@ -0,0 +1,1114 @@
+#include "Curve.h"
+#include "BezierSpline.h"
+#include "CatmullRomSpline.h"
+#include <QtCore/QDebug>
+#include <QtWidgets/QMessageBox>
+#include <QtGui/QImage>
+#pragma warning( disable : 4312 )
+#pragma warning( disable : 4996 )
+#include "../../../external/stb_image/stb_image.c"
+
+namespace nvidia {
+namespace CurveEditor {
+
+Curve::Curve(long segmentCount)
+ : _needSample(true)
+ , _initValueRange(false)
+ , _minValue()
+ , _maxValue(1.0f, 1.0f)
+ , _segmentCount(1)
+ , _samplePoints()
+ , _controlPoints()
+ , _defaultControlPoints()
+{
+ _segmentCount = segmentCount < 1 ? 1 : segmentCount;
+}
+
+void Curve::initValueRange(const QPointF& min, const QPointF& max)
+{
+ if (min.x() >= max.x() || min.y() >max.y())
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("Max value must be larger than min value when initilize value range of curve"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return ;
+ }
+
+ _minValue = min;
+ _maxValue = max;
+ _initValueRange = true;
+}
+
+QPointF Curve::getMinValue()
+{
+ return _minValue;
+}
+
+QPointF Curve::getMaxValue()
+{
+ return _maxValue;
+}
+
+void Curve::appendControlPoint(ControlPoint& controlPoint, bool asDefaultToo)
+{
+ if (!_initValueRange)
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("Curve must be initilized its value range before being used!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return;
+ }
+
+ if (controlPoint.value.x() < _minValue.x()
+ || controlPoint.value.x() > _maxValue.x()
+ || controlPoint.value.y() < _minValue.y()
+ || controlPoint.value.y() > _maxValue.y())
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("The value of the control point to add isn't in value range of the curve to add!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return;
+ }
+
+ _controlPoints.push_back(controlPoint);
+
+ if (asDefaultToo)
+ {
+ _defaultControlPoints.push_back(controlPoint);
+ }
+
+ _needSample = true;
+}
+
+int Curve::appendControlPoint(float x)
+{
+ size_t count = _controlPoints.size();
+ for (int i = 0; i < count - 1; ++i)
+ {
+ ControlPoint& ctrlPntLeft = _controlPoints[i];
+ ControlPoint& ctrlPntRight = _controlPoints[i + 1];
+ if (ctrlPntLeft.value.x() <= x && x <= ctrlPntRight.value.x())
+ {
+ std::vector<ControlPoint>::iterator itr = _controlPoints.begin();
+ std::advance(itr, i+1);
+ ControlPoint pnt(x, getPointByX(x).y(), ctrlPntLeft.mode, ctrlPntLeft.splineData);
+ _controlPoints.insert(itr, pnt);
+ _needSample = true;
+ return i + 1;
+ }
+ }
+
+ return -1;
+}
+
+void Curve::setControlPoint(int index, const ControlPoint& point)
+{
+ if (index < 0 || index > (_controlPoints.size() - 1) )
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("Meet invalid index when setting control point for curve!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return;
+ }
+
+ if (point.value.x() < _minValue.x()
+ || point.value.x() > _maxValue.x()
+ || point.value.y() < _minValue.y()
+ || point.value.y() > _maxValue.y())
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("The setting value isn't in value range of the curve!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return;
+ }
+ std::vector<ControlPoint>::iterator itr = _controlPoints.begin();
+ std::advance(itr, index);
+ *itr = point;
+ _needSample = true;
+}
+
+void Curve::reset(void)
+{
+ if (_defaultControlPoints.size() > 0)
+ {
+ _controlPoints = _defaultControlPoints;
+ _needSample = true;
+ }
+}
+
+void Curve::insertControlPointAt(int index)
+{
+ if (index < 0)
+ index = 0;
+ else if (index > (_controlPoints.size() - 1) )
+ index = (int)(_controlPoints.size() - 1);
+
+ std::vector<ControlPoint>::iterator itrToAdd = _controlPoints.begin();
+ std::advance(itrToAdd, index);
+
+ ControlPoint& ctrlPntFront = _controlPoints[index - 1];
+ ControlPoint& ctrlPntBehind = _controlPoints[index];
+
+ switch (ctrlPntFront.mode)
+ {
+ case eDiscret:
+ {
+ ControlPoint ctrlPntToAdd;
+ ctrlPntToAdd.mode = ctrlPntFront.mode;
+ ctrlPntToAdd.value.setX((ctrlPntFront.value.x() + ctrlPntBehind.value.x()) / 2);
+ ctrlPntToAdd.value.setY(ctrlPntFront.value.y());
+ _controlPoints.insert(itrToAdd, ctrlPntToAdd);
+ break;
+ }
+ case eLinear:
+ {
+ ControlPoint ctrlPntToAdd;
+ ctrlPntToAdd.mode = ctrlPntFront.mode;
+ ctrlPntToAdd.value.setX((ctrlPntFront.value.x() + ctrlPntBehind.value.x()) / 2);
+ ctrlPntToAdd.value.setY(ctrlPntFront.value.y() + (ctrlPntBehind.value.y() - ctrlPntFront.value.y()) / 2);
+ _controlPoints.insert(itrToAdd, ctrlPntToAdd);
+ break;
+ }
+ case eBezierSpline:
+ {
+ BezierSplinePoint bezierPnt0;
+ BezierSplinePoint bezierPnt1;
+
+ float xStride = ctrlPntBehind.value.x() - ctrlPntFront.value.x();
+ bezierPnt0.ctrlPoint0 = ctrlPntFront.value;
+ bezierPnt0.valuePoint = ctrlPntFront.value;
+ float xDelta = ctrlPntFront.splineData.outLen * xStride;
+ bezierPnt0.ctrlPoint1 = ctrlPntFront.value + QPointF(xDelta, xDelta * ctrlPntFront.splineData.outTan);
+
+ if (eBezierSpline == ctrlPntBehind.mode)
+ {
+ xDelta = ctrlPntBehind.splineData.inLen * xStride;
+ bezierPnt1.ctrlPoint0 = ctrlPntBehind.value - QPointF(xDelta, xDelta * ctrlPntBehind.splineData.inTan);
+ bezierPnt1.valuePoint = ctrlPntBehind.value;
+ bezierPnt1.ctrlPoint1 = ctrlPntBehind.value;
+ }
+ else
+ {
+ bezierPnt1.ctrlPoint0 = ctrlPntBehind.value;
+ bezierPnt1.valuePoint = ctrlPntBehind.value;
+ bezierPnt1.ctrlPoint1 = ctrlPntBehind.value;
+ }
+
+ BezierSpline spline(100);
+ spline.appendControlPoint(bezierPnt0);
+ spline.appendControlPoint(bezierPnt1);
+ QPointF pntOnSpline;
+ spline.getPointByX(ctrlPntFront.value.x() + xStride / 2, pntOnSpline);
+
+ ControlPoint ctrlPntToAdd;
+ ctrlPntToAdd.mode = eBezierSpline;
+ ctrlPntToAdd.value = pntOnSpline;
+ ctrlPntToAdd.splineData.inLen = 1.0;
+ ctrlPntToAdd.splineData.inTan = 0.0;
+ ctrlPntToAdd.splineData.outLen = 1.0;
+ ctrlPntToAdd.splineData.outTan = 0.0;
+ _controlPoints.insert(itrToAdd, ctrlPntToAdd);
+ break;
+ }
+ case eCatmullRomSpline:
+ {
+ CatmullRomSpline spline;
+
+ int i = index - 1;
+ for (; i >= 0; --i)
+ {
+ if (eCatmullRomSpline != _controlPoints[i].mode)
+ {
+ ++i;
+ break;
+ }
+ }
+
+ if (i < 0)
+ i = 0;
+
+ for (; i < (int)_controlPoints.size(); ++i)
+ {
+ spline.appendControlPoint(_controlPoints[i].value);
+ if (eCatmullRomSpline != _controlPoints[i].mode)
+ break;
+ }
+
+ QPointF pntOnSpline;
+ spline.getPointByX((ctrlPntFront.value.x() + ctrlPntBehind.value.x()) / 2, pntOnSpline);
+ ControlPoint ctrlPntToAdd;
+ ctrlPntToAdd.mode = eCatmullRomSpline;
+ ctrlPntToAdd.value = pntOnSpline;
+ _controlPoints.insert(itrToAdd, ctrlPntToAdd);
+ break;
+ }
+ default:
+ break;
+ }
+
+ _needSample = true;
+}
+
+void Curve::removeControlPoint(int index)
+{
+ std::vector<ControlPoint>::iterator itr = _controlPoints.begin();
+ std::advance(itr, index);
+ _controlPoints.erase(itr);
+ _needSample = true;
+}
+
+void Curve::removeControlPoints(std::vector<int>& indexes)
+{
+ for (std::vector<int>::iterator itr = indexes.begin(); itr != indexes.end(); ++itr)
+ {
+ std::vector<ControlPoint>::iterator itrToRemove = _controlPoints.begin();
+ std::advance(itrToRemove, *itr);
+ _controlPoints.erase(itrToRemove);
+
+ for (std::vector<int>::iterator itrRight = itr + 1; itrRight != indexes.end(); ++itrRight)
+ {
+ --(*itrRight);
+ }
+ }
+
+ _needSample = true;
+}
+
+QPointF Curve::getPointByX(float x)
+{
+ if (!_initValueRange)
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("Curve must be initilized its value range before being used!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return QPointF(0, 0);
+ }
+
+ if (x < _controlPoints[0].value.x())
+ return _controlPoints[0].value;
+
+ if (x >= _controlPoints[_controlPoints.size() - 1].value.x())
+ return _controlPoints[_controlPoints.size() - 1].value;
+
+ long lPointCount = (long)_samplePoints.size();
+
+ if(lPointCount < 2)
+ {
+ return QPointF(0,0);
+ }
+
+ if (_needSample)
+ _sample();
+
+ QPointF point;
+
+ for (int i = 0; i < lPointCount - 1; i++)
+ {
+ if(_samplePoints[i].x() <= x && _samplePoints[i + 1].x() > x)
+ {
+ point.setX( x );
+ float fRate = (x - _samplePoints[i].x())/ (_samplePoints[i + 1].x() - _samplePoints[i].x());
+ point.setY(_samplePoints[i].y() + (_samplePoints[i+1].y() - _samplePoints[i].y()) * fRate);
+ return point;
+ }
+ }
+
+ return QPointF(0,0);
+}
+
+std::vector<QPointF> Curve::getSamplePoints()
+{
+ if (!_initValueRange)
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("Curve must be initilized its value range before being used!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return std::vector<QPointF>();
+ }
+
+ if (_needSample)
+ _sample();
+
+ return _samplePoints;
+}
+
+Curve Curve::resampleCurve(int resamplePnts, long segmentCount)
+{
+ if (!_initValueRange)
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("Curve must be initilized its value range before being used!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return Curve();
+ }
+
+ Curve resmapleCurve(segmentCount);
+ if (resamplePnts < 2)
+ return resmapleCurve;
+ else
+ {
+ int segment = resamplePnts - 1;
+ float xStart = _controlPoints[0].value.x();
+ float xEnd = _controlPoints[_controlPoints.size() - 1].value.x();
+ float strideX = (xEnd - xStart) / segment;
+ for (int i = 0; i <= segment; ++i)
+ {
+ float x = xStart + strideX * i;
+ QPointF pnt = getPointByX(x);
+ ControlPoint& ctrlPntNear = _getNearCtrlPnt(x);
+
+ ControlPoint ctrlPntNew(pnt.x(), pnt.y(), ctrlPntNear.mode);
+
+ if (eBezierSpline == ctrlPntNear.mode)
+ {
+ ctrlPntNew.splineData = ctrlPntNear.splineData;
+ }
+
+ resmapleCurve.appendControlPoint(ctrlPntNew);
+ }
+ }
+
+ return resmapleCurve;
+}
+
+Curve& Curve::operator = (const Curve& right)
+{
+ if (this == &right)
+ return *this;
+
+ _needSample = right._needSample;
+ _initValueRange = right._initValueRange;
+ _minValue = right._minValue;
+ _maxValue = right._maxValue;
+ _segmentCount = right._segmentCount;
+ _samplePoints = right._samplePoints;
+ _controlPoints = right._controlPoints;
+
+ return *this;
+}
+
+void Curve::_sample()
+{
+ _samplePoints.clear();
+
+ for (size_t i = 1; i < _controlPoints.size(); ++i)
+ {
+ ControlPoint& ctrlPntFront = _controlPoints[i-1];
+ ControlPoint& ctrlPntBehind = _controlPoints[i];
+
+ switch (ctrlPntFront.mode)
+ {
+ case eDiscret:
+ {
+ _samplePoints.push_back(ctrlPntFront.value);
+ _samplePoints.push_back(QPointF(ctrlPntBehind.value.x(), ctrlPntFront.value.y()));
+ break;
+ }
+ case eLinear:
+ {
+ _samplePoints.push_back(ctrlPntFront.value);
+ _samplePoints.push_back(ctrlPntBehind.value);
+ break;
+ }
+ case eBezierSpline:
+ {
+ BezierSplinePoint bezierPnt0;
+ BezierSplinePoint bezierPnt1;
+
+ float xStride = ctrlPntBehind.value.x() - ctrlPntFront.value.x();
+ bezierPnt0.ctrlPoint0 = ctrlPntFront.value;
+ bezierPnt0.valuePoint = ctrlPntFront.value;
+ float xDelta = ctrlPntFront.splineData.outLen * xStride;
+ bezierPnt0.ctrlPoint1 = ctrlPntFront.value + QPointF(xDelta, xDelta * ctrlPntFront.splineData.outTan);
+
+ if (eBezierSpline == ctrlPntBehind.mode)
+ {
+ xDelta = ctrlPntBehind.splineData.inLen * xStride;
+ bezierPnt1.ctrlPoint0 = ctrlPntBehind.value - QPointF(xDelta, xDelta * ctrlPntBehind.splineData.inTan);
+ bezierPnt1.valuePoint = ctrlPntBehind.value;
+ bezierPnt1.ctrlPoint1 = ctrlPntBehind.value;
+ }
+ else
+ {
+ bezierPnt1.ctrlPoint0 = ctrlPntBehind.value;
+ bezierPnt1.valuePoint = ctrlPntBehind.value;
+ bezierPnt1.ctrlPoint1 = ctrlPntBehind.value;
+ }
+
+ BezierSpline spline(_segmentCount);
+ spline.appendControlPoint(bezierPnt0);
+ spline.appendControlPoint(bezierPnt1);
+
+ std::vector<QPointF> pnts = spline.getSamplePoints();
+ _samplePoints.insert(_samplePoints.end(), pnts.begin(), pnts.end());
+ break;
+ }
+ case eCatmullRomSpline:
+ {
+ CatmullRomSpline spline(_segmentCount);
+
+ for (i = i - 1; i < _controlPoints.size(); ++i)
+ {
+ spline.appendControlPoint(_controlPoints[i].value);
+ if (eCatmullRomSpline != _controlPoints[i].mode)
+ {
+ break;
+ }
+ }
+
+ std::vector<QPointF> pnts = spline.getSamplePoints();
+ _samplePoints.insert(_samplePoints.end(), pnts.begin(), pnts.end());
+ break;
+ }
+ }
+ }
+
+ _needSample = false;
+}
+
+ControlPoint& Curve::_getNearCtrlPnt(float x)
+{
+ size_t count = _controlPoints.size();
+ for (int i = 0; i < count - 1; ++i)
+ {
+ ControlPoint& ctrlPntLeft = _controlPoints[i];
+ ControlPoint& ctrlPntRight = _controlPoints[i + 1];
+ if (x < ctrlPntLeft.value.x())
+ return ctrlPntLeft;
+ else if (ctrlPntLeft.value.x() <= x && x <= ctrlPntRight.value.x())
+ {
+ if (abs(x - ctrlPntLeft.value.x()) <= abs(x - ctrlPntRight.value.x()))
+ {
+ return ctrlPntLeft;
+ }
+ else
+ {
+ return ctrlPntRight;
+ }
+ }
+ }
+ return _controlPoints[0];
+}
+
+ColorCurve::ColorCurve(long segmentCount)
+ : _needSample(true)
+ , _initValueRange(false)
+ , _minValue(0.0f)
+ , _maxValue(1.0f)
+ , _colorSamplePnts()
+ , _controlPoints()
+ , _defaultControlPoints()
+{
+ _segmentCount = segmentCount < 1 ? 1 : segmentCount;
+}
+
+void ColorCurve::initValueRange(float min, float max)
+{
+ if (min >= max )
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("Max x must be larger than min x when initilize value range of color curve"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return ;
+ }
+
+ _minValue = min;
+ _maxValue = max;
+ _initValueRange = true;
+}
+
+float ColorCurve::getMinValue()
+{
+ return _minValue;
+}
+
+float ColorCurve::getMaxValue()
+{
+ return _maxValue;
+}
+
+void ColorCurve::appendControlPoint(ColorControlPoint& controlPoint, bool asDefaultToo)
+{
+ if (!_initValueRange)
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("Color curve must be initilized its value range before being used!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return;
+ }
+
+ if (controlPoint.x < _minValue
+ || controlPoint.x > _maxValue)
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("The x value of the control point to add isn't in x value range of the color curve to add!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return;
+ }
+
+ _controlPoints.push_back(controlPoint);
+
+ if (asDefaultToo)
+ {
+ _defaultControlPoints.push_back(controlPoint);
+ }
+
+ if (!controlPoint.texturePath.empty())
+ {
+ _controlPoints[_controlPoints.size() - 1].textureAverageColor = _calcTextureAverageColor(controlPoint.texturePath.c_str());
+ }
+
+ _needSample = true;
+}
+
+void ColorCurve::setControlPoint(int index, const ColorControlPoint& point)
+{
+ if (index < 0 || index > (_controlPoints.size() - 1) )
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("Meet invalid index when setting control point for color curve!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return;
+ }
+
+ if (point.x < _minValue
+ || point.x > _maxValue)
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("The setting value isn't in x value range of the color curve!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return;
+ }
+ std::vector<ColorControlPoint>::iterator itr = _controlPoints.begin();
+ std::advance(itr, index);
+
+ if (!point.texturePath.empty() && point.texturePath != itr->texturePath)
+ {
+ *itr = point;
+ itr->textureAverageColor = _calcTextureAverageColor(point.texturePath.c_str());
+ }
+ else
+ *itr = point;
+
+ _needSample = true;
+}
+
+void ColorCurve::reset(void)
+{
+ if (_defaultControlPoints.size() > 0)
+ {
+ _controlPoints = _defaultControlPoints;
+ _needSample = true;
+ }
+}
+
+void rectifyColorValue(float& colorComponent)
+{
+ if (colorComponent < 0)
+ colorComponent = 0;
+ else if(colorComponent > 255)
+ {
+ colorComponent = 255;
+ }
+}
+
+void rectifyColorValue(QPointF& colorComponent)
+{
+ if (colorComponent.y() < 0)
+ colorComponent.setY(0);
+ else if(colorComponent.y() > 255)
+ {
+ colorComponent.setY(255);
+ }
+}
+
+float getBezierColorByX(ColorControlPoint& ctrlPntFront, ColorControlPoint& ctrlPntBehind, int component, float x)
+{
+ BezierSplinePoint bezierPnt0;
+ BezierSplinePoint bezierPnt1;
+
+ float y0 = 0.0f, y1 = 0.0f;
+ switch (component) {
+ case 0:
+ y0 = ctrlPntFront.color.red();
+ y1 = ctrlPntBehind.color.red();
+ break;
+ case 1:
+ y0 = ctrlPntFront.color.green();
+ y1 = ctrlPntBehind.color.green();
+ break;
+ case 2:
+ y0 = ctrlPntFront.color.blue();
+ y1 = ctrlPntBehind.color.blue();
+ break;
+ case 3:
+ y0 = ctrlPntFront.color.alpha();
+ y1 = ctrlPntBehind.color.alpha();
+ break;
+ default:
+ break;
+ }
+
+ QPointF pntFront = QPointF(ctrlPntFront.x, y0);
+ QPointF pntBehind = QPointF(ctrlPntBehind.x, y1);
+ float xStride = ctrlPntBehind.x - ctrlPntFront.x;
+ bezierPnt0.ctrlPoint0 = pntFront;
+ bezierPnt0.valuePoint = pntFront;
+ float xDelta = ctrlPntFront.splineData.outLen * xStride;
+ bezierPnt0.ctrlPoint1 = pntFront + QPointF(xDelta, xDelta * ctrlPntFront.splineData.outTan);
+
+ if (eBezierSpline == ctrlPntBehind.mode)
+ {
+ xDelta = ctrlPntBehind.splineData.inLen * xStride;
+ bezierPnt1.ctrlPoint0 = pntBehind - QPointF(xDelta, xDelta * ctrlPntBehind.splineData.inTan);
+ bezierPnt1.valuePoint = pntBehind;
+ bezierPnt1.ctrlPoint1 = pntBehind;
+ }
+ else
+ {
+ bezierPnt1.ctrlPoint0 = pntBehind;
+ bezierPnt1.valuePoint = pntBehind;
+ bezierPnt1.ctrlPoint1 = pntBehind;
+ }
+
+ BezierSpline spline(100);
+ spline.appendControlPoint(bezierPnt0);
+ spline.appendControlPoint(bezierPnt1);
+ QPointF pntOnSpline;
+ spline.getPointByX(x, pntOnSpline);
+
+ rectifyColorValue(pntOnSpline);
+ return pntOnSpline.y();
+}
+
+void ColorCurve::insertControlPointAt(int index)
+{
+ if (index < 0)
+ index = 0;
+ else if (index > (_controlPoints.size() - 1) )
+ index = (int)(_controlPoints.size() - 1);
+
+ std::vector<ColorControlPoint>::iterator itrToAdd = _controlPoints.begin();
+ std::advance(itrToAdd, index);
+
+ ColorControlPoint& ctrlPntFront = _controlPoints[index - 1];
+ ColorControlPoint& ctrlPntBehind = _controlPoints[index];
+
+ switch (ctrlPntFront.mode)
+ {
+ case eDiscret:
+ {
+ ColorControlPoint ctrlPntToAdd;
+ ctrlPntToAdd.mode = ctrlPntFront.mode;
+ ctrlPntToAdd.x = ((ctrlPntFront.x + ctrlPntBehind.x) / 2);
+ ctrlPntToAdd.color = ctrlPntFront.color;
+ _controlPoints.insert(itrToAdd, ctrlPntToAdd);
+ break;
+ }
+ case eLinear:
+ {
+ ColorControlPoint ctrlPntToAdd;
+ ctrlPntToAdd.mode = ctrlPntFront.mode;
+ ctrlPntToAdd.x = ((ctrlPntFront.x + ctrlPntBehind.x) / 2);
+ ctrlPntToAdd.color.setRed(ctrlPntFront.color.red() + (ctrlPntBehind.color.red() - ctrlPntFront.color.red()) / 2);
+ ctrlPntToAdd.color.setRed(ctrlPntFront.color.green() + (ctrlPntBehind.color.green() - ctrlPntFront.color.green()) / 2);
+ ctrlPntToAdd.color.setRed(ctrlPntFront.color.blue() + (ctrlPntBehind.color.blue() - ctrlPntFront.color.blue()) / 2);
+ ctrlPntToAdd.color.setRed(ctrlPntFront.color.alpha() + (ctrlPntBehind.color.alpha() - ctrlPntFront.color.alpha()) / 2);
+ _controlPoints.insert(itrToAdd, ctrlPntToAdd);
+ break;
+ }
+ case eBezierSpline:
+ {
+ ColorControlPoint ctrlPntToAdd;
+ ctrlPntToAdd.mode = eBezierSpline;
+ ctrlPntToAdd.x = (ctrlPntFront.x + ctrlPntBehind.x) / 2;
+ ctrlPntToAdd.color.setRed(getBezierColorByX(ctrlPntFront, ctrlPntBehind, 0, ctrlPntToAdd.x));
+ ctrlPntToAdd.color.setGreen(getBezierColorByX(ctrlPntFront, ctrlPntBehind, 1, ctrlPntToAdd.x));
+ ctrlPntToAdd.color.setBlue(getBezierColorByX(ctrlPntFront, ctrlPntBehind, 2, ctrlPntToAdd.x));
+ ctrlPntToAdd.color.setAlpha(getBezierColorByX(ctrlPntFront, ctrlPntBehind, 3, ctrlPntToAdd.x));
+ ctrlPntToAdd.splineData.inLen = 1.0;
+ ctrlPntToAdd.splineData.inTan = 0.0;
+ ctrlPntToAdd.splineData.outLen = 1.0;
+ ctrlPntToAdd.splineData.outTan = 0.0;
+ _controlPoints.insert(itrToAdd, ctrlPntToAdd);
+ break;
+ }
+ case eCatmullRomSpline:
+ {
+ CatmullRomSpline splineRed;
+ CatmullRomSpline splineGreen;
+ CatmullRomSpline splineBlue;
+ CatmullRomSpline splineAlpha;
+
+ int i = index - 1;
+ for (; i >= 0; --i)
+ {
+ if (eCatmullRomSpline != _controlPoints[i].mode)
+ {
+ ++i;
+ break;
+ }
+ }
+
+ for (; i < (int)_controlPoints.size(); ++i)
+ {
+ splineRed.appendControlPoint(QPointF(_controlPoints[i].x, _controlPoints[i].color.red()));
+ splineGreen.appendControlPoint(QPointF(_controlPoints[i].x, _controlPoints[i].color.green()));
+ splineBlue.appendControlPoint(QPointF(_controlPoints[i].x, _controlPoints[i].color.blue()));
+ splineAlpha.appendControlPoint(QPointF(_controlPoints[i].x, _controlPoints[i].color.alpha()));
+ if (eCatmullRomSpline != _controlPoints[i].mode)
+ break;
+ }
+
+ QPointF pntOnSpline;
+ ColorControlPoint ctrlPntToAdd;
+ ctrlPntToAdd.mode = eCatmullRomSpline;
+ ctrlPntToAdd.x = (ctrlPntFront.x + ctrlPntBehind.x) / 2;
+ splineRed.getPointByX(ctrlPntToAdd.x, pntOnSpline);
+ rectifyColorValue(pntOnSpline);
+ ctrlPntToAdd.color.setRed(pntOnSpline.y());
+ splineGreen.getPointByX(ctrlPntToAdd.x, pntOnSpline);
+ rectifyColorValue(pntOnSpline);
+ ctrlPntToAdd.color.setGreen(pntOnSpline.y());
+ splineBlue.getPointByX(ctrlPntToAdd.x, pntOnSpline);
+ rectifyColorValue(pntOnSpline);
+ ctrlPntToAdd.color.setBlue(pntOnSpline.y());
+ splineAlpha.getPointByX(ctrlPntToAdd.x, pntOnSpline);
+ rectifyColorValue(pntOnSpline);
+ ctrlPntToAdd.color.setAlpha(pntOnSpline.y());
+ _controlPoints.insert(itrToAdd, ctrlPntToAdd);
+ break;
+ }
+ default:
+ break;
+ }
+
+ _needSample = true;
+}
+
+void ColorCurve::removeControlPoint(int index)
+{
+ std::vector<ColorControlPoint>::iterator itrToRemove = _controlPoints.begin();
+ std::advance(itrToRemove, index);
+ _controlPoints.erase(itrToRemove);
+
+ _needSample = true;
+}
+
+QColor ColorCurve::getColorByX(float x)
+{
+ if (!_initValueRange)
+ {
+ QMessageBox::critical(nullptr, QObject::tr("critical"), QObject::tr("Color curve must be initilized its value range before being used!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ return QColor();
+ }
+
+ if (x < _controlPoints[0].x)
+ return _controlPoints[0].color;
+
+ if (x >= _controlPoints[_controlPoints.size() - 1].x)
+ return _controlPoints[_controlPoints.size() - 1].color;
+
+ if (_needSample)
+ _doSamplePoints();
+
+ size_t pntCount = _colorSamplePnts.size();
+
+ if(pntCount < 2)
+ {
+ return QColor();
+ }
+
+ for (size_t i = 0; i < pntCount - 1; i++)
+ {
+ if(_colorSamplePnts[i].x <= x && _colorSamplePnts[i + 1].x > x)
+ {
+ ColorPoint& colorPnt0 = _colorSamplePnts[i];
+ ColorPoint& colorPnt1 = _colorSamplePnts[i + 1];
+ float fRate = (x - colorPnt0.x) / (colorPnt1.x - colorPnt0.x);
+
+ float red = colorPnt0.color.red() + fRate * (colorPnt1.color.red() - colorPnt0.color.red());
+ rectifyColorValue(red);
+ float green = colorPnt0.color.green() + fRate * (colorPnt1.color.green() - colorPnt0.color.green());
+ rectifyColorValue(green);
+ float blue = colorPnt0.color.blue() + fRate * (colorPnt1.color.blue() - colorPnt0.color.blue());
+ rectifyColorValue(blue);
+ float alpha = colorPnt0.color.alpha() + fRate * (colorPnt1.color.alpha() - colorPnt0.color.alpha());
+ rectifyColorValue(alpha);
+
+ return QColor(red, green, blue, alpha);
+ }
+ }
+
+ return QColor();
+}
+
+ColorCurve& ColorCurve::operator = (const ColorCurve& right)
+{
+ if (this == &right)
+ return *this;
+
+ _needSample = right._needSample;
+ _initValueRange = right._initValueRange;
+ _minValue = right._minValue;
+ _maxValue = right._maxValue;
+ _segmentCount = right._segmentCount;
+ _colorSamplePnts = right._colorSamplePnts;
+ _controlPoints = right._controlPoints;
+
+ return *this;
+}
+
+BezierSpline _generateColorBezierSpline(ColorControlPoint& ctrlPntFront, ColorControlPoint& ctrlPntBehind, int component, int numSegments = 100)
+{
+ BezierSplinePoint bezierPnt0;
+ BezierSplinePoint bezierPnt1;
+
+ QColor colorFront = ctrlPntFront.color;
+ if (!ctrlPntFront.texturePath.empty())
+ colorFront = ctrlPntFront.textureAverageColor;
+ QColor colorBehind = ctrlPntBehind.color;
+ if (!ctrlPntBehind.texturePath.empty())
+ colorBehind = ctrlPntBehind.textureAverageColor;
+
+ float y0 = 0.0f, y1 = 0.0f;
+ switch (component) {
+ case 0:
+ y0 = colorFront.red();
+ y1 = colorBehind.red();
+ break;
+ case 1:
+ y0 = colorFront.green();
+ y1 = colorBehind.green();
+ break;
+ case 2:
+ y0 = colorFront.blue();
+ y1 = colorBehind.blue();
+ break;
+ case 3:
+ y0 = colorFront.alpha();
+ y1 = colorBehind.alpha();
+ break;
+ default:
+ break;
+ }
+
+ QPointF pntFront = QPointF(ctrlPntFront.x, y0);
+ QPointF pntBehind = QPointF(ctrlPntBehind.x, y1);
+ float xStride = ctrlPntBehind.x - ctrlPntFront.x;
+ bezierPnt0.ctrlPoint0 = pntFront;
+ bezierPnt0.valuePoint = pntFront;
+ float xDelta = ctrlPntFront.splineData.outLen * xStride;
+ bezierPnt0.ctrlPoint1 = pntFront + QPointF(xDelta, xDelta * ctrlPntFront.splineData.outTan);
+
+ if (eBezierSpline == ctrlPntBehind.mode)
+ {
+ xDelta = ctrlPntBehind.splineData.inLen * xStride;
+ bezierPnt1.ctrlPoint0 = pntBehind - QPointF(xDelta, xDelta * ctrlPntBehind.splineData.inTan);
+ bezierPnt1.valuePoint = pntBehind;
+ bezierPnt1.ctrlPoint1 = pntBehind;
+ }
+ else
+ {
+ bezierPnt1.ctrlPoint0 = pntBehind;
+ bezierPnt1.valuePoint = pntBehind;
+ bezierPnt1.ctrlPoint1 = pntBehind;
+ }
+
+ BezierSpline spline(numSegments);
+ spline.appendControlPoint(bezierPnt0);
+ spline.appendControlPoint(bezierPnt1);
+ return spline;
+}
+
+void _doBezierColorSample(ColorControlPoint& ctrlPntFront, ColorControlPoint& ctrlPntBehind, std::vector<ColorPoint>& colorSamplePnts, int numSegments = 100)
+{
+ BezierSpline redSpline = _generateColorBezierSpline(ctrlPntFront, ctrlPntBehind, 0, numSegments);
+ BezierSpline greenSpline = _generateColorBezierSpline(ctrlPntFront, ctrlPntBehind, 1, numSegments);
+ BezierSpline blueSpline = _generateColorBezierSpline(ctrlPntFront, ctrlPntBehind, 2, numSegments);
+ BezierSpline alphaSpline = _generateColorBezierSpline(ctrlPntFront, ctrlPntBehind, 3, numSegments);
+
+ std::vector<QPointF> redSamplePnts = redSpline.getSamplePoints();
+ std::vector<QPointF> greenSamplePnts = greenSpline.getSamplePoints();
+ std::vector<QPointF> blueSamplePnts = blueSpline.getSamplePoints();
+ std::vector<QPointF> alphaSamplePnts = alphaSpline.getSamplePoints();
+
+ size_t samplePntsCount = redSamplePnts.size();
+ for (size_t i = 0; i < samplePntsCount; ++i)
+ {
+ colorSamplePnts.push_back(ColorPoint(redSamplePnts[i].x() , QColor(redSamplePnts[i].y()
+ , greenSamplePnts[i].y()
+ , blueSamplePnts[i].y()
+ , alphaSamplePnts[i].y())));
+ }
+}
+
+float saturate( float v)
+{
+ if( v < 0.0 ) v = 0.0;
+ if( v > 1.0 ) v = 1.0;
+ return v;
+}
+
+float _GetRatio(float s, float weight, float fallOff)
+{
+ float ratio = s;
+
+ // add bias for first/second color variation
+ if (weight < 0.5f)
+ {
+ float slope = 2.0f * weight;
+ ratio = slope * ratio;
+ }
+ else
+ {
+ float slope = 2.0f * (1.0f - weight) ;
+ ratio = slope * (ratio - 1.0f) + 1.0f;
+ }
+
+ // modify ratio for falloff
+ float slope = 1.0f / (fallOff + 0.001f);
+ ratio = saturate(0.5f + slope * (ratio - 0.5f));
+
+ return ratio;
+}
+
+void ColorCurve::_doSamplePoints()
+{
+ _colorSamplePnts.clear();
+
+ for (long i = 1; i < _controlPoints.size(); ++i)
+ {
+ ColorControlPoint& ctrlPntFront = _controlPoints[i-1];
+ ColorControlPoint& ctrlPntBehind = _controlPoints[i];
+ QColor colorFront = ctrlPntFront.color;
+ if (!ctrlPntFront.texturePath.empty())
+ colorFront = ctrlPntFront.textureAverageColor;
+ QColor colorBehind = ctrlPntBehind.color;
+ if (!ctrlPntBehind.texturePath.empty())
+ colorBehind = ctrlPntBehind.textureAverageColor;
+
+ switch (ctrlPntFront.mode)
+ {
+ case eDiscret:
+ {
+ _colorSamplePnts.push_back(ColorPoint(ctrlPntFront.x, colorFront));
+ _colorSamplePnts.push_back(ColorPoint(ctrlPntBehind.x, colorFront));
+ break;
+ }
+ case eLinear:
+ {
+ for (long j = 0; j <= _segmentCount; ++j)
+ {
+ float s = (float)j / _segmentCount;
+ float ratio = s;
+ if (ctrlPntBehind.weight >= 0)
+ ratio = _GetRatio(s, ctrlPntFront.weight, ctrlPntFront.fallOff);
+
+ float xPos = ctrlPntFront.x + s * (ctrlPntBehind.x - ctrlPntFront.x);
+
+ int red = colorBehind.red() - colorFront.red();
+ int green = colorBehind.green() - colorFront.green();
+ int blue = colorBehind.blue() - colorFront.blue();
+ int alpha = colorBehind.alpha() - colorFront.alpha();
+
+ QColor color(colorFront.red() + ratio * red
+ , colorFront.green() + ratio * green
+ , colorFront.blue() + ratio * blue
+ , colorFront.alpha() + ratio * alpha);
+ _colorSamplePnts.push_back(ColorPoint(xPos, color));
+ }
+ break;
+ }
+ case eBezierSpline:
+ {
+ _doBezierColorSample(ctrlPntFront, ctrlPntBehind, _colorSamplePnts, _segmentCount);
+ break;
+ }
+ case eCatmullRomSpline:
+ {
+ CatmullRomSpline redSpline(_segmentCount);
+ CatmullRomSpline greenSpline(_segmentCount);
+ CatmullRomSpline blueSpline(_segmentCount);
+ CatmullRomSpline alphaSpline(_segmentCount);
+
+ for (i = i - 1; i < _controlPoints.size(); ++i)
+ {
+ QColor color = _controlPoints[i].color;
+ if (!_controlPoints[i].texturePath.empty())
+ color = _controlPoints[i].textureAverageColor;
+ redSpline.appendControlPoint(QPointF(_controlPoints[i].x, color.red()));
+ greenSpline.appendControlPoint(QPointF(_controlPoints[i].x, color.green()));
+ blueSpline.appendControlPoint(QPointF(_controlPoints[i].x, color.blue()));
+ alphaSpline.appendControlPoint(QPointF(_controlPoints[i].x, color.alpha()));
+ if (eCatmullRomSpline != _controlPoints[i].mode)
+ {
+ break;
+ }
+ }
+
+ std::vector<QPointF> redSamplePnts = redSpline.getSamplePoints();
+ std::vector<QPointF> greenSamplePnts = greenSpline.getSamplePoints();
+ std::vector<QPointF> blueSamplePnts = blueSpline.getSamplePoints();
+ std::vector<QPointF> alphaSamplePnts = alphaSpline.getSamplePoints();
+
+ size_t samplePntsCount = redSamplePnts.size();
+ for (size_t i = 0; i < samplePntsCount; ++i)
+ {
+ rectifyColorValue(redSamplePnts[i]);
+ rectifyColorValue(greenSamplePnts[i]);
+ rectifyColorValue(blueSamplePnts[i]);
+ rectifyColorValue(alphaSamplePnts[i]);
+ _colorSamplePnts.push_back(ColorPoint(redSamplePnts[i].x() , QColor(redSamplePnts[i].y()
+ , greenSamplePnts[i].y()
+ , blueSamplePnts[i].y()
+ , alphaSamplePnts[i].y())));
+ }
+
+ break;
+ }
+ }
+ }
+
+ _needSample = false;
+}
+
+void ColorCurve::_reOrderControlPoints(int& pickedPoint)
+{
+ for (size_t i = 0; i < _controlPoints.size() - 1; ++i)
+ {
+ if (_controlPoints[i].x > _controlPoints[i+1].x)
+ {
+ ColorControlPoint temp = _controlPoints[i];
+ _controlPoints[i] = _controlPoints[i + 1];
+ _controlPoints[i + 1] = temp;
+
+ if (pickedPoint == i)
+ pickedPoint = (int)(i + 1);
+ else if (pickedPoint == (i + 1) )
+ pickedPoint = (int)i;
+
+ break;
+ }
+ }
+}
+
+QColor ColorCurve::_calcTextureAverageColor(const char* texturePath)
+{
+ QImage img(texturePath);
+ double red = 0, green = 0, blue = 0, alpha = 0;
+
+ // Try stb_image for .TGA
+ int width = 0;
+ int height = 0;
+ int numComponents = 0;
+ unsigned char *pSTBIRes = stbi_load(texturePath, &width, &height, &numComponents, 4);
+
+ if (!pSTBIRes)
+ return QColor(0, 0, 0);
+
+ int colorCount = width * height;
+ unsigned int* pixels = (unsigned int*)pSTBIRes;
+
+ for (int i = 0; i < height; ++i)
+ {
+ for (int j = 0; j < width; ++j)
+ {
+ QRgb pixel = *pixels++;
+ QColor color(pixel);
+ red += color.redF();
+ green += color.greenF();
+ blue += color.blueF();
+ alpha += color.alphaF();
+ }
+ }
+
+ if (colorCount != 0)
+ {
+ red /= colorCount;
+ green /= colorCount;
+ blue /= colorCount;
+ alpha /= colorCount;
+ }
+
+ QColor color;
+ color.setRgbF(red, green, blue, alpha);
+ return color;
+}
+
+} // namespace CurveEditor
+} // namespace nvidia \ No newline at end of file
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Curve/Spline.cpp b/NvBlast/tools/CurveEditor/source/Internal/Curve/Spline.cpp
new file mode 100644
index 0000000..c40a4f9
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Curve/Spline.cpp
@@ -0,0 +1,151 @@
+#include "Spline.h"
+
+namespace nvidia {
+namespace CurveEditor {
+
+Spline::Spline(long segmentCount)
+ : _needSample(true)
+ , _samplePoints()
+ , _edgeLengths()
+ , _totolLength(0.0f)
+{
+ _segmentCount = segmentCount < 1 ? 1 : segmentCount;
+}
+
+Spline::~Spline(void)
+{
+}
+
+bool Spline::getPercentPoint(float percent, QPointF& point)
+{
+ long lPointCount = (long)_samplePoints.size();
+
+ if (lPointCount == 0)
+ {
+ return false;
+ }
+ else if (lPointCount == 1)
+ {
+ point = _samplePoints[0];
+ return true;
+ }
+
+ if (_needSample)
+ _sample();
+
+ if (percent > 1.0)
+ {
+ percent -= (int)percent;
+ }
+
+ if (percent < 0.0)
+ {
+ percent += (int)(-percent) + 1;
+ }
+
+ if (percent <= 0.0)
+ {
+ // return begin point
+ point = _samplePoints[0];
+ return true;
+ }
+ else if (percent >= 1.0)
+ {
+ // return end point
+ point = _samplePoints[_samplePoints.size() - 1];
+ return true;
+ }
+
+ float fCurPos = _totolLength * percent;
+ int index = 0;
+
+ {// get edge's index the point is on based on the percent value
+ long lEdgeCount = (long)_edgeLengths.size();
+ for ( ; index < lEdgeCount; index++)
+ {
+ if (fCurPos < _edgeLengths[index])
+ {
+ break;
+ }
+
+ fCurPos -= _edgeLengths[index];
+ }
+
+ if (index == lEdgeCount)
+ {
+ point = _samplePoints[_samplePoints.size() - 1];
+ return true;
+ }
+ }
+
+ QPointF v1 = _samplePoints[index];
+ QPointF v2 = _samplePoints[index + 1];
+
+ point = v1 + (v2 - v1) * (fCurPos / _edgeLengths[index]);
+
+ return true;
+}
+
+bool Spline::getPointByX(float x, QPointF& point)
+{
+ if (_needSample)
+ _sample();
+
+ long lPointCount = (long)_samplePoints.size();
+
+ if(lPointCount < 2)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < lPointCount - 1; i++)
+ {
+ if(_samplePoints[i].x() <= x && _samplePoints[i + 1].x() > x)
+ {
+ point.setX( x );
+ float fRate = (x - _samplePoints[i].x())/ (_samplePoints[i + 1].x() - _samplePoints[i].x());
+ point.setY(_samplePoints[i].y() + (_samplePoints[i+1].y() - _samplePoints[i].y()) * fRate);
+ return true;
+ }
+ }
+ return false;
+}
+
+void Spline::setSegmentCount(long segmentCount)
+{
+ _segmentCount = segmentCount < 1 ? 1 : segmentCount;
+ _needSample = true;
+}
+
+std::vector<QPointF> Spline::getSamplePoints()
+{
+ if (_needSample)
+ _sample();
+ return _samplePoints;
+}
+
+void Spline::_sample()
+{
+ _samplePoints.clear();
+
+ _doSample();
+
+ // get all edges length and total length
+ _totolLength = 0;
+ _edgeLengths.clear();
+ float fEdgeLength;
+
+ long lPointCount = (long)_samplePoints.size();
+ for (int i = 1; i < lPointCount; i++)
+ {
+ QPointF dist = _samplePoints[i] - _samplePoints[i - 1];
+ fEdgeLength = (sqrt(dist.x()*dist.x() + dist.y() + dist.y()));
+ _edgeLengths.push_back(fEdgeLength);
+ _totolLength += fEdgeLength;
+ }
+
+ _needSample = false;
+}
+
+} // namespace CurveEditor
+} // namespace nvidia \ No newline at end of file
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Curve/Spline.h b/NvBlast/tools/CurveEditor/source/Internal/Curve/Spline.h
new file mode 100644
index 0000000..fc111a7
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Curve/Spline.h
@@ -0,0 +1,43 @@
+#ifndef Spline_h__
+#define Spline_h__
+#include <vector>
+#include <QtCore/QPointF>
+
+namespace nvidia {
+namespace CurveEditor {
+
+class Spline
+{
+public:
+ Spline(long segmentCount = 100);
+ virtual ~Spline(void) = 0;
+
+ // return the point which lies on the polyline after sample.
+ // percent: the length between the returned point and the begin point along the polyline after sample
+ // ������������������������������������������������������������������������������������������
+ // the length between the end point and the begin point along the polyline after sample
+ // [0.0, 1.0]
+ bool getPercentPoint(float percent, QPointF& point);
+
+ bool getPointByX(float x, QPointF& point);
+
+ void setSegmentCount(long segmentCount);
+
+ std::vector<QPointF> getSamplePoints();
+
+protected:
+ void _sample();
+ virtual void _doSample() = 0;
+
+protected:
+ bool _needSample;
+ long _segmentCount;
+ std::vector<QPointF> _samplePoints;
+ std::vector<float> _edgeLengths; // the number of edges + 1 == the number of sample points
+ float _totolLength;// the total length of all edges
+};
+
+} // namespace CurveEditor
+} // namespace nvidia
+
+#endif // Spline_h__
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Window/AlphaDialog.cpp b/NvBlast/tools/CurveEditor/source/Internal/Window/AlphaDialog.cpp
new file mode 100644
index 0000000..a51a802
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Window/AlphaDialog.cpp
@@ -0,0 +1,181 @@
+#include "AlphaDialog.h"
+#include "ui_AlphaDialog.h"
+#include <QtGui/QPaintEvent>
+#include <QtGui/QPainter>
+#include <QtGui/QPainterPath>
+
+namespace nvidia {
+namespace CurveEditor {
+
+const int MARGIN_X = 8;
+const int MARGIN_Y = 8;
+
+const int ALPHA_W = 255;
+const int ALPHA_H = 30;
+
+const int CURSOR_W = 12;
+const int CURSOR_H = 12;
+
+static QImage s_triangleUp;
+
+void InitTriangleResources(int w, int h)
+{
+ s_triangleUp = QImage(w, h, QImage::Format_ARGB32);
+ s_triangleUp.fill(QColor(0, 0, 0, 0));
+
+ // a painter cannot switch device?
+ QPainterPath path;
+ QPainter painter(&s_triangleUp);
+ painter.setRenderHint(QPainter::Antialiasing,true);
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(w>>1, 0);
+ path.lineTo(0, h);
+ path.lineTo(w, h);
+ path.lineTo(w>>1, 0);
+ painter.setPen(Qt::NoPen);
+ painter.fillPath(path, QBrush(QColor(50, 50, 50)));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool isClickedInCursor(const QPoint& cursorPos, const QPoint& p)
+{
+ QVector<QPoint> points;
+ points.push_back(cursorPos);
+ points.push_back(QPoint(cursorPos.x() - (CURSOR_W>>1), cursorPos.y() + CURSOR_H));
+ points.push_back(QPoint(cursorPos.x() + (CURSOR_W>>1), cursorPos.y() + CURSOR_H));
+ points.push_back(cursorPos);
+
+ QPolygon polygon(points);
+ return polygon.containsPoint(p, Qt::OddEvenFill);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+ int AlphaDialog::getAlpha(int alpha, QWidget *parent)
+ {
+ AlphaDialog dlg(parent, alpha);
+ dlg.exec();
+ return dlg._alpha;
+ }
+
+//////////////////////////////////////////////////////////////////////////////
+AlphaDialog::AlphaDialog(QWidget *parent, int alpha) :
+ QDialog(parent),
+ ui(new Ui::AlphaDialog),
+ _drag(false),
+ _alpha(alpha),
+ _xOffset(0)
+{
+ ui->setupUi(this);
+ setWindowFlags(windowFlags()&~Qt::WindowContextHelpButtonHint);
+ setFixedWidth(271);
+ setFixedHeight(120);
+
+ ui->spinBoxAlpha->setValue(_alpha);
+
+ InitTriangleResources(12, 12);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+AlphaDialog::~AlphaDialog()
+{
+ delete ui;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void AlphaDialog::paintEvent(QPaintEvent * e)
+{
+ QDialog::paintEvent(e);
+
+ QPainter painter;
+ painter.begin(this);
+ drawAlphaRectangle(painter);
+ drawCursor(painter, _alpha + MARGIN_X);
+ painter.end();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void AlphaDialog::mousePressEvent( QMouseEvent* e )
+{
+ if(e->button() & Qt::LeftButton)
+ {
+ QPoint mousePos = e->pos();
+
+ if (isClickedInCursor(QPoint(_alpha + MARGIN_X, MARGIN_Y + ALPHA_H), mousePos))
+ {
+ _xOffset = _alpha + MARGIN_X - mousePos.x();
+ _drag = true;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void AlphaDialog::mouseReleaseEvent( QMouseEvent* e )
+{
+ _drag = false;
+ _xOffset = -1;
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void AlphaDialog::mouseMoveEvent( QMouseEvent* e )
+{
+ Qt::MouseButtons buttons = e->buttons();
+
+ if(buttons & Qt::LeftButton)
+ {
+ if (_drag)
+ {
+ QPoint mousePos = e->pos();
+
+ _alpha = mousePos.x() + _xOffset - MARGIN_X;
+ if (_alpha < 0)
+ {
+ _alpha = 0;
+ }
+ else if(_alpha > ALPHA_W)
+ {
+ _alpha = ALPHA_W;
+ }
+ ui->spinBoxAlpha->setValue(_alpha);
+ update();
+ }
+ }
+}
+
+void AlphaDialog::drawAlphaRectangle(QPainter& painter)
+{
+ QPointF topLeftPnt(MARGIN_X, MARGIN_Y);
+ QPointF topRightPnt(MARGIN_X + ALPHA_W, MARGIN_Y);
+ QPointF bottomRightPnt(MARGIN_X + ALPHA_W, MARGIN_Y + ALPHA_H);
+ QPointF bottomLeftPnt(MARGIN_X, MARGIN_Y + ALPHA_H);
+ QPainterPath path;
+ path.moveTo(topLeftPnt);
+ path.lineTo(topRightPnt);
+ path.lineTo(bottomRightPnt);
+ path.lineTo(bottomLeftPnt);
+
+ QColor colorLeft(0, 0, 0, 255);
+ QColor colorRight(255, 255, 255, 255);
+ colorLeft.setAlpha(255);
+ colorRight.setAlpha(255);
+ QLinearGradient indicatorGradient(topLeftPnt,topRightPnt);
+ indicatorGradient.setColorAt(0.0, colorLeft);
+ indicatorGradient.setColorAt(1.0, colorRight);
+
+ painter.fillPath(path, indicatorGradient);
+}
+
+void AlphaDialog::drawCursor(QPainter& painter, int xPos)
+{
+ QRect rect(xPos - (CURSOR_W>>1), MARGIN_Y + ALPHA_H, CURSOR_W, CURSOR_H);
+ painter.drawImage(rect, s_triangleUp);
+
+}
+
+void AlphaDialog::on_spinBoxAlpha_valueChanged(int arg1)
+{
+ _alpha = arg1;
+}
+
+} // namespace CurveEditor
+} // namespace nvidia \ No newline at end of file
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Window/AlphaDialog.h b/NvBlast/tools/CurveEditor/source/Internal/Window/AlphaDialog.h
new file mode 100644
index 0000000..985d0b4
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Window/AlphaDialog.h
@@ -0,0 +1,47 @@
+#ifndef ALPHADIALOG_H
+#define ALPHADIALOG_H
+
+#include <QtWidgets/QDialog>
+
+namespace Ui {
+ class AlphaDialog;
+}
+
+namespace nvidia {
+namespace CurveEditor {
+
+class AlphaDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ static int getAlpha(int alpha = 255, QWidget *parent = 0);
+
+ explicit AlphaDialog(QWidget *parent = 0, int alpha = 255);
+ ~AlphaDialog();
+
+protected:
+ // QWidget events
+ virtual void paintEvent(QPaintEvent * e);
+
+ virtual void mousePressEvent(QMouseEvent* e);
+ virtual void mouseReleaseEvent(QMouseEvent* e);
+ virtual void mouseMoveEvent(QMouseEvent* e);
+private slots:
+ void on_spinBoxAlpha_valueChanged(int arg1);
+
+private:
+ void drawAlphaRectangle(QPainter& painter);
+ void drawCursor(QPainter& painter, int xPos);
+
+private:
+ Ui::AlphaDialog *ui;
+ bool _drag;
+ int _alpha;
+ int _xOffset;
+};
+
+} // namespace CurveEditor
+} // namespace nvidia
+
+#endif // ALPHADIALOG_H
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Window/ColorWidget.cpp b/NvBlast/tools/CurveEditor/source/Internal/Window/ColorWidget.cpp
new file mode 100644
index 0000000..a84ee70
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Window/ColorWidget.cpp
@@ -0,0 +1,1724 @@
+#include "ColorWidget.h"
+#include <QtGui/QPaintEvent>
+#include <QtGui/QPainter>
+#include <QtGui/QPainterPath>
+#include <QtGui/QImage>
+#include <assert.h>
+#include <QtCore/QDebug>
+#include <QtCore/QTime>
+#include <QtWidgets/QToolTip>
+#include "CurveEditorMainWindow.h"
+
+namespace nvidia {
+namespace CurveEditor {
+
+const int MARGIN_X = 8;
+const int MARGIN_Y = 4;
+const int CONTROL_POINT_CURSOR_W = 12;
+const int CONTROL_POINT_CURSOR_H = 12;
+const int WEIGHT_CURSOR_W = 6;
+const int WEIGHT_CURSOR_H = 6;
+const int SPACING_V = 0;
+
+static QImage S_CtrlPntWithTexCursorNormalImg;
+static QImage S_CtrlPntWithTexCursorPickedImg;
+static QImage S_WeightCursorNormalImg;
+static QImage S_WeightCursorPickedImg;
+
+#define ROUND(v) (int(v + 0.5))
+
+class TimeConsumeTracker
+{
+public:
+ TimeConsumeTracker(QString text)
+ : _text(text)
+ {
+ _time.start();
+ }
+
+ ~TimeConsumeTracker()
+ {
+ qDebug()<<_text<<" consume: "<<_time.elapsed();
+ }
+
+ QTime _time;
+ QString _text;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+void InitCursorResources()
+{
+ int w = CONTROL_POINT_CURSOR_W;
+ int h = CONTROL_POINT_CURSOR_H;
+ S_CtrlPntWithTexCursorNormalImg = QImage(w, h, QImage::Format_ARGB32);
+ S_CtrlPntWithTexCursorPickedImg = QImage(w, h, QImage::Format_ARGB32);
+ S_CtrlPntWithTexCursorNormalImg.fill(QColor(0, 0, 0, 0));
+ S_CtrlPntWithTexCursorPickedImg.fill(QColor(0, 0, 0, 0));
+
+ ///////////////////////////////////////////////////////////////////////////
+ QPainter painter(&S_CtrlPntWithTexCursorNormalImg);
+ painter.setRenderHint(QPainter::Antialiasing, true);
+ QPainterPath path; // trick to clear up a path
+ path.moveTo(w >> 1, 0);
+ path.lineTo(w >> 2, h >> 2);
+ path.lineTo(w >> 1, h >> 1);
+ path.lineTo((w >> 1) + (w >> 2), h >> 2);
+ path.lineTo(w >> 1, 0);
+ painter.setPen(Qt::NoPen);
+ painter.fillPath(path, QBrush(QColor(255, 255, 255)));
+
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(w >> 2, h >> 2);
+ path.lineTo(0, h >> 1);
+ path.lineTo(w >> 2, (h >> 1) + (h >> 2));
+ path.lineTo(w >> 1, h >> 1);
+ path.lineTo(w >> 2, h >> 2);
+ painter.setPen(Qt::NoPen);
+ painter.fillPath(path, (QColor(0, 0, 0)));
+
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(w >> 1, h >> 1);
+ path.lineTo(w >> 2, (h >> 1) + (h >> 2));
+ path.lineTo(w >> 1, h);
+ path.lineTo((w >> 1) + (w >> 2), (h >> 1) + (h >> 2));
+ path.lineTo(w >> 1, h >> 1);
+ painter.setPen(Qt::NoPen);
+ painter.fillPath(path, QBrush(QColor(255, 255, 255)));
+
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo((w >> 1) + (w >> 2), h >> 2);
+ path.lineTo(w >> 1, h >> 1);
+ path.lineTo((w >> 1) + (w >> 2), (h >> 1) + (h >> 2));
+ path.lineTo(w, h >> 1);
+ path.lineTo((w >> 1) + (w >> 2), h >> 2);
+ painter.setPen(Qt::NoPen);
+ painter.fillPath(path, (QColor(0, 0, 0)));
+
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(w >> 1, 0);
+ path.lineTo(0, h >> 1);
+ path.lineTo(w >> 1, h);
+ path.lineTo(w, h >> 1);
+ path.lineTo(w >> 1, 0);
+ painter.setPen(QPen(Qt::white, 1, Qt::SolidLine));
+ painter.drawPath(path);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // a painter cannot switch device?
+ QPainter painter2(&S_CtrlPntWithTexCursorPickedImg);
+ painter2.setRenderHint(QPainter::Antialiasing,true);
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(w>>1, 0);
+ path.lineTo(w>>2, h>>2);
+ path.lineTo(w>>1, h>>1);
+ path.lineTo((w>>1)+(w>>2), h>>2);
+ path.lineTo(w>>1, 0);
+ painter2.setPen(Qt::NoPen);
+ painter2.fillPath(path, QBrush(QColor(255, 255, 255)));
+
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(w>>2, h>>2);
+ path.lineTo(0, h>>1);
+ path.lineTo(w>>2, (h>>1)+(h>>2));
+ path.lineTo(w>>1, h>>1);
+ path.lineTo(w>>2, h>>2);
+ painter2.setPen(Qt::NoPen);
+ painter2.fillPath(path, (QColor(0, 0, 0)));
+
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(w>>1, h>>1);
+ path.lineTo(w>>2, (h>>1)+(h>>2));
+ path.lineTo(w>>1, h);
+ path.lineTo((w>>1)+(w>>2), (h>>1)+(h>>2));
+ path.lineTo(w>>1, h>>1);
+ painter2.setPen(Qt::NoPen);
+ painter2.fillPath(path, QBrush(QColor(255, 255, 255)));
+
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo((w>>1)+(w>>2), h>>2);
+ path.lineTo(w>>1, h>>1);
+ path.lineTo((w>>1)+(w>>2), (h>>1)+(h>>2));
+ path.lineTo(w, h>>1);
+ path.lineTo((w>>1)+(w>>2), h>>2);
+ painter2.setPen(Qt::NoPen);
+ painter2.fillPath(path, (QColor(0, 0, 0)));
+
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(w>>1, 0);
+ path.lineTo(0, h>>1);
+ path.lineTo(w>>1, h);
+ path.lineTo(w, h>>1);
+ path.lineTo(w>>1, 0);
+ painter2.setPen(QPen(Qt::green,1, Qt::SolidLine));
+ painter2.drawPath(path);
+
+ ///////////////////////////////////////////////////////////////////////////
+ w = WEIGHT_CURSOR_W;
+ h = WEIGHT_CURSOR_H;
+ S_WeightCursorNormalImg = QImage(w, h, QImage::Format_ARGB32);
+ S_WeightCursorPickedImg = QImage(w, h, QImage::Format_ARGB32);
+ S_WeightCursorNormalImg.fill(QColor(0, 0, 0, 0));
+ S_WeightCursorPickedImg.fill(QColor(0, 0, 0, 0));
+ ///////////////////////////////////////////////////////////////////////////
+ QPainter painter3(&S_WeightCursorNormalImg);
+ painter3.setRenderHints(QPainter::Antialiasing,true);
+
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(w>>1, 0);
+ path.lineTo(0, h>>1);
+ path.lineTo(w>>1, h);
+ path.lineTo(w, h>>1);
+ path.lineTo(w>>1, 0);
+ painter3.setPen(QPen(Qt::black, 1, Qt::SolidLine));
+ painter3.drawPath(path);
+ painter3.fillPath(path, QBrush(QColor(255, 255, 255)));
+
+ ///////////////////////////////////////////////////////////////////////////
+ QPainter painter4(&S_WeightCursorPickedImg);
+ painter4.setRenderHints(QPainter::Antialiasing,true);
+
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(w>>1, 0);
+ path.lineTo(0, h>>1);
+ path.lineTo(w>>1, h);
+ path.lineTo(w, h>>1);
+ path.lineTo(w>>1, 0);
+ painter4.setPen(QPen(Qt::black, 1, Qt::SolidLine));
+ painter4.drawPath(path);
+ painter4.fillPath(path, QBrush(QColor(0, 0, 0)));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+float NDCToScreenCoord(QWidget* pWidget, float xValueOfUnitInterval)
+{
+ int w = pWidget->width();
+ return MARGIN_X + (w - MARGIN_X * 2.0) * xValueOfUnitInterval;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+float _screenToNDC(QWidget* pWidget, int xPos)
+{
+ int w = pWidget->width();
+ return ((float)(xPos - MARGIN_X)) / (w - MARGIN_X * 2.0f);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool isClickedInCtrlPntCursor(const QPointF& cursorPos, const QPointF& p)
+{
+ QVector<QPointF> points;
+ points.push_back(cursorPos);
+ points.push_back(QPointF(cursorPos.x() - CONTROL_POINT_CURSOR_W/2, cursorPos.y() + CONTROL_POINT_CURSOR_H/2));
+ points.push_back(QPointF(cursorPos.x(), cursorPos.y() + CONTROL_POINT_CURSOR_H));
+ points.push_back(QPointF(cursorPos.x() + CONTROL_POINT_CURSOR_W/2, cursorPos.y() + CONTROL_POINT_CURSOR_H/2));
+ points.push_back(cursorPos);
+ QPolygonF polygon(points);
+ return polygon.containsPoint(p, Qt::OddEvenFill);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool isClickedInWeightCursor(const QPointF& cursorPos, const QPointF& p)
+{
+ QVector<QPointF> points;
+ points.push_back(cursorPos);
+ points.push_back(QPointF(cursorPos.x() - WEIGHT_CURSOR_W/2, cursorPos.y() + WEIGHT_CURSOR_H/2));
+ points.push_back(QPointF(cursorPos.x(), cursorPos.y() + WEIGHT_CURSOR_H));
+ points.push_back(QPointF(cursorPos.x() + WEIGHT_CURSOR_W/2, cursorPos.y() + WEIGHT_CURSOR_H/2));
+ points.push_back(cursorPos);
+ QPolygonF polygon(points);
+ return polygon.containsPoint(p, Qt::OddEvenFill);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QImage genControlPointCursorImg(const QColor& color, bool picked = false)
+{
+ int w = CONTROL_POINT_CURSOR_W;
+ int h = CONTROL_POINT_CURSOR_H;
+ QImage image = QImage(w, h, QImage::Format_ARGB32);
+ image.fill(QColor(0, 0, 0, 0));
+
+ QPainter painter(&image);
+ painter.setRenderHints(QPainter::Antialiasing,true);
+
+ QPainterPath path;
+ path.moveTo(w>>1, 0);
+ path.lineTo(0, h>>1);
+ path.lineTo(w>>1, h);
+ path.lineTo(w, h>>1);
+ path.lineTo(w>>1, 0);
+ if (picked)
+ {
+ painter.setPen(QPen(Qt::green, 1, Qt::SolidLine));
+ painter.drawPath(path);
+ }
+
+ painter.fillPath(path, QBrush(color));
+
+ return image;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+ColorWidget::ColorWidget(QWidget *parent) :
+ QFrame(parent),
+ _isLink(false),
+ _colorAttribute(nullptr),
+ _colorCurve(nullptr),
+ _alphaCurve(nullptr),
+ _canAddRemoveControlPoint(false),
+ _canAddCtrlPntByClick(false),
+ _canRemoveCtrlPntByClick(false),
+ _curveFitWindowScale(1),
+ _curveFitWindowOffset(0),
+ _pickedColorCtrlPnt(-1),
+ _pickedAlphaCtrlPnt(-1),
+ _pickedColorWeight(-1),
+ _pickedAlphaWeight(-1),
+ _dragColorCtrlPnt(false),
+ _dragAlphaCtrlPnt(false),
+ _dragColorWeight(false),
+ _dragAlphaWeight(false),
+ _colorCtrlPntToRemove(-1),
+ _alphaCtrlPntToRemove(-1),
+ _contextMenu(nullptr),
+ _removeCtrlPntAction(nullptr)
+{
+ setFocusPolicy(Qt::ClickFocus );
+
+ InitCursorResources();
+
+ setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(onShowContextMenu(const QPoint&)));
+
+ _contextMenu = new QMenu(this);;
+ _removeCtrlPntAction = new QAction(this);
+ _removeCtrlPntAction->setText(tr("Remove Control Point"));
+ _contextMenu->addAction(_removeCtrlPntAction);
+
+ connect(_removeCtrlPntAction, SIGNAL(triggered()), this, SLOT(onRemoveControlPoint()) );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QColor ColorWidget::getColor()
+{
+ QColor color;
+ if (_pickedColorCtrlPnt != -1)
+ {
+ color = _colorCurve->getControlPoint(_pickedColorCtrlPnt).color;
+ }
+ return color;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+int ColorWidget::getAlpha()
+{
+ if (_pickedAlphaCtrlPnt != -1)
+ {
+ if (_isLink)
+ {
+ return _colorCurve->getControlPoint(_pickedAlphaCtrlPnt).color.alpha();
+ }
+ else
+ {
+ return _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt).color.alpha();
+ }
+ }
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setColor(const QColor& color)
+{
+ if (_pickedColorCtrlPnt != -1)
+ {
+ ColorControlPoint pickedColorPnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+
+ pickedColorPnt.color.setRed(color.red());
+ pickedColorPnt.color.setGreen(color.green());
+ pickedColorPnt.color.setBlue(color.blue());
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, pickedColorPnt);
+
+ emit ColorAttributeChanged(_colorAttribute);
+ update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setAlpha(int alpha)
+{
+ if (_pickedColorCtrlPnt != -1)
+ {
+ ColorControlPoint pickedColorPnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ pickedColorPnt.color.setAlpha(alpha);
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, pickedColorPnt);
+
+ emit ColorAttributeChanged(_colorAttribute);
+ update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+float ColorWidget::getColorFallOff()
+{
+ if (_colorCurve && -1 != _pickedColorCtrlPnt)
+ {
+ const ColorControlPoint& pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ return pnt.fallOff;
+ }
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setColorFallOff(float fallOff)
+{
+ if (_colorCurve && -1 != _pickedColorCtrlPnt)
+ {
+ ColorControlPoint pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ pnt.fallOff = fallOff;
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+float ColorWidget::getAlphaFallOff()
+{
+ if (_isLink)
+ {
+ if (_colorCurve && -1 != _pickedColorCtrlPnt)
+ {
+ const ColorControlPoint& pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ return pnt.fallOff;
+ }
+ }
+ else
+ {
+ if (_alphaCurve && -1 != _pickedAlphaCtrlPnt)
+ {
+ const ColorControlPoint& pnt = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt);
+ return pnt.fallOff;
+ }
+ }
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setAlphaFallOff(float fallOff)
+{
+ if (_isLink)
+ {
+ if (_colorCurve && -1 != _pickedColorCtrlPnt)
+ {
+ ColorControlPoint pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ pnt.fallOff = fallOff;
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ update();
+ }
+ }
+ else
+ {
+ if (_alphaCurve && -1 != _pickedAlphaCtrlPnt)
+ {
+ ColorControlPoint pnt = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt);
+ pnt.fallOff = fallOff;
+ _alphaCurve->setControlPoint(_pickedAlphaCtrlPnt, pnt);
+
+ emit ColorAttributeChanged(_colorAttribute);
+ update();
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setColorAttribute(ColorAttribute* colorAttribute)
+{
+ _colorAttribute = colorAttribute;
+ if (colorAttribute != nullptr)
+ {
+ _colorCurve = &(colorAttribute->colorCurve);
+ _alphaCurve = &(colorAttribute->alphaCurve);
+ }
+ else
+ {
+ _colorCurve = nullptr;
+ _alphaCurve = nullptr;
+ }
+
+ if (_alphaCurve !=nullptr && _alphaCurve->getControlPointCount() < 2)
+ {
+ _isLink = true;
+ }
+ else
+ {
+ _isLink = false;
+ }
+
+ _pickedColorCtrlPnt = -1;
+ _pickedAlphaCtrlPnt = -1;
+ _pickedColorWeight = -1;
+ _pickedAlphaWeight = -1;
+ _dragColorCtrlPnt = false;
+ _dragAlphaCtrlPnt = false;
+ _dragColorWeight = false;
+ _dragAlphaWeight = false;
+
+ _updateCurveFitWindowPara();
+ if (_colorCurve)
+ _colorCurve->_needSample = true;
+ if (_alphaCurve)
+ _alphaCurve->_needSample = true;
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::reset()
+{
+ if (_colorAttribute)
+ {
+ _colorAttribute->colorCurve.reset();
+ _colorAttribute->alphaCurve.reset();
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::addControlPointsBeforeSelected()
+{
+ if (-1 != _pickedColorCtrlPnt)
+ {
+ if (_pickedColorCtrlPnt == 0)
+ return;
+
+ _colorCurve->insertControlPointAt(_pickedColorCtrlPnt);
+ ++_pickedColorCtrlPnt;
+ }
+ else if (-1 != _pickedAlphaCtrlPnt)
+ {
+ if (_pickedAlphaCtrlPnt == 0)
+ return;
+
+ _alphaCurve->insertControlPointAt(_pickedAlphaCtrlPnt);
+ ++_pickedAlphaCtrlPnt;
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::addControlPointsAfterSelected()
+{
+ if (-1 != _pickedColorCtrlPnt )
+ {
+ _colorCurve->insertControlPointAt(_pickedColorCtrlPnt + 1);
+ }
+ else if (-1 != _pickedAlphaCtrlPnt)
+ {
+ _alphaCurve->insertControlPointAt(_pickedAlphaCtrlPnt + 1);
+ }
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::removeSelectedControlPoint()
+{
+ if (-1 != _pickedColorCtrlPnt)
+ {
+ _colorCurve->removeControlPoint(_pickedColorCtrlPnt);
+ _pickedColorCtrlPnt = -1;
+ }
+ else if (-1 != _pickedAlphaCtrlPnt)
+ {
+ _alphaCurve->removeControlPoint(_pickedAlphaCtrlPnt);
+ _pickedAlphaCtrlPnt = -1;
+ }
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setTangentType(InterpolateMode mode)
+{
+ if (-1 != _pickedColorCtrlPnt)
+ {
+ ColorControlPoint pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ pnt.mode = mode;
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+ else if (-1 != _pickedAlphaCtrlPnt)
+ {
+ ColorControlPoint pnt = _alphaCurve->getControlPoint(_pickedColorCtrlPnt);
+ pnt.mode = mode;
+ _alphaCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setSmoothTangent()
+{
+ if (-1 != _pickedColorCtrlPnt && _pickedColorCtrlPnt < (_colorCurve->getControlPointCount() - 1) )
+ {
+ ColorControlPoint ctrlctrlPntFront = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ ctrlctrlPntFront.mode = eBezierSpline;
+ ctrlctrlPntFront.splineData.outLen = 1.0;
+ ctrlctrlPntFront.splineData.outTan = 0;
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, ctrlctrlPntFront);
+
+ ColorControlPoint ctrlPntBehiand = _colorCurve->getControlPoint(_pickedColorCtrlPnt + 1);
+ ctrlPntBehiand.mode = eBezierSpline;
+ ctrlPntBehiand.splineData.inLen = 1.0;
+ ctrlPntBehiand.splineData.inTan = 0.0;
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt + 1, ctrlPntBehiand);
+
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+ else if (-1 != _pickedAlphaCtrlPnt && _pickedAlphaCtrlPnt < (_alphaCurve->getControlPointCount() - 1) )
+ {
+ ColorControlPoint ctrlctrlPntFront = _alphaCurve->getControlPoint(_pickedColorCtrlPnt);
+ ctrlctrlPntFront.mode = eBezierSpline;
+ ctrlctrlPntFront.splineData.outLen = 1.0;
+ ctrlctrlPntFront.splineData.outTan = 0;
+ _alphaCurve->setControlPoint(_pickedColorCtrlPnt, ctrlctrlPntFront);
+
+ ColorControlPoint ctrlPntBehiand = _alphaCurve->getControlPoint(_pickedColorCtrlPnt + 1);
+ ctrlPntBehiand.mode = eBezierSpline;
+ ctrlPntBehiand.splineData.inLen = 1.0;
+ ctrlPntBehiand.splineData.inTan = 0.0;
+ _alphaCurve->setControlPoint(_pickedColorCtrlPnt + 1, ctrlPntBehiand);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setEaseInTangent()
+{
+ if (-1 != _pickedColorCtrlPnt && _pickedColorCtrlPnt < (_colorCurve->getControlPointCount() - 1) )
+ {
+ ColorControlPoint ctrlctrlPntFront = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ ctrlctrlPntFront.mode = eBezierSpline;
+ ctrlctrlPntFront.splineData.outLen = 0.0;
+ ctrlctrlPntFront.splineData.outTan = 0;
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, ctrlctrlPntFront);
+
+ ColorControlPoint ctrlPntBehiand = _colorCurve->getControlPoint(_pickedColorCtrlPnt + 1);
+ ctrlPntBehiand.mode = eBezierSpline;
+ ctrlPntBehiand.splineData.inLen = 1.0;
+ ctrlPntBehiand.splineData.inTan = 0;
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt + 1, ctrlPntBehiand);
+
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+ else if (-1 != _pickedAlphaCtrlPnt && _pickedAlphaCtrlPnt < (_alphaCurve->getControlPointCount() - 1) )
+ {
+ ColorControlPoint ctrlctrlPntFront = _alphaCurve->getControlPoint(_pickedColorCtrlPnt);
+ ctrlctrlPntFront.mode = eBezierSpline;
+ ctrlctrlPntFront.splineData.outLen = 0.0;
+ ctrlctrlPntFront.splineData.outTan = 0;
+ _alphaCurve->setControlPoint(_pickedColorCtrlPnt, ctrlctrlPntFront);
+
+ ColorControlPoint ctrlPntBehiand = _alphaCurve->getControlPoint(_pickedColorCtrlPnt + 1);
+ ctrlPntBehiand.mode = eBezierSpline;
+ ctrlPntBehiand.splineData.inLen = 1.0;
+ ctrlPntBehiand.splineData.inTan = 0;
+ _alphaCurve->setControlPoint(_pickedColorCtrlPnt + 1, ctrlPntBehiand);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setEaseOutTangent()
+{
+ if (-1 != _pickedColorCtrlPnt && _pickedColorCtrlPnt < (_colorCurve->getControlPointCount() - 1) )
+ {
+ ColorControlPoint ctrlctrlPntFront = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ ctrlctrlPntFront.mode = eBezierSpline;
+ ctrlctrlPntFront.splineData.outLen = 1.0;
+ ctrlctrlPntFront.splineData.outTan = 0;
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, ctrlctrlPntFront);
+
+ ColorControlPoint ctrlPntBehiand = _colorCurve->getControlPoint(_pickedColorCtrlPnt + 1);
+ ctrlPntBehiand.mode = eBezierSpline;
+ ctrlPntBehiand.splineData.inLen = 0.0;
+ ctrlPntBehiand.splineData.inTan = 0;
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt + 1, ctrlPntBehiand);
+
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+ else if (-1 != _pickedAlphaCtrlPnt && _pickedAlphaCtrlPnt < (_alphaCurve->getControlPointCount() - 1) )
+ {
+ ColorControlPoint ctrlctrlPntFront = _alphaCurve->getControlPoint(_pickedColorCtrlPnt);
+ ctrlctrlPntFront.mode = eBezierSpline;
+ ctrlctrlPntFront.splineData.outLen = 1.0;
+ ctrlctrlPntFront.splineData.outTan = 0;
+ _alphaCurve->setControlPoint(_pickedColorCtrlPnt, ctrlctrlPntFront);
+
+ ColorControlPoint ctrlPntBehiand = _alphaCurve->getControlPoint(_pickedColorCtrlPnt + 1);
+ ctrlPntBehiand.mode = eBezierSpline;
+ ctrlPntBehiand.splineData.inLen = 0.0;
+ ctrlPntBehiand.splineData.inTan = 0;
+ _alphaCurve->setControlPoint(_pickedColorCtrlPnt + 1, ctrlPntBehiand);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QString ColorWidget::getColorTex()
+{
+ if (-1 != _pickedColorCtrlPnt)
+ {
+ ColorControlPoint pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ return pnt.texturePath.c_str();
+ }
+ return "";
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setColorTex(const QString& strPath)
+{
+ if (-1 != _pickedColorCtrlPnt)
+ {
+ ColorControlPoint pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ pnt.texturePath = strPath.toStdString();
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::reloadColorTex()
+{
+ if (-1 != _pickedColorCtrlPnt)
+ {
+ emit ReloadColorAttributeTexture(_colorAttribute, true, _pickedColorCtrlPnt);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::clearColorTex()
+{
+ if (-1 != _pickedColorCtrlPnt)
+ {
+ ColorControlPoint pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ pnt.texturePath = "";
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QString ColorWidget::getAlphaTex()
+{
+ if (-1 != _pickedColorCtrlPnt && _isLink)
+ {
+ ColorControlPoint pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ return pnt.texturePath.c_str();
+ }
+ else if (-1 != _pickedAlphaCtrlPnt)
+ {
+ ColorControlPoint pnt = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt);
+ return pnt.texturePath.c_str();
+ }
+
+ return "";
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setAlphaTex(const QString& strPath)
+{
+ if (-1 != _pickedColorCtrlPnt && _isLink)
+ {
+ ColorControlPoint pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ pnt.texturePath = strPath.toStdString();
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+ else if (-1 != _pickedAlphaCtrlPnt)
+ {
+ ColorControlPoint pnt = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt);
+ pnt.texturePath = strPath.toStdString();
+ _alphaCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::reloadAlphaTex()
+{
+ if (-1 != _pickedColorCtrlPnt && _isLink)
+ {
+ emit ReloadColorAttributeTexture(_colorAttribute, false, _pickedColorCtrlPnt);
+ }
+ else if (-1 != _pickedAlphaCtrlPnt)
+ {
+ emit ReloadColorAttributeTexture(_colorAttribute, false, _pickedAlphaCtrlPnt);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::clearAlphaTex()
+{
+ if (-1 != _pickedColorCtrlPnt && _isLink)
+ {
+ ColorControlPoint pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ pnt.texturePath = "";
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+ else if (-1 != _pickedAlphaCtrlPnt)
+ {
+ ColorControlPoint pnt = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt);
+ pnt.texturePath = "";
+ _alphaCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::setUseAlphaFromColor(bool val)
+{
+ if (_colorAttribute && _colorAttribute->useAlphaFromColor != val)
+ {
+ _colorAttribute->useAlphaFromColor = val;
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::onShowContextMenu(const QPoint& pos)
+{
+ _colorCtrlPntToRemove = _checkColorCtrlPntCursorSelected(pos);
+ _alphaCtrlPntToRemove = _checkAlphaCtrlPntCursorSelected(pos);
+
+ if ( !_canAddRemoveControlPoint
+ || (-1 == _colorCtrlPntToRemove && -1 == _alphaCtrlPntToRemove)
+ || 2 == _colorCurve->_controlPoints.size() && -1 != _colorCtrlPntToRemove
+ || 2 == _alphaCurve->_controlPoints.size() && -1 != _alphaCtrlPntToRemove)
+ {
+ _removeCtrlPntAction->setEnabled(false);
+ }
+ else
+ {
+ _removeCtrlPntAction->setEnabled(true);
+ }
+ _contextMenu->exec(QCursor::pos());
+}
+
+void ColorWidget::onRemoveControlPoint()
+{
+ if (-1 != _colorCtrlPntToRemove)
+ {
+ _colorCurve->removeControlPoint(_colorCtrlPntToRemove);
+
+ if (_colorCtrlPntToRemove == _pickedColorCtrlPnt)
+ {
+ if (_isLink)
+ {
+ _colorCtrlPntToRemove = -1;
+ _pickedColorCtrlPnt = -1;
+ _pickedAlphaCtrlPnt = -1;
+ }
+ else
+ {
+ _colorCtrlPntToRemove = -1;
+ _pickedColorCtrlPnt = -1;
+ }
+ }
+
+ _colorCurve->_needSample = true;
+ emit ColorAttributeChanged(_colorAttribute);
+ update();
+ }
+ else if (-1 != _alphaCtrlPntToRemove && _isLink)
+ {
+ _colorCurve->removeControlPoint(_alphaCtrlPntToRemove);
+
+ if (_alphaCtrlPntToRemove == _pickedAlphaCtrlPnt)
+ {
+ _alphaCtrlPntToRemove = -1;
+ _pickedColorCtrlPnt = -1;
+ _pickedAlphaCtrlPnt = -1;
+ }
+
+ _colorCurve->_needSample = true;
+ emit ColorAttributeChanged(_colorAttribute);
+ update();
+ }
+ else if (-1 != _alphaCtrlPntToRemove && !_isLink)
+ {
+ _alphaCurve->removeControlPoint(_alphaCtrlPntToRemove);
+
+ if (_alphaCtrlPntToRemove == _pickedAlphaCtrlPnt)
+ {
+ _colorCtrlPntToRemove = -1;
+ _pickedColorCtrlPnt = -1;
+ }
+
+ _alphaCurve->_needSample = true;
+ emit ColorAttributeChanged(_colorAttribute);
+ update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool ColorWidget::event(QEvent *event)
+{
+ if (event->type() == QEvent::ToolTip) {
+ QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
+ QPoint mousePos = helpEvent->pos();
+
+ QPointF mousePosF(mousePos.x(), mousePos.y());
+ int pickedColorCtrlPnt = _checkColorCtrlPntCursorSelected(mousePosF);
+ int pickedAlphaCtrlPnt = _checkAlphaCtrlPntCursorSelected(mousePosF);
+
+ if (-1 != pickedColorCtrlPnt)
+ {
+ const std::string& tex = _colorCurve->getControlPoint(pickedColorCtrlPnt).texturePath;
+ if (!tex.empty())
+ QToolTip::showText(helpEvent->globalPos(), tex.c_str());
+
+ }
+ else if (-1 != pickedAlphaCtrlPnt)
+ {
+ if (_isLink)
+ {
+ const std::string& tex = _colorCurve->getControlPoint(pickedAlphaCtrlPnt).texturePath;
+ if (!tex.empty())
+ QToolTip::showText(helpEvent->globalPos(), tex.c_str());
+ }
+ else
+ {
+ const std::string& tex = _alphaCurve->getControlPoint(pickedAlphaCtrlPnt).texturePath;
+ if (!tex.empty())
+ QToolTip::showText(helpEvent->globalPos(), tex.c_str());
+ }
+ }
+ else
+ {
+ QToolTip::hideText();
+ event->ignore();
+ }
+
+ return true;
+ }
+ return QWidget::event(event);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::paintEvent(QPaintEvent * e)
+{
+ //TimeConsumeTracker t("update");
+ QFrame::paintEvent(e);
+
+ QPainter painter;
+ painter.begin(this);
+ painter.setRenderHints(QPainter::Antialiasing, true);
+
+ if (_colorCurve)
+ {
+ _drawRampArea(painter);
+ _drawCtrlPntCursors(painter);
+ _drawWeightCursors(painter);
+ }
+ painter.end();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::resizeEvent(QResizeEvent* e)
+{
+ if (_colorCurve)
+ _updateCurveFitWindowPara();
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::mousePressEvent( QMouseEvent* e )
+{
+ if(_colorCurve && e->button() & Qt::LeftButton)
+ {
+ QPoint mousePos = e->pos();
+ QPointF mousePosF(mousePos.x(), mousePos.y());
+ int pickedColorCtrlPnt = _checkColorCtrlPntCursorSelected(mousePosF);
+ int pickedAlphaCtrlPnt = _checkAlphaCtrlPntCursorSelected(mousePosF);
+
+ if (-1 != pickedColorCtrlPnt || -1 != pickedAlphaCtrlPnt)
+ {
+ if (_canAddRemoveControlPoint && _canRemoveCtrlPntByClick)
+ {
+ if (-1 != pickedColorCtrlPnt)
+ {
+ _colorCurve->removeControlPoint(pickedColorCtrlPnt);
+ _pickedColorCtrlPnt = -1;
+ }
+
+ if (-1 != pickedAlphaCtrlPnt)
+ {
+ if (_isLink)
+ {
+ _colorCurve->removeControlPoint(pickedAlphaCtrlPnt);
+ _pickedColorCtrlPnt = -1;
+ pickedAlphaCtrlPnt = -1;
+ }
+ else
+ {
+ _alphaCurve->removeControlPoint(pickedAlphaCtrlPnt);
+ pickedAlphaCtrlPnt = -1;
+ }
+ }
+ return;
+ }
+
+ _pickedColorCtrlPnt = pickedColorCtrlPnt;
+ _pickedAlphaCtrlPnt = pickedAlphaCtrlPnt;
+
+ if (-1 < _pickedColorCtrlPnt)
+ _dragColorCtrlPnt = true;
+
+ if (-1 < _pickedAlphaCtrlPnt)
+ _dragAlphaCtrlPnt = true;
+
+ if (_isLink)
+ {
+ if (-1 != pickedColorCtrlPnt)
+ {
+ _pickedAlphaCtrlPnt = _pickedColorCtrlPnt;
+ _dragAlphaCtrlPnt = _dragColorCtrlPnt;
+ }
+
+ if (-1 != pickedAlphaCtrlPnt)
+ {
+ _pickedColorCtrlPnt = _pickedAlphaCtrlPnt;
+ _dragColorCtrlPnt = _dragAlphaCtrlPnt;
+ }
+ PickedControlPointChanged(true);
+ }
+ else
+ {
+ if (-1 != pickedColorCtrlPnt)
+ {
+ PickedControlPointChanged(true);
+ }
+
+ if (-1 != pickedAlphaCtrlPnt)
+ {
+ PickedControlPointChanged(false);
+ }
+ }
+
+
+ }
+ else
+ {
+ int pickedColorWeight = _checkColorWeightCursorSelected(mousePosF);
+ int pickedAlphaWeight = _checkAlphaWeightCursorSelected(mousePosF);
+
+ if (-1 != pickedColorWeight || -1 != pickedAlphaWeight)
+ {
+ _pickedColorWeight = pickedColorWeight;
+ _pickedAlphaWeight = pickedAlphaWeight;
+
+ if (-1 < _pickedColorWeight)
+ _dragColorWeight = true;
+
+ if (-1 < _pickedAlphaCtrlPnt)
+ _dragAlphaWeight = true;
+
+ if (_isLink)
+ {
+ if (-1 != _pickedColorWeight)
+ {
+ _pickedAlphaWeight = _pickedColorWeight;
+ _dragAlphaWeight = _dragColorWeight;
+ }
+
+ if (-1 != _pickedAlphaWeight)
+ {
+ _pickedColorWeight = _pickedAlphaWeight;
+ _dragColorWeight = _dragAlphaWeight;
+ }
+ }
+ }
+ else
+ {
+ if (_canAddRemoveControlPoint && _canAddCtrlPntByClick)
+ {
+ int yMiddle = height() / 2;
+ if (mousePos.y() <= yMiddle)
+ {
+ _addColorControlPoint(mousePos.x());
+ PickedControlPointChanged(true);
+ }
+ else if (mousePos.y() > yMiddle)
+ {
+ if (_isLink)
+ {
+ _addColorControlPoint(mousePos.x());
+ PickedControlPointChanged(true);
+ }
+ else
+ {
+ _addAlphaControlPoint(mousePos.x());
+ PickedControlPointChanged(false);
+ }
+ }
+ }
+ }
+ }
+ update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::mouseReleaseEvent( QMouseEvent* /*e*/ )
+{
+ _dragColorCtrlPnt = false;
+ _dragAlphaCtrlPnt = false;
+ _dragColorWeight = false;
+ _dragAlphaWeight = false;
+ _pickedColorWeight = -1;
+ _pickedAlphaWeight = -1;
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::mouseMoveEvent( QMouseEvent* e )
+{
+ Qt::MouseButtons buttons = e->buttons();
+
+ if(_colorCurve && buttons & Qt::LeftButton)
+ {
+ if (_dragColorCtrlPnt)
+ {
+ if (!_colorAttribute->canMoveControlPointHorizontally())
+ return;
+
+ QPoint mousePos = e->pos();
+ ColorControlPoint pnt = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ pnt.x = _screenToValue(mousePos.x());
+
+ //make control point move in value range
+ if (pnt.x < _colorCurve->getMinValue())
+ pnt.x = _colorCurve->getMinValue();
+ else if (pnt.x > _colorCurve->getMaxValue())
+ pnt.x = _colorCurve->getMaxValue();
+
+ _colorCurve->setControlPoint(_pickedColorCtrlPnt, pnt);
+ _colorCurve->_reOrderControlPoints(_pickedColorCtrlPnt);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ if (_dragColorWeight)
+ {
+ QPoint mousePos = e->pos();
+ ColorControlPoint pnt0 = _colorCurve->getControlPoint(_pickedColorWeight);
+ ColorControlPoint pnt1 = _colorCurve->getControlPoint(_pickedColorWeight + 1);
+ int xPnt0Screen = _valueToScreen(pnt0.x);
+ int xPnt1Screen = _valueToScreen(pnt1.x);
+ if (mousePos.x() < (xPnt0Screen + WEIGHT_CURSOR_W))
+ mousePos.setX(xPnt0Screen + WEIGHT_CURSOR_W);
+ if (mousePos.x() > (xPnt1Screen - WEIGHT_CURSOR_W))
+ mousePos.setX(xPnt1Screen - WEIGHT_CURSOR_W);
+ pnt0.weight = ((float)(mousePos.x() - xPnt0Screen))/(xPnt1Screen - xPnt0Screen);
+ _colorCurve->setControlPoint(_pickedColorWeight, pnt0);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ if (!_isLink)
+ {
+ if (_dragAlphaCtrlPnt)
+ {
+ if (!_colorAttribute->canMoveControlPointHorizontally())
+ return;
+
+ QPoint mousePos = e->pos();
+ ColorControlPoint pnt = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt);
+ pnt.x = _screenToValue(mousePos.x());
+
+ //make control point move in value range
+ if (pnt.x < _alphaCurve->getMinValue())
+ pnt.x = _alphaCurve->getMinValue();
+ else if (pnt.x > _alphaCurve->getMaxValue())
+ pnt.x = _alphaCurve->getMaxValue();
+
+ _alphaCurve->setControlPoint(_pickedAlphaCtrlPnt, pnt);
+ _alphaCurve->_reOrderControlPoints(_pickedAlphaCtrlPnt);
+ _alphaCurve->_needSample = true;
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+
+ if (_dragAlphaWeight)
+ {
+ QPoint mousePos = e->pos();
+ ColorControlPoint pnt0 = _alphaCurve->getControlPoint(_pickedAlphaWeight);
+ ColorControlPoint pnt1 = _alphaCurve->getControlPoint(_pickedAlphaWeight + 1);
+ int xPnt0Screen = _valueToScreen(pnt0.x);
+ int xPnt1Screen = _valueToScreen(pnt1.x);
+ if (mousePos.x() < (xPnt0Screen + WEIGHT_CURSOR_W))
+ mousePos.setX(xPnt0Screen + WEIGHT_CURSOR_W);
+ if (mousePos.x() > (xPnt1Screen - WEIGHT_CURSOR_W))
+ mousePos.setX(xPnt1Screen - WEIGHT_CURSOR_W);
+ pnt0.weight = ((float)(mousePos.x() - xPnt0Screen))/(xPnt1Screen - xPnt0Screen);
+ _alphaCurve->setControlPoint(_pickedAlphaWeight, pnt0);
+ emit ColorAttributeChanged(_colorAttribute);
+ }
+ }
+
+ update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::_updateCurveFitWindowPara()
+{
+ int widgetWidth = width();
+
+ if (_colorCurve && _colorCurve->getControlPointCount() > 1)
+ {
+ float minX = _colorCurve->getMinValue();
+ float maxX = _colorCurve->getMaxValue();
+
+ if (!_isLink)
+ {
+ if (minX < _alphaCurve->getMinValue())
+ minX = _alphaCurve->getMinValue();
+
+ if (maxX < _alphaCurve->getMaxValue())
+ maxX = _alphaCurve->getMaxValue();
+ }
+
+ float curveWidth = maxX - minX;
+
+ if (0 == curveWidth)
+ {
+ curveWidth = 1.0;
+ }
+
+ _curveFitWindowScale = (widgetWidth - MARGIN_X * 2) / curveWidth;
+ _curveFitWindowOffset = MARGIN_X - minX * _curveFitWindowScale;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+float ColorWidget::_valueToScreen(float x)
+{
+ return ROUND(_curveFitWindowScale * x + _curveFitWindowOffset);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+float ColorWidget::_screenToValue(float x)
+{
+ return (x - _curveFitWindowOffset) / _curveFitWindowScale;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void ColorWidget::_fillRampImage(QImage& colorImg, QImage& alphaImg)
+{
+ assert(colorImg.width() == alphaImg.width());
+ assert(colorImg.height() == alphaImg.height());
+
+ int width = colorImg.width();
+ int height = colorImg.height();
+
+ QRgb *colorPixels = nullptr;
+ QRgb *alphaPixels = nullptr;
+ {
+ colorPixels = new QRgb[width];
+ //TimeConsumeTracker t("calcuate one line colorPixels");
+ for (int i = 0; i < width; ++i)
+ {
+ colorPixels[i] = _colorCurve->getColorByX(_screenToValue(i + MARGIN_X)).rgba();
+ }
+
+ if (!_isLink)
+ {
+ alphaPixels = new QRgb[width];
+ //TimeConsumeTracker t("calcuate one line alphaPixels");
+ for (int i = 0; i < width; ++i)
+ {
+ alphaPixels[i] = _alphaCurve->getColorByX(_screenToValue(i + MARGIN_X)).rgba();
+ }
+ }
+ }
+
+ {
+ //TimeConsumeTracker tt("fill images' pixel");
+ for (int m = 0; m < height; ++m)
+ {
+ void* bytesPerLine = const_cast<uchar*>(colorImg.scanLine(m));
+ memcpy(bytesPerLine, colorPixels, sizeof(QRgb) * width);
+
+ bytesPerLine = const_cast<uchar*>(alphaImg.scanLine(m));
+ if (nullptr == alphaPixels)
+ memcpy(bytesPerLine, colorPixels, sizeof(QRgb) * width);
+ else
+ memcpy(bytesPerLine, alphaPixels, sizeof(QRgb) * width);
+ }
+ }
+
+ delete[] colorPixels;
+}
+
+void ColorWidget::_drawRampArea(QPainter& painter)
+{
+ QImage colorImg(width() - MARGIN_X * 2, (height() - SPACING_V - CONTROL_POINT_CURSOR_H * 2 - MARGIN_Y * 2) / 2, QImage::Format_RGB32);
+ QImage alphaImg(width() - MARGIN_X * 2, (height() - SPACING_V - CONTROL_POINT_CURSOR_H * 2 - MARGIN_Y * 2) / 2, QImage::Format_RGB32);
+ _fillRampImage(colorImg, alphaImg);
+ painter.drawImage(MARGIN_X, MARGIN_Y + CONTROL_POINT_CURSOR_H, colorImg);
+ painter.drawImage(MARGIN_X, MARGIN_Y + CONTROL_POINT_CURSOR_H + (height() - SPACING_V - CONTROL_POINT_CURSOR_H * 2 - MARGIN_Y * 2) / 2, alphaImg);
+}
+
+void ColorWidget::_drawCtrlPntCursors(QPainter& painter)
+{
+ int colorCtrlPntCount = _colorCurve->getControlPointCount();
+
+ for (int i = 0; i < colorCtrlPntCount; ++i)
+ {
+ const ColorControlPoint& pnt = _colorCurve->getControlPoint(i);
+
+ float xPosCtrlPnt = ROUND(_valueToScreen(pnt.x));
+ float yColorCtrlPnt = MARGIN_Y;
+ float yAlphaCtrlPnt = height() - SPACING_V - CONTROL_POINT_CURSOR_H - MARGIN_Y;
+
+ QRect rcColorCtrnPntCursor(xPosCtrlPnt - CONTROL_POINT_CURSOR_W / 2, yColorCtrlPnt, CONTROL_POINT_CURSOR_W, CONTROL_POINT_CURSOR_H);
+ QRect rcAlphaCtrnPntCursor(xPosCtrlPnt - CONTROL_POINT_CURSOR_W / 2, yAlphaCtrlPnt, CONTROL_POINT_CURSOR_W, CONTROL_POINT_CURSOR_H);
+ if (i == _pickedColorCtrlPnt)
+ {
+ if (pnt.texturePath.empty())
+ painter.drawImage(rcColorCtrnPntCursor, genControlPointCursorImg(QColor(pnt.color.red(), pnt.color.green(), pnt.color.blue(), 255), true));
+ else
+ painter.drawImage(rcColorCtrnPntCursor, S_CtrlPntWithTexCursorPickedImg);
+
+ if (_isLink)
+ {
+ if (pnt.texturePath.empty())
+ painter.drawImage(rcAlphaCtrnPntCursor, genControlPointCursorImg(QColor(pnt.color.alpha(), pnt.color.alpha(), pnt.color.alpha()), true));
+ else
+ painter.drawImage(rcAlphaCtrnPntCursor, S_CtrlPntWithTexCursorPickedImg);
+ }
+ }
+ else
+ {
+ if (pnt.texturePath.empty())
+ painter.drawImage(rcColorCtrnPntCursor, genControlPointCursorImg(QColor(pnt.color.red(), pnt.color.green(), pnt.color.blue(), 255)));
+ else
+ painter.drawImage(rcColorCtrnPntCursor, S_CtrlPntWithTexCursorNormalImg);
+
+ if (_isLink)
+ {
+ if (pnt.texturePath.empty())
+ painter.drawImage(rcAlphaCtrnPntCursor, genControlPointCursorImg(QColor(pnt.color.alpha(), pnt.color.alpha(), pnt.color.alpha())));
+ else
+ painter.drawImage(rcAlphaCtrnPntCursor, S_CtrlPntWithTexCursorNormalImg);
+ }
+
+ }
+ }
+
+ if (!_isLink)
+ {
+ int alphaCtrlPntCount = _alphaCurve->getControlPointCount();
+
+ for (int i = 0; i < alphaCtrlPntCount; ++i)
+ {
+ const ColorControlPoint& pnt = _alphaCurve->getControlPoint(i);
+
+ float xPosCtrlPnt = ROUND(_valueToScreen(pnt.x));
+ float yAlphaCtrlPnt = height() - SPACING_V - CONTROL_POINT_CURSOR_H - MARGIN_Y;
+
+ QRect rcAlphaCtrnPntCursor(xPosCtrlPnt - CONTROL_POINT_CURSOR_W / 2, yAlphaCtrlPnt, CONTROL_POINT_CURSOR_W, CONTROL_POINT_CURSOR_H);
+
+ if (i == _pickedAlphaCtrlPnt)
+ {
+ if (pnt.texturePath.empty())
+ painter.drawImage(rcAlphaCtrnPntCursor, genControlPointCursorImg(QColor(pnt.color.alpha(), pnt.color.alpha(), pnt.color.alpha()), true));
+ else
+ painter.drawImage(rcAlphaCtrnPntCursor, S_CtrlPntWithTexCursorPickedImg);
+ }
+ else
+ {
+ if (pnt.texturePath.empty())
+ painter.drawImage(rcAlphaCtrnPntCursor, genControlPointCursorImg(QColor(pnt.color.alpha(), pnt.color.alpha(), pnt.color.alpha()) ));
+ else
+ painter.drawImage(rcAlphaCtrnPntCursor, S_CtrlPntWithTexCursorNormalImg);
+ }
+ }
+ }
+}
+
+void ColorWidget::_drawWeightCursors(QPainter& painter)
+{
+ float yColorWeight = MARGIN_Y + CONTROL_POINT_CURSOR_H - WEIGHT_CURSOR_H;
+
+ int colorCtrlPntCount = _colorCurve->getControlPointCount();
+ if (0 == _pickedColorCtrlPnt)
+ {
+ const ColorControlPoint& pnt0 = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ const ColorControlPoint& pnt1 = _colorCurve->getControlPoint(_pickedColorCtrlPnt + 1);
+
+ _drawColorWeightCursor(painter, pnt0, pnt1, _pickedColorCtrlPnt == _pickedColorWeight);
+ }
+ else if ((colorCtrlPntCount - 1) == _pickedColorCtrlPnt)
+ {
+ const ColorControlPoint& pnt0 = _colorCurve->getControlPoint(_pickedColorCtrlPnt - 1);
+ const ColorControlPoint& pnt1 = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+
+ _drawColorWeightCursor(painter, pnt0, pnt1, (_pickedColorCtrlPnt - 1) == _pickedColorWeight);
+ }
+ else if (0 < _pickedColorCtrlPnt && _pickedColorCtrlPnt < (colorCtrlPntCount - 1))
+ {
+ const ColorControlPoint& pnt0 = _colorCurve->getControlPoint(_pickedColorCtrlPnt - 1);
+ const ColorControlPoint& pnt1 = _colorCurve->getControlPoint(_pickedColorCtrlPnt);
+ const ColorControlPoint& pnt2 = _colorCurve->getControlPoint(_pickedColorCtrlPnt + 1);
+
+ _drawColorWeightCursor(painter, pnt0, pnt1, (_pickedColorCtrlPnt - 1) == _pickedColorWeight);
+ _drawColorWeightCursor(painter, pnt1, pnt2, _pickedColorCtrlPnt == _pickedColorWeight);
+ }
+
+ if (!_isLink)
+ {
+ float yAlphaWeight = height() - SPACING_V - WEIGHT_CURSOR_H - MARGIN_Y;
+ int alphaCtrlPntCount = _alphaCurve->getControlPointCount();
+ if (0 == _pickedAlphaCtrlPnt)
+ {
+ const ColorControlPoint& pnt0 = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt);
+ const ColorControlPoint& pnt1 = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt + 1);
+
+ _drawAlphaWeightCursor(painter, pnt0, pnt1, _pickedAlphaCtrlPnt == _pickedAlphaWeight);
+ }
+ else if ((alphaCtrlPntCount - 1) == _pickedAlphaCtrlPnt)
+ {
+ const ColorControlPoint& pnt0 = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt - 1);
+ const ColorControlPoint& pnt1 = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt);
+
+ _drawAlphaWeightCursor(painter, pnt0, pnt1, (_pickedAlphaCtrlPnt - 1) == _pickedAlphaWeight);
+ }
+ else if (0 < _pickedAlphaCtrlPnt && _pickedAlphaCtrlPnt < (alphaCtrlPntCount - 1))
+ {
+ const ColorControlPoint& pnt0 = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt - 1);
+ const ColorControlPoint& pnt1 = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt);
+ const ColorControlPoint& pnt2 = _alphaCurve->getControlPoint(_pickedAlphaCtrlPnt + 1);
+
+ _drawAlphaWeightCursor(painter, pnt0, pnt1, (_pickedAlphaCtrlPnt - 1) == _pickedAlphaWeight);
+ _drawAlphaWeightCursor(painter, pnt1, pnt2, _pickedAlphaCtrlPnt == _pickedAlphaWeight);
+ }
+ }
+}
+
+void ColorWidget::_drawColorWeightCursor(QPainter& painter, const ColorControlPoint& pnt0, const ColorControlPoint& pnt1, bool picked)
+{
+ if (pnt0.mode != eLinear)
+ return ;
+
+ float yColorWeight = MARGIN_Y + CONTROL_POINT_CURSOR_H - WEIGHT_CURSOR_H;
+ float yAlphaWeight = height() - SPACING_V - CONTROL_POINT_CURSOR_H - MARGIN_Y;
+
+ float xPosWeightCursor = ROUND(_valueToScreen(pnt0.x + pnt0.weight * (pnt1.x - pnt0.x)));
+ QRect rcColorWeightCursor(xPosWeightCursor - WEIGHT_CURSOR_W / 2, yColorWeight, WEIGHT_CURSOR_W, WEIGHT_CURSOR_H);
+ QRect rcAlphaWeightCursor(xPosWeightCursor - WEIGHT_CURSOR_W / 2, yAlphaWeight, WEIGHT_CURSOR_W, WEIGHT_CURSOR_H);
+
+ painter.drawImage(rcColorWeightCursor, picked?S_WeightCursorPickedImg:S_WeightCursorNormalImg);
+
+ if (_isLink)
+ painter.drawImage(rcAlphaWeightCursor, picked?S_WeightCursorPickedImg:S_WeightCursorNormalImg);
+}
+
+void ColorWidget::_drawAlphaWeightCursor(QPainter& painter, const ColorControlPoint& pnt0, const ColorControlPoint& pnt1, bool picked)
+{
+ if (pnt0.mode != eLinear)
+ return ;
+
+ float yColorWeight = MARGIN_Y + CONTROL_POINT_CURSOR_H - WEIGHT_CURSOR_H;
+ float yAlphaWeight = height() - SPACING_V - CONTROL_POINT_CURSOR_H - MARGIN_Y;
+
+ float xPosWeightCursor = ROUND(_valueToScreen(pnt0.x + pnt0.weight * (pnt1.x - pnt0.x)));
+ QRect rcColorWeightCursor(xPosWeightCursor - WEIGHT_CURSOR_W / 2, yColorWeight, WEIGHT_CURSOR_W, WEIGHT_CURSOR_H);
+ QRect rcAlphaWeightCursor(xPosWeightCursor - WEIGHT_CURSOR_W / 2, yAlphaWeight, WEIGHT_CURSOR_W, WEIGHT_CURSOR_H);
+
+ painter.drawImage(rcAlphaWeightCursor, picked?S_WeightCursorPickedImg:S_WeightCursorNormalImg);
+
+ if (_isLink)
+ painter.drawImage(rcColorWeightCursor, picked?S_WeightCursorPickedImg:S_WeightCursorNormalImg);
+}
+
+int ColorWidget::_checkColorCtrlPntCursorSelected(const QPointF& pickPos)
+{
+ if (nullptr == _colorCurve)
+ return -1;
+ int colorCtrlPntCount = _colorCurve->getControlPointCount();
+ for (int i = 0; i < colorCtrlPntCount; ++i)
+ {
+ const ColorControlPoint& pnt = _colorCurve->getControlPoint(i);
+
+ float xPos = _valueToScreen(pnt.x);
+ float yPos = MARGIN_Y;
+ bool picked = isClickedInCtrlPntCursor(QPointF(xPos, yPos), pickPos);
+ if (picked)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int ColorWidget::_checkAlphaCtrlPntCursorSelected(const QPointF& pickPos)
+{
+ if (_isLink)
+ {
+ if (nullptr == _colorCurve)
+ return -1;
+ int colorCtrlPntCount = _colorCurve->getControlPointCount();
+ for (int i = 0; i < colorCtrlPntCount; ++i)
+ {
+ const ColorControlPoint& pnt = _colorCurve->getControlPoint(i);
+
+ float xPos = _valueToScreen(pnt.x);
+ float yPos = height() - SPACING_V - CONTROL_POINT_CURSOR_H - MARGIN_Y;
+ bool picked = isClickedInCtrlPntCursor(QPointF(xPos, yPos), pickPos);
+ if (picked)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ if (nullptr == _alphaCurve)
+ return -1;
+ int colorCtrlPntCount = _alphaCurve->getControlPointCount();
+ for (int i = 0; i < colorCtrlPntCount; ++i)
+ {
+ const ColorControlPoint& pnt = _alphaCurve->getControlPoint(i);
+
+ float xPos = _valueToScreen(pnt.x);
+ float yPos = height() - SPACING_V - CONTROL_POINT_CURSOR_H - MARGIN_Y;
+ bool picked = isClickedInCtrlPntCursor(QPointF(xPos, yPos), pickPos);
+ if (picked)
+ {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int ColorWidget::_checkColorWeightCursorSelected(const QPointF& pickPos)
+{
+ int colorCtrlPntCount = _colorCurve->getControlPointCount();
+ if (-1 != _pickedColorCtrlPnt)
+ {
+ if (0 == _pickedColorCtrlPnt)
+ {
+ return _checkColorWeightCursorSelected(0, pickPos);
+ }
+ else if ((colorCtrlPntCount - 1) == _pickedColorCtrlPnt)
+ {
+ return _checkColorWeightCursorSelected(_pickedColorCtrlPnt - 1, pickPos);
+ }
+ else if (0 < _pickedColorCtrlPnt && _pickedColorCtrlPnt < (colorCtrlPntCount - 1))
+ {
+ int pickedWeightCursor = _checkColorWeightCursorSelected(_pickedColorCtrlPnt - 1, pickPos);
+ if (-1 != pickedWeightCursor)
+ return pickedWeightCursor;
+ else
+ return _checkColorWeightCursorSelected(_pickedColorCtrlPnt, pickPos);
+ }
+ }
+
+ return -1;
+}
+
+int ColorWidget::_checkColorWeightCursorSelected(int pickedCtrlPnt, const QPointF& pickPos)
+{
+ const ColorControlPoint& pnt0 = _colorCurve->getControlPoint(pickedCtrlPnt);
+ const ColorControlPoint& pnt1 = _colorCurve->getControlPoint(pickedCtrlPnt + 1);
+
+ if (pnt0.weight >= 0)
+ {
+ float xPos = _valueToScreen(pnt0.x + pnt0.weight * (pnt1.x - pnt0.x));
+ float yPos = MARGIN_Y + CONTROL_POINT_CURSOR_H - WEIGHT_CURSOR_H;
+ bool picked = isClickedInWeightCursor(QPointF(xPos, yPos), pickPos);
+ if (picked)
+ {
+ return pickedCtrlPnt;
+ }
+ }
+
+ return - 1;
+}
+
+int ColorWidget::_checkAlphaWeightCursorSelected(const QPointF& pickPos)
+{
+ if (_isLink)
+ {
+ int count = _colorCurve->getControlPointCount();
+ if (-1 != _pickedAlphaCtrlPnt)
+ {
+ if (0 == _pickedAlphaCtrlPnt)
+ {
+ return _checkAlphaWeightCursorSelected(0, pickPos);
+ }
+ else if ((count - 1) == _pickedAlphaCtrlPnt)
+ {
+ return _checkAlphaWeightCursorSelected(_pickedColorCtrlPnt - 1, pickPos);
+ }
+ else if (0 < _pickedAlphaCtrlPnt && _pickedAlphaCtrlPnt < (count - 1))
+ {
+ int pickedWeightCursor = _checkAlphaWeightCursorSelected(_pickedColorCtrlPnt - 1, pickPos);
+ if (-1 != pickedWeightCursor)
+ return pickedWeightCursor;
+ else
+ return _checkAlphaWeightCursorSelected(_pickedColorCtrlPnt, pickPos);
+ }
+ }
+ }
+ else
+ {
+ int count = _alphaCurve->getControlPointCount();
+ if (-1 != _pickedAlphaCtrlPnt)
+ {
+ if (0 == _pickedAlphaCtrlPnt)
+ {
+ return _checkAlphaWeightCursorSelected(0, pickPos);
+ }
+ else if ((count - 1) == _pickedAlphaCtrlPnt)
+ {
+ return _checkAlphaWeightCursorSelected(count - 1, pickPos);
+ }
+ else if (0 < _pickedAlphaCtrlPnt && _pickedAlphaCtrlPnt < (count - 1))
+ {
+ int pickedWeightCursor = _checkAlphaWeightCursorSelected(_pickedColorCtrlPnt - 1, pickPos);
+ if (-1 != pickedWeightCursor)
+ return pickedWeightCursor;
+ else
+ return _checkAlphaWeightCursorSelected(_pickedColorCtrlPnt, pickPos);
+ }
+ }
+ }
+
+ return -1;
+}
+
+int ColorWidget::_checkAlphaWeightCursorSelected(int pickedCtrlPnt, const QPointF& pickPos)
+{
+ if (_isLink)
+ {
+ const ColorControlPoint& pnt0 = _colorCurve->getControlPoint(pickedCtrlPnt);
+ const ColorControlPoint& pnt1 = _colorCurve->getControlPoint(pickedCtrlPnt + 1);
+
+ if (pnt0.weight >= 0)
+ {
+ float xPos = _valueToScreen(pnt0.x + pnt0.weight * (pnt1.x - pnt0.x));
+ float yPos = height() - SPACING_V - CONTROL_POINT_CURSOR_H - MARGIN_Y;
+ bool picked = isClickedInWeightCursor(QPointF(xPos, yPos), pickPos);
+ if (picked)
+ {
+ return pickedCtrlPnt;
+ }
+ }
+ }
+ else
+ {
+ int colorCtrlPntCount = _alphaCurve->getControlPointCount();
+ for (int i = 0; i < colorCtrlPntCount - 1; ++i)
+ {
+ const ColorControlPoint& pnt0 = _alphaCurve->getControlPoint(i);
+ const ColorControlPoint& pnt1 = _alphaCurve->getControlPoint(i + 1);
+
+ if (pnt0.weight >= 0)
+ {
+ float xPos = _valueToScreen(pnt0.x + pnt0.weight * (pnt1.x - pnt0.x));
+ float yPos = height() - SPACING_V - CONTROL_POINT_CURSOR_H - MARGIN_Y;
+ bool picked = isClickedInCtrlPntCursor(QPointF(xPos, yPos), pickPos);
+ if (picked)
+ {
+ return i;
+ }
+ }
+ else
+ break;
+ }
+ }
+
+ return -1;
+}
+
+void ColorWidget::_addColorControlPoint(int xPos)
+{
+ float x = _screenToValue(xPos);
+
+ int ctrlPntCount = _colorCurve->getControlPointCount();
+ for (int i = 0; i < ctrlPntCount - 1; ++i)
+ {
+ const ColorControlPoint& pntLeft = _colorCurve->getControlPoint(i);
+ const ColorControlPoint& pntRight = _colorCurve->getControlPoint(i + 1);
+
+ if (pntLeft.x < x && x < pntRight.x)
+ {
+ QColor color = _colorCurve->getColorByX(x);
+ ColorControlPoint newCtrlPnt(x, color, pntLeft.mode);
+
+ std::vector<ColorControlPoint>::iterator itr = _colorCurve->_controlPoints.begin();
+ std::advance(itr, i + 1);
+ _colorCurve->_controlPoints.insert(itr, newCtrlPnt);
+
+ _pickedColorCtrlPnt = i + 1;
+ if (_isLink)
+ _pickedAlphaCtrlPnt = _pickedColorCtrlPnt;
+
+ break;
+ }
+ }
+}
+
+void ColorWidget::_addAlphaControlPoint(int xPos)
+{
+ float x = _screenToValue(xPos);
+
+ int ctrlPntCount = _alphaCurve->getControlPointCount();
+ for (int i = 0; i < ctrlPntCount - 1; ++i)
+ {
+ const ColorControlPoint& pntLeft = _alphaCurve->getControlPoint(i);
+ const ColorControlPoint& pntRight = _alphaCurve->getControlPoint(i + 1);
+
+ if (pntLeft.x < x && x < pntRight.x)
+ {
+ QColor color = _alphaCurve->getColorByX(x);
+ ColorControlPoint newCtrlPnt(x, color, pntLeft.mode);
+
+ std::vector<ColorControlPoint>::iterator itr = _alphaCurve->_controlPoints.begin();
+ std::advance(itr, i + 1);
+ _alphaCurve->_controlPoints.insert(itr, newCtrlPnt);
+
+ _pickedAlphaCtrlPnt = i + 1;
+ if (_isLink)
+ _pickedColorCtrlPnt = _pickedAlphaCtrlPnt;
+
+ break;
+ }
+ }
+}
+
+} // namespace CurveEditor
+} // namespace nvidia \ No newline at end of file
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Window/ColorWidget.h b/NvBlast/tools/CurveEditor/source/Internal/Window/ColorWidget.h
new file mode 100644
index 0000000..d910789
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Window/ColorWidget.h
@@ -0,0 +1,126 @@
+#ifndef COLORWIDGET_H
+#define COLORWIDGET_H
+
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QMenu>
+#include <QtWidgets/QAction>
+#include "Attribute.h"
+
+namespace nvidia {
+namespace CurveEditor {
+
+class ColorWidget : public QFrame
+{
+ Q_OBJECT
+public:
+ explicit ColorWidget(QWidget *parent = 0);
+
+ inline bool isLink() { return _isLink; }
+ QColor getColor();
+ int getAlpha();
+ void setColor(const QColor& color);
+ void setAlpha(int alpha);
+ float getColorFallOff();
+ void setColorFallOff(float fallOff);
+ float getAlphaFallOff();
+ void setAlphaFallOff(float fallOff);
+
+ // if alphaCurve of colorAttribute is with less than 2 control points,
+ // it treats that rgb color curve and alpha curve share same control points
+ // else, it uses rgb components of colorCurve of ColorAttribute, and it uses alpha component of alphaCurve of ColorAttribute
+ void setColorAttribute(ColorAttribute* colorAttribute);
+ void reset();
+ inline void setCanAddRemoveControlPoint(bool val) { _canAddRemoveControlPoint = val; }
+
+ void addControlPointsBeforeSelected();
+ void addControlPointsAfterSelected();
+ void removeSelectedControlPoint();
+
+ void setTangentType(InterpolateMode mode);
+ void setSmoothTangent();
+ void setEaseInTangent();
+ void setEaseOutTangent();
+
+ QString getColorTex();
+ void setColorTex(const QString& strPath);
+ void reloadColorTex();
+ void clearColorTex();
+ QString getAlphaTex();
+ void setAlphaTex(const QString& strPath);
+ void reloadAlphaTex();
+ void clearAlphaTex();
+
+ void setAddCtrlPntByClick(bool value) { _canAddCtrlPntByClick = value; }
+ void setRemoveCtrlPntByClick(bool value) { _canRemoveCtrlPntByClick = value; }
+
+ void setUseAlphaFromColor(bool val);
+
+signals:
+ void PickedControlPointChanged(bool isColorCtrlPnt);
+ void ColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute);
+ void ReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex);
+
+private slots:
+ void onShowContextMenu(const QPoint& pos);
+ void onRemoveControlPoint();
+
+protected:
+ // QWidget events
+ virtual bool event(QEvent *event);
+ virtual void paintEvent(QPaintEvent * e);
+ virtual void resizeEvent(QResizeEvent* e);
+ virtual void mousePressEvent(QMouseEvent* e);
+ virtual void mouseReleaseEvent(QMouseEvent* e);
+ virtual void mouseMoveEvent(QMouseEvent* e);
+
+private:
+ void _updateCurveFitWindowPara();
+ inline float _valueToScreen(float x);
+ inline float _screenToValue(float x);
+
+ void _fillRampImage(QImage& colorImg, QImage& alphaImg);
+ void _drawRampArea(QPainter& painter);
+ void _drawCtrlPntCursors(QPainter& painter);
+ void _drawWeightCursors(QPainter& painter);
+ void _drawColorWeightCursor(QPainter& painter, const ColorControlPoint& pnt0, const ColorControlPoint& pnt1, bool picked = false);
+ void _drawAlphaWeightCursor(QPainter& painter, const ColorControlPoint& pnt0, const ColorControlPoint& pnt1, bool picked = false);
+ int _checkColorCtrlPntCursorSelected(const QPointF& pickPos);
+ int _checkAlphaCtrlPntCursorSelected(const QPointF& pickPos);
+ int _checkColorWeightCursorSelected(const QPointF& pickPos);
+ int _checkColorWeightCursorSelected(int pickedCtrlPnt, const QPointF& pickPos);
+ int _checkAlphaWeightCursorSelected(const QPointF& pickPos);
+ int _checkAlphaWeightCursorSelected(int pickedCtrlPnt, const QPointF& pickPos);
+ void _addColorControlPoint(int xPos);
+ void _addAlphaControlPoint(int xPos);
+
+private:
+ bool _isLink; // if it's true, rgb color and alpha share the same control points
+ ColorAttribute* _colorAttribute;
+ ColorCurve* _colorCurve;
+ ColorCurve* _alphaCurve;
+ bool _canAddRemoveControlPoint;
+ bool _canAddCtrlPntByClick;
+ bool _canRemoveCtrlPntByClick;
+
+ float _curveFitWindowScale;
+ float _curveFitWindowOffset;
+
+ int _pickedColorCtrlPnt;
+ int _pickedAlphaCtrlPnt;
+ int _pickedColorWeight;
+ int _pickedAlphaWeight;
+ bool _dragColorCtrlPnt;
+ bool _dragAlphaCtrlPnt;
+ bool _dragColorWeight;
+ bool _dragAlphaWeight;
+
+ int _colorCtrlPntToRemove;
+ int _alphaCtrlPntToRemove;
+ QMenu* _contextMenu;
+ QAction* _removeCtrlPntAction;
+};
+
+} // namespace CurveEditor
+} // namespace nvidia
+
+#endif // COLORWIDGET_H
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Window/CurveEditorMainWindow.cpp b/NvBlast/tools/CurveEditor/source/Internal/Window/CurveEditorMainWindow.cpp
new file mode 100644
index 0000000..b11c4cf
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Window/CurveEditorMainWindow.cpp
@@ -0,0 +1,1530 @@
+#include "CurveEditorMainWindow.h"
+#include "ui_CurveEditorMainWindow.h"
+#include <QtWidgets/QSplitter>
+#include <QtWidgets/QColorDialog>
+#include "CurveWidget.h"
+#include "ColorWidget.h"
+#include "AlphaDialog.h"
+#include <QtCore/QDebug>
+#include <QtWidgets/QFileDialog>
+#include <QtWidgets/QMessageBox>
+#include <float.h>
+
+namespace nvidia {
+namespace CurveEditor {
+
+// each value is associated with the tab index of tab control of attributes
+enum AttributesTabIndex
+{
+ eCurveTab = 0,
+ eColorTab = 1,
+};
+
+/////////////////////////////////////////////////////////////////////////////////////
+QString InterpolateModeToString(InterpolateMode mode)
+{
+ switch(mode)
+ {
+ case eDiscret:
+ return "Discret";
+ case eLinear:
+ return "Linear";
+ case eBezierSpline:
+ return "BezierSpline";
+ case eCatmullRomSpline:
+ return "CatmullRomSpline";
+ default:
+ return "Discret";
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+InterpolateMode StringToInterpolateMode(const QString& mode)
+{
+ if (mode == "Discret")
+ {
+ return eDiscret;
+ }
+ else if (mode == "Linear")
+ {
+ return eLinear;
+ }
+ else if (mode == "BezierSpline")
+ {
+ return eBezierSpline;
+ }
+ else if (mode == "CatmullRomSpline")
+ {
+ return eCatmullRomSpline;
+ }
+ else
+ {
+ return eDiscret;
+ }
+}
+
+QString OpenTextureFile( QString lastDir, QString title = "")
+{
+ QString titleStr = "Open Texture File";
+ if(!title.isEmpty())
+ titleStr = title;
+
+ QString fileName = QFileDialog::getOpenFileName(nullptr, titleStr, lastDir, "Images (*.dds *.png *.bmp *.jpg *.tga)");
+
+ return fileName;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+void setTextureButtons(QPushButton *pTex, QPushButton *pReload, QPushButton *pClear)
+{
+ pTex->setIcon(QIcon(":/AppMainWindow/Icon/TextureEnabled_icon.png"));
+ pReload->setIcon(QIcon(":/AppMainWindow/Icon/Refresh_icon.png"));
+ pClear->setIcon(QIcon(":/AppMainWindow/Icon/Remove_icon.png"));
+
+ pTex->setIconSize(QSize(12,12));
+ pReload->setIconSize(QSize(12,12));
+ pClear->setIconSize(QSize(12,12));
+}
+
+//////////////////////////////////////////////////////////
+QString addStar(QString text, bool add)
+{
+ QByteArray ba = text.toUtf8();
+
+ const char* in = ba.data();
+ char out[1024];
+
+ int i = 0;
+ for (i = 0; i < strlen(in); i++)
+ {
+ if (in[i] == '*')
+ break;
+ out[i] = in[i];
+ }
+ out[i] = 0;
+
+ QString newtext;
+ if (add)
+ newtext = QString((const char*)out) + QString("*");
+ else
+ newtext = QString((const char*)out) ;
+ return newtext;
+}
+
+//////////////////////////////////////////////////////////
+void setFocusColor(QWidget* qWidget, bool sameForAllAttributes)
+{
+ if (!qWidget)
+ return;
+
+ QString sameStyle = QString("font: ; color: rgb(150,150,150);") ;
+ QString differentStyle = QString("font: bold; color: rgb(255,55,55);");
+ QString style = (sameForAllAttributes) ? sameStyle : differentStyle;
+
+ qWidget->setStyleSheet(style);
+
+ QLabel* label = dynamic_cast<QLabel*>(qWidget);
+ if (label)
+ {
+ QString newtext = addStar(label->text(), !sameForAllAttributes);
+
+ label->setFrameStyle(0);
+ label->setText(newtext);
+ }
+}
+
+//////////////////////////////////////////////////////////
+void pickColor(QColor& color, QWidget* parent)
+{
+ QColor newColor = QColorDialog::getColor(color, parent);
+ if(newColor.isValid())
+ {
+ color = newColor;
+ }
+}
+
+//////////////////////////////////////////////////////////
+void pickAlpha(int& alpha, QWidget* parent)
+{
+ alpha = AlphaDialog::getAlpha(alpha, parent);
+}
+
+//////////////////////////////////////////////////////////
+void setButtonColor(QPushButton *button, const QColor& color)
+{
+ QString specBtnStyle = QString("background-color: rgb(%1,%2,%3);")
+ .arg(color.red())
+ .arg(color.green())
+ .arg(color.blue());
+
+ button->setStyleSheet(specBtnStyle);
+}
+
+//////////////////////////////////////////////////////////
+void setButtonTex(QPushButton *button, bool used)
+{
+ if (used)
+ button->setIcon(QIcon(":/AppMainWindow/Icon/TextureIsUsed_icon.png"));
+ else
+ button->setIcon(QIcon(":/AppMainWindow/Icon/TextureEnabled_icon.png"));
+}
+
+CurveEditorMainWindow::CurveEditorMainWindow(QWidget *parent)
+ : QMainWindow(parent)
+ , ui(new Ui::CurveEditorMainWindow)
+ , _curveWidget(nullptr)
+ , _colorWidget(nullptr)
+ , _curveAttributeCache(nullptr)
+ , _colorAttributeCache(nullptr)
+ , _updateUIFromData(false)
+ , _canMoveCurveControlPointHorizontally(true)
+ , _canAddRemoveCurveControlPoint(true)
+ , _canChangeCurveTangentType(true)
+{
+ Q_INIT_RESOURCE(CurveEditor);
+
+ ui->setupUi(this);
+
+ setTextureButtons(ui->btnColorTex, ui->btnColorReload, ui->btnColorClear);
+ setTextureButtons(ui->btnAlphaTex, ui->btnAlphaReload, ui->btnAlphaClear);
+
+ ui->centralWidget->setStretchFactor(0, 30);
+ ui->centralWidget->setStretchFactor(1, 70);
+
+ {
+ QActionGroup* groupSnap = new QActionGroup(this);
+ groupSnap->addAction(ui->actionSnap_All);
+ groupSnap->addAction(ui->actionSnap_Horizontal);
+ groupSnap->addAction(ui->actionSnap_Vertical);
+ }
+
+ {
+ QActionGroup* groupAddRemoveCtrlPnt = new QActionGroup(this);
+ groupAddRemoveCtrlPnt->addAction(ui->actionAdd_Control_Point_By_Click);
+ groupAddRemoveCtrlPnt->addAction(ui->actionRemove_Control_Point_By_Click);
+ }
+
+ _fillCurveAttributesTree();
+
+ _fillColorAttributesTree();
+
+ {
+ _curveWidget = new CurveWidget(ui->frameCurveEditorArea);
+ ui->layoutCurveEditorArea->addWidget(_curveWidget);
+ connect(_curveWidget, SIGNAL(PickedControlPointChanged(const std::vector<CurveEntity*>)), this, SLOT(onCurvePickedControlPointChanged(const std::vector<CurveEntity*>)));
+ connect(_curveWidget, SIGNAL(PickedControlPointValueChanged(QPointF&)), this, SLOT(onCurvePickedControlPointValueChanged(QPointF&)));
+ }
+
+ {
+ _colorWidget = new ColorWidget(ui->frameColorAlphaRamp);
+ ui->layoutColorEditorArea->addWidget(_colorWidget);
+ connect(_colorWidget, SIGNAL(PickedControlPointChanged(bool)), this, SLOT(onColorPickedControlPointChanged(bool)));
+
+ QColor color = _colorWidget->getColor();
+ setButtonColor(ui->btnColor, color);
+ setButtonColor(ui->btnAlpha, QColor(color.alpha(), color.alpha(), color.alpha()));
+ }
+
+ connect(_curveWidget, SIGNAL(CurveAttributeChanged(nvidia::CurveEditor::CurveAttribute*)), this, SIGNAL(CurveAttributeChanged(nvidia::CurveEditor::CurveAttribute*)));
+ connect(_colorWidget, SIGNAL(ColorAttributeChanged(nvidia::CurveEditor::ColorAttribute*)), this, SIGNAL(ColorAttributeChanged(nvidia::CurveEditor::ColorAttribute*)));
+ connect(_colorWidget, SIGNAL(ReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute*, bool, int)), this, SIGNAL(ReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute*, bool, int)));
+
+ QString defFilePath;
+
+ QString appDir = qApp->applicationDirPath();
+ QDir dir(appDir);
+ if (dir.cd("../../media"))
+ defFilePath = dir.absolutePath();
+
+ _lastFilePath = defFilePath;
+ _presetPath = _lastFilePath + "/Presets/";
+}
+
+CurveEditorMainWindow::~CurveEditorMainWindow()
+{
+ delete ui;
+ ui = nullptr;
+}
+
+void CurveEditorMainWindow::setCurveAttributes(const std::vector<CurveAttributeBase*>& attributes)
+{
+ _curveWidget->setCurveAttributes(std::vector<CurveAttributeBase*>());
+
+ _curveAttributes = attributes;
+ _fillCurveAttributesTree();
+
+ _canMoveCurveControlPointHorizontally = false;
+ _canAddRemoveCurveControlPoint = false;
+ _canChangeCurveTangentType = false;
+ size_t countAttributes = _curveAttributes.size();
+ for (size_t i = 0; i < countAttributes; ++i)
+ {
+ CurveAttributeBase* attribute = _curveAttributes[i];
+
+ if (attribute->getType() == eGroupAttr)
+ {
+ CurveAttributeGroup* attributeGroup = static_cast<CurveAttributeGroup*>(attribute);
+ size_t countAttributesInGroup = attributeGroup->attributes.size();
+ for (size_t j = 0; j < countAttributesInGroup; ++j)
+ {
+ CurveAttribute* attributeInGroup = static_cast<CurveAttribute*>(attributeGroup->attributes[j]);
+ if (attributeInGroup->canMoveControlPointHorizontally())
+ _canMoveCurveControlPointHorizontally = true;
+ if (attributeInGroup->canAddRemoveControlPoint())
+ _canAddRemoveCurveControlPoint = true;
+ if (attributeInGroup->canChangeTangentType())
+ _canChangeCurveTangentType = true;
+ }
+ }
+ else
+ {
+ CurveAttribute* attributeSecific = static_cast<CurveAttribute*>(attribute);
+ if (attributeSecific->canMoveControlPointHorizontally())
+ _canMoveCurveControlPointHorizontally = true;
+ if (attributeSecific->canAddRemoveControlPoint())
+ _canAddRemoveCurveControlPoint = true;
+ if (attributeSecific->canChangeTangentType())
+ _canChangeCurveTangentType = true;
+ }
+ }
+
+ ui->spinBoxLocation->setEnabled(_canMoveCurveControlPointHorizontally);
+ _syncUIStatusWithSelectedAttribute(_canAddRemoveCurveControlPoint, _canChangeCurveTangentType);
+}
+
+void CurveEditorMainWindow::setColorCurveAttributes(const std::vector<ColorAttribute*>& attributes)
+{
+ _colorWidget->setColorAttribute(nullptr);
+
+ _colorAttributes = attributes;
+ _fillColorAttributesTree();
+}
+
+void CurveEditorMainWindow::setSelectedCurveAttributes(const std::vector<CurveAttributeBase*>& attributes)
+{
+ ui->tabWidgetAttributes->setCurrentIndex(eCurveTab);
+
+ for (size_t i = 0; i < attributes.size(); ++i)
+ {
+ CurveAttributeBase* attribute = attributes[i];
+ QList<QTreeWidgetItem*> items = ui->treeWidgetCurveAttributes->findItems(attribute->getName().c_str(), Qt::MatchExactly);
+ if (items.size() > 0)
+ items[0]->setSelected(true);
+ }
+}
+
+void CurveEditorMainWindow::setSelectedColorAttribute(const ColorAttribute* attribute)
+{
+ ui->tabWidgetAttributes->setCurrentIndex(eColorTab);
+
+ if (attribute)
+ {
+ QList<QTreeWidgetItem*> items = ui->treeWidgetColorAttributes->findItems(attribute->getName().c_str(), Qt::MatchExactly);
+ if (items.size() > 0)
+ items[0]->setSelected(true);
+ }
+}
+
+void CurveEditorMainWindow::setResampleEnabled(bool enable)
+{
+ ui->checkBoxResamplePoints->setVisible(enable);
+ ui->spinBoxResamplePoints->setVisible(enable);
+ ui->checkBoxResamplePoints->setEnabled(enable);
+ ui->spinBoxResamplePoints->setEnabled(enable);
+}
+
+void CurveEditorMainWindow::on_actionCopy_triggered()
+{
+ if (eCurveTab == ui->tabWidgetAttributes->currentIndex())
+ {
+ QList<QTreeWidgetItem*> items = ui->treeWidgetCurveAttributes->selectedItems();
+ if (1 == items.count())
+ {
+ CurveAttributeTreeItem* item = static_cast<CurveAttributeTreeItem*>(items.at(0));
+
+ if (eSingleAttr == item->_attribute->getType())
+ {
+ if (_curveAttributeCache == nullptr)
+ _curveAttributeCache = new CurveAttribute("curveAttributeCache");
+
+ CurveAttribute* selectedAttribute = static_cast<CurveAttribute*>(item->_attribute);
+ _curveAttributeCache->curve = selectedAttribute->curve;
+ return ;
+ }
+ }
+
+ QMessageBox::warning(this, tr("Warning"), tr("You should select only one attribute to copy attribute data."));
+ }
+ else if (eColorTab == ui->tabWidgetAttributes->currentIndex())
+ {
+ QList<QTreeWidgetItem*> items = ui->treeWidgetColorAttributes->selectedItems();
+ if (1 == items.count())
+ {
+ ColorAttributeTreeItem* item = static_cast<ColorAttributeTreeItem*>(items.at(0));
+
+ if (eColorAttr == item->_attribute->getType())
+ {
+ if (_colorAttributeCache == nullptr)
+ _colorAttributeCache = new ColorAttribute("colorAttributeCache");
+
+ ColorAttribute* selectedAttribute = static_cast<ColorAttribute*>(item->_attribute);
+ _colorAttributeCache->colorCurve = selectedAttribute->colorCurve;
+ _colorAttributeCache->alphaCurve = selectedAttribute->alphaCurve;
+ return ;
+ }
+ }
+ }
+}
+
+void CurveEditorMainWindow::on_actionPaste_triggered()
+{
+ if (eCurveTab == ui->tabWidgetAttributes->currentIndex())
+ {
+ if (nullptr == _curveAttributeCache)
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("You should copy or load an curve attribute's data first."));
+ return ;
+ }
+
+ QList<QTreeWidgetItem*> items = ui->treeWidgetCurveAttributes->selectedItems();
+ if (1 == items.count())
+ {
+ CurveAttributeTreeItem* item = static_cast<CurveAttributeTreeItem*>(items.at(0));
+
+ if (eSingleAttr == item->_attribute->getType())
+ {
+ CurveAttribute* selectedAttribute = static_cast<CurveAttribute*>(item->_attribute);
+ bool compatible = true;
+ if (compatible)
+ {
+ selectedAttribute->curve = _curveAttributeCache->curve;
+ on_treeWidgetCurveAttributes_itemSelectionChanged();
+ CurveAttributeChanged(selectedAttribute);
+ }
+ else
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("The data types between the curve attribute copyed from and the curve attribute copy to are incompatible ."));
+ }
+ return ;
+ }
+ }
+
+ QMessageBox::warning(this, tr("Warning"), tr("You should select only one curve attribute to paste curve attribute data."));
+ }
+ else if (eColorTab == ui->tabWidgetAttributes->currentIndex())
+ {
+ if (nullptr == _colorAttributeCache)
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("You should copy or load an color attribute's data first."));
+ return ;
+ }
+
+ QList<QTreeWidgetItem*> items = ui->treeWidgetColorAttributes->selectedItems();
+ if (1 == items.count())
+ {
+ ColorAttributeTreeItem* item = static_cast<ColorAttributeTreeItem*>(items.at(0));
+
+ if (eColorAttr == item->_attribute->getType())
+ {
+ ColorAttribute* selectedAttribute = static_cast<ColorAttribute*>(item->_attribute);
+ bool compatible = true;
+ if (compatible)
+ {
+ selectedAttribute->colorCurve = _colorAttributeCache->colorCurve;
+ selectedAttribute->alphaCurve = _colorAttributeCache->alphaCurve;
+ on_treeWidgetColorAttributes_itemSelectionChanged();
+ ColorAttributeChanged(selectedAttribute);
+ }
+ else
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("The data types between copy from attribute and copy to attribute are incompatible ."));
+ }
+ return ;
+ }
+ }
+
+ QMessageBox::warning(this, tr("Warning"), tr("You should select only one attribute to paste attribute data."));
+ }
+}
+
+void CurveEditorMainWindow::on_actionSave_Selected_as_Preset_triggered()
+{
+ QDir dir(_presetPath);
+ if (!dir.exists())
+ dir.mkdir(_presetPath);
+
+ CurveAttribute* curveAttribute = nullptr;
+ ColorAttribute* colorAttribute = nullptr;
+ QString presetFile = _presetPath;
+
+ if (eCurveTab == ui->tabWidgetAttributes->currentIndex())
+ {
+ QList<QTreeWidgetItem*> items = ui->treeWidgetCurveAttributes->selectedItems();
+ if (1 != items.count())
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("You should select one attribute only to save preset."));
+ return ;
+ }
+
+ CurveAttributeTreeItem* item = static_cast<CurveAttributeTreeItem*>(items.at(0));
+
+ if (eSingleAttr != item->_attribute->getType())
+ {
+ return;
+ }
+
+ curveAttribute = static_cast<CurveAttribute*>(item->_attribute);
+ presetFile += curveAttribute->getName().c_str();
+ presetFile += ".cps";
+ }
+ else if (eColorTab == ui->tabWidgetAttributes->currentIndex())
+ {
+ QList<QTreeWidgetItem*> items = ui->treeWidgetColorAttributes->selectedItems();
+ if (1 != items.count())
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("You should select one attribute only to save preset."));
+ return ;
+ }
+
+ ColorAttributeTreeItem* item = static_cast<ColorAttributeTreeItem*>(items.at(0));
+
+ if (eColorAttr != item->_attribute->getType())
+ {
+ return;
+ }
+
+ colorAttribute = item->_attribute;
+ presetFile += colorAttribute->getName().c_str();
+ presetFile += ".cps";
+ }
+
+ QString filePath = QFileDialog::getSaveFileName(this, tr("Save Curve PreSet"), presetFile, tr("Curve PreSet(*.cps)"));
+ if (filePath.length() == 0)
+ {
+ QMessageBox::warning(this, tr("Path"), tr("You didn't select any files."));
+ return ;
+ }
+
+ QFileInfo fileInfo(filePath);
+ _presetPath = fileInfo.absoluteDir().absolutePath();
+ if (!_presetPath.endsWith("/"))
+ _presetPath += "/";
+
+ QFile file(filePath);
+ if (!file.open(QIODevice::WriteOnly|QIODevice::Truncate))
+ {
+ return;
+ }
+ QTextStream out(&file);
+
+ QDomDocument xmlDoc;
+ QDomElement rootElm = xmlDoc.createElement(tr("CurvePreSet"));
+ xmlDoc.appendChild(rootElm);
+
+ if (curveAttribute != nullptr)
+ {
+ _saveAttribute(rootElm, curveAttribute);
+ }
+ else if (colorAttribute != nullptr)
+ {
+ _saveAttribute(rootElm, colorAttribute);
+ }
+ // 4 is count of indent
+ xmlDoc.save(out, 4);
+}
+
+void CurveEditorMainWindow::on_actionLoad_Preset_to_Copy_Buffer_triggered()
+{
+ QString filePath = QFileDialog::getOpenFileName(this, tr("Open Curve PreSet"), _presetPath, tr("Curve PreSet(*.cps)"));
+ if (filePath.length() == 0)
+ {
+ QMessageBox::warning(this, tr("Path"), tr("You didn't select any files."));
+ return;
+ }
+
+ QFileInfo fileInfo(filePath);
+ _presetPath = fileInfo.absoluteDir().absolutePath();
+ if (!_presetPath.endsWith("/"))
+ _presetPath += "/";
+
+ QFile file(filePath);
+
+ if (!file.open(QIODevice::ReadOnly))
+ {
+ return;
+ }
+
+ QDomDocument xmlDoc;
+ if (!xmlDoc.setContent(&file))
+ {
+ file.close();
+ return;
+ }
+ file.close();
+
+ if (xmlDoc.isNull() || xmlDoc.documentElement().tagName() != tr("CurvePreSet"))
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("The file you selected is empty or not a cps file."));
+ return;
+ }
+
+ QDomElement elm = xmlDoc.documentElement().firstChildElement();
+ CurveAttributeBase* presetAttribute = _loadAttribute(elm);
+ if (nullptr == presetAttribute)
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("Faid to load the cps file!"));
+ return;
+ }
+
+ if (eSingleAttr == presetAttribute->_type)
+ {
+ if (_curveAttributeCache == nullptr)
+ _curveAttributeCache = new CurveAttribute("curveAttributeCache");
+
+ CurveAttribute* presetCurveAttribute = static_cast<CurveAttribute*>(presetAttribute);
+ _curveAttributeCache->curve = presetCurveAttribute->curve;
+ }
+ else if (eColorAttr == presetAttribute->_type)
+ {
+ if (_colorAttributeCache == nullptr)
+ _colorAttributeCache = new ColorAttribute("colorAttributeCache");
+
+ ColorAttribute* presetColorAttribute = static_cast<ColorAttribute*>(presetAttribute);
+ _colorAttributeCache->colorCurve = presetColorAttribute->colorCurve;
+ _colorAttributeCache->alphaCurve = presetColorAttribute->alphaCurve;
+ }
+}
+
+void CurveEditorMainWindow::on_actionImport_Preset_onto_Selected_triggered()
+{
+ CurveAttribute* curveAttribute = nullptr;
+ ColorAttribute* colorAttribute = nullptr;
+ if (eCurveTab == ui->tabWidgetAttributes->currentIndex())
+ {
+ QList<QTreeWidgetItem*> items = ui->treeWidgetCurveAttributes->selectedItems();
+ if (1 != items.count())
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("You should select only one attribute to import preset."));
+ return;
+ }
+
+ CurveAttributeTreeItem* item = static_cast<CurveAttributeTreeItem*>(items.at(0));
+
+ if (eSingleAttr != item->_attribute->getType())
+ {
+ return;
+ }
+
+ curveAttribute = static_cast<CurveAttribute*>(item->_attribute);
+ }
+ else if (eColorTab == ui->tabWidgetAttributes->currentIndex())
+ {
+ QList<QTreeWidgetItem*> items = ui->treeWidgetColorAttributes->selectedItems();
+ if (1 != items.count())
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("You should select only one attribute to import preset."));
+ return;
+ }
+
+ ColorAttributeTreeItem* item = static_cast<ColorAttributeTreeItem*>(items.at(0));
+
+ if (eColorAttr != item->_attribute->getType())
+ {
+ return;
+ }
+
+ colorAttribute = item->_attribute;
+ }
+
+ QString filePath = QFileDialog::getOpenFileName(this, tr("Open Curve PreSet"), _presetPath, tr("Curve PreSet(*.cps)"));
+ if (filePath.length() == 0)
+ {
+ QMessageBox::warning(this, tr("Path"), tr("You didn't select any files."));
+ return;
+ }
+
+ QFileInfo fileInfo(filePath);
+ _presetPath = fileInfo.absoluteDir().absolutePath();
+ if (!_presetPath.endsWith("/"))
+ _presetPath += "/";
+
+ QFile file(filePath);
+
+ if (!file.open(QIODevice::ReadOnly))
+ {
+ return;
+ }
+
+ QDomDocument xmlDoc;
+ if (!xmlDoc.setContent(&file))
+ {
+ file.close();
+ return;
+ }
+ file.close();
+
+ if (xmlDoc.isNull() || xmlDoc.documentElement().tagName() != tr("CurvePreSet"))
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("The file you selected is empty or not a cps file."));
+ return;
+ }
+
+ QDomElement elm = xmlDoc.documentElement().firstChildElement();
+ CurveAttributeBase* presetAttribute = _loadAttribute(elm);
+ if (nullptr == presetAttribute)
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("Faid to load the cps file!"));
+ return;
+ }
+
+ if (eSingleAttr == presetAttribute->_type)
+ {
+ CurveAttribute* presetCurveAttribute = static_cast<CurveAttribute*>(presetAttribute);
+
+ bool compatible = (curveAttribute != nullptr) ? true:false;
+ if (compatible)
+ {
+ curveAttribute->curve = presetCurveAttribute->curve;
+ on_treeWidgetCurveAttributes_itemSelectionChanged();
+ CurveAttributeChanged(curveAttribute);
+ }
+ else
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("The selected attribute is incompatible with preset attribute."));
+ }
+ }
+ else if (eColorAttr == presetAttribute->_type)
+ {
+ ColorAttribute* presetColorAttribute = static_cast<ColorAttribute*>(presetAttribute);
+
+ bool compatible = (colorAttribute != nullptr) ? true:false;;
+ if (compatible)
+ {
+ colorAttribute->colorCurve = presetColorAttribute->colorCurve;
+ colorAttribute->alphaCurve = presetColorAttribute->alphaCurve;
+ on_treeWidgetColorAttributes_itemSelectionChanged();
+ ColorAttributeChanged(colorAttribute);
+ }
+ else
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("The selected attribute is incompatible with preset attribute."));
+ }
+ }
+}
+
+void CurveEditorMainWindow::on_actionReset_Curve_triggered()
+{
+ if (ui->tabWidgetAttributes->currentIndex() == eCurveTab)
+ {
+ _curveWidget->reset();
+ }
+ else if (ui->tabWidgetAttributes->currentIndex() == eColorTab)
+ {
+ _colorWidget->reset();
+ }
+
+}
+
+void CurveEditorMainWindow::on_actionAdd_Before_Selected_triggered()
+{
+ if (_curveWidget->hasFocus())
+ _curveWidget->addControlPointsBeforeSelected();
+
+ if (_colorWidget->hasFocus())
+ _colorWidget->addControlPointsBeforeSelected();
+}
+
+void CurveEditorMainWindow::on_actionAdd_After_Selected_triggered()
+{
+ if (_curveWidget->hasFocus())
+ _curveWidget->addControlPointsAfterSelected();
+
+ if (_colorWidget->hasFocus())
+ _colorWidget->addControlPointsAfterSelected();
+}
+
+void CurveEditorMainWindow::on_actionRemove_Selected_triggered()
+{
+ if (_curveWidget->hasFocus())
+ _curveWidget->removeSelectedControlPoints();
+
+ if (_colorWidget->hasFocus())
+ _colorWidget->removeSelectedControlPoint();
+}
+
+void CurveEditorMainWindow::on_actionTangent_Stepped_triggered()
+{
+ if (_curveWidget->hasFocus())
+ _curveWidget->setTangentType(eDiscret);
+
+ if (_colorWidget->hasFocus())
+ _colorWidget->setTangentType(eDiscret);
+}
+
+void CurveEditorMainWindow::on_actionTangent_Linear_triggered()
+{
+ if (_curveWidget->hasFocus())
+ _curveWidget->setTangentType(eLinear);
+
+ if (_colorWidget->hasFocus())
+ _colorWidget->setTangentType(eLinear);
+}
+
+void CurveEditorMainWindow::on_actionTangent_Smooth_triggered()
+{
+ if (_curveWidget->hasFocus())
+ _curveWidget->setSmoothTangent();
+
+ if (_colorWidget->hasFocus())
+ _colorWidget->setSmoothTangent();
+}
+
+void CurveEditorMainWindow::on_actionTangent_Ease_Out_triggered()
+{
+ if (_curveWidget->hasFocus())
+ _curveWidget->setEaseOutTangent();
+
+ if (_colorWidget->hasFocus())
+ _colorWidget->setEaseOutTangent();
+}
+
+void CurveEditorMainWindow::on_actionTangent_Ease_In_triggered()
+{
+ if (_curveWidget->hasFocus())
+ _curveWidget->setEaseInTangent();
+
+ if (_colorWidget->hasFocus())
+ _colorWidget->setEaseInTangent();
+}
+
+void CurveEditorMainWindow::on_actionTangent_Spline_triggered()
+{
+ if (_curveWidget->hasFocus())
+ _curveWidget->setTangentType(eCatmullRomSpline);
+
+ if (_colorWidget->hasFocus())
+ _colorWidget->setTangentType(eCatmullRomSpline);
+}
+
+void CurveEditorMainWindow::on_actionSnap_All_triggered()
+{
+ _curveWidget->setSnapAll();
+}
+
+void CurveEditorMainWindow::on_actionSnap_Horizontal_triggered()
+{
+ _curveWidget->setSnapHorizontal();
+}
+
+void CurveEditorMainWindow::on_actionSnap_Vertical_triggered()
+{
+ _curveWidget->setSnapVertical();
+}
+
+void CurveEditorMainWindow::on_actionContract_Horizontally_triggered()
+{
+ _curveWidget->decreaseCurveScaleHorizontally();
+}
+
+void CurveEditorMainWindow::on_actionExpand_Horizontally_triggered()
+{
+ _curveWidget->increaseCurveScaleHorizontally();
+}
+
+void CurveEditorMainWindow::on_actionContract_Vertically_triggered()
+{
+ _curveWidget->decreaseCurveScaleVertically();
+}
+
+void CurveEditorMainWindow::on_actionExpand_Vertically_triggered()
+{
+ _curveWidget->increaseCurveScaleVertically();
+}
+
+void CurveEditorMainWindow::on_actionFrame_Horizontally_triggered()
+{
+ _curveWidget->frameCurveScaleHorizontally();
+}
+
+void CurveEditorMainWindow::on_actionFrame_Vertically_triggered()
+{
+ _curveWidget->frameCurveScaleVertically();
+}
+
+void CurveEditorMainWindow::on_actionFrame_All_triggered()
+{
+ _curveWidget->frameCurveScale();
+}
+
+void CurveEditorMainWindow::on_spinBoxLocation_valueChanged(double value)
+{
+ if (!_updateUIFromData)
+ _curveWidget->setLocation(value);
+}
+
+void CurveEditorMainWindow::on_spinBoxValue_valueChanged(double value)
+{
+ if (!_updateUIFromData)
+ _curveWidget->setValue(value);
+}
+
+void CurveEditorMainWindow::on_btnColor_clicked()
+{
+ QColor color = _colorWidget->getColor();
+ pickColor(color, nullptr);
+ _colorWidget->setColor(color);
+ setButtonColor(ui->btnColor, color);
+}
+
+void CurveEditorMainWindow::on_btnColorTex_clicked()
+{
+ QString filePath = OpenTextureFile(_colorWidget->getColorTex().isEmpty() ? _lastFilePath : _colorWidget->getColorTex());
+ _colorWidget->setColorTex(filePath);
+ setButtonTex(ui->btnColorTex, !filePath.isEmpty());
+
+ if (!filePath.isEmpty())
+ {
+ QFileInfo fileInfo(filePath);
+ _lastFilePath = fileInfo.absoluteDir().absolutePath();
+ }
+}
+
+void CurveEditorMainWindow::on_btnColorReload_clicked()
+{
+ QList<QTreeWidgetItem*> items = ui->treeWidgetColorAttributes->selectedItems();
+ if (0 ==items.count())
+ return;
+
+ _colorWidget->reloadColorTex();
+}
+
+void CurveEditorMainWindow::on_btnColorClear_clicked()
+{
+ _colorWidget->clearColorTex();
+ setButtonTex(ui->btnColorTex, false);
+}
+
+void CurveEditorMainWindow::on_btnAlpha_clicked()
+{
+ int alpha = _colorWidget->getAlpha();
+ pickAlpha(alpha, nullptr);
+ _colorWidget->setAlpha(alpha);
+ setButtonColor(ui->btnAlpha, QColor(alpha, alpha, alpha));
+}
+
+void CurveEditorMainWindow::on_btnAlphaTex_clicked()
+{
+ QString filePath = OpenTextureFile(_colorWidget->getAlphaTex().isEmpty() ? _lastFilePath : _colorWidget->getAlphaTex());
+ _colorWidget->setAlphaTex(filePath);
+ setButtonTex(ui->btnAlphaTex, !filePath.isEmpty());
+
+ if (!filePath.isEmpty())
+ {
+ QFileInfo fileInfo(filePath);
+ _lastFilePath = fileInfo.absoluteDir().absolutePath();
+ }
+}
+
+void CurveEditorMainWindow::on_btnAlphaReload_clicked()
+{
+ QList<QTreeWidgetItem*> items = ui->treeWidgetColorAttributes->selectedItems();
+ if (0 ==items.count())
+ return;
+
+ _colorWidget->reloadAlphaTex();
+}
+
+void CurveEditorMainWindow::on_btnAlphaClear_clicked()
+{
+ _colorWidget->clearAlphaTex();
+ setButtonTex(ui->btnAlphaTex, false);
+}
+
+void CurveEditorMainWindow::on_checkBoxUseAlphaChannellFromColor_stateChanged(int val)
+{
+ _colorWidget->setUseAlphaFromColor(0 != val);
+}
+
+void CurveEditorMainWindow::on_treeWidgetCurveAttributes_itemSelectionChanged()
+{
+ std::vector<CurveAttributeBase*> attributes;
+
+ QList<QTreeWidgetItem*> items = ui->treeWidgetCurveAttributes->selectedItems();
+ int count = items.count();
+ for (int i = 0; i < items.count(); ++i)
+ {
+ CurveAttributeTreeItem* item = static_cast<CurveAttributeTreeItem*>(items.at(i));
+
+ attributes.push_back(item->_attribute);
+
+ qDebug()<< item->_attribute->getName().c_str();
+ }
+
+ _curveWidget->setCurveAttributes(attributes);
+
+ bool canMoveControlPointHorizontally = _canMoveCurveControlPointHorizontally;
+ bool canAddRemoveControlPoint = _canAddRemoveCurveControlPoint;
+ bool canChangeTangentType = _canChangeCurveTangentType;
+ for (size_t i = 0; i < attributes.size(); ++i)
+ {
+ CurveAttributeBase* attribute = attributes[i];
+ if (eGroupAttr == attribute->getType())
+ {
+ CurveAttributeGroup* attributeGroup = static_cast<CurveAttributeGroup*>(attribute);
+ for (size_t j = 0; j < attributeGroup->attributes.size(); ++j)
+ {
+ CurveAttributeBase* attributeInGroup = attributeGroup->attributes[j];
+
+ if (attributeInGroup->canMoveControlPointHorizontally())
+ canMoveControlPointHorizontally = true;
+
+ if (attributeInGroup->canAddRemoveControlPoint())
+ canAddRemoveControlPoint = true;
+
+ if (attributeInGroup->canChangeTangentType())
+ canChangeTangentType = true;
+ }
+ }
+ else
+ {
+ if (attribute->canMoveControlPointHorizontally())
+ canMoveControlPointHorizontally = true;
+
+ if (attribute->canAddRemoveControlPoint())
+ canAddRemoveControlPoint = attribute->canAddRemoveControlPoint();
+
+ if (attribute->canChangeTangentType())
+ canChangeTangentType = true;
+ }
+ }
+
+ ui->spinBoxLocation->setEnabled(canMoveControlPointHorizontally);
+ _syncUIStatusWithSelectedAttribute(canAddRemoveControlPoint, canChangeTangentType);
+}
+
+void CurveEditorMainWindow::on_treeWidgetColorAttributes_itemSelectionChanged()
+{
+ QList<QTreeWidgetItem*> items = ui->treeWidgetColorAttributes->selectedItems();
+ if (0 == items.count())
+ return;
+
+ ColorAttributeTreeItem* item = static_cast<ColorAttributeTreeItem*>(items.at(0));
+ _colorWidget->setColorAttribute(item->_attribute);
+ _colorWidget->setCanAddRemoveControlPoint(item->_attribute->canAddRemoveControlPoint());
+
+ _syncUIStatusWithSelectedAttribute(item->_attribute->canAddRemoveControlPoint(), item->_attribute->canChangeTangentType());
+}
+
+void CurveEditorMainWindow::on_tabWidgetAttributes_currentChanged(int index)
+{
+ //if (eCurveTab == index)
+ //{
+ // _setCurveExclusiveUIEnable(true);
+ //}
+ //else if (eColorTab == index)
+ //{
+ // _setCurveExclusiveUIEnable(false);
+ //}
+}
+
+void CurveEditorMainWindow::on_sliderColorFallOff_sliderMoved(int value)
+{
+ if (!_updateUIFromData)
+ {
+ _colorWidget->setColorFallOff((float)value/100);
+
+ if (_colorWidget->isLink())
+ {
+ _updateUIFromData = true;
+ ui->sliderAlphaFallOff->setValue(value);
+ _updateUIFromData = false;
+ }
+ }
+}
+
+void CurveEditorMainWindow::on_sliderAlphaFallOff_sliderMoved(int value)
+{
+ if (!_updateUIFromData)
+ {
+ _colorWidget->setAlphaFallOff((float)value/100);
+
+ if (_colorWidget->isLink())
+ {
+ _updateUIFromData = true;
+ ui->sliderAlphaFallOff->setValue(value);
+ _updateUIFromData = false;
+ }
+ }
+}
+
+void CurveEditorMainWindow::on_actionAdd_Control_Point_By_Click_triggered(bool val)
+{
+ _curveWidget->setAddCtrlPntByClick(val);
+ _curveWidget->setRemoveCtrlPntByClick(false);
+
+ _colorWidget->setAddCtrlPntByClick(val);
+ _colorWidget->setRemoveCtrlPntByClick(false);
+}
+
+void CurveEditorMainWindow::on_actionRemove_Control_Point_By_Click_triggered(bool val)
+{
+ _curveWidget->setAddCtrlPntByClick(false);
+ _curveWidget->setRemoveCtrlPntByClick(val);
+
+ _colorWidget->setAddCtrlPntByClick(false);
+ _colorWidget->setRemoveCtrlPntByClick(val);
+}
+
+void CurveEditorMainWindow::onCurvePickedControlPointChanged(const std::vector<CurveEntity*>& pickedCurves)
+{
+ bool enableChangeTangentType = true;
+ bool enableAddRemoveCtrlPnts = true;
+ bool enableLoactionEditor = true;
+ bool locationSameForAllAttributes = true;
+ bool valueSameForAllAttributes = true;
+ float location = FLT_MIN, value = FLT_MIN;
+ _updateUIFromData = true;
+ ui->spinBoxLocation->setValue(location);
+ ui->spinBoxValue->setValue(value);
+ _updateUIFromData = false;
+ for(size_t i = 0; i < pickedCurves.size(); ++i)
+ {
+ CurveEntity* curveEntity = pickedCurves[i];
+ std::vector<int>& pickedControlPoints = pickedCurves[i]->getPickedControlPointIndexes();
+ const ControlPoint& ctrlPnt = pickedCurves[i]->_curve->getControlPoint(pickedControlPoints[0]);
+
+ if (!curveEntity->_attribute->canMoveControlPointHorizontally())
+ enableLoactionEditor = false;
+
+ if (pickedControlPoints.size() > 1)
+ enableLoactionEditor = false;
+
+ if (location == FLT_MIN)
+ {
+ location = ctrlPnt.value.x();
+ _updateUIFromData = true;
+ ui->spinBoxLocation->setValue(location);
+ _updateUIFromData = false;
+ }
+ else if (location != ctrlPnt.value.x())
+ locationSameForAllAttributes = false;
+
+ if (value == FLT_MIN)
+ {
+ value = ctrlPnt.value.y();
+ _updateUIFromData = true;
+ ui->spinBoxValue->setValue(value);
+ _updateUIFromData = false;
+ }
+ else if (value != ctrlPnt.value.y())
+ valueSameForAllAttributes = false;
+
+ if (!curveEntity->_attribute->canChangeTangentType() && pickedControlPoints.size() != 0)
+ enableChangeTangentType = false;
+
+ if (!curveEntity->_attribute->canAddRemoveControlPoint() && pickedControlPoints.size() != 0)
+ enableAddRemoveCtrlPnts = false;
+
+ }
+
+ if (pickedCurves.size() > 0)
+ {
+ ui->spinBoxLocation->setEnabled(enableLoactionEditor);
+
+ setFocusColor(ui->labelLoacation, locationSameForAllAttributes);
+ setFocusColor(ui->labelValue, valueSameForAllAttributes);
+
+ _setTangentTypeUIStatus(enableChangeTangentType);
+ _setAddRemoveCtrlPntUIStatus(enableAddRemoveCtrlPnts);
+ }
+ else
+ {
+ on_treeWidgetCurveAttributes_itemSelectionChanged();
+ }
+
+}
+
+void CurveEditorMainWindow::onCurvePickedControlPointValueChanged(QPointF& value)
+{
+ _updateUIFromData = true;
+ ui->spinBoxLocation->setValue(value.x());
+ ui->spinBoxValue->setValue(value.y());
+ _updateUIFromData = false;
+
+ QList<QTreeWidgetItem*> selectedAttributes = ui->treeWidgetCurveAttributes->selectedItems();
+ if (selectedAttributes.count() > 0)
+ {
+
+ }
+}
+
+void CurveEditorMainWindow::_fillCurveAttributesTree()
+{
+ ui->treeWidgetCurveAttributes->clear();
+
+ size_t countAttributes = _curveAttributes.size();
+ for (size_t i = 0; i < countAttributes; ++i)
+ {
+ CurveAttributeBase* attribute = _curveAttributes[i];
+ CurveAttributeTreeItem* itemFirstLevel = new CurveAttributeTreeItem(ui->treeWidgetCurveAttributes, attribute);
+ itemFirstLevel->setText(0, attribute->getName().c_str());
+
+ if (attribute->getType() == eGroupAttr)
+ {
+ CurveAttributeGroup* attributeGroup = static_cast<CurveAttributeGroup*>(attribute);
+ size_t countAttributesInGroup = attributeGroup->attributes.size();
+ for (size_t j = 0; j < countAttributesInGroup; ++j)
+ {
+ CurveAttribute* attributeInGroup = static_cast<CurveAttribute*>(attributeGroup->attributes[j]);
+ CurveAttributeTreeItem* itemSecondLevel = new CurveAttributeTreeItem(itemFirstLevel, attributeInGroup);
+ itemSecondLevel->setText(0, attributeInGroup->getName().c_str());
+ itemSecondLevel->setForeground(0, QBrush(attributeInGroup->color));
+ }
+ }
+ else
+ {
+ CurveAttribute* attributeSecific = static_cast<CurveAttribute*>(attribute);
+ itemFirstLevel->setForeground(0, QBrush(attributeSecific->color));
+ }
+ }
+}
+
+void CurveEditorMainWindow::_fillColorAttributesTree()
+{
+ ui->treeWidgetColorAttributes->clear();
+
+ size_t countAttributes = _colorAttributes.size();
+ for (size_t i = 0; i < countAttributes; ++i)
+ {
+ ColorAttribute* attribute = _colorAttributes[i];
+ ColorAttributeTreeItem* itemFirstLevel = new ColorAttributeTreeItem(ui->treeWidgetColorAttributes, attribute);
+ itemFirstLevel->setText(0, attribute->getName().c_str());
+ }
+}
+
+void CurveEditorMainWindow::_syncUIStatusWithSelectedAttribute(bool canAddRemoveControlPoint, bool canChangeTangentType)
+{
+ _setAddRemoveCtrlPntUIStatus(canAddRemoveControlPoint);
+ _setTangentTypeUIStatus(canChangeTangentType);
+}
+
+void CurveEditorMainWindow::_setCurveExclusiveUIEnable(bool enable)
+{
+ ui->actionSnap_All->setEnabled(enable);
+ ui->actionSnap_Horizontal->setEnabled(enable);
+ ui->actionSnap_Vertical->setEnabled(enable);
+ ui->actionExpand_Horizontally->setEnabled(enable);
+ ui->actionExpand_Vertically->setEnabled(enable);
+ ui->actionFrame_Horizontally->setEnabled(enable);
+ ui->actionFrame_Vertically->setEnabled(enable);
+ ui->actionFrame_All->setEnabled(enable);
+ ui->actionContract_Horizontally->setEnabled(enable);
+ ui->actionContract_Vertically->setEnabled(enable);
+}
+
+void CurveEditorMainWindow::_setColorUIEnable(bool enable)
+{
+ ui->btnColor->setEnabled(enable);
+ ui->btnColorTex->setEnabled(enable);
+ ui->btnColorReload->setEnabled(enable);
+ ui->btnColorClear->setEnabled(enable);
+ ui->sliderColorFallOff->setEnabled(enable);
+}
+
+void CurveEditorMainWindow::_setAlphaUIEnable(bool enable)
+{
+ if (_colorWidget->isLink())
+ ui->btnAlpha->setEnabled(true);
+ else
+ ui->btnAlpha->setEnabled(enable);
+ ui->btnAlphaTex->setEnabled(enable);
+ ui->btnAlphaReload->setEnabled(enable);
+ ui->btnAlphaClear->setEnabled(enable);
+ ui->sliderAlphaFallOff->setEnabled(enable);
+}
+
+void CurveEditorMainWindow::onColorPickedControlPointChanged(bool isColorCtrlPnt)
+{
+ QColor color = _colorWidget->getColor();
+ setButtonColor(ui->btnColor, color);
+ int alpha = _colorWidget->getAlpha();
+ setButtonColor(ui->btnAlpha, QColor(alpha, alpha, alpha));
+
+ QString colorTex = _colorWidget->getColorTex();
+ setButtonTex(ui->btnColorTex, !colorTex.isEmpty());
+ QString alphaTex = _colorWidget->getAlphaTex();
+ setButtonTex(ui->btnAlphaTex, !alphaTex.isEmpty());
+
+ _updateUIFromData = true;
+ ui->sliderColorFallOff->setValue(_colorWidget->getColorFallOff() * 100);
+ ui->sliderAlphaFallOff->setValue(_colorWidget->getAlphaFallOff() * 100);
+ _setColorUIEnable(isColorCtrlPnt);
+ _setAlphaUIEnable(!isColorCtrlPnt);
+ _updateUIFromData = false;
+}
+
+void CurveEditorMainWindow::_saveAttribute(QDomElement& parentElm, CurveAttribute* attribute)
+{
+ QDomElement newElm = parentElm.ownerDocument().createElement(tr("Attribute"));
+ parentElm.appendChild(newElm);
+ newElm.setAttribute(tr("Name"), attribute->getName().c_str());
+ newElm.setAttribute(tr("Color"), QString().setNum(attribute->color.rgba(), 16));
+ if (!ui->checkBoxResamplePoints->isChecked())
+ {
+ _saveCurve(newElm, attribute->curve);
+ }
+ else
+ {
+ _saveCurve(newElm, attribute->curve.resampleCurve(ui->spinBoxResamplePoints->value()));
+ }
+}
+
+void CurveEditorMainWindow::_saveAttribute(QDomElement& parentElm, ColorAttribute* attribute)
+{
+ QDomElement newElm = parentElm.ownerDocument().createElement(tr("Attribute"));
+ parentElm.appendChild(newElm);
+ newElm.setAttribute(tr("Name"), attribute->getName().c_str());
+
+ _saveCurve(newElm, attribute->colorCurve, tr("ColorCurve"));
+ if (attribute->alphaCurve.getControlPointCount() > 0)
+ _saveCurve(newElm, attribute->alphaCurve, tr("AlphaCurve"));
+}
+
+void CurveEditorMainWindow::_saveCurve(QDomElement& parentElm, Curve& curve)
+{
+ QDomDocument domDoc = parentElm.ownerDocument();
+ QDomElement curveElm = domDoc.createElement(tr("Curve"));
+ parentElm.appendChild(curveElm);
+ curveElm.setAttribute(tr("MinValueX"), curve.getMinValue().x());
+ curveElm.setAttribute(tr("MinValueY"), curve.getMinValue().y());
+ curveElm.setAttribute(tr("MaxValueX"), curve.getMaxValue().x());
+ curveElm.setAttribute(tr("MaxValueY"), curve.getMaxValue().y());
+
+ int ctrlPntCount = curve.getControlPointCount();
+ for (int i = 0; i < ctrlPntCount; ++i)
+ {
+ const ControlPoint& ctrlPnt = curve.getControlPoint(i);
+ _saveCtrlPnt(curveElm, ctrlPnt);
+ }
+}
+
+void CurveEditorMainWindow::_saveCurve(QDomElement& parentElm, ColorCurve& curve, const QString& curveName)
+{
+ QDomDocument domDoc = parentElm.ownerDocument();
+ QDomElement curveElm = domDoc.createElement(curveName);
+ parentElm.appendChild(curveElm);
+ curveElm.setAttribute(tr("MinValue"), curve.getMinValue());
+ curveElm.setAttribute(tr("MaxValue"), curve.getMaxValue());
+
+ int ctrlPntCount = curve.getControlPointCount();
+ for (int i = 0; i < ctrlPntCount; ++i)
+ {
+ const ColorControlPoint& ctrlPnt = curve.getControlPoint(i);
+ _saveCtrlPnt(curveElm, ctrlPnt);
+ }
+}
+
+void CurveEditorMainWindow::_saveCtrlPnt(QDomElement& parentElm, const ControlPoint& ctrlPnt)
+{
+ QDomDocument domDoc = parentElm.ownerDocument();
+ QDomElement ctrlPntElm = domDoc.createElement(tr("ControlPoint"));
+ parentElm.appendChild(ctrlPntElm);
+
+ QDomElement valueElm = domDoc.createElement(tr("Value"));
+ ctrlPntElm.appendChild(valueElm);
+ valueElm.setAttribute(tr("X"), ctrlPnt.value.x());
+ valueElm.setAttribute(tr("Y"), ctrlPnt.value.y());
+
+ QDomElement modeElm = domDoc.createElement(tr("InterpolateMode"));
+ ctrlPntElm.appendChild(modeElm);
+ QDomNode txt = domDoc.createTextNode(InterpolateModeToString(ctrlPnt.mode));
+ modeElm.appendChild(txt);
+
+ if (eBezierSpline == ctrlPnt.mode)
+ {
+ QDomElement bezierSplineDataElm = domDoc.createElement(tr("BezierSplineData"));
+ ctrlPntElm.appendChild(bezierSplineDataElm);
+
+ bezierSplineDataElm.setAttribute(tr("InTan"), QString("%0").arg(ctrlPnt.splineData.inTan));
+ bezierSplineDataElm.setAttribute(tr("InLen"), QString("%0").arg(ctrlPnt.splineData.inLen));
+ bezierSplineDataElm.setAttribute(tr("OutTan"), QString("%0").arg(ctrlPnt.splineData.outTan));
+ bezierSplineDataElm.setAttribute(tr("OutLen"), QString("%0").arg(ctrlPnt.splineData.outLen));
+ }
+}
+
+void CurveEditorMainWindow::_saveCtrlPnt(QDomElement& parentElm, const ColorControlPoint& ctrlPnt)
+{
+ QDomDocument domDoc = parentElm.ownerDocument();
+ QDomElement ctrlPntElm = domDoc.createElement(tr("ColorControlPoint"));
+ parentElm.appendChild(ctrlPntElm);
+
+ QDomElement valueElm = domDoc.createElement(tr("Value"));
+ ctrlPntElm.appendChild(valueElm);
+ valueElm.setAttribute(tr("X"), ctrlPnt.x);
+ valueElm.setAttribute(tr("Color"), QString().setNum(ctrlPnt.color.rgba(), 16));
+ valueElm.setAttribute(tr("Weight"), ctrlPnt.weight);
+ valueElm.setAttribute(tr("FallOff"), ctrlPnt.fallOff);
+ valueElm.setAttribute(tr("TexturePath"), ctrlPnt.texturePath.c_str());
+
+ QDomElement modeElm = domDoc.createElement(tr("InterpolateMode"));
+ ctrlPntElm.appendChild(modeElm);
+ QDomNode txt = domDoc.createTextNode(InterpolateModeToString(ctrlPnt.mode));
+ modeElm.appendChild(txt);
+
+ if (eBezierSpline == ctrlPnt.mode)
+ {
+ QDomElement bezierSplineDataElm = domDoc.createElement(tr("BezierSplineData"));
+ ctrlPntElm.appendChild(bezierSplineDataElm);
+
+ bezierSplineDataElm.setAttribute(tr("InTan"), QString("%0").arg(ctrlPnt.splineData.inTan));
+ bezierSplineDataElm.setAttribute(tr("InLen"), QString("%0").arg(ctrlPnt.splineData.inLen));
+ bezierSplineDataElm.setAttribute(tr("OutTan"), QString("%0").arg(ctrlPnt.splineData.outTan));
+ bezierSplineDataElm.setAttribute(tr("OutLen"), QString("%0").arg(ctrlPnt.splineData.outLen));
+ }
+}
+
+CurveAttributeBase* CurveEditorMainWindow::_loadAttribute(QDomElement& elm)
+{
+ QString name = elm.attribute(tr("Name"));
+
+ QDomElement curveElm = elm.firstChildElement(tr("Curve"));
+ if (!curveElm.isNull())
+ {
+ CurveAttribute* attribute = new CurveAttribute("");
+ attribute->_name = name.toStdString();
+ //qDebug()<<"attribute Name"<<name<<" Color:"<<elm.attribute(tr("Color"));
+ attribute->color.setRgba(elm.attribute(tr("Color")).toUInt(0, 16));
+ //qDebug()<<"color:::"<<QString().setNum(attrData->color.rgba(), 16);
+ float minValueX = curveElm.attribute(tr("MinValueX")).toFloat();
+ float minValueY = curveElm.attribute(tr("MinValueY")).toFloat();
+ float maxValueX = curveElm.attribute(tr("MaxValueX")).toFloat();
+ float maxValueY = curveElm.attribute(tr("MaxValueY")).toFloat();
+ attribute->curve.initValueRange(QPointF(minValueX, minValueY), QPointF(maxValueX, maxValueY));
+ _loadCurve(curveElm, attribute->curve);
+
+ return attribute;
+ }
+ else
+ {
+ curveElm = elm.firstChildElement(tr("ColorCurve"));
+
+ if (!curveElm.isNull())
+ {
+ ColorAttribute* attribute = new ColorAttribute("");
+ attribute->_name = name.toStdString();
+ float minValue = curveElm.attribute(tr("MinValue")).toFloat();
+ float maxValue = curveElm.attribute(tr("MaxValue")).toFloat();
+ attribute->colorCurve.initValueRange(minValue, maxValue);
+ _loadCurve(curveElm, attribute->colorCurve);
+
+ curveElm = elm.firstChildElement(tr("AlphaCurve"));
+ minValue = curveElm.attribute(tr("MinValue")).toFloat();
+ maxValue = curveElm.attribute(tr("MaxValue")).toFloat();
+ attribute->alphaCurve.initValueRange(minValue, maxValue);
+ _loadCurve(curveElm, attribute->alphaCurve);
+ return attribute;
+ }
+ }
+
+ return nullptr;
+}
+
+void CurveEditorMainWindow::_loadCurve(QDomElement& elm, Curve& curve)
+{
+ QDomNodeList nodeList = elm.elementsByTagName(tr("ControlPoint"));
+ for (int i = 0; i < nodeList.count(); ++i)
+ {
+ QDomElement ctrlElm = nodeList.at(i).toElement();
+
+ ControlPoint ctrlPnt;
+ if (!ctrlElm.isNull())
+ {
+ _loadCtrlPnt(ctrlElm, ctrlPnt);
+ curve.appendControlPoint(ctrlPnt, false);
+ }
+ }
+}
+
+void CurveEditorMainWindow::_loadCurve(QDomElement& elm, ColorCurve& curve)
+{
+ QDomNodeList nodeList = elm.elementsByTagName(tr("ColorControlPoint"));
+ for (int i = 0; i < nodeList.count(); ++i)
+ {
+ QDomElement ctrlElm = nodeList.at(i).toElement();
+
+ ColorControlPoint ctrlPnt;
+ if (!ctrlElm.isNull())
+ {
+ _loadCtrlPnt(ctrlElm, ctrlPnt);
+ curve.appendControlPoint(ctrlPnt, false);
+ }
+ }
+}
+
+void CurveEditorMainWindow::_loadCtrlPnt(QDomElement& elm, ControlPoint& ctrlPnt)
+{
+ QDomElement valueElm = elm.firstChildElement(tr("Value"));
+ ctrlPnt.value.setX(valueElm.attribute(tr("X")).toFloat());
+ ctrlPnt.value.setY(valueElm.attribute(tr("Y")).toFloat());
+
+ QDomElement modeElm = elm.firstChildElement(tr("InterpolateMode"));
+
+ ctrlPnt.mode = StringToInterpolateMode(modeElm.text());
+
+ if (eBezierSpline == ctrlPnt.mode)
+ {
+ QDomElement bezierElm = elm.firstChildElement(tr("BezierSplineData"));
+
+ ctrlPnt.splineData.inTan = bezierElm.attribute(tr("InTan")).toFloat();
+ ctrlPnt.splineData.inLen = bezierElm.attribute(tr("InLen")).toFloat();
+ ctrlPnt.splineData.outTan = bezierElm.attribute(tr("OutTan")).toFloat();
+ ctrlPnt.splineData.outLen = bezierElm.attribute(tr("OutLen")).toFloat();
+ }
+}
+
+void CurveEditorMainWindow::_loadCtrlPnt(QDomElement& elm, ColorControlPoint& ctrlPnt)
+{
+ QDomElement valueElm = elm.firstChildElement(tr("Value"));
+ ctrlPnt.x = valueElm.attribute(tr("X")).toFloat();
+ ctrlPnt.color.setRgba(valueElm.attribute(tr("Color")).toUInt(0, 16));
+ ctrlPnt.weight = valueElm.attribute(tr("Weight")).toFloat();
+ ctrlPnt.fallOff = valueElm.attribute(tr("FallOff")).toFloat();
+ ctrlPnt.weight = valueElm.attribute(tr("Weight")).toFloat();
+ ctrlPnt.texturePath = valueElm.attribute(tr("TexturePath")).toStdString();
+
+ QDomElement modeElm = elm.firstChildElement(tr("InterpolateMode"));
+
+ ctrlPnt.mode = StringToInterpolateMode(modeElm.text());
+
+ if (eBezierSpline == ctrlPnt.mode)
+ {
+ QDomElement bezierElm = elm.firstChildElement(tr("BezierSplineData"));
+
+ ctrlPnt.splineData.inTan = bezierElm.attribute(tr("InTan")).toFloat();
+ ctrlPnt.splineData.inLen = bezierElm.attribute(tr("InLen")).toFloat();
+ ctrlPnt.splineData.outTan = bezierElm.attribute(tr("OutTan")).toFloat();
+ ctrlPnt.splineData.outLen = bezierElm.attribute(tr("OutLen")).toFloat();
+ }
+}
+
+void CurveEditorMainWindow::_setTangentTypeUIStatus(bool enable)
+{
+ ui->actionTangent_Stepped->setEnabled(enable);
+ ui->actionTangent_Linear->setEnabled(enable);
+ ui->actionTangent_Smooth->setEnabled(enable);
+ ui->actionTangent_Ease_Out->setEnabled(enable);
+ ui->actionTangent_Ease_In->setEnabled(enable);
+ ui->actionTangent_Spline->setEnabled(enable);
+}
+
+void CurveEditorMainWindow::_setAddRemoveCtrlPntUIStatus(bool enable)
+{
+ ui->actionAdd_Before_Selected->setEnabled(enable);
+ ui->actionAdd_After_Selected->setEnabled(enable);
+ ui->actionRemove_Selected->setEnabled(enable);
+ ui->actionAdd_Control_Point_By_Click->setEnabled(enable);
+ ui->actionRemove_Control_Point_By_Click->setEnabled(enable);
+}
+
+} // namespace CurveEditor
+} // namespace nvidia \ No newline at end of file
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Window/CurveWidget.cpp b/NvBlast/tools/CurveEditor/source/Internal/Window/CurveWidget.cpp
new file mode 100644
index 0000000..fc778e5
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Window/CurveWidget.cpp
@@ -0,0 +1,1229 @@
+#include "CurveWidget.h"
+
+#include <QtWidgets/QLabel>
+#include <QtGui/QImage>
+#include <QtWidgets/QVBoxLayout>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QPaintEvent>
+#include <QtGui/QPainter>
+#include <QtGui/QPainterPath>
+#include <QtCore/QDebug>
+#include "CurveEditorMainWindow.h"
+
+namespace nvidia {
+namespace CurveEditor {
+
+const int MARGIN_X = 2;
+const int MARGIN_Y = 2;
+const int SNAP_DISTANCE = 5;
+const float CROSS_THRESHOLD = 5.0f;
+const int GRID_INTIAL_SEGMENT_COUNT = 4;
+const int CTRL_PNT_ICON_SIZE = 6;
+const int CLICK_ON_CURVE_THRESHOLD = 4;
+const int CURVE_WIDTH = 2;
+const QColor GRID_COLOR = QColor(32, 32, 32, 64);
+
+//////////////////////////////////////////////////////////////////////////////
+QPointF NDCToScreenCoord(QWidget* pWidget, QPointF p)
+{
+ int w = pWidget->width();
+ int h = pWidget->height();
+
+ float x = MARGIN_X + p.x() * (w - MARGIN_X * 2.0f);
+ float y = h - MARGIN_Y * 2.0 + p.y() * (MARGIN_Y * 3.0f - h);
+
+ return QPointF(x, y);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QPointF ScreenToNDC(QWidget* pWidget, QPointF p)
+{
+ int w = pWidget->width();
+ int h = pWidget->height();
+
+ float sizey = 1.0f - 2.0f * MARGIN_Y;
+
+ float x = (p.x() - MARGIN_X) / (2 - MARGIN_X * 2.0f);
+ float y = (MARGIN_Y * 2.0f + p.y() - h) / (MARGIN_Y * 3.0f - h);
+
+ return QPointF(x, y);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool IsInSelectedCtrlPnts(const std::vector<int>& pickedPoints, int pointIndex)
+{
+ for (std::vector<int>::const_iterator itr = pickedPoints.begin(); itr != pickedPoints.end(); ++itr)
+ {
+ if (*itr == pointIndex)
+ return true;
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool IsSamePoint(const QPointF& pntA, const QPointF& pntB, int threshold)
+{
+ float dx = pntB.x() - pntA.x();
+ float dy = pntB.y() - pntA.y();
+
+ float r = sqrt(dx * dx + dy * dy);
+ if (r <= threshold)
+ return true;
+ else
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+int FindSelectedCtrlPnt(const std::vector<QPointF>& points, const QPointF& pickPos)
+{
+ for (size_t i = 0; i < points.size(); i++)
+ {
+ if (IsSamePoint(points[i], pickPos, CTRL_PNT_ICON_SIZE/2))
+ return (int)i;
+ }
+ return -1;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+CurveEntity::CurveEntity(CurveWidget* holder, CurveAttribute* attribute, const QColor& color)
+ : _holder(holder)
+ , _attribute(attribute)
+ , _curve(&(attribute->curve))
+ , _color(color)
+ , _pickedPoint(-1)
+ , _pickedPoints()
+ , _lastMousePosScreen()
+ , _ctrlPntToRemove(-1)
+{
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::setLocation(float location)
+{
+ if (_pickedPoints.size() != 1)
+ return ;
+
+ ControlPoint pnt = _curve->getControlPoint(_pickedPoints[0]);
+ pnt.value.setX(location);
+ _curve->setControlPoint(_pickedPoints[0], pnt);
+ emit _holder->CurveAttributeChanged(_attribute);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::setValue(float value)
+{
+ if (_pickedPoints.size() != 1)
+ return ;
+
+ ControlPoint pnt = _curve->getControlPoint(_pickedPoints[0]);
+ pnt.value.setY(value);
+ _curve->setControlPoint(_pickedPoints[0], pnt);
+ emit _holder->CurveAttributeChanged(_attribute);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::addControlPointsBeforeSelected()
+{
+ bool update = false;
+ for (std::vector<int>::iterator itr = _pickedPoints.begin(); itr != _pickedPoints.end(); ++itr)
+ {
+ if (*itr == 0)
+ continue;
+
+ _curve->insertControlPointAt(*itr);
+ ++(*itr);
+ update = true;
+
+ if (*itr <= _pickedPoint)
+ {
+ ++_pickedPoint;
+ }
+
+ for (std::vector<int>::iterator itrRight = itr + 1; itrRight != _pickedPoints.end(); ++itrRight)
+ {
+ ++(*itrRight);
+ }
+ }
+
+ if (update)
+ {
+ _curve->_needSample = true;
+ emit _holder->CurveAttributeChanged(_attribute);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::addControlPointsAfterSelected()
+{
+ bool update = false;
+ for (std::vector<int>::iterator itr = _pickedPoints.begin(); itr != _pickedPoints.end(); ++itr)
+ {
+ _curve->insertControlPointAt(*itr + 1);
+ update = true;
+
+ if ((*itr + 1) < _pickedPoint)
+ {
+ ++_pickedPoint;
+ }
+
+ for (std::vector<int>::iterator itrRight = itr + 1; itrRight != _pickedPoints.end(); ++itrRight)
+ {
+ ++(*itrRight);
+ }
+ }
+
+ if (update)
+ {
+ _curve->_needSample = true;
+ emit _holder->CurveAttributeChanged(_attribute);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::removeSelectedControlPoints()
+{
+ if (_pickedPoints.size() > 0)
+ {
+ _curve->removeControlPoints(_pickedPoints);
+ _pickedPoints.clear();
+ _pickedPoint = -1;
+ _curve->_needSample = true;
+ emit _holder->CurveAttributeChanged(_attribute);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::setTangentType(InterpolateMode mode)
+{
+ size_t pointsCount = _curve->getControlPointCount();
+ for (int i = 0; i < pointsCount; i++)
+ {
+ if (IsInSelectedCtrlPnts(_pickedPoints, i))
+ {
+ ControlPoint ctrlPnt = _curve->getControlPoint(i);
+ ctrlPnt.mode = mode;
+ _curve->setControlPoint(i, ctrlPnt);
+ emit _holder->CurveAttributeChanged(_attribute);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::setSmoothTangent()
+{
+ size_t pointsCount = _curve->getControlPointCount();
+ for (int i = 0; i < pointsCount; i++)
+ {
+ if (IsInSelectedCtrlPnts(_pickedPoints, i) && i != pointsCount - 1)
+ {
+ ControlPoint ctrlctrlPntFront = _curve->getControlPoint(i);
+ ctrlctrlPntFront.mode = eBezierSpline;
+ ctrlctrlPntFront.splineData.outLen = 1.0;
+ ctrlctrlPntFront.splineData.outTan = 0;
+ _curve->setControlPoint(i, ctrlctrlPntFront);
+
+ ControlPoint ctrlPntBehiand = _curve->getControlPoint(i + 1);
+ ctrlPntBehiand.mode = eBezierSpline;
+ ctrlPntBehiand.splineData.inLen = 1.0;
+ ctrlPntBehiand.splineData.inTan = 0.0;
+ _curve->setControlPoint(i + 1, ctrlPntBehiand);
+
+ emit _holder->CurveAttributeChanged(_attribute);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::setEaseInTangent()
+{
+ size_t pointsCount = _curve->getControlPointCount();
+ for (int i = 0; i < pointsCount; i++)
+ {
+ if (IsInSelectedCtrlPnts(_pickedPoints, i) && i != pointsCount - 1)
+ {
+ ControlPoint ctrlctrlPntFront = _curve->getControlPoint(i);
+ ctrlctrlPntFront.mode = eBezierSpline;
+ ctrlctrlPntFront.splineData.outLen = 0.0;
+ ctrlctrlPntFront.splineData.outTan = 0;
+ _curve->setControlPoint(i, ctrlctrlPntFront);
+
+ ControlPoint ctrlPntBehiand = _curve->getControlPoint(i + 1);
+ ctrlPntBehiand.mode = eBezierSpline;
+ ctrlPntBehiand.splineData.inLen = 1.0;
+ ctrlPntBehiand.splineData.inTan = 0;
+ _curve->setControlPoint(i + 1, ctrlPntBehiand);
+
+ emit _holder->CurveAttributeChanged(_attribute);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::setEaseOutTangent()
+{
+ size_t pointsCount = _curve->getControlPointCount();
+ for (int i = 0; i < pointsCount; i++)
+ {
+ if (IsInSelectedCtrlPnts(_pickedPoints, i) && i != pointsCount - 1)
+ {
+ ControlPoint ctrlctrlPntFront = _curve->getControlPoint(i);
+ ctrlctrlPntFront.mode = eBezierSpline;
+ ctrlctrlPntFront.splineData.outLen = 1.0;
+ ctrlctrlPntFront.splineData.outTan = 0;
+ _curve->setControlPoint(i, ctrlctrlPntFront);
+
+ ControlPoint ctrlPntBehiand = _curve->getControlPoint(i + 1);
+ ctrlPntBehiand.mode = eBezierSpline;
+ ctrlPntBehiand.splineData.inLen = 0.0;
+ ctrlPntBehiand.splineData.inTan = 0;
+ _curve->setControlPoint(i + 1, ctrlPntBehiand);
+
+ emit _holder->CurveAttributeChanged(_attribute);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+int CurveEntity::getControlPointCount()
+{
+ return _curve->getControlPointCount();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QRectF CurveEntity::getBoundingBox()
+{
+ return QRectF(_curve->getMinValue(), _curve->getMaxValue());
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::mousePressEvent( QMouseEvent* e, bool& pickedPoint)
+{
+ if (!(e->modifiers() & Qt::ControlModifier))
+ {
+ _pickedPoints.clear();
+ }
+
+ std::vector<QPointF> points;
+ _makePoints(points);
+ QPoint mousePos = e->pos();
+ _lastMousePosScreen = mousePos;
+
+ _pickedPoint = FindSelectedCtrlPnt(points, mousePos);
+ if (-1 != _pickedPoint)
+ {
+ if (_holder->_canRemoveCtrlPntByClick && _attribute->canAddRemoveControlPoint())
+ {
+ _curve->removeControlPoint(_pickedPoint);
+ _pickedPoint = -1;
+ return;
+ }
+ pickedPoint = true;
+ }
+ else
+ {
+ if (_holder->_canAddCtrlPntByClick)
+ {
+ _addCtrlPntByClick(mousePos);
+ }
+ return ;
+ }
+
+ std::vector<int>::iterator itr = _pickedPoints.begin();
+ for (; itr != _pickedPoints.end(); ++itr)
+ {
+ if (*itr == _pickedPoint)
+ break;
+ else if (*itr > _pickedPoint)
+ {
+ itr = _pickedPoints.insert(itr, _pickedPoint);
+ break;
+ }
+ }
+
+ if (itr == _pickedPoints.end())
+ {
+ _pickedPoints.insert(itr, _pickedPoint);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::mouseReleaseEvent( QMouseEvent* e )
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::mouseMoveEvent( QMouseEvent* e )
+{
+ Qt::MouseButton buttons = e->button();
+
+ {
+ //if (_pickedPoint >= 0)
+ QPointF mousePosScreen = e->pos();
+ QPointF deltaPosScreen = mousePosScreen - _lastMousePosScreen;
+ QPointF destinationPosScreen = mousePosScreen;
+ _lastMousePosScreen = mousePosScreen;
+ std::vector<int>::iterator itr = _pickedPoints.begin();
+ for (; itr != _pickedPoints.end(); ++itr)
+ {
+ int pickedPoint = *itr;
+ ControlPoint pickedCtrlPnt = _curve->getControlPoint(pickedPoint);
+ QPointF ctrlPntLastScreenPos = _holder->_valueToScreen(pickedCtrlPnt.value);
+
+ destinationPosScreen = ctrlPntLastScreenPos + deltaPosScreen;
+ destinationPosScreen = _holder->_getSnapSreenPos(destinationPosScreen);
+
+ if (!_attribute->canMoveControlPointHorizontally())
+ destinationPosScreen.setX(ctrlPntLastScreenPos.x());
+ else
+ {
+ // make sure this picked control point not move accross other control point
+ if (pickedPoint == 0)
+ {
+ QPointF nextCtrlPntScreenPos = _holder->_valueToScreen(_curve->getControlPoint(pickedPoint + 1).value);
+ if (destinationPosScreen.x() > (nextCtrlPntScreenPos.x() - CROSS_THRESHOLD))
+ destinationPosScreen.setX(nextCtrlPntScreenPos.x() - CROSS_THRESHOLD);
+ }
+ else if (pickedPoint == (_curve->getControlPointCount() - 1) )
+ {
+ QPointF fomerCtrlPntScreenPos = _holder->_valueToScreen(_curve->getControlPoint(pickedPoint - 1).value);
+ if (destinationPosScreen.x() < (fomerCtrlPntScreenPos.x() + CROSS_THRESHOLD))
+ destinationPosScreen.setX(fomerCtrlPntScreenPos.x() + CROSS_THRESHOLD);
+ }
+ else
+ {
+ QPointF fomerCtrlPntScreenPos = _holder->_valueToScreen(_curve->getControlPoint(pickedPoint - 1).value);
+ QPointF nextCtrlPntScreenPos = _holder->_valueToScreen(_curve->getControlPoint(pickedPoint + 1).value);
+ if (destinationPosScreen.x() < (fomerCtrlPntScreenPos.x() + CROSS_THRESHOLD))
+ destinationPosScreen.setX(fomerCtrlPntScreenPos.x() + CROSS_THRESHOLD);
+ if (destinationPosScreen.x() > (nextCtrlPntScreenPos.x() - CROSS_THRESHOLD))
+ destinationPosScreen.setX(nextCtrlPntScreenPos.x() - CROSS_THRESHOLD);
+ }
+ }
+
+ QPointF p = _holder->_screenToValue(destinationPosScreen);
+
+ QPointF min = _curve->getMinValue();
+ QPointF max = _curve->getMaxValue();
+
+ //make control point move in value range
+ {
+ if (p.x() < min.x())
+ p.setX(min.x());
+ else if (p.x() > max.x())
+ p.setX(max.x());
+
+ if (p.y() < min.y())
+ p.setY(min.y());
+ else if (p.y() > max.y())
+ p.setY(max.y());
+ }
+
+ pickedCtrlPnt.value = p;
+ _curve->setControlPoint(pickedPoint, pickedCtrlPnt);
+ emit _holder->PickedControlPointValueChanged(p);
+
+ emit _holder->CurveAttributeChanged(_attribute);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::draw(QPainter &painter)
+{
+ std::vector<QPointF> points;
+ _makePoints(points);
+
+ _drawCurve(painter);
+
+ _drawPoints(points, painter, _pickedPoints);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::_drawCurve(QPainter &painter)
+{
+ painter.save();
+
+ {
+ QPen pen( Qt::black );
+ pen.setColor(_color);
+ pen.setWidth(CURVE_WIDTH);
+ pen.setStyle(Qt::SolidLine);
+
+ painter.setPen(pen);
+ painter.setRenderHint(QPainter::Antialiasing, false);
+ }
+
+ QPainterPath path;
+
+ std::vector<QPointF> samplePoints = _curve->getSamplePoints();
+ path.moveTo(_holder->_valueToScreen(samplePoints[0]));
+
+ for (size_t i = 0; i < samplePoints.size(); ++i)
+ {
+ path.lineTo(_holder->_valueToScreen(samplePoints[i]));
+ }
+ painter.drawPath(path);
+
+ painter.restore();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::_makePoints(std::vector<QPointF>& points)
+{
+ size_t ctrlPntsCount = _curve->getControlPointCount();
+ for (int i = 0; i < ctrlPntsCount; i++)
+ points.push_back( _holder->_valueToScreen(_curve->getControlPoint(i).value) );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::_drawPoints(const std::vector<QPointF>& points, QPainter &painter, const std::vector<int>& pickedPoints)
+{
+ {
+ QPen pen( Qt::black );
+ pen.setColor(QColor(255,255,255));
+ pen.setWidth(6);
+ pen.setStyle(Qt::SolidLine);
+
+ painter.setPen(pen);
+ painter.setRenderHint(QPainter::Antialiasing, false);
+ }
+
+ for (int i = 0; i < points.size(); i++)
+ {
+ QPen pen( Qt::black );
+ pen.setWidth(CTRL_PNT_ICON_SIZE);
+ pen.setStyle(Qt::SolidLine);
+
+ if (IsInSelectedCtrlPnts(pickedPoints,i))
+ pen.setColor(QColor(255,0,0));
+ else
+ pen.setColor(QColor(255,255,255));
+
+ painter.setPen(pen);
+ painter.drawPoint( points[i] );
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveEntity::_addCtrlPntByClick(const QPointF& mouseScreenPos)
+{
+ if (!_attribute->canAddRemoveControlPoint())
+ return ;
+
+ QPointF pos= _holder->_screenToValue(mouseScreenPos);
+
+ QPointF pntOnCurve = _curve->getPointByX(pos.x());
+ QPointF pntOnCurveScreen = _holder->_valueToScreen(pntOnCurve);
+
+ if ( IsSamePoint(mouseScreenPos, pntOnCurveScreen, CLICK_ON_CURVE_THRESHOLD) )
+ {
+ _pickedPoint = _curve->appendControlPoint(pntOnCurve.x());
+ _holder->update();
+ }
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+bool CurveEntity::_canRemoveCtrlPntByRightClick(const QPointF& mouseScreenPos)
+{
+ std::vector<QPointF> points;
+ _makePoints(points);
+
+ _ctrlPntToRemove = FindSelectedCtrlPnt(points, mouseScreenPos);
+
+ if ( !_attribute->canAddRemoveControlPoint()
+ || (-1 == _ctrlPntToRemove)
+ || 2 == _curve->_controlPoints.size() && -1 != _ctrlPntToRemove)
+ {
+ return false;
+ }
+ else
+ return true;
+}
+
+void CurveEntity::_removeCtrlPntByRightClick()
+{
+ if (-1 != _ctrlPntToRemove && _attribute->canAddRemoveControlPoint())
+ {
+ _curve->removeControlPoint(_ctrlPntToRemove);
+ }
+ _ctrlPntToRemove = -1;
+ _pickedPoint = -1;
+ _pickedPoints.clear();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+CurveWidget::CurveWidget(QWidget* parent)
+ : QFrame(parent)
+ , _parent(parent)
+ , _moveCrossOtherCtrlPnt(false)
+ , _moveCtrlPnt(false)
+ , _pan(false)
+ , _snapHorizontal(false)
+ , _snapVertical(false)
+ , _canAddCtrlPntByClick(false)
+ , _canRemoveCtrlPntByClick(false)
+ , _curveFitWindowScale(1.0, 1.0)
+ , _curveFitWindowOffset(0.0, 0.0)
+ , _curveScaleLevel(1.0, 1.0)
+ , _contextMenu(nullptr)
+ , _removeCtrlPntAction(nullptr)
+{
+ setFocusPolicy(Qt::ClickFocus );
+ //QString focusStyle = QString("QFrame:focus { border:1px solid #FF0000; }");
+ //setStyleSheet(focusStyle);
+
+ setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(onShowContextMenu(const QPoint&)));
+
+ _contextMenu = new QMenu(this);;
+ _removeCtrlPntAction = new QAction(this);
+ _removeCtrlPntAction->setText(tr("Remove Control Point"));
+ _contextMenu->addAction(_removeCtrlPntAction);
+
+ connect(_removeCtrlPntAction, SIGNAL(triggered()), this, SLOT(onRemoveControlPoint()) );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::onShowContextMenu(const QPoint& pos)
+{
+ bool enableRemoveCtrlPntAction = false;
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ if (curveEntity._canRemoveCtrlPntByRightClick(pos))
+ enableRemoveCtrlPntAction = true;
+ }
+
+ _removeCtrlPntAction->setEnabled(enableRemoveCtrlPntAction);
+ _contextMenu->exec(QCursor::pos());
+}
+
+void CurveWidget::onRemoveControlPoint()
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity._removeCtrlPntByRightClick();
+ }
+
+ std::vector<CurveEntity*> pickedCurves;
+ emit PickedControlPointChanged(pickedCurves);
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::paintEvent(QPaintEvent * e)
+{
+ QFrame::paintEvent(e);
+
+ QPainter painter(this);
+ painter.setRenderHints(QPainter::Antialiasing, true);
+
+ _drawGrid(painter);
+
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.draw(painter);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::resizeEvent(QResizeEvent* e)
+{
+ _updateCurveFitWindowPara();
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::mousePressEvent( QMouseEvent* e )
+{
+ if (e->buttons() == Qt::MiddleButton)
+ {
+ setCursor(Qt::OpenHandCursor);
+ _mousePressScreenPos = QPointF(e->pos().x(), e->pos().y());
+ _pan = true;
+ }
+ else
+ {
+ std::vector<CurveEntity*> pickedCurves;
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.mousePressEvent(e, _moveCtrlPnt);
+ if (curveEntity.getPickedControlPointIndexes().size() > 0)
+ pickedCurves.push_back(&curveEntity);
+ }
+
+ emit PickedControlPointChanged(pickedCurves);
+
+ update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::mouseReleaseEvent( QMouseEvent* e )
+{
+ if (_moveCtrlPnt)
+ {
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.mouseReleaseEvent(e);
+ }
+ }
+ else if (_pan)
+ {
+ setCursor(Qt::ArrowCursor);
+ _curOrinScreenPos = _lastOrinScreenPos + (QPointF(e->pos().x() - _mousePressScreenPos.x(), _mousePressScreenPos.y() - e->pos().y()));
+ _lastOrinScreenPos = _curOrinScreenPos;
+ _updateCurveFitWindowPara();
+
+ }
+
+ _moveCtrlPnt = false;
+ _pan = false;
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::mouseMoveEvent( QMouseEvent* e )
+{
+ if (_moveCtrlPnt)
+ {
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.mouseMoveEvent(e);
+ }
+ }
+ else if (e->buttons() & Qt::MiddleButton)
+ {
+ _curOrinScreenPos = _lastOrinScreenPos + (QPointF(e->pos().x() - _mousePressScreenPos.x(), _mousePressScreenPos.y() - e->pos().y()));
+ _updateCurveFitWindowPara();
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::wheelEvent(QWheelEvent *e)
+{
+ int numDegrees = e->delta() / 8;
+
+ float zoom = 1.0 + numDegrees / 360.0f;
+ _curveScaleLevel.setX(_curveScaleLevel.x() * zoom);
+ _curveScaleLevel.setY(_curveScaleLevel.y() * zoom);
+
+ _updateCurveFitWindowPara();
+ update();
+ e->accept();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::keyPressEvent(QKeyEvent *e)
+{
+ bool move = false;
+ switch(e->key())
+ {
+ case Qt::Key_Left:
+ _curOrinScreenPos = _lastOrinScreenPos + QPointF(-1.0f, 0.0f);
+ _lastOrinScreenPos = _curOrinScreenPos;
+ move = true;
+ break;
+ case Qt::Key_Up:
+ _curOrinScreenPos = _lastOrinScreenPos + QPointF(0.0f, 1.0f);
+ _lastOrinScreenPos = _curOrinScreenPos;
+ move = true;
+ break;
+ case Qt::Key_Right:
+ _curOrinScreenPos = _lastOrinScreenPos + QPointF(1.0f, 0.0f);
+ _lastOrinScreenPos = _curOrinScreenPos;
+ move = true;
+ break;
+ case Qt::Key_Down:
+ _curOrinScreenPos = _lastOrinScreenPos + QPointF(0.0f, -1.0f);
+ _lastOrinScreenPos = _curOrinScreenPos;
+ move = true;
+ break;
+ }
+
+ if (move)
+ {
+ _updateCurveFitWindowPara();
+ update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::setLocation(float location)
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.setLocation(location);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::setValue(float value)
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.setValue(value);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::setCurveAttributes(std::vector<CurveAttributeBase*> attributes)
+{
+ _curves.clear();
+
+ for (std::vector<CurveAttributeBase*>::iterator itr = attributes.begin(); itr != attributes.end(); ++itr)
+ {
+ CurveAttributeBase* attribute = *itr;
+ if (attribute->getType() == eSingleAttr)
+ {
+ CurveAttribute* attributeSpecific = static_cast<CurveAttribute*>(attribute);
+
+ CurveEntity curveEntity(this, attributeSpecific, attributeSpecific->color);
+ _curves.push_back(curveEntity);
+ }
+ else if (attribute->getType() == eGroupAttr)
+ {
+ CurveAttributeGroup* attributeGroup = static_cast<CurveAttributeGroup*>(attribute);
+ size_t countAttributesInGroup = attributeGroup->attributes.size();
+ for (size_t i = 0; i < countAttributesInGroup; ++i)
+ {
+ CurveAttribute* attributeInGroup = attributeGroup->attributes[i];
+
+ CurveEntity curveEntity(this, attributeInGroup, attributeInGroup->color);
+ _curves.push_back(curveEntity);
+ }
+ }
+ }
+
+ _updateCurveFitWindowPara();
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::reset()
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity._attribute->curve.reset();
+ emit CurveAttributeChanged(curveEntity._attribute);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::addControlPointsBeforeSelected()
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.addControlPointsBeforeSelected();
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::addControlPointsAfterSelected()
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.addControlPointsAfterSelected();
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::removeSelectedControlPoints()
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.removeSelectedControlPoints();
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::setTangentType(InterpolateMode mode)
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.setTangentType(mode);
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::setSmoothTangent()
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.setSmoothTangent();
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::setEaseInTangent()
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.setEaseInTangent();
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::setEaseOutTangent()
+{
+ size_t curveCount = _curves.size();
+ for (size_t i = 0; i < curveCount; ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+ curveEntity.setEaseOutTangent();
+ }
+
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::increaseCurveScaleHorizontally()
+{
+ _curveScaleLevel.setX(_curveScaleLevel.x() * 2);
+ _updateCurveFitWindowPara();
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::decreaseCurveScaleHorizontally()
+{
+ _curveScaleLevel.setX(_curveScaleLevel.x() / 2);
+ _updateCurveFitWindowPara();
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::increaseCurveScaleVertically()
+{
+ _curveScaleLevel.setY(_curveScaleLevel.y() * 2);
+ _updateCurveFitWindowPara();
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::decreaseCurveScaleVertically()
+{
+ _curveScaleLevel.setY(_curveScaleLevel.y() / 2);
+ _updateCurveFitWindowPara();
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::frameCurveScaleHorizontally()
+{
+ _curveScaleLevel.setX(1.0f);
+ _curOrinScreenPos.setX(0);
+ _lastOrinScreenPos.setX(0);
+ _updateCurveFitWindowPara();
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::frameCurveScaleVertically()
+{
+ _curveScaleLevel.setY(1.0f);
+ _curOrinScreenPos.setY(0);
+ _lastOrinScreenPos.setY(0);
+ _updateCurveFitWindowPara();
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::frameCurveScale()
+{
+ _curveScaleLevel.setX(1.0f);
+ _curveScaleLevel.setY(1.0f);
+ _curOrinScreenPos = QPointF(0,0);
+ _lastOrinScreenPos = QPointF(0,0);
+ _updateCurveFitWindowPara();
+ update();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::_updateCurveFitWindowPara()
+{
+ QRect winSize = rect();
+
+ float minX = 0;
+ float minY = 0;
+ float maxX = 0;
+ float maxY = 0;
+
+ for (size_t i = 0; i < _curves.size(); ++i)
+ {
+ CurveEntity& curveEntity = _curves[i];
+
+ QRectF boundingBox = curveEntity.getBoundingBox();
+
+ if (minX > boundingBox.x())
+ minX = boundingBox.x();
+
+ if (minY > boundingBox.y())
+ minY = boundingBox.y();
+
+ if (maxX < boundingBox.right())
+ maxX = boundingBox.right();
+
+ if (maxY < boundingBox.bottom())
+ maxY = boundingBox.bottom();
+ }
+
+ float curveWidth = maxX - minX;
+ float curveHeight = maxY - minY;
+
+ if (0 == curveWidth && 0 == curveHeight)
+ {
+ curveWidth = 1.0;
+ curveHeight = 1.0;
+ }
+ else if (0 == curveWidth)
+ {
+ curveWidth = curveHeight;
+ }
+ else if (0 == curveHeight)
+ {
+ curveHeight = curveWidth;
+ }
+
+ float widthScale = (winSize.width() - MARGIN_X * 2.0f) / curveWidth;
+ float heightScale = (MARGIN_Y * 2.0f - winSize.height()) / curveHeight;
+ _curveFitWindowScale = QPointF(widthScale, heightScale);
+
+ float widthOffset = MARGIN_X + _curOrinScreenPos.x() - minX * widthScale * _curveScaleLevel.x();
+ float heightOffset = (winSize.height() - MARGIN_Y - _curOrinScreenPos.y())- minY * heightScale * _curveScaleLevel.y();
+ _curveFitWindowOffset = QPointF(widthOffset, heightOffset);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QPointF CurveWidget::_valueToScreen(const QPointF& pnt)
+{
+ QPointF curveScale = QPointF(_curveFitWindowScale.x() * _curveScaleLevel.x(), _curveFitWindowScale.y() * _curveScaleLevel.y());
+
+ float x = pnt.x() * curveScale.x() + _curveFitWindowOffset.x();
+ float y = pnt.y() * curveScale.y() + _curveFitWindowOffset.y();
+ return QPointF(x, y);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QPointF CurveWidget::_screenToValue(const QPointF& pnt)
+{
+ QPointF curveScale = QPointF(_curveFitWindowScale.x() * _curveScaleLevel.x(), _curveFitWindowScale.y() * _curveScaleLevel.y());
+
+ float x = (pnt.x() - _curveFitWindowOffset.x()) / curveScale.x();
+ float y = (pnt.y() - _curveFitWindowOffset.y()) / curveScale.y();
+
+ return QPointF(x, y);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::_drawAxis(QPainter &painter)
+{
+ painter.save();
+ {
+ QPen pen( Qt::black );
+ pen.setColor(GRID_COLOR);
+ pen.setWidth(2);
+ pen.setStyle(Qt::SolidLine);
+
+ painter.setPen(pen);
+ painter.setRenderHint(QPainter::Antialiasing, false);
+ }
+
+ {
+ int w = width() - MARGIN_X * 2;
+ int h = height() - MARGIN_Y * 2;
+
+ QPainterPath path;
+
+ QPointF x = _dragedCoordinateToScreen(QPointF(w, 0));
+ QPointF y = _dragedCoordinateToScreen(QPointF(0, h));
+
+ path.moveTo(_dragedCoordinateToScreen(QPointF(0, 0)));
+ path.lineTo(x);
+ path.moveTo(_dragedCoordinateToScreen(QPointF(0, 0)));
+ path.lineTo(y);
+
+ painter.drawPath(path);
+ }
+
+ painter.restore();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CurveWidget::_drawGrid(QPainter &painter)
+{
+ painter.save();
+ {
+ QPen pen( Qt::black );
+ pen.setColor(GRID_COLOR);
+ pen.setWidth(1);
+ pen.setStyle(Qt::SolidLine);
+
+ painter.setPen(pen);
+ painter.setRenderHint(QPainter::Antialiasing, false);
+ }
+
+ {
+ QPainterPath path;
+
+ int w = width() - MARGIN_X * 2;
+ int h = height() - MARGIN_Y * 2;
+
+ QPointF newOri = _dragedCoordinateToScreen(_curOrinScreenPos);
+
+ float width = w;
+ float height = h;
+ int gridXSegmentCount = GRID_INTIAL_SEGMENT_COUNT / _curveScaleLevel.x();
+ int gridYSegmentCount = GRID_INTIAL_SEGMENT_COUNT / _curveScaleLevel.y();
+
+ if (_curveScaleLevel.x() > 1)
+ {
+ width = w * _curveScaleLevel.x();
+ gridXSegmentCount *= _curveScaleLevel.x();
+ }
+
+ if (_curveScaleLevel.y() > 1)
+ {
+ height = h * _curveScaleLevel.y();
+ gridYSegmentCount *= _curveScaleLevel.y();
+ }
+
+ // draw horizontal lines
+ for (int i = 0 - gridXSegmentCount; i <= gridXSegmentCount * 2; ++i)
+ {
+ QPointF bottom = _dragedCoordinateToScreen(QPointF(width * i / (float)gridXSegmentCount, -height));
+ QPointF up = _dragedCoordinateToScreen(QPointF(width * i / (float)gridXSegmentCount, height * 2));
+ path.moveTo(bottom);
+ path.lineTo(up);
+
+ painter.drawPath(path);
+ }
+
+ // draw vertical lines
+ for (int i = 0 - gridYSegmentCount; i <= gridYSegmentCount * 2; ++i)
+ {
+ QPointF left = _dragedCoordinateToScreen(QPointF(-width, i * height / (float)gridYSegmentCount));
+ QPointF right = _dragedCoordinateToScreen(QPointF(2 * width, i * height / (float)gridYSegmentCount));
+ path.moveTo(left);
+ path.lineTo(right);
+
+ painter.drawPath(path);
+ }
+
+ }
+ painter.restore();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QPointF CurveWidget::_getSnapSreenPos(const QPointF& mouseScreenPos)
+{
+ int w = width() - MARGIN_X * 2;
+ int h = height() - MARGIN_Y * 2;
+
+ QPointF pos = _screenToDragedCoordinate(mouseScreenPos);
+
+ // snap horizontally
+ if (_snapHorizontal)
+ {
+ int gridXSegmentCount = GRID_INTIAL_SEGMENT_COUNT / _curveScaleLevel.x();
+ if (gridXSegmentCount < 2)
+ gridXSegmentCount = 2;
+ for (int i = 0; i <= gridXSegmentCount; ++i)
+ {
+ if (abs(i * w / gridXSegmentCount - pos.x()) <= SNAP_DISTANCE )
+ {
+ pos.setX(i * w / gridXSegmentCount);
+ break;
+ }
+ }
+ }
+
+ // snap vertically
+ if (_snapVertical)
+ {
+ int gridYSegmentCount = GRID_INTIAL_SEGMENT_COUNT / _curveScaleLevel.y();
+ if (gridYSegmentCount < 2)
+ gridYSegmentCount = 2;
+ for (int i = 0; i <= gridYSegmentCount; ++i)
+ {
+ if (abs(i * h / gridYSegmentCount - pos.y()) <= SNAP_DISTANCE)
+ {
+ pos.setY(i * h / gridYSegmentCount);
+ }
+ }
+ }
+
+ return _dragedCoordinateToScreen(pos);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QPointF CurveWidget::_dragedCoordinateToScreen(const QPointF& pnt)
+{
+ float x = pnt.x() + MARGIN_X + _curOrinScreenPos.x();
+ float y = height() - MARGIN_Y - pnt.y() - _curOrinScreenPos.y();
+ return QPointF(x, y);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+QPointF CurveWidget::_screenToDragedCoordinate(const QPointF& pnt)
+{
+ float x = pnt.x() - MARGIN_X - _curOrinScreenPos.x();
+ float y = height() - MARGIN_Y - pnt.y() - _curOrinScreenPos.y();
+ return QPointF(x, y);
+}
+
+} // namespace CurveEditor
+} // namespace nvidia \ No newline at end of file
diff --git a/NvBlast/tools/CurveEditor/source/Internal/Window/CurveWidget.h b/NvBlast/tools/CurveEditor/source/Internal/Window/CurveWidget.h
new file mode 100644
index 0000000..04c38d0
--- /dev/null
+++ b/NvBlast/tools/CurveEditor/source/Internal/Window/CurveWidget.h
@@ -0,0 +1,158 @@
+#ifndef CurveWidget_h__
+#define CurveWidget_h__
+
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QMenu>
+#include <QtWidgets/QAction>
+#include <vector>
+#include "Curve.h"
+
+namespace nvidia {
+namespace CurveEditor {
+
+class CurveAttributeBase;
+class CurveAttribute;
+class CurveWidget;
+
+class CurveEntity
+{
+ friend class CurveWidget;
+ friend class CurveEditorMainWindow;
+public:
+ CurveEntity(CurveWidget* holder, CurveAttribute* attribute, const QColor& color);
+
+ void setLocation(float location);
+ void setValue(float value);
+
+ void addControlPointsBeforeSelected();
+ void addControlPointsAfterSelected();
+ void removeSelectedControlPoints();
+ void setTangentType(InterpolateMode mode);
+ void setSmoothTangent();
+ void setEaseInTangent();
+ void setEaseOutTangent();
+
+ int getControlPointCount();
+ int getPickedControlPointIndex() { return _pickedPoint; }
+ std::vector<int>& getPickedControlPointIndexes() { return _pickedPoints; }
+
+ QRectF getBoundingBox();
+
+ void mousePressEvent(QMouseEvent* e, bool& pickedPoint);
+ void mouseReleaseEvent(QMouseEvent* e);
+ void mouseMoveEvent(QMouseEvent* e);
+
+ void draw(QPainter &painter);
+
+private:
+ void _drawCurve(QPainter &painter);
+ void _makePoints(std::vector<QPointF>& points);
+ void _drawPoints(const std::vector<QPointF>& points, QPainter &painter, const std::vector<int>& pickedPoints);
+ void _addCtrlPntByClick(const QPointF& mouseScreenPos);
+ bool _canRemoveCtrlPntByRightClick(const QPointF& mouseScreenPos);
+ void _removeCtrlPntByRightClick();
+
+ CurveWidget* _holder;
+ CurveAttribute* _attribute;
+ Curve* _curve;
+ QColor _color;
+ int _pickedPoint;
+ std::vector<int> _pickedPoints;
+ QPointF _lastMousePosScreen;
+ int _ctrlPntToRemove;
+};
+
+class CurveWidget : public QFrame
+{
+ Q_OBJECT
+
+ friend class CurveEntity;
+
+public:
+ explicit CurveWidget(QWidget* parent);
+
+ void setLocation(float location);
+ void setValue(float value);
+
+ void setCurveAttributes(std::vector<CurveAttributeBase*> attributes);
+ void reset();
+
+ void addControlPointsBeforeSelected();
+ void addControlPointsAfterSelected();
+ void removeSelectedControlPoints();
+ void setTangentType(InterpolateMode mode);
+ void setSmoothTangent();
+ void setEaseInTangent();
+ void setEaseOutTangent();
+
+ void setSnapAll() { _snapHorizontal = true; _snapVertical = true; }
+ void setSnapHorizontal() { _snapHorizontal = true; _snapVertical = false; }
+ void setSnapVertical() { _snapHorizontal = false; _snapVertical = true; }
+
+ void increaseCurveScaleHorizontally();
+ void decreaseCurveScaleHorizontally();
+ void increaseCurveScaleVertically();
+ void decreaseCurveScaleVertically();
+ void frameCurveScaleHorizontally();
+ void frameCurveScaleVertically();
+ void frameCurveScale();
+
+ void setAddCtrlPntByClick(bool value) { _canAddCtrlPntByClick = value; }
+ void setRemoveCtrlPntByClick(bool value) { _canRemoveCtrlPntByClick = value; }
+
+signals:
+ void PickedControlPointValueChanged(QPointF& value);
+ void PickedControlPointChanged(const std::vector<CurveEntity*> pickedCurves);
+ void CurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute);
+
+private slots:
+ void onShowContextMenu(const QPoint& pos);
+ void onRemoveControlPoint();
+
+private:
+ // QWidget events
+ virtual void paintEvent(QPaintEvent * e);
+ virtual void resizeEvent(QResizeEvent* e);
+
+ virtual void mousePressEvent(QMouseEvent* e);
+ virtual void mouseReleaseEvent(QMouseEvent* e);
+ virtual void mouseMoveEvent(QMouseEvent* e);
+ virtual void wheelEvent(QWheelEvent *e);
+ virtual void keyPressEvent(QKeyEvent *e);
+
+ void _updateCurveFitWindowPara();
+ QPointF _valueToScreen(const QPointF& pnt);
+ QPointF _screenToValue(const QPointF& pnt);
+ void _drawAxis(QPainter &painter);
+ void _drawGrid(QPainter &painter);
+ QPointF _getSnapSreenPos(const QPointF& mouseScreenPos);
+ QPointF _dragedCoordinateToScreen(const QPointF& pnt);
+ QPointF _screenToDragedCoordinate(const QPointF& pnt);
+
+private:
+ QWidget* _parent;
+ bool _moveCrossOtherCtrlPnt;// whether can move control point across other control points
+ bool _moveCtrlPnt;
+ bool _pan;
+ bool _snapHorizontal;
+ bool _snapVertical;
+ bool _canAddCtrlPntByClick;
+ bool _canRemoveCtrlPntByClick;
+ std::vector<CurveEntity> _curves;
+ QPointF _curveFitWindowScale;
+ QPointF _curveFitWindowOffset;
+ QPointF _curveScaleLevel;
+ QPointF _mousePressScreenPos;
+ QPointF _lastOrinScreenPos;
+ QPointF _curOrinScreenPos;
+
+ QMenu* _contextMenu;
+ QAction* _removeCtrlPntAction;
+};
+
+} // namespace CurveEditor
+} // namespace nvidia
+
+#endif // CurveWidget_h__
diff --git a/NvBlast/tools/DataConverter/src/Main.cpp b/NvBlast/tools/DataConverter/src/Main.cpp
new file mode 100644
index 0000000..fb9be66
--- /dev/null
+++ b/NvBlast/tools/DataConverter/src/Main.cpp
@@ -0,0 +1,88 @@
+#include "NvBlastExtDataConverter.h"
+#include <string>
+#include <iostream>
+#include "tclap/CmdLine.h"
+#include <stdint.h>
+#include <iterator>
+#include <fstream>
+#include <functional>
+
+#define IDE_DEBUG_MODE 0
+
+int customMain(std::vector<std::string>& args)
+{
+ try
+ {
+ // setup cmd line
+ TCLAP::CmdLine cmd("Blast SDK: Data Converter", ' ', "0.1");
+
+ TCLAP::ValueArg<int32_t> outversionArg("v", "outversion", "Output binary block version. Pass -1 or ignore this parameter to convert to latest version.", false, -1, "outversion");
+ cmd.add(outversionArg);
+ TCLAP::ValueArg<std::string> outfileArg("o", "outfile", "Output binary file.", true, "", "outfile");
+ cmd.add(outfileArg);
+ TCLAP::ValueArg<std::string> infileArg("i", "infile", "Input binary file.", true, "", "infile");
+ cmd.add(infileArg);
+
+ // parse cmd input
+ cmd.parse(args);
+
+ // get cmd parse results
+ std::string infile = infileArg.getValue();
+ std::string outfile = outfileArg.getValue();
+ int32_t outBlockVersion = outversionArg.getValue();
+
+ // read input file
+ std::ifstream infileStream(infile.c_str(), std::ios::binary);
+ if (!infileStream.is_open())
+ {
+ std::cerr << "FAIL: Can't open input file: " << infile << std::endl;
+ return 0;
+ }
+ std::vector<char> inBlock((std::istreambuf_iterator<char>(infileStream)), std::istreambuf_iterator<char>());
+ infileStream.close();
+
+ // convert
+ std::vector<char> outBlock;
+ if (Nv::Blast::convertDataBlock(outBlock, inBlock, outBlockVersion >= 0 ? (uint32_t*)&outBlockVersion : nullptr))
+ {
+ std::ofstream outfileStream(outfile, std::ios::binary | std::ios::out);
+ if (!outfileStream.is_open())
+ {
+ std::cerr << "FAIL: Can't open output file: " << outfile << std::endl;
+ return 0;
+ }
+ outfileStream.write((char*)&outBlock[0], outBlock.size());
+ outfileStream.close();
+
+ std::cout << "Conversion success, result written in file: " << outfile << std::endl;
+ }
+ else
+ {
+ std::cout << "Conversion failed." << std::endl;
+ }
+ }
+ catch (TCLAP::ArgException &e) // catch any exceptions
+ {
+ std::cout << "error: " << e.error() << " for arg " << e.argId() << std::endl;
+ }
+
+ return 0;
+}
+
+int main(int argc, const char* const* argv)
+{
+ std::vector<std::string> args;
+#if IDE_DEBUG_MODE
+ NV_UNUSED(argc);
+ NV_UNUSED(argv);
+
+ args.push_back("");
+ args.push_back("-i wall.blast");
+ args.push_back("-o wall_new.blast");
+ args.push_back("-v 5");
+#else
+ for (int i = 0; i < argc; i++)
+ args.push_back(argv[i]);
+#endif
+ return customMain(args);
+}
diff --git a/NvBlast/tools/common/BlastDataExporter.cpp b/NvBlast/tools/common/BlastDataExporter.cpp
new file mode 100644
index 0000000..622901a
--- /dev/null
+++ b/NvBlast/tools/common/BlastDataExporter.cpp
@@ -0,0 +1,106 @@
+#include <BlastDataExporter.h>
+#include "NvBlastExtPxManager.h"
+#include <NvBlastExtAuthoringCollisionBuilder.h>
+#include <Log.h>
+#include "PsFileBuffer.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlast.h"
+#include <NvBlastTkAsset.h>
+
+using namespace Nv::Blast;
+
+
+ExtPxAsset* BlastDataExporter::createExtBlastAsset(std::vector<NvBlastBondDesc>& bondDescs, const std::vector<NvBlastChunkDesc>& chunkDescs,
+ std::vector<ExtPxAssetDesc::ChunkDesc>& physicsChunks)
+{
+ ExtPxAssetDesc descriptor;
+ descriptor.bondCount = static_cast<uint32_t>(bondDescs.size());
+ descriptor.bondDescs = bondDescs.data();
+ descriptor.chunkCount = static_cast<uint32_t>(chunkDescs.size());
+ descriptor.chunkDescs = chunkDescs.data();
+ descriptor.bondFlags = nullptr;
+ descriptor.pxChunks = physicsChunks.data();
+ ExtPxAsset* asset = ExtPxAsset::create(descriptor, *mFramework);
+ return asset;
+}
+
+
+
+NvBlastAsset* BlastDataExporter::createLlBlastAsset(std::vector<NvBlastBondDesc>& bondDescs, const std::vector<NvBlastChunkDesc>& chunkDescs)
+{
+
+ NvBlastAssetDesc assetDesc;
+ assetDesc.bondCount = static_cast<uint32_t>(bondDescs.size());
+ assetDesc.bondDescs = &bondDescs[0];
+
+ assetDesc.chunkCount = static_cast<uint32_t>(chunkDescs.size());
+ assetDesc.chunkDescs = &chunkDescs[0];
+
+
+ std::vector<uint8_t> scratch(static_cast<unsigned int>(NvBlastGetRequiredScratchForCreateAsset(&assetDesc, m_log)));
+ void* mem = _aligned_malloc(NvBlastGetAssetMemorySize(&assetDesc, m_log), 16);
+ NvBlastAsset* asset = NvBlastCreateAsset(mem, &assetDesc, &scratch[0], m_log);
+ return asset;
+}
+
+TkAsset* BlastDataExporter::createTkBlastAsset(const std::vector<NvBlastBondDesc>& bondDescs, const std::vector<NvBlastChunkDesc>& chunkDescs)
+{
+ TkAssetDesc desc;
+ desc.bondCount = static_cast<uint32_t>(bondDescs.size());
+ desc.bondDescs = bondDescs.data();
+ desc.chunkCount = static_cast<uint32_t>(chunkDescs.size());
+ desc.chunkDescs = chunkDescs.data();
+ desc.bondFlags = nullptr;
+ TkAsset* asset = mFramework->createAsset(desc);
+ return asset;
+};
+
+
+bool BlastDataExporter::saveBlastLLAsset(const std::string& outputFilePath, const NvBlastAsset* asset)
+{
+ uint32_t assetSize = NvBlastAssetGetSize(asset, m_log);
+
+ physx::PsFileBuffer fileBuf(outputFilePath.c_str(), physx::PxFileBuf::OPEN_WRITE_ONLY);
+ if (!fileBuf.isOpen())
+ {
+ NVBLAST_LOG_ERROR(m_log, "Can't open output buffer. \n");
+ return false;
+ }
+ fileBuf.write(asset, sizeof(char) * assetSize);
+ fileBuf.close();
+ return true;
+}
+
+bool BlastDataExporter::saveBlastTkAsset(const std::string& outputFilePath, const TkAsset* asset)
+{
+ physx::PsFileBuffer fileBuf(outputFilePath.c_str(), physx::PxFileBuf::OPEN_WRITE_ONLY);
+ if (!fileBuf.isOpen())
+ {
+ NVBLAST_LOG_ERROR(m_log, "Can't open output buffer. \n");
+ return false;
+ }
+ if (!asset->serialize(fileBuf))
+ {
+ NVBLAST_LOG_ERROR(m_log, "Serialization failed. \n");
+ return false;
+ }
+ fileBuf.close();
+ return true;
+}
+
+bool BlastDataExporter::saveBlastExtAsset(const std::string& outputFilePath, const ExtPxAsset* asset)
+{
+ physx::PsFileBuffer fileBuf(outputFilePath.c_str(), physx::PxFileBuf::OPEN_WRITE_ONLY);
+ if (!fileBuf.isOpen())
+ {
+ NVBLAST_LOG_ERROR(m_log, "Can't open output buffer. \n");
+ return false;
+ }
+ if (!asset->serialize(fileBuf, *mCooking))
+ {
+ NVBLAST_LOG_ERROR(m_log, "ExtPhysicsAsset serialization failed.\n");
+ return false;
+ }
+ fileBuf.close();
+ return true;
+} \ No newline at end of file
diff --git a/NvBlast/tools/common/BlastDataExporter.h b/NvBlast/tools/common/BlastDataExporter.h
new file mode 100644
index 0000000..3e44a7c
--- /dev/null
+++ b/NvBlast/tools/common/BlastDataExporter.h
@@ -0,0 +1,78 @@
+#ifndef BLAST_DATA_EXPORTER
+#define BLAST_DATA_EXPORTER
+
+
+#include <NvBlastIndexFns.h>
+#include <NvBlastExtAuthoringTypes.h>
+#include <NvBlastExtPxAsset.h>
+#include <vector>
+#include <string>
+
+using namespace Nv::Blast;
+
+namespace physx
+{
+ class PxCooking;
+}
+
+
+struct NvBlastBondDesc;
+struct NvBlastChunkDesc;
+
+struct NvBlastAsset;
+namespace Nv
+{
+ namespace Blast
+ {
+ class TkAsset;
+ class ExtPxAsset;
+ }
+}
+/**
+ Tool for Blast asset creation and exporting
+*/
+class BlastDataExporter
+{
+public:
+ BlastDataExporter(TkFramework* framework, physx::PxCooking* cooking, NvBlastLog log) : mFramework(framework), mCooking(cooking), m_log(log) {};
+
+ /**
+ Creates ExtPxAsset
+ */
+ ExtPxAsset* createExtBlastAsset(std::vector<NvBlastBondDesc>& bondDescs, const std::vector<NvBlastChunkDesc>& chunkDescs,
+ std::vector<ExtPxAssetDesc::ChunkDesc>& physicsChunks);
+ /**
+ Creates Low Level Blast asset
+ */
+ NvBlastAsset* createLlBlastAsset(std::vector<NvBlastBondDesc>& bondDescs, const std::vector<NvBlastChunkDesc>& chunkDescs);
+
+ /**
+ Creates Blast Toolkit Asset asset
+ */
+ TkAsset* createTkBlastAsset(const std::vector<NvBlastBondDesc>& bondDescs, const std::vector<NvBlastChunkDesc>& chunkDescs);
+
+ /*
+ Saves Blast LL asset to given path
+ */
+ bool saveBlastLLAsset(const std::string& outputFilePath, const NvBlastAsset* asset);
+
+ /*
+ Saves Blast Tk asset to given path
+ */
+ bool saveBlastTkAsset(const std::string& outputFilePath, const TkAsset* asset);
+
+ /*
+ Saves Blast BPXA asset to given path
+ */
+ bool saveBlastExtAsset(const std::string& outputFilePath, const ExtPxAsset* asset);
+
+private:
+ TkFramework* mFramework;
+ physx::PxCooking* mCooking;
+ NvBlastLog m_log;
+};
+
+
+
+
+#endif \ No newline at end of file
diff --git a/NvBlast/tools/common/FbxFileReader.cpp b/NvBlast/tools/common/FbxFileReader.cpp
new file mode 100644
index 0000000..6b72223
--- /dev/null
+++ b/NvBlast/tools/common/FbxFileReader.cpp
@@ -0,0 +1,170 @@
+#include "FbxFileReader.h"
+#include "fileio/fbxiosettings.h"
+#include "fileio/fbxiosettingspath.h"
+#include "core/base/fbxstringlist.h"
+#include <iostream>
+#include "scene/geometry/fbxmesh.h"
+
+#include "PxVec3.h"
+#include "PxVec2.h"
+
+using physx::PxVec3;
+using physx::PxVec2;
+using Nv::Blast::Mesh;
+
+
+FbxFileReader::FbxFileReader()
+{
+ setConvertToUE4(false);
+}
+
+FbxAMatrix FbxFileReader::getTransformForNode(FbxNode* node)
+{
+ return node->EvaluateGlobalTransform();
+}
+
+std::shared_ptr<Nv::Blast::Mesh> FbxFileReader::loadFromFile(std::string filename)
+{
+ // Wrap in a shared ptr so that when it deallocates we get an auto destroy and all of the other assets created don't leak.
+ std::shared_ptr<FbxManager> sdkManager = std::shared_ptr<FbxManager>(FbxManager::Create(), [=](FbxManager* manager)
+ {
+ std::cout << "Deleting FbxManager" << std::endl;
+ manager->Destroy();
+ });
+
+ FbxIOSettings* ios = FbxIOSettings::Create(sdkManager.get(), IOSROOT);
+ // Set some properties on the io settings
+
+ sdkManager->SetIOSettings(ios);
+
+
+ FbxImporter* importer = FbxImporter::Create(sdkManager.get(), "");
+
+ bool importStatus = importer->Initialize(filename.c_str(), -1, sdkManager->GetIOSettings());
+
+ if (!importStatus)
+ {
+ std::cerr << "Call to FbxImporter::Initialize failed." << std::endl;
+ std::cerr << "Error returned: " << importer->GetStatus().GetErrorString() << std::endl;
+
+ return nullptr;
+ }
+
+ FbxScene* scene = FbxScene::Create(sdkManager.get(), "importScene");
+
+ importStatus = importer->Import(scene);
+
+ if (!importStatus)
+ {
+ std::cerr << "Call to FbxImporter::Import failed." << std::endl;
+ std::cerr << "Error returned: " << importer->GetStatus().GetErrorString() << std::endl;
+
+ return nullptr;
+ }
+
+ if (getConvertToUE4())
+ {
+ // Convert to UE4
+ FbxAxisSystem::EFrontVector FrontVector = (FbxAxisSystem::EFrontVector) - FbxAxisSystem::eParityOdd;
+ const FbxAxisSystem UnrealZUp(FbxAxisSystem::eZAxis, FrontVector, FbxAxisSystem::eRightHanded);
+
+ UnrealZUp.ConvertScene(scene);
+ }
+
+
+ // Recurse the fbx tree and find all meshes
+ std::vector<FbxNode*> meshNodes;
+ getFbxMeshes(scene->GetRootNode(), meshNodes);
+
+ std::cout << "Found " << meshNodes.size() << " meshes." << std::endl;
+
+ // Process just 0, because dumb. Fail out if more than 1?
+
+ FbxNode* meshNode = meshNodes[0];
+ FbxMesh* mesh = meshNode->GetMesh();
+
+ int polyCount = mesh->GetPolygonCount();
+
+
+ bool bAllTriangles = true;
+ // Verify that the mesh is triangulated.
+ for (int i = 0; i < polyCount; i++)
+ {
+ if (mesh->GetPolygonSize(i) != 3)
+ {
+ bAllTriangles = false;
+ }
+ }
+
+ if (!bAllTriangles)
+ {
+ std::cerr << "Mesh 0 has " << polyCount << " but not all polygons are triangles. Mesh must be triangulated." << std::endl;
+ return nullptr;
+ }
+
+ FbxStringList uvSetNames;
+
+ mesh->GetUVSetNames(uvSetNames);
+
+ const char * uvSetName = uvSetNames.GetStringAt(0);
+
+ std::vector<PxVec3> positions;
+ std::vector<PxVec3> normals;
+ std::vector<PxVec2> uv;
+ std::vector<uint32_t> indices;
+
+ int* polyVertices = mesh->GetPolygonVertices();
+
+ uint32_t vertIndex = 0;
+
+ FbxAMatrix trans = getTransformForNode(meshNode);
+
+ for (int i = 0; i < polyCount; i++)
+ {
+ for (int vi = 0; vi < 3; vi++)
+ {
+ int polyCPIdx = polyVertices[i*3+vi];
+
+ FbxVector4 vert = mesh->GetControlPointAt(polyCPIdx);
+ FbxVector4 normVec;
+ FbxVector2 uvVec;
+ bool bUnmapped;
+ mesh->GetPolygonVertexNormal(i, vi, normVec);
+ mesh->GetPolygonVertexUV(i, vi, uvSetName, uvVec, bUnmapped);
+
+ vert = trans.MultT(vert);
+ normVec = trans.MultT(normVec);
+
+ positions.push_back(PxVec3((float) vert[0], (float)vert[1], (float)vert[2]));
+ normals.push_back(PxVec3((float)normVec[0], (float)normVec[1], (float)normVec[2]));
+ uv.push_back(PxVec2((float)uvVec[0], (float)uvVec[1]));
+
+ indices.push_back(vertIndex++);
+ }
+
+ }
+
+ PxVec3* nr = (!normals.empty()) ? normals.data() : nullptr;
+ PxVec2* uvp = (!uv.empty()) ? uv.data() : nullptr;
+
+ return std::make_shared<Mesh>(positions.data(), nr, uvp, static_cast<uint32_t>(positions.size()), indices.data(), static_cast<uint32_t>(indices.size()));
+}
+
+void FbxFileReader::getFbxMeshes(FbxNode* node, std::vector<FbxNode*>& meshNodes)
+{
+ FbxMesh* mesh = node->GetMesh();
+
+ if (mesh != nullptr)
+ {
+ meshNodes.push_back(node);
+ }
+
+ int childCount = node->GetChildCount();
+
+ for (int i = 0; i < childCount; i++)
+ {
+ FbxNode * childNode = node->GetChild(i);
+
+ getFbxMeshes(childNode, meshNodes);
+ }
+}
diff --git a/NvBlast/tools/common/FbxFileReader.h b/NvBlast/tools/common/FbxFileReader.h
new file mode 100644
index 0000000..ca288ad
--- /dev/null
+++ b/NvBlast/tools/common/FbxFileReader.h
@@ -0,0 +1,23 @@
+#pragma once
+#include "IMeshFileReader.h"
+#include "fbxsdk.h"
+
+class FbxFileReader: public IMeshFileReader
+{
+public:
+ FbxFileReader();
+ ~FbxFileReader() = default;
+
+ /*
+ Load from the specified file path, returning a mesh or nullptr if failed
+ */
+ std::shared_ptr<Nv::Blast::Mesh> loadFromFile(std::string filename) override;
+
+private:
+
+ // Should we convert the scene to UE4 coordinate system on load?
+ bool bConvertToUE4;
+
+ FbxAMatrix getTransformForNode(FbxNode* node);
+ void getFbxMeshes(FbxNode* node, std::vector<FbxNode*>& meshNodes);
+}; \ No newline at end of file
diff --git a/NvBlast/tools/common/FbxFileWriter.cpp b/NvBlast/tools/common/FbxFileWriter.cpp
new file mode 100644
index 0000000..a71896e
--- /dev/null
+++ b/NvBlast/tools/common/FbxFileWriter.cpp
@@ -0,0 +1,645 @@
+#include "FbxFileWriter.h"
+#include "fbxsdk.h"
+#include "FbxUtils.h"
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include "NvBlastTypes.h"
+#include "NvBlastTkFramework.h"
+#include "NvBlast.h"
+#include "PxVec3.h"
+#include "NvBlastAssert.h"
+#include <unordered_set>
+#include <functional>
+
+
+FbxFileWriter::FbxFileWriter():
+ bOutputFBXAscii(false)
+{
+ // Wrap in a shared ptr so that when it deallocates we get an auto destroy and all of the other assets created don't leak.
+ sdkManager = std::shared_ptr<FbxManager>(FbxManager::Create(), [=](FbxManager* manager)
+ {
+ std::cout << "Deleting FbxManager" << std::endl;
+ manager->Destroy();
+ });
+
+ setConvertToUE4(false);
+}
+
+/*
+
+ Add the NvBlastAsset as a param
+ Walk the NvBlastChunk tree
+ -- Get the triangles for each chunk, however we do that
+ -- create a skin, clusters and bone node for each chunk, linked to their parent with the proper link mode
+
+*/
+bool FbxFileWriter::saveToFile(const NvBlastAsset* asset, std::vector<std::vector<Nv::Blast::Triangle>> chunksGeometry, std::string assetName, std::string outputPath)
+{
+
+ FbxIOSettings* ios = FbxIOSettings::Create(sdkManager.get(), IOSROOT);
+ // Set some properties on the io settings
+
+// ios->SetBoolProp(EXP_ASCIIFBX, true);
+
+ sdkManager->SetIOSettings(ios);
+
+ sdkManager->GetIOSettings()->SetBoolProp(EXP_ASCIIFBX, bOutputFBXAscii);
+
+ FbxScene* scene = FbxScene::Create(sdkManager.get(), "Export Scene");
+
+ if (getConvertToUE4())
+ {
+ FbxAxisSystem::EFrontVector FrontVector = (FbxAxisSystem::EFrontVector) - FbxAxisSystem::eParityOdd;
+ const FbxAxisSystem UnrealZUp(FbxAxisSystem::eZAxis, FrontVector, FbxAxisSystem::eRightHanded);
+
+ scene->GetGlobalSettings().SetAxisSystem(UnrealZUp);
+ }
+
+ // Otherwise default to Maya defaults
+
+ FbxMesh* mesh = FbxMesh::Create(sdkManager.get(), "meshgeo");
+
+ FbxGeometryElementNormal* geNormal = mesh->CreateElementNormal();
+ geNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);
+ geNormal->SetReferenceMode(FbxGeometryElement::eDirect);
+
+ FbxGeometryElementUV* geUV = mesh->CreateElementUV("diffuseElement");
+ geUV->SetMappingMode(FbxGeometryElement::eByPolygonVertex);
+ geUV->SetReferenceMode(FbxGeometryElement::eDirect);
+
+ // Get the triangles count for all of the mesh parts
+
+ size_t triangleCount = 0;
+ for (auto triangles : chunksGeometry)
+ {
+ triangleCount += triangles.size();
+ }
+
+ mesh->InitControlPoints((int)triangleCount * 3);
+
+ FbxNode* meshNode = FbxNode::Create(scene, "meshnode");
+ meshNode->SetNodeAttribute(mesh);
+ meshNode->SetShadingMode(FbxNode::eTextureShading);
+
+ FbxNode* lRootNode = scene->GetRootNode();
+ lRootNode->AddChild(meshNode);
+
+ FbxSkin* skin = FbxSkin::Create(sdkManager.get(), "Skin of the thing");
+ skin->SetGeometry(mesh);
+
+ mesh->AddDeformer(skin);
+
+ // Add a material otherwise UE4 freaks out on import
+
+ FbxGeometryElementMaterial* matElement = mesh->CreateElementMaterial();
+ matElement->SetMappingMode(FbxGeometryElement::eByPolygon);
+ matElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
+
+ FbxSurfacePhong* material = FbxSurfacePhong::Create(sdkManager.get(), "FirstExportMaterial");
+
+ material->Diffuse.Set(FbxDouble3(1.0, 1.0, 0));
+ material->DiffuseFactor.Set(1.0);
+
+ meshNode->AddMaterial(material);
+
+ FbxSurfacePhong* material2 = FbxSurfacePhong::Create(sdkManager.get(), "SecondExportMaterial");
+
+ material2->Diffuse.Set(FbxDouble3(1.0, 0.0, 1.0));
+ material2->DiffuseFactor.Set(1.0);
+
+ meshNode->AddMaterial(material2);
+
+ // Now walk the tree and create a skeleton with geometry at the same time
+ // Find a "root" chunk and walk the tree from there.
+ uint32_t chunkCount = NvBlastAssetGetChunkCount(asset, NvBlastTkFrameworkGet()->getLogFn());
+
+ auto chunks = NvBlastAssetGetChunks(asset, NvBlastTkFrameworkGet()->getLogFn());
+
+ currentDepth = 0;
+ uint32_t cpIdx = 0;
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ const NvBlastChunk* chunk = &chunks[i];
+
+ if (chunk->parentChunkIndex == UINT32_MAX)
+ {
+ uint32_t addedCps = createChunkRecursive(cpIdx, i, meshNode, lRootNode, skin, asset, chunksGeometry);
+
+ cpIdx += addedCps;
+ }
+ }
+
+ return finalizeFbxAndSave(scene, skin, outputPath, assetName);}
+
+/*
+ Recursive method that creates this chunk and all it's children.
+
+ This creates a FbxNode with an FbxCluster, and all of the geometry for this chunk.
+
+ Returns the number of added control points
+*/
+uint32_t FbxFileWriter::createChunkRecursive(uint32_t currentCpIdx, uint32_t chunkIndex, FbxNode *meshNode, FbxNode* parentNode, FbxSkin* skin, const NvBlastAsset* asset, std::vector<std::vector<Nv::Blast::Triangle>> chunksGeometry)
+{
+ currentDepth++;
+
+// if (currentDepth >= 4)
+// {
+// return 0;
+// }
+
+ auto chunks = NvBlastAssetGetChunks(asset, NvBlastTkFrameworkGet()->getLogFn());
+ const NvBlastChunk* chunk = &chunks[chunkIndex];
+ auto triangles = chunksGeometry[chunkIndex];
+ physx::PxVec3 centroid = physx::PxVec3(chunk->centroid[0], chunk->centroid[1], chunk->centroid[2]);
+
+ std::ostringstream namestream;
+
+ //mesh->InitTextureUV(triangles.size() * 3);
+
+ std::ostringstream().swap(namestream); // Swap namestream with a default constructed ostringstream
+ namestream << "bone_" << chunkIndex;
+ std::string boneName = namestream.str();
+
+ FbxSkeleton* skelAttrib;
+ if (chunk->parentChunkIndex == UINT32_MAX)
+ {
+ skelAttrib = FbxSkeleton::Create(sdkManager.get(), "SkelRootAttrib");
+ skelAttrib->SetSkeletonType(FbxSkeleton::eRoot);
+
+ // Change the centroid to origin
+ centroid = physx::PxVec3(0.0f);
+ }
+ else
+ {
+ skelAttrib = FbxSkeleton::Create(sdkManager.get(), boneName.c_str());
+ skelAttrib->SetSkeletonType(FbxSkeleton::eLimbNode);
+ }
+
+ skelAttrib->Size.Set(1.0); // What's this for?
+
+
+ FbxNode* boneNode = FbxNode::Create(sdkManager.get(), boneName.c_str());
+ boneNode->SetNodeAttribute(skelAttrib);
+
+ auto mat = parentNode->EvaluateGlobalTransform().Inverse();
+
+ FbxVector4 vec(centroid.x, centroid.y, centroid.z, 0);
+ FbxVector4 c2 = mat.MultT(vec);
+
+ boneNode->LclTranslation.Set(c2);
+
+ parentNode->AddChild(boneNode);
+
+ std::ostringstream().swap(namestream); // Swap namestream with a default constructed ostringstream
+ namestream << "cluster_" << std::setw(5) << std::setfill('0') << chunkIndex;
+ std::string clusterName = namestream.str();
+
+ FbxCluster* cluster = FbxCluster::Create(sdkManager.get(), clusterName.c_str());
+ cluster->SetTransformMatrix(FbxAMatrix());
+ cluster->SetLink(boneNode);
+ cluster->SetLinkMode(FbxCluster::eTotalOne);
+
+ skin->AddCluster(cluster);
+
+ FbxMesh* mesh = static_cast<FbxMesh*>(meshNode->GetNodeAttribute());
+
+ FbxVector4* controlPoints = mesh->GetControlPoints();
+ auto geNormal = mesh->GetElementNormal();
+ auto geUV = mesh->GetElementUV("diffuseElement");
+ FbxGeometryElementMaterial* matElement = mesh->GetElementMaterial();
+
+ auto addVert = [&](Nv::Blast::Vertex vert, int controlPointIdx)
+ {
+ FbxVector4 vertex;
+ FbxVector4 normal;
+ FbxVector2 uv;
+
+ FbxUtils::VertexToFbx(vert, vertex, normal, uv);
+
+ controlPoints[controlPointIdx] = vertex;
+ geNormal->GetDirectArray().Add(normal);
+ geUV->GetDirectArray().Add(uv);
+ // Add this control point to the bone with weight 1.0
+ cluster->AddControlPointIndex(controlPointIdx, 1.0);
+ };
+
+ uint32_t cpIdx = 0;
+ uint32_t polyCount = mesh->GetPolygonCount();
+ for (auto tri : triangles)
+ {
+ addVert(tri.a, currentCpIdx + cpIdx + 0);
+ addVert(tri.b, currentCpIdx + cpIdx + 1);
+ addVert(tri.c, currentCpIdx + cpIdx + 2);
+
+ mesh->BeginPolygon();
+ mesh->AddPolygon(currentCpIdx + cpIdx + 0);
+ mesh->AddPolygon(currentCpIdx + cpIdx + 1);
+ mesh->AddPolygon(currentCpIdx + cpIdx + 2);
+ mesh->EndPolygon();
+ if (tri.userInfo == 0)
+ {
+ matElement->GetIndexArray().SetAt(polyCount, 0);
+ }
+ else
+ {
+ matElement->GetIndexArray().SetAt(polyCount, 1);
+ }
+ polyCount++;
+ cpIdx += 3;
+ }
+
+ mat = meshNode->EvaluateGlobalTransform();
+ cluster->SetTransformMatrix(mat);
+
+ mat = boneNode->EvaluateGlobalTransform();
+ cluster->SetTransformLinkMatrix(mat);
+
+ uint32_t addedCps = static_cast<uint32_t>(triangles.size() * 3);
+
+ for (uint32_t i = chunk->firstChildIndex; i < chunk->childIndexStop; i++)
+ {
+ addedCps += createChunkRecursive(currentCpIdx + addedCps, i, meshNode, boneNode, skin, asset, chunksGeometry);
+ }
+
+ return addedCps;
+}
+
+
+uint32_t FbxFileWriter::createChunkRecursive(uint32_t currentCpIdx, uint32_t chunkIndex, FbxNode *meshNode, FbxNode* parentNode, FbxSkin* skin, const NvBlastAsset* asset,
+ const std::vector<std::vector<std::vector<int32_t> > >& posIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& normIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& texIndex)
+{
+ currentDepth++;
+
+ // if (currentDepth >= 4)
+ // {
+ // return 0;
+ // }
+
+ auto chunks = NvBlastAssetGetChunks(asset, NvBlastTkFrameworkGet()->getLogFn());
+ const NvBlastChunk* chunk = &chunks[chunkIndex];
+ physx::PxVec3 centroid = physx::PxVec3(chunk->centroid[0], chunk->centroid[1], chunk->centroid[2]);
+
+ std::ostringstream namestream;
+
+ //mesh->InitTextureUV(triangles.size() * 3);
+
+ std::ostringstream().swap(namestream); // Swap namestream with a default constructed ostringstream
+ namestream << "bone_" << chunkIndex;
+ std::string boneName = namestream.str();
+
+ FbxSkeleton* skelAttrib;
+ if (chunk->parentChunkIndex == UINT32_MAX)
+ {
+ skelAttrib = FbxSkeleton::Create(sdkManager.get(), "SkelRootAttrib");
+ skelAttrib->SetSkeletonType(FbxSkeleton::eRoot);
+
+ // Change the centroid to origin
+ centroid = physx::PxVec3(0.0f);
+ }
+ else
+ {
+ skelAttrib = FbxSkeleton::Create(sdkManager.get(), boneName.c_str());
+ skelAttrib->SetSkeletonType(FbxSkeleton::eLimbNode);
+ }
+
+ skelAttrib->Size.Set(1.0); // What's this for?
+
+
+ FbxNode* boneNode = FbxNode::Create(sdkManager.get(), boneName.c_str());
+ boneNode->SetNodeAttribute(skelAttrib);
+
+ auto mat = parentNode->EvaluateGlobalTransform().Inverse();
+
+ FbxVector4 vec(centroid.x, centroid.y, centroid.z, 0);
+ FbxVector4 c2 = mat.MultT(vec);
+
+ boneNode->LclTranslation.Set(c2);
+
+ parentNode->AddChild(boneNode);
+
+ std::ostringstream().swap(namestream); // Swap namestream with a default constructed ostringstream
+ namestream << "cluster_" << std::setw(5) << std::setfill('0') << chunkIndex;
+ std::string clusterName = namestream.str();
+
+ FbxCluster* cluster = FbxCluster::Create(sdkManager.get(), clusterName.c_str());
+ cluster->SetTransformMatrix(FbxAMatrix());
+ cluster->SetLink(boneNode);
+ cluster->SetLinkMode(FbxCluster::eTotalOne);
+
+ skin->AddCluster(cluster);
+
+ FbxMesh* mesh = static_cast<FbxMesh*>(meshNode->GetNodeAttribute());
+
+ auto geNormal = mesh->GetElementNormal();
+ auto geUV = mesh->GetElementUV("diffuseElement");
+ auto matr = mesh->GetElementMaterial();
+
+
+
+ auto posIndices = posIndex[chunkIndex];
+ auto normIndices = normIndex[chunkIndex];
+ auto uvIndices = texIndex[chunkIndex];
+ uint32_t cPolygCount = mesh->GetPolygonCount();
+ int32_t addedVertices = 0;
+ for (uint32_t subMesh = 0; subMesh < posIndices.size(); ++subMesh)
+ {
+ for (uint32_t tr = 0; tr < posIndices[subMesh].size(); tr += 3)
+ {
+ mesh->BeginPolygon();
+ mesh->AddPolygon(posIndices[subMesh][tr + 0]);
+ mesh->AddPolygon(posIndices[subMesh][tr + 1]);
+ mesh->AddPolygon(posIndices[subMesh][tr + 2]);
+ mesh->EndPolygon();
+ geNormal->GetIndexArray().SetAt(currentCpIdx + addedVertices, normIndices[subMesh][tr + 0]);
+ geNormal->GetIndexArray().SetAt(currentCpIdx + addedVertices + 1, normIndices[subMesh][tr + 1]);
+ geNormal->GetIndexArray().SetAt(currentCpIdx + addedVertices + 2, normIndices[subMesh][tr + 2]);
+
+ geUV->GetIndexArray().SetAt(currentCpIdx + addedVertices, uvIndices[subMesh][tr + 0]);
+ geUV->GetIndexArray().SetAt(currentCpIdx + addedVertices + 1, uvIndices[subMesh][tr + 1]);
+ geUV->GetIndexArray().SetAt(currentCpIdx + addedVertices + 2, uvIndices[subMesh][tr + 2]);
+ if (subMesh == 0)
+ {
+ matr->GetIndexArray().SetAt(cPolygCount, 0);
+ }
+ else
+ {
+ matr->GetIndexArray().SetAt(cPolygCount, 1);
+ }
+ cPolygCount++;
+ addedVertices += 3;
+
+ cluster->AddControlPointIndex(posIndices[subMesh][tr + 0], 1.0);
+ cluster->AddControlPointIndex(posIndices[subMesh][tr + 1], 1.0);
+ cluster->AddControlPointIndex(posIndices[subMesh][tr + 2], 1.0);
+ }
+ }
+ mat = meshNode->EvaluateGlobalTransform();
+ cluster->SetTransformMatrix(mat);
+
+ mat = boneNode->EvaluateGlobalTransform();
+ cluster->SetTransformLinkMatrix(mat);
+
+
+ for (uint32_t i = chunk->firstChildIndex; i < chunk->childIndexStop; i++)
+ {
+ addedVertices +=createChunkRecursive(addedVertices, i, meshNode, boneNode, skin, asset, posIndex, normIndex, texIndex);
+ }
+
+ return addedVertices;
+
+}
+
+void FbxFileWriter::addControlPoints(FbxMesh* mesh, const std::vector<physx::PxVec3>& pos, std::vector<std::vector<std::vector<int32_t> > >& posIndex)
+{
+ std::vector<uint32_t> vertices;
+ std::cout << "Adding control points" << std::endl;
+ std::vector<int32_t> mapping(pos.size(), -1);
+ for (uint32_t ch = 0; ch < posIndex.size(); ++ch)
+ {
+ mapping.assign(pos.size(), -1);
+ for (uint32_t sb = 0; sb < posIndex[ch].size(); ++sb)
+ {
+ for (uint32_t pi = 0; pi < posIndex[ch][sb].size(); ++pi)
+ {
+ uint32_t p = posIndex[ch][sb][pi];
+ if (mapping[p] == -1)
+ {
+ mapping[p] = (int)vertices.size();
+ vertices.push_back(posIndex[ch][sb][pi]);
+ posIndex[ch][sb][pi] = mapping[p];
+ }
+ else
+ {
+ posIndex[ch][sb][pi] = mapping[p];
+ }
+ }
+ }
+ }
+ mesh->InitControlPoints((int)vertices.size());
+ FbxVector4* controlPoints = mesh->GetControlPoints();
+ for (auto v : vertices)
+ {
+ *controlPoints = FbxVector4(pos[v].x, pos[v].y, pos[v].z, 0);
+ ++controlPoints;
+ }
+ std::cout << "Adding control points: done" << std::endl;
+}
+
+bool FbxFileWriter::finalizeFbxAndSave(FbxScene* scene, FbxSkin* skin, const std::string& outputPath, const std::string& name)
+{
+ // Store the bind pose
+
+ std::unordered_set<FbxNode*> clusterNodes;
+
+ std::function<void(FbxNode*)> addRecursively = [&](FbxNode* node)
+ {
+ if (node)
+ {
+ addRecursively(node->GetParent());
+
+ clusterNodes.insert(node);
+ }
+ };
+
+ for (uint32_t i = 0; i < (uint32_t)skin->GetClusterCount(); i++)
+ {
+ FbxNode* clusterNode = skin->GetCluster(i)->GetLink();
+
+ addRecursively(clusterNode);
+ }
+
+ NVBLAST_ASSERT(clusterNodes.size() > 0);
+
+ FbxPose* pose = FbxPose::Create(sdkManager.get(), "BasePose");
+ pose->SetIsBindPose(true);
+
+ for (auto node : clusterNodes)
+ {
+ FbxMatrix bindMat = node->EvaluateGlobalTransform();
+
+ pose->Add(node, bindMat);
+ }
+
+ scene->AddPose(pose);
+
+ FbxExporter* exporter = FbxExporter::Create(sdkManager.get(), "Scene Exporter");
+
+ auto path = outputPath + "\\" + name + ".fbx";
+
+ int lFormat;
+
+ if (bOutputFBXAscii)
+ {
+ lFormat = sdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX ascii (*.fbx)");
+ }
+ else
+ {
+ lFormat = sdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX binary (*.fbx)");
+ }
+
+ bool exportStatus = exporter->Initialize(path.c_str(), lFormat, sdkManager->GetIOSettings());
+
+ if (!exportStatus)
+ {
+ std::cerr << "Call to FbxExporter::Initialize failed" << std::endl;
+ std::cerr << "Error returned: " << exporter->GetStatus().GetErrorString() << std::endl;
+ return false;
+ }
+
+ exportStatus = exporter->Export(scene);
+
+ if (!exportStatus)
+ {
+ auto fbxStatus = exporter->GetStatus();
+
+ std::cerr << "Call to FbxExporter::Export failed" << std::endl;
+ std::cerr << "Error returned: " << fbxStatus.GetErrorString() << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+bool FbxFileWriter::saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm,
+ const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& posIndexInp,
+ const std::vector<std::vector<std::vector<int32_t> > >& normIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& texIndex,
+ const std::vector<std::string>& texPathes,
+ const uint32_t submeshCount)
+{
+ NV_UNUSED(submeshCount);
+ NV_UNUSED(texPathes);
+
+ auto posIndex = posIndexInp;
+ /**
+ Get polygon count
+ */
+ uint32_t polygCount = 0;
+ for (uint32_t ch = 0; ch < posIndex.size(); ++ch)
+ {
+ for (uint32_t sbm = 0; sbm < posIndex[ch].size(); ++sbm)
+ {
+ polygCount += (uint32_t)posIndex[ch][sbm].size() / 3;
+ }
+ }
+
+ FbxIOSettings* ios = FbxIOSettings::Create(sdkManager.get(), IOSROOT);
+ // Set some properties on the io settings
+
+ // ios->SetBoolProp(EXP_ASCIIFBX, true);
+
+ sdkManager->SetIOSettings(ios);
+
+ sdkManager->GetIOSettings()->SetBoolProp(EXP_ASCIIFBX, bOutputFBXAscii);
+
+ FbxScene* scene = FbxScene::Create(sdkManager.get(), "Export Scene");
+
+ if (getConvertToUE4())
+ {
+ FbxAxisSystem::EFrontVector FrontVector = (FbxAxisSystem::EFrontVector) - FbxAxisSystem::eParityOdd;
+ const FbxAxisSystem UnrealZUp(FbxAxisSystem::eZAxis, FrontVector, FbxAxisSystem::eRightHanded);
+
+ scene->GetGlobalSettings().SetAxisSystem(UnrealZUp);
+ }
+
+ // Otherwise default to Maya defaults
+
+ FbxMesh* mesh = FbxMesh::Create(sdkManager.get(), "meshgeo");
+
+ FbxGeometryElementNormal* geNormal = mesh->CreateElementNormal();
+ geNormal->SetMappingMode(FbxGeometryElement::eByPolygonVertex);
+ geNormal->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
+
+ FbxGeometryElementUV* geUV = mesh->CreateElementUV("diffuseElement");
+ geUV->SetMappingMode(FbxGeometryElement::eByPolygonVertex);
+ geUV->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
+
+
+ FbxNode* meshNode = FbxNode::Create(scene, "meshnode");
+ meshNode->SetNodeAttribute(mesh);
+ meshNode->SetShadingMode(FbxNode::eTextureShading);
+
+ FbxNode* lRootNode = scene->GetRootNode();
+ lRootNode->AddChild(meshNode);
+
+ FbxSkin* skin = FbxSkin::Create(sdkManager.get(), "Skin of the thing");
+ skin->SetGeometry(mesh);
+
+ mesh->AddDeformer(skin);
+
+ /**
+ Create control points, copy data to buffers
+ */
+ addControlPoints(mesh, pos, posIndex);
+
+ auto normalsElem = mesh->GetElementNormal();
+ for (uint32_t i = 0; i < norm.size(); ++i)
+ {
+ normalsElem->GetDirectArray().Add(FbxVector4(norm[i].x, norm[i].y, norm[i].z, 0));
+ }
+ auto uvsElem = mesh->GetElementUV("diffuseElement");
+ for (uint32_t i = 0; i < uvs.size(); ++i)
+ {
+ uvsElem->GetDirectArray().Add(FbxVector2(uvs[i].x, uvs[i].y));
+ }
+
+
+ // Add a material otherwise UE4 freaks out on import
+
+ FbxGeometryElementMaterial* matElement = mesh->CreateElementMaterial();
+ matElement->SetMappingMode(FbxGeometryElement::eByPolygon);
+ matElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
+
+ FbxSurfacePhong* material = FbxSurfacePhong::Create(sdkManager.get(), "FirstExportMaterial");
+
+ material->Diffuse.Set(FbxDouble3(1.0, 1.0, 0));
+ material->DiffuseFactor.Set(1.0);
+
+ meshNode->AddMaterial(material);
+
+ FbxSurfacePhong* material2 = FbxSurfacePhong::Create(sdkManager.get(), "SecondExportMaterial");
+
+ material2->Diffuse.Set(FbxDouble3(1.0, 0.0, 1.0));
+ material2->DiffuseFactor.Set(1.0);
+
+ meshNode->AddMaterial(material2);
+
+
+ matElement->GetIndexArray().SetCount(polygCount);
+ normalsElem->GetIndexArray().SetCount(polygCount * 3);
+ uvsElem->GetIndexArray().SetCount(polygCount * 3);
+
+
+ std::cout << "Create chunks recursive" << std::endl;
+
+ // Now walk the tree and create a skeleton with geometry at the same time
+ // Find a "root" chunk and walk the tree from there.
+ uint32_t chunkCount = NvBlastAssetGetChunkCount(asset, NvBlastTkFrameworkGet()->getLogFn());
+ auto chunks = NvBlastAssetGetChunks(asset, NvBlastTkFrameworkGet()->getLogFn());
+ currentDepth = 0;
+ uint32_t cpIdx = 0;
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ const NvBlastChunk* chunk = &chunks[i];
+
+ if (chunk->parentChunkIndex == UINT32_MAX)
+ {
+ uint32_t addedCps = createChunkRecursive(cpIdx, i, meshNode, lRootNode, skin, asset, posIndex, normIndex, texIndex);
+ cpIdx += addedCps;
+ }
+ }
+
+ return finalizeFbxAndSave(scene, skin, outputPath, name);
+}
+
+bool FbxFileWriter::saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm, const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& indices)
+{
+ std::vector<std::string> matnames;
+ matnames.push_back("");
+ return saveToFile(asset, name, outputPath, pos, norm, uvs, indices, indices, indices, matnames, 1);
+} \ No newline at end of file
diff --git a/NvBlast/tools/common/FbxFileWriter.h b/NvBlast/tools/common/FbxFileWriter.h
new file mode 100644
index 0000000..646d1ec
--- /dev/null
+++ b/NvBlast/tools/common/FbxFileWriter.h
@@ -0,0 +1,49 @@
+#pragma once
+#include "IMeshFileWriter.h"
+#include "fbxsdk.h"
+#include <memory>
+
+struct NvBlastAsset;
+
+class FbxFileWriter : public IMeshFileWriter
+{
+public:
+
+ FbxFileWriter();
+ ~FbxFileWriter() = default;
+
+ virtual bool saveToFile(const NvBlastAsset* asset, std::vector<std::vector<Nv::Blast::Triangle>> chunksGeometry, std::string assetName, std::string outputPath) override;
+
+
+
+ virtual bool saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm,
+ const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& posIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& normIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& texIndex,
+ const std::vector<std::string>& texPathes,
+ const uint32_t submeshCount) override;
+
+ virtual bool saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm, const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& indices) override;
+
+ bool bOutputFBXAscii;
+
+private:
+
+ uint32_t currentDepth;
+
+ std::shared_ptr<FbxManager> sdkManager;
+
+ uint32_t createChunkRecursive(uint32_t currentCpIdx, uint32_t chunkIndex, FbxNode *meshNode, FbxNode* parentNode, FbxSkin* skin, const NvBlastAsset* asset, std::vector<std::vector<Nv::Blast::Triangle>> chunksGeometry);
+
+ uint32_t createChunkRecursive(uint32_t currentCpIdx, uint32_t chunkIndex, FbxNode *meshNode, FbxNode* parentNode, FbxSkin* skin, const NvBlastAsset* asset,
+ const std::vector<std::vector<std::vector<int32_t> > >& posIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& normIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& texIndex);
+
+ void addControlPoints(FbxMesh* mesh, const std::vector<physx::PxVec3>& pos, std::vector<std::vector<std::vector<int32_t> > >& posIndex);
+
+ bool finalizeFbxAndSave(FbxScene* scene, FbxSkin* skin, const std::string& outputPath, const std::string& name);
+
+};
diff --git a/NvBlast/tools/common/FbxUtils.cpp b/NvBlast/tools/common/FbxUtils.cpp
new file mode 100644
index 0000000..b0bd94b
--- /dev/null
+++ b/NvBlast/tools/common/FbxUtils.cpp
@@ -0,0 +1,30 @@
+#include "fbxsdk.h"
+#include "FbxUtils.h"
+#include "PxVec3.h"
+#include "PxVec2.h"
+#include "NvBlastExtAuthoringTypes.h"
+
+using physx::PxVec3;
+using physx::PxVec2;
+
+
+void FbxUtils::VertexToFbx(Nv::Blast::Vertex& vert, FbxVector4& outVertex, FbxVector4& outNormal, FbxVector2& outUV)
+{
+ PxVec3ToFbx(vert.p, outVertex);
+ PxVec3ToFbx(vert.n, outNormal);
+ PxVec2ToFbx(vert.uv[0], outUV);
+}
+
+void FbxUtils::PxVec3ToFbx(physx::PxVec3& inVector, FbxVector4& outVector)
+{
+ outVector[0] = inVector.x;
+ outVector[1] = inVector.y;
+ outVector[2] = inVector.z;
+ outVector[3] = 0;
+}
+
+void FbxUtils::PxVec2ToFbx(physx::PxVec2& inVector, FbxVector2& outVector)
+{
+ outVector[0] = inVector.x;
+ outVector[1] = inVector.y;
+}
diff --git a/NvBlast/tools/common/FbxUtils.h b/NvBlast/tools/common/FbxUtils.h
new file mode 100644
index 0000000..902af21
--- /dev/null
+++ b/NvBlast/tools/common/FbxUtils.h
@@ -0,0 +1,20 @@
+#pragma once
+#include "PxVec3.h"
+#include "PxVec2.h"
+
+namespace Nv
+{
+ namespace Blast
+ {
+ struct Vertex;
+ }
+}
+
+class FbxUtils
+{
+public:
+ static void VertexToFbx(Nv::Blast::Vertex& vert, FbxVector4& outVertex, FbxVector4& outNormal, FbxVector2& outUV);
+
+ static void PxVec3ToFbx(physx::PxVec3& inVector, FbxVector4& outVector);
+ static void PxVec2ToFbx(physx::PxVec2& inVector, FbxVector2& outVector);
+};
diff --git a/NvBlast/tools/common/IMeshFileReader.h b/NvBlast/tools/common/IMeshFileReader.h
new file mode 100644
index 0000000..d632a2f
--- /dev/null
+++ b/NvBlast/tools/common/IMeshFileReader.h
@@ -0,0 +1,21 @@
+#pragma once
+#include <memory>
+#include <string>
+#include "NvBlastExtAuthoringMesh.h"
+
+
+class IMeshFileReader
+{
+public:
+
+ /*
+ Load from the specified file path, returning a mesh or nullptr if failed
+ */
+ virtual std::shared_ptr<Nv::Blast::Mesh> loadFromFile(std::string filename) = 0;
+
+ virtual bool getConvertToUE4() { return bConvertToUE4; }
+ virtual void setConvertToUE4(bool bConvert) { bConvertToUE4 = bConvert; }
+
+private:
+ bool bConvertToUE4;
+}; \ No newline at end of file
diff --git a/NvBlast/tools/common/IMeshFileWriter.h b/NvBlast/tools/common/IMeshFileWriter.h
new file mode 100644
index 0000000..562df70
--- /dev/null
+++ b/NvBlast/tools/common/IMeshFileWriter.h
@@ -0,0 +1,41 @@
+#pragma once
+#include "NvBlastExtAuthoringTypes.h"
+#include <string>
+#include <memory>
+#include <vector>
+
+struct NvBlastAsset;
+
+class IMeshFileWriter
+{
+public:
+
+ /**
+ Input mesh geometry as triangle array
+ */
+ virtual bool saveToFile(const NvBlastAsset* asset, std::vector<std::vector<Nv::Blast::Triangle>> chunksGeometry, std::string assetName, std::string outputPath) = 0;
+
+
+ /**
+ Input mesh geometry as vertex buffers with separate indices for positions, normals and uvs. Is used for compressed output to .obj file.
+ */
+ virtual bool saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm,
+ const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& posIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& normIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& texIndex,
+ const std::vector<std::string>& texPathes,
+ const uint32_t submeshCount) = 0;
+
+
+ /**
+ Input mesh geometry as vertex buffers and single index array.
+ */
+ virtual bool saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm, const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& indices) = 0;
+
+ virtual bool getConvertToUE4() { return bConvertToUE4; }
+ virtual void setConvertToUE4(bool bConvert) { bConvertToUE4 = bConvert; }
+private:
+ bool bConvertToUE4;
+};
diff --git a/NvBlast/tools/common/Log.cpp b/NvBlast/tools/common/Log.cpp
new file mode 100644
index 0000000..4371a7d
--- /dev/null
+++ b/NvBlast/tools/common/Log.cpp
@@ -0,0 +1,59 @@
+#include "Log.h"
+
+#include "PsString.h"
+
+#include <iomanip>
+#include <stdarg.h>
+#include <stdio.h>
+
+///////////////////////////////////////////////////////////////////////////
+
+namespace Nv
+{
+namespace Blast
+{
+
+void fLogf(const char* format, ...)
+{
+ char buf[4096], *p = buf;
+ va_list args;
+ int n;
+
+ va_start(args, format);
+ //n = _vsnprintf(p, sizeof buf - 3, format, args);
+ n = vsprintf_s(p, sizeof(buf)-3, format, args);
+ va_end(args);
+
+ p += (n < 0) ? sizeof buf - 3 : n;
+
+ while (p > buf && isspace((unsigned char)p[-1]))
+ {
+ *--p = '\0';
+ }
+
+ *p++ = '\r';
+ *p++ = '\n';
+ *p = '\0';
+
+ fLog(buf, Log::TYPE_INFO);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+void Log::flushDeferredMessages()
+{
+ if (mDeferredMessages.size() == 0) return;
+
+ std::cout << std::endl;
+ for (std::vector<std::string>::iterator it = mDeferredMessages.begin(); it != mDeferredMessages.end(); ++it)
+ {
+ log(*it, mMinVerbosity);
+ }
+ mDeferredMessages.clear();
+}
+
+
+
+} // namespace Blast
+} // namespace Nv
diff --git a/NvBlast/tools/common/Log.h b/NvBlast/tools/common/Log.h
new file mode 100644
index 0000000..528a3b9
--- /dev/null
+++ b/NvBlast/tools/common/Log.h
@@ -0,0 +1,122 @@
+#ifndef LOG_H
+#define LOG_H
+
+#include "Utils.h"
+#include "PxVec3.h"
+
+#include <sstream>
+
+namespace Nv
+{
+namespace Blast
+{
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+void fLogf(const char* format, ...);
+
+class Log : public Singleton<Log>
+{
+ friend class Singleton<Log>;
+
+public:
+
+ enum MessageType {
+ TYPE_INFO = 0,
+ TYPE_WARNING,
+ TYPE_ERROR,
+ TYPE_DEFERRED,
+
+ NUM_TYPES,
+ MOST_VERBOSE = TYPE_INFO,
+ LEAST_VERBOSE = TYPE_ERROR
+#if defined(_DEBUG)
+ , DEFAULT_VERBOSITY = MOST_VERBOSE
+#else
+ , DEFAULT_VERBOSITY = LEAST_VERBOSE
+#endif
+ };
+ typedef MessageType Verbosity;
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ template<typename T>
+ Log& log(const T& value, MessageType messageType);
+
+ void flushDeferredMessages();
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ void setCurrentVerbosity(Verbosity verbosity) { mCurrentVerbosity = verbosity; }
+ Verbosity getCurrentVerbosity() const { return mCurrentVerbosity; }
+
+ // Messages types below this level will be ignored
+ void setMinVerbosity(Verbosity verbosity) { mMinVerbosity = verbosity; }
+ Verbosity getMinVerbosity() const { return mMinVerbosity; }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+protected:
+ Log(MessageType verbosity = DEFAULT_VERBOSITY)
+ : mCurrentVerbosity(LEAST_VERBOSE),
+ mMinVerbosity(verbosity) { }
+
+private:
+ Verbosity mCurrentVerbosity;
+ Verbosity mMinVerbosity;
+ std::vector<std::string> mDeferredMessages;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+PX_INLINE std::ostream& operator<< (std::ostream& stream, const physx::PxVec3& vec)
+{
+ return stream << "(" << vec.x << ", " << vec.y << ", " << vec.z << ")";
+}
+
+template<typename T>
+Log& Log::log(const T& value, Log::MessageType messageType)
+{
+ if (TYPE_DEFERRED == messageType)
+ {
+ std::stringstream ss;
+ ss << value;
+ mDeferredMessages.push_back(ss.str());
+ }
+ else if(mMinVerbosity <= messageType)
+ {
+ std::cout << value;
+ }
+ return *this;
+}
+
+PX_INLINE Log& lout() { return Log::instance(); }
+
+template <typename T>
+PX_INLINE void fLog(const T& value, Log::MessageType messageType = Log::TYPE_INFO)
+{
+ lout().log<T>(value, messageType);
+}
+template <typename T>
+PX_INLINE Log& operator<<(Log& logger, const T& value)
+{
+ return logger.log<T>(value, logger.getCurrentVerbosity());
+}
+PX_INLINE Log& operator<<(Log& logger, Log::MessageType verbosity)
+{
+ logger.setCurrentVerbosity(verbosity);
+ return logger;
+}
+typedef std::ostream& (*ostream_manipulator)(std::ostream&);
+PX_INLINE Log& operator<<(Log& logger, ostream_manipulator pf)
+{
+ return operator<< <ostream_manipulator> (logger, pf);
+}
+
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif
diff --git a/NvBlast/tools/common/ObjFileReader.cpp b/NvBlast/tools/common/ObjFileReader.cpp
new file mode 100644
index 0000000..30b4c5c
--- /dev/null
+++ b/NvBlast/tools/common/ObjFileReader.cpp
@@ -0,0 +1,63 @@
+#include "ObjFileReader.h"
+
+#pragma warning(push)
+#pragma warning(disable:4706)
+#define TINYOBJLOADER_IMPLEMENTATION
+#include "tiny_obj_loader.h"
+#pragma warning(pop)
+
+
+#include <iostream>
+#include "PxVec3.h"
+#include "PxVec2.h"
+
+using physx::PxVec3;
+using physx::PxVec2;
+using Nv::Blast::Mesh;
+
+
+ObjFileReader::ObjFileReader()
+{
+ setConvertToUE4(false);
+}
+
+std::shared_ptr<Nv::Blast::Mesh> ObjFileReader::loadFromFile(std::string filename)
+{
+ std::vector<tinyobj::shape_t> shapes;
+ std::vector<tinyobj::material_t> mats;
+ std::string err;
+ std::string mtlPath;
+ bool ret = tinyobj::LoadObj(shapes, mats, err, filename.c_str());
+ // can't load?
+ if (!ret)
+ return nullptr;
+
+ if (shapes.size() > 1)
+ {
+ std::cout << "Can load only one object per mesh" << std::endl;
+ }
+
+ std::vector<PxVec3> positions;
+ std::vector<PxVec3> normals;
+ std::vector<PxVec2> uv;
+
+ auto& psVec = shapes[0].mesh.positions;
+ for (uint32_t i = 0; i < psVec.size() / 3; ++i)
+ {
+ positions.push_back(PxVec3(psVec[i * 3], psVec[i * 3 + 1], psVec[i * 3 + 2]));
+ }
+ auto& nmVec = shapes[0].mesh.normals;
+ for (uint32_t i = 0; i < nmVec.size() / 3; ++i)
+ {
+ normals.push_back(PxVec3(nmVec[i * 3], nmVec[i * 3 + 1], nmVec[i * 3 + 2]));
+ }
+ auto& txVec = shapes[0].mesh.texcoords;
+ for (uint32_t i = 0; i < txVec.size() / 2; ++i)
+ {
+ uv.push_back(PxVec2(txVec[i * 2], txVec[i * 2 + 1]));
+ }
+ PxVec3* nr = (!normals.empty()) ? normals.data() : 0;
+ PxVec2* uvp = (!uv.empty()) ? uv.data() : 0;
+
+ return std::make_shared<Mesh>(positions.data(), nr, uvp, static_cast<uint32_t>(positions.size()), shapes[0].mesh.indices.data(), static_cast<uint32_t>(shapes[0].mesh.indices.size()));
+}
diff --git a/NvBlast/tools/common/ObjFileReader.h b/NvBlast/tools/common/ObjFileReader.h
new file mode 100644
index 0000000..acc85ba
--- /dev/null
+++ b/NvBlast/tools/common/ObjFileReader.h
@@ -0,0 +1,16 @@
+#pragma once
+#include <memory>
+#include "IMeshFileReader.h"
+
+class ObjFileReader: public IMeshFileReader
+{
+public:
+ ObjFileReader();
+ ~ObjFileReader() = default;
+
+ /*
+ Load from the specified file path, returning a mesh or nullptr if failed
+ */
+ std::shared_ptr<Nv::Blast::Mesh> loadFromFile(std::string filename);
+
+};
diff --git a/NvBlast/tools/common/ObjFileWriter.cpp b/NvBlast/tools/common/ObjFileWriter.cpp
new file mode 100644
index 0000000..94aad7d
--- /dev/null
+++ b/NvBlast/tools/common/ObjFileWriter.cpp
@@ -0,0 +1,142 @@
+#include "ObjFileWriter.h"
+#include <PxVec3.h>
+#include <sstream>
+
+using namespace physx;
+using namespace Nv::Blast;
+
+bool ObjFileWriter::saveToFile(const NvBlastAsset* asset, std::vector<std::vector<Nv::Blast::Triangle>> chunksGeometry, std::string assetName, std::string outputPath)
+{
+ NV_UNUSED(asset);
+
+ std::vector<PxVec3> pos;
+ std::vector<PxVec3> norm;
+ std::vector<PxVec2> tex;
+ for (uint32_t vc = 0; vc < chunksGeometry.size(); ++vc)
+ {
+ std::vector<Triangle>& chunk = chunksGeometry[vc];
+ for (uint32_t i = 0; i < chunk.size(); ++i)
+ {
+ pos.push_back(chunk[i].a.p);
+ pos.push_back(chunk[i].b.p);
+ pos.push_back(chunk[i].c.p);
+
+ norm.push_back(chunk[i].a.n);
+ norm.push_back(chunk[i].b.n);
+ norm.push_back(chunk[i].c.n);
+
+ tex.push_back(chunk[i].a.uv[0]);
+ tex.push_back(chunk[i].b.uv[0]);
+ tex.push_back(chunk[i].c.uv[0]);
+ }
+ }
+ std::vector < std::vector<std::vector<int32_t> > > indices(chunksGeometry.size());
+ int32_t index = 0;
+ for (uint32_t vc = 0; vc < chunksGeometry.size(); ++vc)
+ {
+ indices[vc].push_back(std::vector<int32_t>());
+ for (uint32_t i = 0; i < chunksGeometry[vc].size() * 3; ++i)
+ {
+ indices[vc][0].push_back(index);
+ index++;
+ }
+ }
+
+ return saveToFile(asset, assetName, outputPath, pos, norm, tex, indices);
+}
+
+bool ObjFileWriter::saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm,
+ const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& posIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& normIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& texIndex,
+ const std::vector<std::string>& texPathes,
+ const uint32_t submeshCount)
+{
+ NV_UNUSED(asset);
+
+ uint32_t chunkCount = static_cast<uint32_t>(posIndex.size());
+ if (posIndex.size() != normIndex.size() || normIndex.size() != texIndex.size())
+ {
+ return false;
+ }
+
+ // export materials (mtl file)
+ {
+ std::ostringstream mtlFilePath;
+ mtlFilePath << outputPath << "\\" << name << ".mtl";
+ FILE* f = fopen(mtlFilePath.str().c_str(), "w");
+ if (!f)
+ return false;
+
+ for (uint32_t submeshIndex = 0; submeshIndex < submeshCount; ++submeshIndex)
+ {
+ fprintf(f, "newmtl mat%d\n", submeshIndex);
+ fprintf(f, "\tmap_Kd %s\n", texPathes[submeshIndex].data());
+ fprintf(f, "\n");
+ }
+
+ fclose(f);
+ }
+
+ /// Export geometry to *.obj file
+ {
+ std::ostringstream objFilePath;
+ objFilePath << outputPath << "\\" << name << ".obj";
+ FILE* f = fopen(objFilePath.str().c_str(), "w");
+ if (!f)
+ return false;
+
+ fprintf(f, "mtllib %s.mtl\n", name.c_str());
+ fprintf(f, "o frac \n");
+
+
+ /// Write compressed vertices
+ for (uint32_t i = 0; i < pos.size(); ++i)
+ {
+ fprintf(f, "v %.4f %.4f %.4f\n", pos[i].x, pos[i].y, pos[i].z);
+ }
+ for (uint32_t i = 0; i < norm.size(); ++i)
+ {
+ fprintf(f, "vn %.4f %.4f %.4f\n", norm[i].x, norm[i].y, norm[i].z);
+ }
+ for (uint32_t i = 0; i < uvs.size(); ++i)
+ {
+ fprintf(f, "vt %.4f %.4f\n", uvs[i].y, uvs[i].x);
+ }
+
+ for (uint32_t chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex)
+ {
+ for (uint32_t submeshIndex = 0; submeshIndex < posIndex[chunkIndex].size(); ++submeshIndex)
+ {
+ fprintf(f, "g %d_%d \n", chunkIndex, submeshIndex);
+ fprintf(f, "usemtl mat%d\n", submeshIndex);
+ uint32_t indexCount = static_cast<uint32_t>(posIndex[chunkIndex][submeshIndex].size());
+ const std::vector<int32_t>& pI = posIndex[chunkIndex][submeshIndex];
+ const std::vector<int32_t>& nI = normIndex[chunkIndex][submeshIndex];
+ const std::vector<int32_t>& tI = texIndex[chunkIndex][submeshIndex];
+
+ for (uint32_t i = 0; i < indexCount;)
+ {
+ fprintf(f, "f %d/%d/%d ", pI[i] + 1, tI[i] + 1, nI[i] + 1);
+ ++i;
+ fprintf(f, "%d/%d/%d ", pI[i] + 1, tI[i] + 1, nI[i] + 1);
+ ++i;
+ fprintf(f, "%d/%d/%d\n", pI[i] + 1, tI[i] + 1, nI[i] + 1);
+ ++i;
+ }
+ }
+ }
+ fclose(f);
+ }
+ return true;
+
+}
+
+bool ObjFileWriter::saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm, const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& indices)
+{
+ std::vector<std::string> matnames;
+ matnames.push_back("");
+ return saveToFile(asset, name, outputPath, pos, norm, uvs, indices, indices, indices, matnames, 1);
+} \ No newline at end of file
diff --git a/NvBlast/tools/common/ObjFileWriter.h b/NvBlast/tools/common/ObjFileWriter.h
new file mode 100644
index 0000000..547ba62
--- /dev/null
+++ b/NvBlast/tools/common/ObjFileWriter.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "IMeshFileWriter.h"
+#include <memory>
+
+struct NvBlastAsset;
+
+class ObjFileWriter : public IMeshFileWriter
+{
+public:
+
+ ObjFileWriter() {};
+ ~ObjFileWriter() = default;
+
+ virtual bool saveToFile(const NvBlastAsset* asset, std::vector<std::vector<Nv::Blast::Triangle>> chunksGeometry, std::string assetName, std::string outputPath) override;
+
+ virtual bool saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm,
+ const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& posIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& normIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& texIndex,
+ const std::vector<std::string>& texPathes,
+ const uint32_t submeshCount) override;
+
+ virtual bool saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm, const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& indices) override;
+};
diff --git a/NvBlast/tools/common/Utils.cpp b/NvBlast/tools/common/Utils.cpp
new file mode 100644
index 0000000..736159e
--- /dev/null
+++ b/NvBlast/tools/common/Utils.cpp
@@ -0,0 +1,166 @@
+#include "Utils.h"
+
+#include "Log.h"
+
+#include <string.h>
+
+#if PX_WINDOWS_FAMILY
+#include <direct.h>
+#define getCwd _getcwd
+#else
+#include <unistd.h>
+#define getCwd getcwd
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+
+namespace Nv
+{
+namespace Blast
+{
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void addSlashToPath(std::string& path)
+{
+ if (path[path.length() - 1] != '/' && path[path.length() - 1] != '\\')
+ {
+ path.append("/");
+ }
+}
+
+FileUtils::FileUtils()
+{
+ mSearchPaths.push_back("");
+ char currentPathTemp[FILENAME_MAX];
+ if (getCwd(currentPathTemp, sizeof(currentPathTemp)))
+ {
+ std::string currentPath(currentPathTemp);
+ addSlashToPath(currentPath);
+ addAbsolutePath(currentPath);
+ mCurrentPath = currentPath;
+ }
+}
+
+std::string FileUtils::getDirectory(const std::string& filePath)
+{
+ return filePath.substr(0, filePath.find_last_of("/\\") + 1);
+}
+
+std::string FileUtils::getFilename(const std::string& filePath, bool bWithExtension)
+{
+ size_t p0 = filePath.find_last_of("/\\") + 1;
+ if (bWithExtension)
+ {
+ return filePath.substr(p0);
+ }
+ else
+ {
+ return filePath.substr(p0, filePath.find_last_of(".") - p0);
+ }
+}
+
+std::string FileUtils::getFileExtension(const std::string& filePath)
+{
+ std::string filename = getFilename(filePath);
+ size_t p0 = filename.find_last_of(".");
+ if (p0 != std::string::npos)
+ return filePath.substr(p0);// + 1);
+ return "";
+}
+
+void FileUtils::addAbsolutePath(const std::string& path)
+{
+ if (path.empty())
+ {
+ return;
+ }
+
+ std::string newPath = path;
+ addSlashToPath(newPath);
+
+ mSearchPaths.push_back(newPath);
+}
+
+void FileUtils::addRelativePath(const std::string& relPath)
+{
+ addAbsolutePath(mCurrentPath + relPath);
+}
+
+void FileUtils::clearPaths()
+{
+ mSearchPaths.clear();
+}
+
+FILE* FileUtils::findFile(const std::string& path, bool bVerbose)
+{
+ FILE* file;
+ if (find(path, &file, NULL, bVerbose))
+ {
+ return file;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+std::string FileUtils::findPath(const std::string& path, bool bVerbose)
+{
+ std::string fullPath;
+ if (find(path, NULL, &fullPath, bVerbose))
+ {
+ return fullPath;
+ }
+ else
+ {
+ return path;
+ }
+}
+
+bool FileUtils::find(const std::string& path, FILE** ppFile, std::string* pFullPath, bool bVerbose)
+{
+ if (mSearchPaths.empty() || path.empty())
+ {
+ if (bVerbose)
+ {
+ lout() << Log::TYPE_ERROR << "Error: Invalid search path configuration.";
+ }
+ return false;
+ }
+
+ std::string fullPath;
+
+ FILE* file = NULL;
+ const uint32_t numSearchPaths = (uint32_t)mSearchPaths.size();
+ for (uint32_t i = 0; i < numSearchPaths; ++i)
+ {
+ fullPath = mSearchPaths[i] + path;
+ fopen_s(&file, fullPath.c_str(), "rb");
+ if (file)
+ {
+ break;
+ }
+ }
+
+ if (!file)
+ {
+ if (bVerbose)
+ lout() << Log::TYPE_ERROR << std::endl << "Error: Unable to find file " << path << std::endl;
+ return false;
+ }
+
+ if (ppFile)
+ *ppFile = file;
+ else
+ fclose(file);
+
+ if (pFullPath)
+ *pFullPath = fullPath;
+
+ return true;
+}
+
+
+} // namespace Blast
+} // namespace Nv
diff --git a/NvBlast/tools/common/Utils.h b/NvBlast/tools/common/Utils.h
new file mode 100644
index 0000000..26299e8
--- /dev/null
+++ b/NvBlast/tools/common/Utils.h
@@ -0,0 +1,113 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#include "PsString.h"
+
+#include <string>
+#include <iostream>
+#include <vector>
+#include <map>
+
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace Nv
+{
+namespace Blast
+{
+
+///////////////////////////////////////////////////////////////////////////
+
+template<class T>
+PX_INLINE bool isNull(const T* p) { return nullptr == p; }
+
+template<class Releasable, class Releaser> class ScopedResource;
+template<class Releasable, class Releaser>
+PX_INLINE bool isNull(const ScopedResource<Releasable,Releaser>& p) { return !p; }
+
+PX_INLINE bool isNullString(const char* pString)
+{
+ return (nullptr == pString || pString[0] == '\0' || physx::shdfnd::strcmp(pString, "null") == 0);
+}
+
+template<class T>
+PX_INLINE bool isValid(const T& p) { return !isNull(p.get()); }
+
+PX_INLINE bool isValidString(const char* pString) { return !isNullString(pString); }
+
+///////////////////////////////////////////////////////////////////////////
+
+// Note: This is not a thread safe singleton class
+template <class T>
+class Singleton
+{
+ // The fact that I cannot declare T a friend directly is rather absurd...
+ typedef T Type;
+ friend typename Singleton<T>::Type;
+
+ //////////////////////////////////////////////////////////////////////////////
+
+public:
+ static T& instance()
+ {
+ static T _instance;
+ return _instance;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+private:
+ Singleton() { }
+ ~Singleton() { };
+ Singleton(const Singleton&);
+ Singleton& operator=(const Singleton&);
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+class FileUtils : public Singleton<FileUtils>
+{
+ friend class Singleton<FileUtils>;
+
+public:
+ void addAbsolutePath(const std::string&);
+ void addRelativePath(const std::string&);
+ void clearPaths();
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ FILE* findFile(const std::string&, bool bVerbose = true);
+ std::string findPath(const std::string&, bool bVerbose = true);
+ bool find(const std::string&, FILE**, std::string*, bool bVerbose = true);
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ const std::string& getCurrentPath() const
+ {
+ return mCurrentPath;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ static std::string getDirectory(const std::string&);
+ static std::string getFilename(const std::string&, bool bWithExtension = true);
+ static std::string getFileExtension(const std::string&);
+
+ //////////////////////////////////////////////////////////////////////////////
+
+protected:
+ FileUtils();
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ std::string mCurrentPath;
+ std::vector<std::string> mSearchPaths;
+};
+
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif
diff --git a/NvBlast/tools/compiler/cmake/ApexImporter.cmake b/NvBlast/tools/compiler/cmake/ApexImporter.cmake
new file mode 100644
index 0000000..13a691e
--- /dev/null
+++ b/NvBlast/tools/compiler/cmake/ApexImporter.cmake
@@ -0,0 +1,82 @@
+#
+# Build ApexImporter common
+#
+
+SET(APEXIMPORTER_SOURCE_DIR ${PROJECT_SOURCE_DIR}/ApexImporter/src)
+SET(TOOLS_COMMON_DIR ${BLAST_ROOT_DIR}/tools/common)
+FIND_PACKAGE(PhysXSDK $ENV{PM_PhysX_VERSION} REQUIRED)
+FIND_PACKAGE(ApexSDK $ENV{PM_Apex_VERSION} REQUIRED)
+FIND_PACKAGE(PxSharedSDK $ENV{PM_PxShared_VERSION} REQUIRED)
+FIND_PACKAGE(tclap $ENV{PM_tclap_VERSION} REQUIRED)
+FIND_PACKAGE(FBXSDK $ENV{PM_FBXSDK_VERSION} REQUIRED)
+
+# Include here after the directories are defined so that the platform specific file can use the variables.
+include(${PROJECT_CMAKE_FILES_DIR}/${TARGET_BUILD_PLATFORM}/ApexImporter.cmake)
+
+SET(COMMON_FILES
+ ${APEXIMPORTER_PLATFORM_COMMON_FILES}
+
+ ${APEXIMPORTER_SOURCE_DIR}/Main.cpp
+ ${APEXIMPORTER_SOURCE_DIR}/ApexDestructibleObjExporter.cpp
+ ${APEXIMPORTER_SOURCE_DIR}/ApexDestructibleObjExporter.h
+ ${BLAST_ROOT_DIR}/tools/common/BlastDataExporter.cpp
+ ${BLAST_ROOT_DIR}/tools/common/BlastDataExporter.h
+ ${TOOLS_COMMON_DIR}/IMeshFileWriter.h
+ ${TOOLS_COMMON_DIR}/ObjFileWriter.h
+ ${TOOLS_COMMON_DIR}/ObjFileWriter.cpp
+ ${TOOLS_COMMON_DIR}/FbxFileWriter.h
+ ${TOOLS_COMMON_DIR}/FbxFileWriter.cpp
+ ${TOOLS_COMMON_DIR}/FbxUtils.h
+ ${TOOLS_COMMON_DIR}/FbxUtils.cpp
+)
+
+ADD_EXECUTABLE(ApexImporter
+ ${COMMON_FILES}
+)
+
+set_target_properties(ApexImporter
+ PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}
+ CHECKED_POSTFIX ${CMAKE_CHECKED_POSTFIX}
+ RELEASE_POSTFIX ${CMAKE_RELEASE_POSTFIX}
+ PROFILE_POSTFIX ${CMAKE_PROFILE_POSTFIX}
+)
+
+SOURCE_GROUP("src" FILES ${COMMON_FILES})
+
+# Target specific compile options
+
+TARGET_INCLUDE_DIRECTORIES(ApexImporter
+ PRIVATE ${APEXIMPORTER_PLATFORM_INCLUDES}
+
+ PRIVATE ${BLAST_ROOT_DIR}/sdk/common
+ PRIVATE ${TOOLS_COMMON_DIR}
+
+ PRIVATE ${PHYSXSDK_INCLUDE_DIRS}
+ PRIVATE ${APEXSDK_INCLUDE_DIRS}
+ PRIVATE ${PXSHAREDSDK_INCLUDE_DIRS}
+ PRIVATE ${TCLAP_INCLUDE_DIRS}
+ PRIVATE ${FBXSDK_INCLUDE_DIRS}
+)
+
+TARGET_COMPILE_DEFINITIONS(ApexImporter
+ PRIVATE ${APEXIMPORTER_COMPILE_DEFS}
+)
+
+SET_TARGET_PROPERTIES(ApexImporter PROPERTIES
+ COMPILE_PDB_NAME_DEBUG "ApexImporter${CMAKE_DEBUG_POSTFIX}"
+ COMPILE_PDB_NAME_CHECKED "ApexImporter${CMAKE_CHECKED_POSTFIX}"
+ COMPILE_PDB_NAME_PROFILE "ApexImporter${CMAKE_PROFILE_POSTFIX}"
+ COMPILE_PDB_NAME_RELEASE "ApexImporter${CMAKE_RELEASE_POSTFIX}"
+)
+
+# Do final direct sets after the target has been defined
+TARGET_LINK_LIBRARIES(ApexImporter
+ PRIVATE NvBlast NvBlastExtPhysX NvBlastExtAuthoring NvBlastExtImport Rpcrt4 $<$<OR:$<CONFIG:debug>,$<CONFIG:checked>,$<CONFIG:profile>>:${NVTOOLSEXT_LIB}>
+ PRIVATE ${FBXSDK_LIBRARIES}
+)
+
+ADD_CUSTOM_COMMAND(TARGET ApexImporter POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${APEXSDK_DLLS} ${PHYSXSDK_DLLS} ${PXSHAREDSDK_DLLS}
+ ${BL_EXE_OUTPUT_DIR}
+)
diff --git a/NvBlast/tools/compiler/cmake/AuthoringTool.cmake b/NvBlast/tools/compiler/cmake/AuthoringTool.cmake
new file mode 100644
index 0000000..3ba77d8
--- /dev/null
+++ b/NvBlast/tools/compiler/cmake/AuthoringTool.cmake
@@ -0,0 +1,98 @@
+#
+# Build AuthoringTool common
+#
+
+SET(AUTHORTINGTOOL_SOURCE_DIR ${PROJECT_SOURCE_DIR}/AuthoringTool/src)
+SET(TOOLS_COMMON_SOURCE_DIR ${PROJECT_SOURCE_DIR}/common)
+
+SET(EXT_AUTHORING_INCLUDE_DIR ${BLAST_ROOT_DIR}/sdk/extensions/authoring/include)
+SET(TK_INCLUDE_DIR ${BLAST_ROOT_DIR}/sdk/toolkit/include)
+
+FIND_PACKAGE(PhysXSDK $ENV{PM_PhysXSDK_VERSION} REQUIRED)
+FIND_PACKAGE(PxSharedSDK $ENV{PM_PxSharedSDK_VERSION} REQUIRED)
+FIND_PACKAGE(tclap $ENV{PM_tclap_VERSION} REQUIRED)
+FIND_PACKAGE(tinyObjLoader $ENV{PM_tinyObjLoader_VERSION} REQUIRED)
+FIND_PACKAGE(FBXSDK $ENV{PM_FBXSDK_VERSION} REQUIRED)
+
+
+# Include here after the directories are defined so that the platform specific file can use the variables.
+include(${PROJECT_CMAKE_FILES_DIR}/${TARGET_BUILD_PLATFORM}/AuthoringTool.cmake)
+
+SET(COMMON_FILES
+ ${AUTHORTINGTOOL_PLATFORM_COMMON_FILES}
+
+ ${AUTHORTINGTOOL_SOURCE_DIR}/AuthoringTool.cpp
+ ${TOOLS_COMMON_SOURCE_DIR}/IMeshFileReader.h
+ ${TOOLS_COMMON_SOURCE_DIR}/IMeshFileWriter.h
+ ${TOOLS_COMMON_SOURCE_DIR}/FbxFileReader.h
+ ${TOOLS_COMMON_SOURCE_DIR}/FbxFileReader.cpp
+ ${TOOLS_COMMON_SOURCE_DIR}/ObjFileReader.h
+ ${TOOLS_COMMON_SOURCE_DIR}/ObjFileReader.cpp
+ ${TOOLS_COMMON_SOURCE_DIR}/ObjFileWriter.h
+ ${TOOLS_COMMON_SOURCE_DIR}/ObjFileWriter.cpp
+ ${TOOLS_COMMON_SOURCE_DIR}/FbxFileWriter.h
+ ${TOOLS_COMMON_SOURCE_DIR}/FbxFileWriter.cpp
+ ${TOOLS_COMMON_SOURCE_DIR}/FbxUtils.h
+ ${TOOLS_COMMON_SOURCE_DIR}/FbxUtils.cpp
+ ${AUTHORTINGTOOL_SOURCE_DIR}/SimpleRandomGenerator.h
+ ${AUTHORTINGTOOL_SOURCE_DIR}/FractureProcessor.h
+ ${AUTHORTINGTOOL_SOURCE_DIR}/FractureProcessor.cpp
+ ${TOOLS_COMMON_SOURCE_DIR}/BlastDataExporter.h
+ ${TOOLS_COMMON_SOURCE_DIR}/BlastDataExporter.cpp
+)
+
+ADD_EXECUTABLE(AuthoringTool
+ ${COMMON_FILES}
+)
+
+set_target_properties(AuthoringTool
+ PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}
+ CHECKED_POSTFIX ${CMAKE_CHECKED_POSTFIX}
+ RELEASE_POSTFIX ${CMAKE_RELEASE_POSTFIX}
+ PROFILE_POSTFIX ${CMAKE_PROFILE_POSTFIX}
+)
+
+SOURCE_GROUP("src" FILES ${COMMON_FILES})
+
+# Target specific compile options
+
+TARGET_INCLUDE_DIRECTORIES(AuthoringTool
+ PRIVATE ${AUTHORTINGTOOL_PLATFORM_INCLUDES}
+
+ PRIVATE ${TOOLS_COMMON_SOURCE_DIR}
+ PRIVATE ${EXT_AUTHORING_INCLUDE_DIR}
+ PRIVATE ${TK_INCLUDE_DIR}
+ PRIVATE ${BLAST_ROOT_DIR}/sdk/common
+
+ PRIVATE ${PHYSXSDK_INCLUDE_DIRS}
+ PRIVATE ${PXSHAREDSDK_INCLUDE_DIRS}
+ PRIVATE ${TCLAP_INCLUDE_DIRS}
+ PRIVATE ${TINYOBJLOADER_INCLUDE_DIRS}
+ PRIVATE ${FBXSDK_INCLUDE_DIRS}
+)
+
+TARGET_COMPILE_DEFINITIONS(AuthoringTool
+ PRIVATE ${AUTHORTINGTOOL_COMPILE_DEFS}
+)
+
+SET_TARGET_PROPERTIES(AuthoringTool PROPERTIES
+ PDB_NAME_DEBUG "AuthoringTool${CMAKE_DEBUG_POSTFIX}"
+ PDB_NAME_CHECKED "AuthoringTool${CMAKE_CHECKED_POSTFIX}"
+ PDB_NAME_PROFILE "AuthoringTool${CMAKE_PROFILE_POSTFIX}"
+ PDB_NAME_RELEASE "AuthoringTool${CMAKE_RELEASE_POSTFIX}"
+)
+
+# Do final direct sets after the target has been defined
+TARGET_LINK_LIBRARIES(AuthoringTool
+ PRIVATE NvBlast NvBlastTk NvBlastExtSerialization NvBlastExtPhysX NvBlastExtAuthoring
+ PRIVATE ${FBXSDK_LIBRARIES}
+)
+
+# Copy the dlls from the deps
+
+ADD_CUSTOM_COMMAND(TARGET AuthoringTool POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${APEXSDK_DLLS} ${PHYSXSDK_DLLS} ${PXSHAREDSDK_DLLS}
+ ${BL_EXE_OUTPUT_DIR}
+)
+
diff --git a/NvBlast/tools/compiler/cmake/DataConverter.cmake b/NvBlast/tools/compiler/cmake/DataConverter.cmake
new file mode 100644
index 0000000..3239f61
--- /dev/null
+++ b/NvBlast/tools/compiler/cmake/DataConverter.cmake
@@ -0,0 +1,60 @@
+#
+# Build DataConverter common
+#
+
+SET(DATACONVERTER_SOURCE_DIR ${PROJECT_SOURCE_DIR}/DataConverter/src)
+
+FIND_PACKAGE(tclap $ENV{PM_tclap_VERSION} REQUIRED)
+
+# Include here after the directories are defined so that the platform specific file can use the variables.
+include(${PROJECT_CMAKE_FILES_DIR}/${TARGET_BUILD_PLATFORM}/DataConverter.cmake)
+
+SET(COMMON_FILES
+ ${DATACONVERTER_PLATFORM_COMMON_FILES}
+
+ ${DATACONVERTER_SOURCE_DIR}/Main.cpp
+)
+
+ADD_EXECUTABLE(DataConverter
+ ${COMMON_FILES}
+)
+
+set_target_properties(DataConverter
+ PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}
+ CHECKED_POSTFIX ${CMAKE_CHECKED_POSTFIX}
+ RELEASE_POSTFIX ${CMAKE_RELEASE_POSTFIX}
+ PROFILE_POSTFIX ${CMAKE_PROFILE_POSTFIX}
+)
+
+
+SOURCE_GROUP("src" FILES ${COMMON_FILES})
+
+# Target specific compile options
+
+TARGET_INCLUDE_DIRECTORIES(DataConverter
+ PRIVATE ${DATACONVERTER_PLATFORM_INCLUDES}
+ PRIVATE ${BLAST_ROOT_DIR}/source/common
+
+ PRIVATE ${TCLAP_INCLUDE_DIRS}
+)
+
+TARGET_COMPILE_DEFINITIONS(DataConverter
+ PRIVATE ${DATACONVERTER_COMPILE_DEFS}
+)
+
+SET_TARGET_PROPERTIES(DataConverter PROPERTIES
+ PDB_NAME_DEBUG "DataConverter${CMAKE_DEBUG_POSTFIX}"
+ PDB_NAME_CHECKED "DataConverter${CMAKE_CHECKED_POSTFIX}"
+ PDB_NAME_PROFILE "DataConverter${CMAKE_PROFILE_POSTFIX}"
+ PDB_NAME_RELEASE "DataConverter${CMAKE_RELEASE_POSTFIX}"
+)
+
+# Do final direct sets after the target has been defined
+TARGET_LINK_LIBRARIES(DataConverter NvBlast NvBlastExtConverterLL)
+
+
+ADD_CUSTOM_COMMAND(TARGET DataConverter POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${PHYSXSDK_DLLS} ${PXSHAREDSDK_DLLS}
+ ${BL_EXE_OUTPUT_DIR}
+)
diff --git a/NvBlast/tools/compiler/cmake/Windows/ApexImporter.cmake b/NvBlast/tools/compiler/cmake/Windows/ApexImporter.cmake
new file mode 100644
index 0000000..f6ad72b
--- /dev/null
+++ b/NvBlast/tools/compiler/cmake/Windows/ApexImporter.cmake
@@ -0,0 +1,22 @@
+#
+# Build ApexImporter Windows
+#
+
+SET(APEXIMPORTER_PLATFORM_COMMON_FILES
+)
+
+SET(APEXIMPORTER_PLATFORM_INCLUDES
+)
+
+SET(APEXIMPORTER_COMPILE_DEFS
+ # Common to all configurations
+ ${BLASTTOOLS_SLN_COMPILE_DEFS};_CONSOLE
+
+ $<$<CONFIG:debug>:${BLASTTOOLS_SLN_DEBUG_COMPILE_DEFS}>
+ $<$<CONFIG:checked>:${BLASTTOOLS_SLN_CHECKED_COMPILE_DEFS}>
+ $<$<CONFIG:profile>:${BLASTTOOLS_SLN_PROFILE_COMPILE_DEFS}>
+ $<$<CONFIG:release>:${BLASTTOOLS_SLN_RELEASE_COMPILE_DEFS}>
+)
+
+#TARGET_LINK_LIBRARIES(NvBlast PUBLIC ${NVTOOLSEXT_LIBRARIES})
+#SET_TARGET_PROPERTIES(NvBlast PROPERTIES LINK_FLAGS "/MAP" )
diff --git a/NvBlast/tools/compiler/cmake/Windows/AuthoringTool.cmake b/NvBlast/tools/compiler/cmake/Windows/AuthoringTool.cmake
new file mode 100644
index 0000000..f981c1f
--- /dev/null
+++ b/NvBlast/tools/compiler/cmake/Windows/AuthoringTool.cmake
@@ -0,0 +1,22 @@
+#
+# Build AuthoringTool Windows
+#
+
+SET(AUTHORTINGTOOL_PLATFORM_COMMON_FILES
+)
+
+SET(AUTHORTINGTOOL_PLATFORM_INCLUDES
+)
+
+SET(AUTHORTINGTOOL_COMPILE_DEFS
+ # Common to all configurations
+ ${BLASTTOOLS_SLN_COMPILE_DEFS};_CONSOLE
+
+ $<$<CONFIG:debug>:${BLASTTOOLS_SLN_DEBUG_COMPILE_DEFS}>
+ $<$<CONFIG:checked>:${BLASTTOOLS_SLN_CHECKED_COMPILE_DEFS}>
+ $<$<CONFIG:profile>:${BLASTTOOLS_SLN_PROFILE_COMPILE_DEFS}>
+ $<$<CONFIG:release>:${BLASTTOOLS_SLN_RELEASE_COMPILE_DEFS}>
+)
+
+#TARGET_LINK_LIBRARIES(NvBlast PUBLIC ${NVTOOLSEXT_LIBRARIES})
+#SET_TARGET_PROPERTIES(NvBlast PROPERTIES LINK_FLAGS "/MAP" )
diff --git a/NvBlast/tools/compiler/cmake/Windows/CMakeLists.txt b/NvBlast/tools/compiler/cmake/Windows/CMakeLists.txt
new file mode 100644
index 0000000..541a209
--- /dev/null
+++ b/NvBlast/tools/compiler/cmake/Windows/CMakeLists.txt
@@ -0,0 +1,58 @@
+#Platform specific compile flags and project includes
+
+SET(CMAKE_CXX_FLAGS "/EHsc /GR- /GF /MP /Gy /d2Zi+ /errorReport:prompt /fp:fast /Gd /Gm- /GS- /nologo /W4 /WX /Zc:forScope /Zc:inline /Zc:wchar_t /Zi")
+
+# Are we using the static or dynamic RT library? Whatever we use, it needs to be the same in any dependencies
+# we pull in or we're potentially having mismatch issues.
+IF(STATIC_WINCRT)
+ SET(WINCRT_NDEBUG "/MT")
+ SET(WINCRT_DEBUG "/MTd")
+ELSE()
+ SET(WINCRT_NDEBUG "/MD")
+ SET(WINCRT_DEBUG "/MDd")
+ENDIF()
+
+SET(CMAKE_CXX_FLAGS_DEBUG "/Od /RTCsu ${WINCRT_DEBUG}")
+SET(CMAKE_CXX_FLAGS_CHECKED "/Ox ${WINCRT_NDEBUG}")
+SET(CMAKE_CXX_FLAGS_PROFILE "/Ox ${WINCRT_NDEBUG}")
+SET(CMAKE_CXX_FLAGS_RELEASE "/Ox ${WINCRT_NDEBUG}")
+
+# Build PDBs for all configurations
+SET(CMAKE_SHARED_LINKER_FLAGS "/DEBUG")
+
+IF(CMAKE_CL_64)
+ ADD_DEFINITIONS(-DWIN64)
+ENDIF(CMAKE_CL_64)
+
+SET(BLASTTOOLS_SLN_COMPILE_DEFS WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;)
+
+SET(BLASTTOOLS_SLN_DEBUG_COMPILE_DEFS _DEBUG;NV_DEBUG=1;)
+SET(BLASTTOOLS_SLN_CHECKED_COMPILE_DEFS NDEBUG;NV_CHECKED=1;)
+SET(BLASTTOOLS_SLN_PROFILE_COMPILE_DEFS NDEBUG;NV_PROFILE=1;)
+SET(BLASTTOOLS_SLN_RELEASE_COMPILE_DEFS NDEBUG;)
+
+IF(CMAKE_CL_64)
+ SET(LIBPATH_SUFFIX "x64")
+ELSE(CMAKE_CL_64)
+ SET(LIBPATH_SUFFIX "x86")
+ENDIF(CMAKE_CL_64)
+
+SET(CMAKE_DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}_${LIBPATH_SUFFIX}")
+SET(CMAKE_PROFILE_POSTFIX "${CMAKE_PROFILE_POSTFIX}_${LIBPATH_SUFFIX}")
+SET(CMAKE_CHECKED_POSTFIX "${CMAKE_CHECKED_POSTFIX}_${LIBPATH_SUFFIX}")
+SET(CMAKE_RELEASE_POSTFIX "${CMAKE_RELEASE_POSTFIX}_${LIBPATH_SUFFIX}")
+
+# Should this be here or in the common part?
+#ADD_SUBDIRECTORY(${BLAST_ROOT_DIR}/sdk "${CMAKE_CURRENT_BINARY_DIR}/blast_bin")
+
+
+# Include all of the projects
+INCLUDE(${PROJECT_CMAKE_FILES_DIR}/ApexImporter.cmake)
+INCLUDE(${PROJECT_CMAKE_FILES_DIR}/DataConverter.cmake)
+
+# Exclude AuthoringTool because VC12 can't handle Capn Proto.
+if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.0.0.0)
+ INCLUDE(${PROJECT_CMAKE_FILES_DIR}/AuthoringTool.cmake)
+else()
+ SET(SERIALIZATION_INCLUDED 0)
+endif()
diff --git a/NvBlast/tools/compiler/cmake/Windows/DataConverter.cmake b/NvBlast/tools/compiler/cmake/Windows/DataConverter.cmake
new file mode 100644
index 0000000..a0c5316
--- /dev/null
+++ b/NvBlast/tools/compiler/cmake/Windows/DataConverter.cmake
@@ -0,0 +1,22 @@
+#
+# Build DataConverter Windows
+#
+
+SET(DATACONVERTER_PLATFORM_COMMON_FILES
+)
+
+SET(DATACONVERTER_PLATFORM_INCLUDES
+)
+
+SET(DATACONVERTER_COMPILE_DEFS
+ # Common to all configurations
+ ${BLASTTOOLS_SLN_COMPILE_DEFS};_CONSOLE
+
+ $<$<CONFIG:debug>:${BLASTTOOLS_SLN_DEBUG_COMPILE_DEFS}>
+ $<$<CONFIG:checked>:${BLASTTOOLS_SLN_CHECKED_COMPILE_DEFS}>
+ $<$<CONFIG:profile>:${BLASTTOOLS_SLN_PROFILE_COMPILE_DEFS}>
+ $<$<CONFIG:release>:${BLASTTOOLS_SLN_RELEASE_COMPILE_DEFS}>
+)
+
+#TARGET_LINK_LIBRARIES(NvBlast PUBLIC ${NVTOOLSEXT_LIBRARIES})
+#SET_TARGET_PROPERTIES(NvBlast PROPERTIES LINK_FLAGS "/MAP" )