diff --git a/Source/Editor/Content/Import/ModelImportEntry.cs b/Source/Editor/Content/Import/ModelImportEntry.cs
index 58e438c46..23a15157a 100644
--- a/Source/Editor/Content/Import/ModelImportEntry.cs
+++ b/Source/Editor/Content/Import/ModelImportEntry.cs
@@ -163,6 +163,12 @@ namespace FlaxEditor.Content.Import
[EditorOrder(90), DefaultValue(ModelLightmapUVsSource.Disable), EditorDisplay("Geometry", "Lightmap UVs Source"), Tooltip("Model lightmap UVs source")]
public ModelLightmapUVsSource LightmapUVsSource { get; set; } = ModelLightmapUVsSource.Disable;
+ ///
+ /// If specified, all meshes which name starts with this prefix will be imported as a separate collision data (excluded used for rendering).
+ ///
+ [EditorOrder(100), DefaultValue(""), EditorDisplay("Geometry")]
+ public string CollisionMeshesPrefix { get; set; }
+
///
/// Custom uniform import scale.
///
@@ -284,7 +290,7 @@ namespace FlaxEditor.Content.Import
///
[EditorOrder(420), DefaultValue(true), EditorDisplay("Materials", "Restore Materials On Reimport"), Tooltip("If checked, the importer will try to restore the assigned materials to the model slots.")]
public bool RestoreMaterialsOnReimport { get; set; } = true;
-
+
///
/// If checked, the imported mesh/animations are splitted into separate assets. Used if ObjectIndex is set to -1.
///
@@ -314,6 +320,7 @@ namespace FlaxEditor.Content.Import
public byte ImportVertexColors;
public byte ImportBlendShapes;
public ModelLightmapUVsSource LightmapUVsSource;
+ public string CollisionMeshesPrefix;
// Transform
public float Scale;
@@ -364,6 +371,7 @@ namespace FlaxEditor.Content.Import
ImportVertexColors = (byte)(ImportVertexColors ? 1 : 0),
ImportBlendShapes = (byte)(ImportBlendShapes ? 1 : 0),
LightmapUVsSource = LightmapUVsSource,
+ CollisionMeshesPrefix = CollisionMeshesPrefix,
Scale = Scale,
Rotation = Rotation,
Translation = Translation,
@@ -403,6 +411,7 @@ namespace FlaxEditor.Content.Import
ImportVertexColors = options.ImportVertexColors != 0;
ImportBlendShapes = options.ImportBlendShapes != 0;
LightmapUVsSource = options.LightmapUVsSource;
+ CollisionMeshesPrefix = options.CollisionMeshesPrefix;
Scale = options.Scale;
Rotation = options.Rotation;
Translation = options.Translation;
diff --git a/Source/Editor/Content/Proxy/CollisionDataProxy.cs b/Source/Editor/Content/Proxy/CollisionDataProxy.cs
index da82f73c5..c07873189 100644
--- a/Source/Editor/Content/Proxy/CollisionDataProxy.cs
+++ b/Source/Editor/Content/Proxy/CollisionDataProxy.cs
@@ -86,6 +86,7 @@ namespace FlaxEditor.Content
{
foreach (var child in modelItem.ParentFolder.Children)
{
+ // Check if there is collision that was made with this model
if (child is BinaryAssetItem b && b.IsOfType())
{
var collisionData = FlaxEngine.Content.Load(b.ID);
@@ -97,6 +98,25 @@ namespace FlaxEditor.Content
return;
}
}
+
+ // Check if there is a auto-imported collision
+ if (child is ContentFolder childFolder && childFolder.ShortName == modelItem.ShortName)
+ {
+ foreach (var childFolderChild in childFolder.Children)
+ {
+ if (childFolderChild is BinaryAssetItem c && c.IsOfType())
+ {
+ var collisionData = FlaxEngine.Content.Load(c.ID);
+ if (collisionData && collisionData.Options.Model == model.ID || collisionData.Options.Model == Guid.Empty)
+ {
+ Editor.Instance.Windows.ContentWin.Select(c);
+ if (created != null)
+ FlaxEngine.Scripting.InvokeOnUpdate(() => created(collisionData));
+ return;
+ }
+ }
+ }
+ }
}
}
diff --git a/Source/Editor/Managed/ManagedEditor.Internal.cpp b/Source/Editor/Managed/ManagedEditor.Internal.cpp
index da04854ec..b02267647 100644
--- a/Source/Editor/Managed/ManagedEditor.Internal.cpp
+++ b/Source/Editor/Managed/ManagedEditor.Internal.cpp
@@ -166,6 +166,7 @@ struct InternalModelOptions
byte ImportVertexColors;
byte ImportBlendShapes;
ModelLightmapUVsSource LightmapUVsSource;
+ MonoString* CollisionMeshesPrefix;
// Transform
float Scale;
@@ -212,7 +213,7 @@ struct InternalModelOptions
to->ImportLODs = from->ImportLODs;
to->ImportVertexColors = from->ImportVertexColors;
to->ImportBlendShapes = from->ImportBlendShapes;
- to->LightmapUVsSource = from->LightmapUVsSource;
+ to->CollisionMeshesPrefix = MUtils::ToString(from->CollisionMeshesPrefix);
to->Scale = from->Scale;
to->Rotation = from->Rotation;
to->Translation = from->Translation;
@@ -251,6 +252,7 @@ struct InternalModelOptions
to->ImportVertexColors = from->ImportVertexColors;
to->ImportBlendShapes = from->ImportBlendShapes;
to->LightmapUVsSource = from->LightmapUVsSource;
+ to->CollisionMeshesPrefix = MUtils::ToString(from->CollisionMeshesPrefix);
to->Scale = from->Scale;
to->Rotation = from->Rotation;
to->Translation = from->Translation;
diff --git a/Source/Engine/ContentImporters/CreateCollisionData.h b/Source/Engine/ContentImporters/CreateCollisionData.h
index 3126cfd56..547a10485 100644
--- a/Source/Engine/ContentImporters/CreateCollisionData.h
+++ b/Source/Engine/ContentImporters/CreateCollisionData.h
@@ -6,7 +6,9 @@
#if COMPILE_WITH_ASSETS_IMPORTER
+#if COMPILE_WITH_PHYSICS_COOKING
#include "Engine/Physics/CollisionCooking.h"
+#endif
///
/// Creating collision data asset utility
@@ -23,7 +25,6 @@ public:
static CreateAssetResult Create(CreateAssetContext& context);
#if COMPILE_WITH_PHYSICS_COOKING
-
///
/// Cooks the mesh collision data and saves it to the asset using format.
///
@@ -31,7 +32,6 @@ public:
/// The input argument data.
/// True if failed, otherwise false. See log file to track errors better.
static bool CookMeshCollision(const String& outputPath, CollisionCooking::Argument& arg);
-
#endif
};
diff --git a/Source/Engine/Graphics/Models/ModelData.cpp b/Source/Engine/Graphics/Models/ModelData.cpp
index 4b39cef65..d1e867c6c 100644
--- a/Source/Engine/Graphics/Models/ModelData.cpp
+++ b/Source/Engine/Graphics/Models/ModelData.cpp
@@ -589,6 +589,17 @@ void MeshData::Merge(MeshData& other)
}
}
+bool MaterialSlotEntry::UsesProperties() const
+{
+ return Diffuse.Color != Color::White ||
+ Diffuse.TextureIndex != -1 ||
+ Emissive.Color != Color::Transparent ||
+ Emissive.TextureIndex != -1 ||
+ !Math::IsOne(Opacity.Value) ||
+ Opacity.TextureIndex != -1 ||
+ Normals.TextureIndex != -1;
+}
+
void ModelData::CalculateLODsScreenSizes()
{
const float autoComputeLodPowerBase = 0.5f;
diff --git a/Source/Engine/Graphics/Models/ModelData.h b/Source/Engine/Graphics/Models/ModelData.h
index 2b99d0c83..4d4733fb7 100644
--- a/Source/Engine/Graphics/Models/ModelData.h
+++ b/Source/Engine/Graphics/Models/ModelData.h
@@ -373,16 +373,7 @@ struct FLAXENGINE_API MaterialSlotEntry
bool TwoSided = false;
- bool UsesProperties() const
- {
- return Diffuse.Color != Color::White ||
- Diffuse.TextureIndex != -1 ||
- Emissive.Color != Color::Transparent ||
- Emissive.TextureIndex != -1 ||
- !Math::IsOne(Opacity.Value) ||
- Opacity.TextureIndex != -1 ||
- Normals.TextureIndex != -1;
- }
+ bool UsesProperties() const;
};
///
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Build.cs b/Source/Engine/Tools/ModelTool/ModelTool.Build.cs
index 720527cb0..25f43d98a 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.Build.cs
+++ b/Source/Engine/Tools/ModelTool/ModelTool.Build.cs
@@ -63,6 +63,7 @@ public class ModelTool : EngineModule
options.PrivateDependencies.Add("meshoptimizer");
options.PrivateDependencies.Add("MikkTSpace");
+ options.PrivateDependencies.Add("Physics");
options.PublicDefinitions.Add("COMPILE_WITH_MODEL_TOOL");
}
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Options.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Options.cpp
index d59563160..2b3620616 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.Options.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.Options.cpp
@@ -42,6 +42,7 @@ void ModelTool::Options::Serialize(SerializeStream& stream, const void* otherObj
SERIALIZE(ImportVertexColors);
SERIALIZE(ImportBlendShapes);
SERIALIZE(LightmapUVsSource);
+ SERIALIZE(CollisionMeshesPrefix);
SERIALIZE(Scale);
SERIALIZE(Rotation);
SERIALIZE(Translation);
@@ -79,6 +80,7 @@ void ModelTool::Options::Deserialize(DeserializeStream& stream, ISerializeModifi
DESERIALIZE(ImportVertexColors);
DESERIALIZE(ImportBlendShapes);
DESERIALIZE(LightmapUVsSource);
+ DESERIALIZE(CollisionMeshesPrefix);
DESERIALIZE(Scale);
DESERIALIZE(Rotation);
DESERIALIZE(Translation);
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp
index b18392d7d..f014bd571 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp
@@ -16,6 +16,7 @@
#include "Engine/Tools/TextureTool/TextureTool.h"
#include "Engine/ContentImporters/AssetsImportingManager.h"
#include "Engine/ContentImporters/CreateMaterial.h"
+#include "Engine/ContentImporters/CreateCollisionData.h"
#include "Editor/Utilities/EditorUtilities.h"
#include
@@ -562,7 +563,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
materialOptions.Opacity.Texture = data.Textures[material.Opacity.TextureIndex].AssetID;
if (material.Normals.TextureIndex != -1)
materialOptions.Normals.Texture = data.Textures[material.Normals.TextureIndex].AssetID;
- if (material.TwoSided | material.Diffuse.HasAlphaMask)
+ if (material.TwoSided || material.Diffuse.HasAlphaMask)
materialOptions.Info.CullMode = CullMode::TwoSided;
if (!Math::IsOne(material.Opacity.Value) || material.Opacity.TextureIndex != -1)
materialOptions.Info.BlendMode = MaterialBlendMode::Transparent;
@@ -624,6 +625,41 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
}
}
+ // Collision mesh output
+ if (options.CollisionMeshesPrefix.HasChars())
+ {
+ // Extract collision meshes
+ ModelData collisionModel;
+ for (auto& lod : data.LODs)
+ {
+ for (int32 i = lod.Meshes.Count() - 1; i >= 0; i--)
+ {
+ auto mesh = lod.Meshes[i];
+ if (mesh->Name.StartsWith(options.CollisionMeshesPrefix, StringSearchCase::IgnoreCase))
+ {
+ if (collisionModel.LODs.Count() == 0)
+ collisionModel.LODs.AddOne();
+ collisionModel.LODs[0].Meshes.Add(mesh);
+ lod.Meshes.RemoveAtKeepOrder(i);
+ if (lod.Meshes.IsEmpty())
+ break;
+ }
+ }
+ }
+ if (collisionModel.LODs.HasItems())
+ {
+ // Create collision
+ CollisionCooking::Argument arg;
+ arg.Type = CollisionDataType::TriangleMesh;
+ arg.OverrideModelData = &collisionModel;
+ auto assetPath = autoImportOutput / StringUtils::GetFileNameWithoutExtension(path) + TEXT("Collision") ASSET_FILES_EXTENSION_WITH_DOT;
+ if (CreateCollisionData::CookMeshCollision(assetPath, arg))
+ {
+ LOG(Error, "Failed to create collision mesh.");
+ }
+ }
+ }
+
// For generated lightmap UVs coordinates needs to be moved so all meshes are in unique locations in [0-1]x[0-1] coordinates space
if (options.LightmapUVsSource == ModelLightmapUVsSource::Generate && data.LODs.HasItems() && data.LODs[0].Meshes.Count() > 1)
{
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.h b/Source/Engine/Tools/ModelTool/ModelTool.h
index fc38b8192..6e22b4cd6 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.h
+++ b/Source/Engine/Tools/ModelTool/ModelTool.h
@@ -177,6 +177,7 @@ public:
bool ImportVertexColors = true;
bool ImportBlendShapes = false;
ModelLightmapUVsSource LightmapUVsSource = ModelLightmapUVsSource::Disable;
+ String CollisionMeshesPrefix;
// Transform
float Scale = 1.0f;