diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs
index 5cada5d87..d3e71b474 100644
--- a/Source/Editor/Editor.cs
+++ b/Source/Editor/Editor.cs
@@ -755,7 +755,7 @@ namespace FlaxEditor
/// The convex mesh generation flags.
/// The convex mesh vertex limit. Use values in range [8;255]
/// True if failed, otherwise false.
- public static bool CookMeshCollision(string path, CollisionDataType type, Model model, int modelLodIndex = 0, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags.None, int convexVertexLimit = 255)
+ public static bool CookMeshCollision(string path, CollisionDataType type, ModelBase model, int modelLodIndex = 0, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags.None, int convexVertexLimit = 255)
{
if (string.IsNullOrEmpty(path))
throw new ArgumentNullException(nameof(path));
diff --git a/Source/Editor/Managed/ManagedEditor.Internal.cpp b/Source/Editor/Managed/ManagedEditor.Internal.cpp
index 7b178b956..f56d8f3e6 100644
--- a/Source/Editor/Managed/ManagedEditor.Internal.cpp
+++ b/Source/Editor/Managed/ManagedEditor.Internal.cpp
@@ -715,7 +715,7 @@ public:
return str;
}
- static bool CookMeshCollision(MonoString* pathObj, CollisionDataType type, Model* modelObj, int32 modelLodIndex, ConvexMeshGenerationFlags convexFlags, int32 convexVertexLimit)
+ static bool CookMeshCollision(MonoString* pathObj, CollisionDataType type, ModelBase* modelObj, int32 modelLodIndex, ConvexMeshGenerationFlags convexFlags, int32 convexVertexLimit)
{
#if COMPILE_WITH_PHYSICS_COOKING
CollisionCooking::Argument arg;
@@ -727,7 +727,6 @@ public:
arg.ModelLodIndex = modelLodIndex;
arg.ConvexFlags = convexFlags;
arg.ConvexVertexLimit = convexVertexLimit;
-
return CreateCollisionData::CookMeshCollision(path, arg);
#else
LOG(Warning, "Collision cooking is disabled.");
diff --git a/Source/Editor/Viewport/Previews/ModelBasePreview.cs b/Source/Editor/Viewport/Previews/ModelBasePreview.cs
new file mode 100644
index 000000000..59ed5f318
--- /dev/null
+++ b/Source/Editor/Viewport/Previews/ModelBasePreview.cs
@@ -0,0 +1,122 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using FlaxEditor.GUI.Input;
+using FlaxEngine;
+using Object = FlaxEngine.Object;
+
+namespace FlaxEditor.Viewport.Previews
+{
+ ///
+ /// Model Base asset preview editor viewport.
+ ///
+ ///
+ public class ModelBasePreview : AssetPreview
+ {
+ ///
+ /// Gets or sets the model asset to preview.
+ ///
+ public ModelBase Asset
+ {
+ get => (ModelBase)StaticModel.Model ?? AnimatedModel.SkinnedModel;
+ set
+ {
+ StaticModel.Model = value as Model;
+ AnimatedModel.SkinnedModel = value as SkinnedModel;
+ }
+ }
+
+ ///
+ /// The static model for display.
+ ///
+ public StaticModel StaticModel;
+
+ ///
+ /// The animated model for display.
+ ///
+ public AnimatedModel AnimatedModel;
+
+ ///
+ /// Gets or sets a value indicating whether scale the model to the normalized bounds.
+ ///
+ public bool ScaleToFit { get; set; } = true;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// if set to true use widgets.
+ public ModelBasePreview(bool useWidgets)
+ : base(useWidgets)
+ {
+ Task.Begin += OnBegin;
+
+ // Setup preview scene
+ StaticModel = new StaticModel();
+ AnimatedModel = new AnimatedModel();
+
+ // Link actors for rendering
+ Task.AddCustomActor(StaticModel);
+ Task.AddCustomActor(AnimatedModel);
+
+ if (useWidgets)
+ {
+ // Preview LOD
+ {
+ var previewLOD = ViewWidgetButtonMenu.AddButton("Preview LOD");
+ var previewLODValue = new IntValueBox(-1, 90, 2, 70.0f, -1, 10, 0.02f)
+ {
+ Parent = previewLOD
+ };
+ previewLODValue.ValueChanged += () =>
+ {
+ StaticModel.ForcedLOD = previewLODValue.Value;
+ AnimatedModel.ForcedLOD = previewLODValue.Value;
+ };
+ ViewWidgetButtonMenu.VisibleChanged += control => previewLODValue.Value = StaticModel.ForcedLOD;
+ }
+ }
+ }
+
+ private void OnBegin(RenderTask task, GPUContext context)
+ {
+ var position = Vector3.Zero;
+ var scale = Vector3.One;
+
+ // Update preview model scale to fit the preview
+ var model = Asset;
+ if (ScaleToFit && model && model.IsLoaded)
+ {
+ float targetSize = 50.0f;
+ BoundingBox box = model is Model ? ((Model)model).GetBox() : ((SkinnedModel)model).GetBox();
+ float maxSize = Mathf.Max(0.001f, box.Size.MaxValue);
+ scale = new Vector3(targetSize / maxSize);
+ position = box.Center * (-0.5f * scale.X) + new Vector3(0, -10, 0);
+ }
+
+ StaticModel.Transform = new Transform(position, StaticModel.Orientation, scale);
+ AnimatedModel.Transform = new Transform(position, AnimatedModel.Orientation, scale);
+ }
+
+ ///
+ public override bool OnKeyDown(KeyboardKeys key)
+ {
+ switch (key)
+ {
+ case KeyboardKeys.F:
+ // Pay respect..
+ ViewportCamera.SetArcBallView(StaticModel.Model != null ? StaticModel.Box : AnimatedModel.Box);
+ break;
+ }
+ return base.OnKeyDown(key);
+ }
+
+ ///
+ public override void OnDestroy()
+ {
+ // Ensure to cleanup created actor objects
+ Object.Destroy(ref StaticModel);
+ Object.Destroy(ref AnimatedModel);
+
+ base.OnDestroy();
+ }
+ }
+}
diff --git a/Source/Editor/Windows/Assets/CollisionDataWindow.cs b/Source/Editor/Windows/Assets/CollisionDataWindow.cs
index 23f9ae5ed..9191283dc 100644
--- a/Source/Editor/Windows/Assets/CollisionDataWindow.cs
+++ b/Source/Editor/Windows/Assets/CollisionDataWindow.cs
@@ -34,7 +34,7 @@ namespace FlaxEditor.Windows.Assets
public CollisionDataType Type;
[EditorOrder(10), EditorDisplay("General"), Tooltip("Source model asset to use for collision data generation")]
- public Model Model;
+ public ModelBase Model;
[EditorOrder(20), Limit(0, 5), EditorDisplay("General", "Model LOD Index"), Tooltip("Source model LOD index to use for collision data generation (will be clamped to the actual model LODs collection size)")]
public int ModelLodIndex;
@@ -90,12 +90,12 @@ namespace FlaxEditor.Windows.Assets
{
private PropertiesProxy Proxy;
private CollisionDataType Type;
- private Model Model;
+ private ModelBase Model;
private int ModelLodIndex;
private ConvexMeshGenerationFlags ConvexFlags;
private int ConvexVertexLimit;
- public CookData(PropertiesProxy proxy, string resultUrl, CollisionDataType type, Model model, int modelLodIndex, ConvexMeshGenerationFlags convexFlags, int convexVertexLimit)
+ public CookData(PropertiesProxy proxy, string resultUrl, CollisionDataType type, ModelBase model, int modelLodIndex, ConvexMeshGenerationFlags convexFlags, int convexVertexLimit)
: base("Collision Data", resultUrl)
{
Proxy = proxy;
@@ -135,7 +135,7 @@ namespace FlaxEditor.Windows.Assets
Type = options.Type;
if (Type == CollisionDataType.None)
Type = CollisionDataType.ConvexMesh;
- Model = FlaxEngine.Content.LoadAsync(options.Model);
+ Model = FlaxEngine.Content.LoadAsync(options.Model);
ModelLodIndex = options.ModelLodIndex;
ConvexFlags = options.ConvexFlags;
ConvexVertexLimit = options.ConvexVertexLimit;
@@ -151,7 +151,7 @@ namespace FlaxEditor.Windows.Assets
}
private readonly SplitPanel _split;
- private readonly ModelPreview _preview;
+ private readonly ModelBasePreview _preview;
private readonly CustomEditorPresenter _propertiesPresenter;
private readonly PropertiesProxy _properties;
private Model _collisionWiresModel;
@@ -176,7 +176,7 @@ namespace FlaxEditor.Windows.Assets
};
// Model preview
- _preview = new ModelPreview(true)
+ _preview = new ModelBasePreview(true)
{
ViewportCamera = new FPSCamera(),
Parent = _split.Panel1
@@ -195,7 +195,7 @@ namespace FlaxEditor.Windows.Assets
// Sync helper actor size with actual preview model (preview scales model for better usage experience)
if (_collisionWiresShowActor && _collisionWiresShowActor.IsActive)
{
- _collisionWiresShowActor.Transform = _preview.PreviewActor.Transform;
+ _collisionWiresShowActor.Transform = _preview.StaticModel.Transform;
}
base.Update(deltaTime);
@@ -230,14 +230,14 @@ namespace FlaxEditor.Windows.Assets
}
_collisionWiresShowActor.Model = _collisionWiresModel;
_collisionWiresShowActor.SetMaterial(0, FlaxEngine.Content.LoadAsyncInternal(EditorAssets.WiresDebugMaterial));
- _preview.Model = FlaxEngine.Content.LoadAsync(_asset.Options.Model);
+ _preview.Asset = FlaxEngine.Content.LoadAsync(_asset.Options.Model);
}
///
protected override void UnlinkItem()
{
_properties.OnClean();
- _preview.Model = null;
+ _preview.Asset = null;
base.UnlinkItem();
}
@@ -245,7 +245,7 @@ namespace FlaxEditor.Windows.Assets
///
protected override void OnAssetLinked()
{
- _preview.Model = null;
+ _preview.Asset = null;
base.OnAssetLinked();
}
diff --git a/Source/Engine/Physics/CollisionCooking.cpp b/Source/Engine/Physics/CollisionCooking.cpp
index 9076d979e..0cb8fa7a9 100644
--- a/Source/Engine/Physics/CollisionCooking.cpp
+++ b/Source/Engine/Physics/CollisionCooking.cpp
@@ -5,6 +5,7 @@
#include "CollisionCooking.h"
#include "Engine/Threading/Task.h"
#include "Engine/Graphics/Async/GPUTask.h"
+#include "Engine/Graphics/Models/MeshBase.h"
#include "Engine/Core/Log.h"
#include "Physics.h"
#include
@@ -186,14 +187,15 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
}
// Pick a proper model LOD
- const int32 lodIndex = Math::Clamp(arg.ModelLodIndex, 0, arg.Model->LODs.Count());
- auto lod = &arg.Model->LODs[lodIndex];
+ const int32 lodIndex = Math::Clamp(arg.ModelLodIndex, 0, arg.Model->GetLODsCount());
+ Array meshes;
+ arg.Model->GetMeshes(meshes, lodIndex);
// Download model LOD data from the GPU.
// It's easier than reading internal, versioned mesh storage format.
// Also it works with virtual assets that have no dedicated storage.
// Note: request all meshes data at once and wait for the tasks to be done.
- const int32 meshesCount = lod->Meshes.Count();
+ const int32 meshesCount = meshes.Count();
Array vertexBuffers;
Array indexBuffers;
vertexBuffers.Resize(meshesCount);
@@ -205,9 +207,9 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
Array tasks(meshesCount + meshesCount);
for (int32 i = 0; i < meshesCount; i++)
{
- const auto& mesh = lod->Meshes[i];
+ const auto& mesh = *meshes[i];
- auto task = mesh.ExtractDataAsync(MeshBufferType::Vertex0, vertexBuffers[i]);
+ auto task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex0, vertexBuffers[i]);
if (task == nullptr)
return true;
task->Start();
@@ -216,7 +218,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
if (needIndexBuffer)
{
- task = mesh.ExtractDataAsync(MeshBufferType::Index, indexBuffers[i]);
+ task = mesh.DownloadDataGPUAsync(MeshBufferType::Index, indexBuffers[i]);
if (task == nullptr)
return true;
task->Start();
@@ -236,7 +238,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
int32 vertexCounter = 0, indexCounter = 0;
for (int32 i = 0; i < meshesCount; i++)
{
- const auto& mesh = lod->Meshes[i];
+ const auto& mesh = *meshes[i];
const auto& vData = vertexBuffers[i];
const int32 firstVertexIndex = vertexCounter;
@@ -251,7 +253,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
if (mesh.Use16BitIndexBuffer())
{
auto dst = finalIndexData.Get() + indexCounter;
- auto src = (uint16*)iData.Get();
+ auto src = iData.Get();
for (int32 j = 0; j < indexCount; j++)
{
*dst++ = firstVertexIndex + *src++;
@@ -261,7 +263,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
else
{
auto dst = finalIndexData.Get() + indexCounter;
- auto src = (uint32*)iData.Get();
+ auto src = iData.Get();
for (int32 j = 0; j < indexCount; j++)
{
*dst++ = firstVertexIndex + *src++;
diff --git a/Source/Engine/Physics/CollisionCooking.h b/Source/Engine/Physics/CollisionCooking.h
index 658f88428..57ef98922 100644
--- a/Source/Engine/Physics/CollisionCooking.h
+++ b/Source/Engine/Physics/CollisionCooking.h
@@ -7,7 +7,7 @@
#include "Engine/Core/Types/DataContainer.h"
#include "Engine/Physics/CollisionData.h"
#include "Engine/Graphics/Models/ModelData.h"
-#include "Engine/Content/Assets/Model.h"
+#include "Engine/Content/Assets/ModelBase.h"
namespace physx
{
@@ -40,7 +40,7 @@ public:
{
CollisionDataType Type = CollisionDataType::None;
ModelData* OverrideModelData = nullptr;
- AssetReference Model;
+ AssetReference Model;
int32 ModelLodIndex = 0;
ConvexMeshGenerationFlags ConvexFlags = ConvexMeshGenerationFlags::None;
int32 ConvexVertexLimit = 255;
diff --git a/Source/Engine/Physics/CollisionData.cpp b/Source/Engine/Physics/CollisionData.cpp
index 8de5bfcaa..8ab4049d4 100644
--- a/Source/Engine/Physics/CollisionData.cpp
+++ b/Source/Engine/Physics/CollisionData.cpp
@@ -23,7 +23,7 @@ CollisionData::CollisionData(const SpawnParams& params, const AssetInfo* info)
#if COMPILE_WITH_PHYSICS_COOKING
-bool CollisionData::CookCollision(CollisionDataType type, Model* modelObj, int32 modelLodIndex, ConvexMeshGenerationFlags convexFlags, int32 convexVertexLimit)
+bool CollisionData::CookCollision(CollisionDataType type, ModelBase* modelObj, int32 modelLodIndex, ConvexMeshGenerationFlags convexFlags, int32 convexVertexLimit)
{
// Validate state
if (!IsVirtual())
diff --git a/Source/Engine/Physics/CollisionData.h b/Source/Engine/Physics/CollisionData.h
index d3621f8d9..9a8d67b0b 100644
--- a/Source/Engine/Physics/CollisionData.h
+++ b/Source/Engine/Physics/CollisionData.h
@@ -4,11 +4,17 @@
#include "Engine/Content/BinaryAsset.h"
#include "Engine/Core/Math/BoundingBox.h"
-#include "Engine/Physics/Types.h"
class Model;
+class ModelBase;
class ModelData;
+namespace physx
+{
+ class PxConvexMesh;
+ class PxTriangleMesh;
+}
+
///
/// A storage data type.
///
@@ -156,8 +162,8 @@ public:
private:
CollisionDataOptions _options;
- PxConvexMesh* _convexMesh;
- PxTriangleMesh* _triangleMesh;
+ physx::PxConvexMesh* _convexMesh;
+ physx::PxTriangleMesh* _triangleMesh;
public:
@@ -173,8 +179,7 @@ public:
///
/// Gets the convex mesh object (valid only if asset is loaded and has cooked convex data).
///
- /// The convex mesh
- FORCE_INLINE PxConvexMesh* GetConvex() const
+ FORCE_INLINE physx::PxConvexMesh* GetConvex() const
{
return _convexMesh;
}
@@ -182,8 +187,7 @@ public:
///
/// Gets the triangle mesh object (valid only if asset is loaded and has cooked triangle data).
///
- /// The triangle mesh
- FORCE_INLINE PxTriangleMesh* GetTriangle() const
+ FORCE_INLINE physx::PxTriangleMesh* GetTriangle() const
{
return _triangleMesh;
}
@@ -203,7 +207,7 @@ public:
/// The source model LOD index.
/// The convex mesh generation flags.
/// The convex mesh vertex limit. Use values in range [8;255]
- API_FUNCTION() bool CookCollision(CollisionDataType type, Model* model, int32 modelLodIndex = 0, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags::None, int32 convexVertexLimit = 255);
+ API_FUNCTION() bool CookCollision(CollisionDataType type, ModelBase* model, int32 modelLodIndex = 0, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags::None, int32 convexVertexLimit = 255);
///
/// Cooks the mesh collision data and updates the virtual asset. action cannot be performed on a main thread.