|
@@ -296,88 +296,104 @@ namespace PhysX
|
|
|
const AZ::SceneAPI::Containers::SceneGraph& sceneGraph)
|
|
|
{
|
|
|
AssetMaterialsData assetMaterialData;
|
|
|
+ bool errorFound = false;
|
|
|
|
|
|
const auto& sceneNodeSelectionList = meshGroup.GetSceneNodeSelectionList();
|
|
|
- size_t selectedNodeCount = sceneNodeSelectionList.GetSelectedNodeCount();
|
|
|
-
|
|
|
- for (size_t index = 0; index < selectedNodeCount; index++)
|
|
|
- {
|
|
|
- AZ::SceneAPI::Containers::SceneGraph::NodeIndex nodeIndex = sceneGraph.Find(sceneNodeSelectionList.GetSelectedNode(index));
|
|
|
- if (!nodeIndex.IsValid())
|
|
|
- {
|
|
|
- AZ_TracePrintf(
|
|
|
- AZ::SceneAPI::Utilities::WarningWindow,
|
|
|
- "Node '%s' was not found in the scene graph.",
|
|
|
- sceneNodeSelectionList.GetSelectedNode(index).c_str()
|
|
|
- );
|
|
|
- continue;
|
|
|
- }
|
|
|
- auto nodeMesh = azrtti_cast<const AZ::SceneAPI::DataTypes::IMeshData*>(*sceneGraph.ConvertToStorageIterator(nodeIndex));
|
|
|
- if (!nodeMesh)
|
|
|
+ sceneNodeSelectionList.EnumerateSelectedNodes(
|
|
|
+ [&](const AZStd::string& name)
|
|
|
{
|
|
|
- continue;
|
|
|
- }
|
|
|
+ AZ::SceneAPI::Containers::SceneGraph::NodeIndex nodeIndex = sceneGraph.Find(name);
|
|
|
+ if (!nodeIndex.IsValid())
|
|
|
+ {
|
|
|
+ AZ_TracePrintf(
|
|
|
+ AZ::SceneAPI::Utilities::WarningWindow,
|
|
|
+ "Node '%s' was not found in the scene graph.",
|
|
|
+ name.c_str());
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ auto nodeMesh =
|
|
|
+ azrtti_cast<const AZ::SceneAPI::DataTypes::IMeshData*>(*sceneGraph.ConvertToStorageIterator(nodeIndex));
|
|
|
+ if (!nodeMesh)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
|
|
|
- AZStd::string_view nodeName = sceneGraph.GetNodeName(nodeIndex).GetName();
|
|
|
+ AZStd::string_view nodeName = sceneGraph.GetNodeName(nodeIndex).GetName();
|
|
|
|
|
|
- const AZStd::vector<AZStd::string> localSourceSceneMaterialsList = GenerateLocalNodeMaterialMap(sceneGraph, nodeIndex);
|
|
|
- if (localSourceSceneMaterialsList.empty())
|
|
|
- {
|
|
|
- AZ_TracePrintf(
|
|
|
- AZ::SceneAPI::Utilities::WarningWindow,
|
|
|
- "Node '%.*s' does not have any material assigned to it. Material '%s' will be used.",
|
|
|
- AZ_STRING_ARG(nodeName), DefaultMaterialName
|
|
|
- );
|
|
|
- }
|
|
|
+ const AZStd::vector<AZStd::string> localSourceSceneMaterialsList =
|
|
|
+ GenerateLocalNodeMaterialMap(sceneGraph, nodeIndex);
|
|
|
+ if (localSourceSceneMaterialsList.empty())
|
|
|
+ {
|
|
|
+ AZ_TracePrintf(
|
|
|
+ AZ::SceneAPI::Utilities::WarningWindow,
|
|
|
+ "Node '%.*s' does not have any material assigned to it. Material '%s' will be used.",
|
|
|
+ AZ_STRING_ARG(nodeName),
|
|
|
+ DefaultMaterialName);
|
|
|
+ }
|
|
|
|
|
|
- const AZ::u32 faceCount = nodeMesh->GetFaceCount();
|
|
|
+ const AZ::u32 faceCount = nodeMesh->GetFaceCount();
|
|
|
|
|
|
- assetMaterialData.m_nodesToPerFaceMaterialIndices.emplace(nodeName, AZStd::vector<AZ::u16>(faceCount));
|
|
|
+ assetMaterialData.m_nodesToPerFaceMaterialIndices.emplace(nodeName, AZStd::vector<AZ::u16>(faceCount));
|
|
|
|
|
|
- // Convex and primitive methods can only have 1 material per node.
|
|
|
- const bool limitToOneMaterial = meshGroup.GetExportAsConvex() || meshGroup.GetExportAsPrimitive();
|
|
|
- AZStd::string firstMaterial;
|
|
|
- AZStd::set<AZStd::string> nodeMaterials;
|
|
|
+ // Convex and primitive methods can only have 1 material per node.
|
|
|
+ const bool limitToOneMaterial = meshGroup.GetExportAsConvex() || meshGroup.GetExportAsPrimitive();
|
|
|
+ AZStd::string firstMaterial;
|
|
|
+ AZStd::set<AZStd::string> nodeMaterials;
|
|
|
|
|
|
- for (AZ::u32 faceIndex = 0; faceIndex < faceCount; ++faceIndex)
|
|
|
- {
|
|
|
- AZStd::string materialName = DefaultMaterialName;
|
|
|
- if (!localSourceSceneMaterialsList.empty())
|
|
|
+ for (AZ::u32 faceIndex = 0; faceIndex < faceCount; ++faceIndex)
|
|
|
{
|
|
|
- const int materialId = nodeMesh->GetFaceMaterialId(faceIndex);
|
|
|
- if (materialId >= localSourceSceneMaterialsList.size())
|
|
|
+ AZStd::string materialName = DefaultMaterialName;
|
|
|
+ if (!localSourceSceneMaterialsList.empty())
|
|
|
{
|
|
|
- AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow,
|
|
|
- "materialId %d for face %d is out of bound for localSourceSceneMaterialsList (size %d).",
|
|
|
- materialId, faceIndex, localSourceSceneMaterialsList.size());
|
|
|
-
|
|
|
- return AZStd::nullopt;
|
|
|
- }
|
|
|
+ const int materialId = nodeMesh->GetFaceMaterialId(faceIndex);
|
|
|
+ if (materialId >= localSourceSceneMaterialsList.size())
|
|
|
+ {
|
|
|
+ AZ_TracePrintf(
|
|
|
+ AZ::SceneAPI::Utilities::ErrorWindow,
|
|
|
+ "materialId %d for face %d is out of bound for localSourceSceneMaterialsList (size %d).",
|
|
|
+ materialId,
|
|
|
+ faceIndex,
|
|
|
+ localSourceSceneMaterialsList.size());
|
|
|
+
|
|
|
+ errorFound = true;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- materialName = localSourceSceneMaterialsList[materialId];
|
|
|
+ materialName = localSourceSceneMaterialsList[materialId];
|
|
|
|
|
|
- // Use the first material found in the mesh when it has to be limited to one.
|
|
|
- if (limitToOneMaterial)
|
|
|
- {
|
|
|
- nodeMaterials.insert(materialName);
|
|
|
- if (firstMaterial.empty())
|
|
|
+ // Use the first material found in the mesh when it has to be limited to one.
|
|
|
+ if (limitToOneMaterial)
|
|
|
{
|
|
|
- firstMaterial = materialName;
|
|
|
+ nodeMaterials.insert(materialName);
|
|
|
+ if (firstMaterial.empty())
|
|
|
+ {
|
|
|
+ firstMaterial = materialName;
|
|
|
+ }
|
|
|
+ materialName = firstMaterial;
|
|
|
}
|
|
|
- materialName = firstMaterial;
|
|
|
}
|
|
|
+
|
|
|
+ const AZ::u16 materialIndex = InsertMaterialIndexByName(materialName, assetMaterialData);
|
|
|
+ assetMaterialData.m_nodesToPerFaceMaterialIndices[nodeName][faceIndex] = materialIndex;
|
|
|
}
|
|
|
|
|
|
- const AZ::u16 materialIndex = InsertMaterialIndexByName(materialName, assetMaterialData);
|
|
|
- assetMaterialData.m_nodesToPerFaceMaterialIndices[nodeName][faceIndex] = materialIndex;
|
|
|
- }
|
|
|
+ if (limitToOneMaterial && nodeMaterials.size() > 1)
|
|
|
+ {
|
|
|
+ AZ_TracePrintf(
|
|
|
+ AZ::SceneAPI::Utilities::WarningWindow,
|
|
|
+ "Node '%s' has %d materials, but cooking methods Convex and Primitive support one material per node. The "
|
|
|
+ "first material '%s' will be used.",
|
|
|
+ name.c_str(),
|
|
|
+ nodeMaterials.size(),
|
|
|
+ firstMaterial.c_str());
|
|
|
+ }
|
|
|
|
|
|
- if (limitToOneMaterial && nodeMaterials.size() > 1)
|
|
|
- {
|
|
|
- AZ_TracePrintf(AZ::SceneAPI::Utilities::WarningWindow,
|
|
|
- "Node '%s' has %d materials, but cooking methods Convex and Primitive support one material per node. The first material '%s' will be used.",
|
|
|
- sceneNodeSelectionList.GetSelectedNode(index).c_str(), nodeMaterials.size(), firstMaterial.c_str());
|
|
|
- }
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (errorFound)
|
|
|
+ {
|
|
|
+ return AZStd::nullopt;
|
|
|
}
|
|
|
|
|
|
return assetMaterialData;
|
|
@@ -843,67 +859,80 @@ namespace PhysX
|
|
|
coordSysConverter = coordinateSystemRule->GetCoordinateSystemConverter();
|
|
|
}
|
|
|
|
|
|
- for (size_t index = 0; index < selectedNodeCount; index++)
|
|
|
- {
|
|
|
- AZ::SceneAPI::Containers::SceneGraph::NodeIndex nodeIndex = graph.Find(sceneNodeSelectionList.GetSelectedNode(index));
|
|
|
- auto nodeMesh = azrtti_cast<const AZ::SceneAPI::DataTypes::IMeshData*>(*graph.ConvertToStorageIterator(nodeIndex));
|
|
|
+ SceneEvents::ProcessingResult enumerationResult = SceneEvents::ProcessingResult::Success;
|
|
|
|
|
|
- if (!nodeMesh)
|
|
|
+ sceneNodeSelectionList.EnumerateSelectedNodes(
|
|
|
+ [&](const AZStd::string& name)
|
|
|
{
|
|
|
- continue;
|
|
|
- }
|
|
|
+ AZ::SceneAPI::Containers::SceneGraph::NodeIndex nodeIndex = graph.Find(name);
|
|
|
+ auto nodeMesh = azrtti_cast<const AZ::SceneAPI::DataTypes::IMeshData*>(*graph.ConvertToStorageIterator(nodeIndex));
|
|
|
|
|
|
- const AZ::SceneAPI::Containers::SceneGraph::Name& nodeName = graph.GetNodeName(nodeIndex);
|
|
|
+ if (!nodeMesh)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
|
|
|
- // CoordinateSystemConverter covers the simple transformations of CoordinateSystemRule and
|
|
|
- // DetermineWorldTransform function covers the advanced mode of CoordinateSystemRule.
|
|
|
- const AZ::SceneAPI::DataTypes::MatrixType worldTransform = coordSysConverter.ConvertMatrix3x4(
|
|
|
- AZ::SceneAPI::Utilities::DetermineWorldTransform(scene, nodeIndex, pxMeshGroup.GetRuleContainerConst()));
|
|
|
+ const AZ::SceneAPI::Containers::SceneGraph::Name& nodeName = graph.GetNodeName(nodeIndex);
|
|
|
|
|
|
- NodeCollisionGeomExportData nodeExportData;
|
|
|
- nodeExportData.m_nodeName = nodeName.GetName();
|
|
|
+ // CoordinateSystemConverter covers the simple transformations of CoordinateSystemRule and
|
|
|
+ // DetermineWorldTransform function covers the advanced mode of CoordinateSystemRule.
|
|
|
+ const AZ::SceneAPI::DataTypes::MatrixType worldTransform = coordSysConverter.ConvertMatrix3x4(
|
|
|
+ AZ::SceneAPI::Utilities::DetermineWorldTransform(scene, nodeIndex, pxMeshGroup.GetRuleContainerConst()));
|
|
|
|
|
|
- const AZ::u32 vertexCount = nodeMesh->GetVertexCount();
|
|
|
- const AZ::u32 faceCount = nodeMesh->GetFaceCount();
|
|
|
+ NodeCollisionGeomExportData nodeExportData;
|
|
|
+ nodeExportData.m_nodeName = nodeName.GetName();
|
|
|
|
|
|
- nodeExportData.m_vertices.resize(vertexCount);
|
|
|
+ const AZ::u32 vertexCount = nodeMesh->GetVertexCount();
|
|
|
+ const AZ::u32 faceCount = nodeMesh->GetFaceCount();
|
|
|
|
|
|
- for (AZ::u32 vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex)
|
|
|
- {
|
|
|
- AZ::Vector3 pos = nodeMesh->GetPosition(vertexIndex);
|
|
|
- pos = worldTransform * pos;
|
|
|
- nodeExportData.m_vertices[vertexIndex] = AZVec3ToLYVec3(pos);
|
|
|
- }
|
|
|
+ nodeExportData.m_vertices.resize(vertexCount);
|
|
|
|
|
|
- nodeExportData.m_indices.resize(faceCount * 3);
|
|
|
+ for (AZ::u32 vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex)
|
|
|
+ {
|
|
|
+ AZ::Vector3 pos = nodeMesh->GetPosition(vertexIndex);
|
|
|
+ pos = worldTransform * pos;
|
|
|
+ nodeExportData.m_vertices[vertexIndex] = AZVec3ToLYVec3(pos);
|
|
|
+ }
|
|
|
|
|
|
- nodeExportData.m_perFaceMaterialIndices = assetMaterialData->m_nodesToPerFaceMaterialIndices[nodeExportData.m_nodeName];
|
|
|
- if (nodeExportData.m_perFaceMaterialIndices.size() != faceCount)
|
|
|
- {
|
|
|
- AZ_TracePrintf(
|
|
|
- AZ::SceneAPI::Utilities::WarningWindow,
|
|
|
- "Node '%s' material information face count %d does not match the node's %d.",
|
|
|
- nodeExportData.m_nodeName.c_str(), nodeExportData.m_perFaceMaterialIndices.size(), faceCount
|
|
|
- );
|
|
|
- return SceneEvents::ProcessingResult::Failure;
|
|
|
- }
|
|
|
+ nodeExportData.m_indices.resize(faceCount * 3);
|
|
|
|
|
|
- for (AZ::u32 faceIndex = 0; faceIndex < faceCount; ++faceIndex)
|
|
|
- {
|
|
|
- const AZ::SceneAPI::DataTypes::IMeshData::Face& face = nodeMesh->GetFaceInfo(faceIndex);
|
|
|
- nodeExportData.m_indices[faceIndex * 3] = face.vertexIndex[0];
|
|
|
- nodeExportData.m_indices[faceIndex * 3 + 1] = face.vertexIndex[1];
|
|
|
- nodeExportData.m_indices[faceIndex * 3 + 2] = face.vertexIndex[2];
|
|
|
- }
|
|
|
+ nodeExportData.m_perFaceMaterialIndices =
|
|
|
+ assetMaterialData->m_nodesToPerFaceMaterialIndices[nodeExportData.m_nodeName];
|
|
|
+ if (nodeExportData.m_perFaceMaterialIndices.size() != faceCount)
|
|
|
+ {
|
|
|
+ AZ_TracePrintf(
|
|
|
+ AZ::SceneAPI::Utilities::WarningWindow,
|
|
|
+ "Node '%s' material information face count %d does not match the node's %d.",
|
|
|
+ nodeExportData.m_nodeName.c_str(),
|
|
|
+ nodeExportData.m_perFaceMaterialIndices.size(),
|
|
|
+ faceCount);
|
|
|
+ enumerationResult = SceneEvents::ProcessingResult::Failure;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- if (pxMeshGroup.GetDecomposeMeshes())
|
|
|
- {
|
|
|
- DecomposeAndAppendMeshes(decomposer, vhacdParams, totalExportData, nodeExportData);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- totalExportData.emplace_back(AZStd::move(nodeExportData));
|
|
|
- }
|
|
|
+ for (AZ::u32 faceIndex = 0; faceIndex < faceCount; ++faceIndex)
|
|
|
+ {
|
|
|
+ const AZ::SceneAPI::DataTypes::IMeshData::Face& face = nodeMesh->GetFaceInfo(faceIndex);
|
|
|
+ nodeExportData.m_indices[faceIndex * 3] = face.vertexIndex[0];
|
|
|
+ nodeExportData.m_indices[faceIndex * 3 + 1] = face.vertexIndex[1];
|
|
|
+ nodeExportData.m_indices[faceIndex * 3 + 2] = face.vertexIndex[2];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pxMeshGroup.GetDecomposeMeshes())
|
|
|
+ {
|
|
|
+ DecomposeAndAppendMeshes(decomposer, vhacdParams, totalExportData, nodeExportData);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ totalExportData.emplace_back(AZStd::move(nodeExportData));
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (enumerationResult == SceneEvents::ProcessingResult::Failure)
|
|
|
+ {
|
|
|
+ return enumerationResult;
|
|
|
}
|
|
|
|
|
|
// Merge triangle meshes if there's more than 1
|