diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index ff8dc31fe..c4f27abf5 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -765,6 +765,8 @@ bool ModelTool::ImportDataAssimp(const String& path, ModelData& data, Options& o flags |= aiProcess_FixInfacingNormals | aiProcess_GenSmoothNormals; if (options.CalculateTangents) flags |= aiProcess_CalcTangentSpace; + if (options.ReverseWindingOrder) + flags &= ~aiProcess_FlipWindingOrder; if (options.OptimizeMeshes) flags |= aiProcess_OptimizeMeshes | aiProcess_SplitLargeMeshes | aiProcess_ImproveCacheLocality; if (options.MergeMeshes) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.AutodeskFbxSdk.cpp b/Source/Engine/Tools/ModelTool/ModelTool.AutodeskFbxSdk.cpp index 1ea6a22ad..7f3dfb355 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.AutodeskFbxSdk.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.AutodeskFbxSdk.cpp @@ -385,6 +385,19 @@ bool ProcessMesh(ImporterData& data, FbxMesh* fbxMesh, MeshData& mesh, String& e mesh.Indices[i] = fbxIndices[i]; } + if (data.Options.ReverseWindingOrder) + { + for (int32 i = 0; i < vertexCount; i += 3) + { + Swap(meshIndices[i + 1], meshIndices[i + 2]); + Swap(meshPositions[i + 1], meshPositions[i + 2]); + if (meshNormals) + Swap(meshNormals[i + 1], meshNormals[i + 2]); + if (meshTangents) + Swap(meshTangents[i + 1], meshTangents[i + 2]); + } + } + // Texture coordinates FbxGeometryElementUV* texcoords = fbxMesh->GetElementUV(0); if (texcoords) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp index dcb0b6c5f..98747086a 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp @@ -775,6 +775,24 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh* } } + // Reverse winding order + if (data.Options.ReverseWindingOrder) + { + uint32* meshIndices = mesh.Indices.Get(); + Float3* meshPositions = mesh.Positions.Get(); + Float3* meshNormals = mesh.Normals.HasItems() ? mesh.Normals.Get() : nullptr; + Float3* meshTangents = mesh.Tangents.HasItems() ? mesh.Tangents.Get() : nullptr; + + for (int i = 0; i < vertexCount; i += 3) { + Swap(meshIndices[i + 1], meshIndices[i + 2]); + Swap(meshPositions[i + 1], meshPositions[i + 2]); + if (meshNormals) + Swap(meshNormals[i + 1], meshNormals[i + 2]); + if (meshTangents) + Swap(meshTangents[i + 1], meshTangents[i + 2]); + } + } + // Lightmap UVs if (data.Options.LightmapUVsSource == ModelLightmapUVsSource::Disable) { diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index 91c2edc06..fec4ba8f5 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -667,6 +667,7 @@ void ModelTool::Options::Serialize(SerializeStream& stream, const void* otherObj SERIALIZE(FlipNormals); SERIALIZE(CalculateTangents); SERIALIZE(SmoothingTangentsAngle); + SERIALIZE(ReverseWindingOrder); SERIALIZE(OptimizeMeshes); SERIALIZE(MergeMeshes); SERIALIZE(ImportLODs); @@ -717,6 +718,7 @@ void ModelTool::Options::Deserialize(DeserializeStream& stream, ISerializeModifi DESERIALIZE(FlipNormals); DESERIALIZE(CalculateTangents); DESERIALIZE(SmoothingTangentsAngle); + DESERIALIZE(ReverseWindingOrder); DESERIALIZE(OptimizeMeshes); DESERIALIZE(MergeMeshes); DESERIALIZE(ImportLODs); diff --git a/Source/Engine/Tools/ModelTool/ModelTool.h b/Source/Engine/Tools/ModelTool/ModelTool.h index 708b94342..bfd8092e7 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.h +++ b/Source/Engine/Tools/ModelTool/ModelTool.h @@ -170,6 +170,9 @@ public: // Specifies the maximum angle (in degrees) that may be between two vertex tangents before their tangents and bi-tangents are smoothed. The default value is 45. API_FIELD(Attributes="EditorOrder(45), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowSmoothingTangentsAngle)), Limit(0, 45, 0.1f)") float SmoothingTangentsAngle = 45.0f; + // If checked, the winding order of the vertices will be reversed. + API_FIELD(Attributes="EditorOrder(47), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))") + bool ReverseWindingOrder = false; // Enable/disable meshes geometry optimization. API_FIELD(Attributes="EditorOrder(50), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))") bool OptimizeMeshes = true;