Add CollisionMeshesPrefix option to import collision data from model asset

This commit is contained in:
Wojtek Figat
2022-02-06 14:11:13 +01:00
parent a186d1a7fc
commit 748d69a3cb
10 changed files with 88 additions and 15 deletions

View File

@@ -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;
/// <summary>
/// If specified, all meshes which name starts with this prefix will be imported as a separate collision data (excluded used for rendering).
/// </summary>
[EditorOrder(100), DefaultValue(""), EditorDisplay("Geometry")]
public string CollisionMeshesPrefix { get; set; }
/// <summary>
/// Custom uniform import scale.
/// </summary>
@@ -284,7 +290,7 @@ namespace FlaxEditor.Content.Import
/// </summary>
[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;
/// <summary>
/// If checked, the imported mesh/animations are splitted into separate assets. Used if ObjectIndex is set to -1.
/// </summary>
@@ -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;

View File

@@ -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<CollisionData>())
{
var collisionData = FlaxEngine.Content.Load<CollisionData>(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<CollisionData>())
{
var collisionData = FlaxEngine.Content.Load<CollisionData>(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;
}
}
}
}
}
}

View File

@@ -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;

View File

@@ -6,7 +6,9 @@
#if COMPILE_WITH_ASSETS_IMPORTER
#if COMPILE_WITH_PHYSICS_COOKING
#include "Engine/Physics/CollisionCooking.h"
#endif
/// <summary>
/// Creating collision data asset utility
@@ -23,7 +25,6 @@ public:
static CreateAssetResult Create(CreateAssetContext& context);
#if COMPILE_WITH_PHYSICS_COOKING
/// <summary>
/// Cooks the mesh collision data and saves it to the asset using <see cref="CollisionData"/> format.
/// </summary>
@@ -31,7 +32,6 @@ public:
/// <param name="arg">The input argument data.</param>
/// <returns>True if failed, otherwise false. See log file to track errors better.</returns>
static bool CookMeshCollision(const String& outputPath, CollisionCooking::Argument& arg);
#endif
};

View File

@@ -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;

View File

@@ -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;
};
/// <summary>

View File

@@ -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");
}

View File

@@ -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);

View File

@@ -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 <ThirdParty/meshoptimizer/meshoptimizer.h>
@@ -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)
{

View File

@@ -177,6 +177,7 @@ public:
bool ImportVertexColors = true;
bool ImportBlendShapes = false;
ModelLightmapUVsSource LightmapUVsSource = ModelLightmapUVsSource::Disable;
String CollisionMeshesPrefix;
// Transform
float Scale = 1.0f;