Integrating github/staging through commit ab87ed9

This commit is contained in:
alexpete
2021-04-09 11:27:37 -07:00
parent ae62a97894
commit 1044dc3da1
1582 changed files with 29374 additions and 519051 deletions
@@ -40,6 +40,7 @@
#include <SceneAPI/SceneCore/DataTypes/Rules/ICoordinateSystemRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/ILodRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/ISkinRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IClothRule.h>
#include <SceneAPI/SceneCore/Events/ExportEventContext.h>
#include <SceneAPI/SceneCore/Utilities/SceneGraphSelector.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
@@ -93,6 +94,11 @@ namespace
const AZ::RHI::Format MorphTargetPositionDeltaFormat = AZ::RHI::Format::R16_UINT; // 16-bit integer per compressed position delta component
const char* ShaderSemanticName_MorphTargetNormalDeltas = "MORPHTARGET_NORMALDELTAS";
const AZ::RHI::Format MorphTargetNormalDeltaFormat = AZ::RHI::Format::R8_UINT; // 8-bit integer per compressed normal delta component
// Cloth data
const char* const ShaderSemanticName_ClothData = "CLOTH_DATA";
const uint32_t ClothDataFloatsPerVert = 4;
const AZ::RHI::Format ClothDataFormat = AZ::RHI::Format::R32G32B32A32_FLOAT;
}
namespace AZ
@@ -113,6 +119,7 @@ namespace AZ
}
ModelAssetBuilderComponent::ModelAssetBuilderComponent()
: m_numSkinJointInfluencesPerVertex(DefaultSkinInfluencesPerVert)
{
BindToCall(&ModelAssetBuilderComponent::BuildModel);
}
@@ -331,6 +338,12 @@ namespace AZ
sourceMesh.m_isMorphed = GetIsMorphed(sceneGraph, node);
// Get the cloth data (only for full mesh LOD 0).
sourceMesh.m_meshClothData = (lodIndex == 0)
? SceneAPI::DataTypes::IClothRule::FindClothData(
sceneGraph, node, sourceMesh.m_meshData->GetVertexCount(), context.m_group.GetRuleContainerConst())
: AZStd::vector<AZ::Color>{};
// We've traversed this node and all its children that hold
// relevant data We can move it into the list of content for this lod
sourceMeshContentList.emplace_back(AZStd::move(sourceMesh));
@@ -371,17 +384,19 @@ namespace AZ
// If the merge meshes option is disabled in the advanced mesh rule, don't merge meshes
canMergeMeshes = false;
}
for (const SourceMeshContent& sourceMesh : sourceMeshContentList)
else
{
if (sourceMesh.m_isMorphed)
for (const SourceMeshContent& sourceMesh : sourceMeshContentList)
{
// Merging meshes shuffles around the order of the vertices, but morph targets rely on having an index that tell them which vertices to morph
// We do not merge morphed meshes so that this index is preserved and correct.
// If we keep track of the ordering changes in MergeMeshesByMaterialUid and then re-mapped the MORPHTARGET_VERTEXINDICES buffer
// we could potentially enable merging meshes that are morphed. But for now, disable merging.
canMergeMeshes = false;
break;
if (sourceMesh.m_isMorphed)
{
// Merging meshes shuffles around the order of the vertices, but morph targets rely on having an index that tell them which vertices to morph
// We do not merge morphed meshes so that this index is preserved and correct.
// If we keep track of the ordering changes in MergeMeshesByMaterialUid and then re-mapped the MORPHTARGET_VERTEXINDICES buffer
// we could potentially enable merging meshes that are morphed. But for now, disable merging.
canMergeMeshes = false;
break;
}
}
}
@@ -396,12 +411,12 @@ namespace AZ
ProductMeshViewList lodMeshViews;
ProductMeshContent mergedMesh;
MergeMeshesToCommonBuffers(context, lodMeshes, mergedMesh, lodMeshViews);
MergeMeshesToCommonBuffers(lodMeshes, mergedMesh, lodMeshViews);
BufferAssetView indexBuffer;
AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo> streamBuffers;
if (!CreateModelLodBuffers(context, mergedMesh, indexBuffer, streamBuffers, lodAssetCreator))
if (!CreateModelLodBuffers(mergedMesh, indexBuffer, streamBuffers, lodAssetCreator))
{
return AZ::SceneAPI::Events::ProcessingResult::Failure;
}
@@ -417,7 +432,7 @@ namespace AZ
uint32_t meshIndex = 0;
for (const ProductMeshContent& mesh : lodMeshes)
{
const ProductMeshView meshView = CreateViewToEntireMesh(context, mesh);
const ProductMeshView meshView = CreateViewToEntireMesh(mesh);
BufferAssetView indexBuffer;
AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo> streamBuffers;
@@ -425,7 +440,7 @@ namespace AZ
// Mesh name in ProductMeshContent could be duplicated so generate unique mesh name using index
m_meshName = AZStd::string::format("mesh%d", meshIndex++);
if (!CreateModelLodBuffers(context, mesh, indexBuffer, streamBuffers, lodAssetCreator))
if (!CreateModelLodBuffers(mesh, indexBuffer, streamBuffers, lodAssetCreator))
{
return AZ::SceneAPI::Events::ProcessingResult::Failure;
}
@@ -614,7 +629,11 @@ namespace AZ
productMeshList.reserve(productMeshCount);
// Get the skin rule
AZStd::shared_ptr<const SceneAPI::DataTypes::ISkinRule> skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>();
if (const auto* skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get())
{
m_numSkinJointInfluencesPerVertex = skinRule->GetMaxWeightsPerVertex();
m_skinWeightThreshold = skinRule->GetWeightThreshold();
}
uint32_t totalVertexCount = 0;
for (size_t i = 0; i < productList.size(); ++i)
@@ -632,6 +651,7 @@ namespace AZ
const auto& colorContentCollection = sourceMesh.m_meshColorData;
const size_t colorSetCount = colorContentCollection.size();
bool processedMorphTargets = false;
bool warnedExcessOfSkinInfluences = false;
for (const auto& it : productsByMaterialUid)
{
@@ -677,6 +697,7 @@ namespace AZ
AZStd::vector<AZ::Name>& uvNames = productMesh.m_uvCustomNames;
AZStd::vector<AZStd::vector<float>>& colorSets = productMesh.m_colorSets;
AZStd::vector<AZ::Name>& colorNames = productMesh.m_colorCustomNames;
AZStd::vector<float>& clothData = productMesh.m_clothData;
const size_t vertexCount = oldToNewIndices.size();
positions.reserve(vertexCount * PositionFloatsPerVert);
@@ -716,7 +737,16 @@ namespace AZ
colorSet.reserve(vertexCount * ColorFloatsPerVert);
}
if (!sourceMesh.m_skinData.empty())
const bool hasClothData = !sourceMesh.m_meshClothData.empty();
if (hasClothData)
{
AZ_Assert(sourceMesh.m_meshClothData.size() == vertexCount,
"Vertex Count %d does not match mesh cloth data size %d", vertexCount, sourceMesh.m_meshClothData.size());
clothData.reserve(vertexCount * ClothDataFloatsPerVert);
}
const bool hasSkinData = !sourceMesh.m_skinData.empty();
if (hasSkinData)
{
// Skinned meshes require that positions, normals, tangents, bitangents, all exist and have the same number
// of total elements. Pad buffers with missing data to make them align with positions and normals
@@ -817,8 +847,23 @@ namespace AZ
colors.push_back(color.alpha);
}
// Gather Cloth Data
if (hasClothData)
{
const AZ::Color& vertexClothData = sourceMesh.m_meshClothData[oldIndex];
clothData.push_back(vertexClothData.GetR());
clothData.push_back(vertexClothData.GetG());
clothData.push_back(vertexClothData.GetB());
clothData.push_back(vertexClothData.GetA());
}
// Gather skinning influences
GatherSkinningInfluences(context, sourceMesh, productMesh, jointNameToIndexMap, oldIndex);
if (hasSkinData)
{
// Warn about excess of skin influences once per-source mesh.
GatherVertexSkinningInfluences(sourceMesh, productMesh, jointNameToIndexMap, oldIndex, warnedExcessOfSkinInfluences);
}
}
if(!processedMorphTargets)
@@ -836,19 +881,16 @@ namespace AZ
return productMeshList;
}
void ModelAssetBuilderComponent::GatherSkinningInfluences(
const ModelAssetBuilderContext& context,
void ModelAssetBuilderComponent::GatherVertexSkinningInfluences(
const SourceMeshContent& sourceMesh,
ProductMeshContent& productMesh,
AZStd::unordered_map<AZStd::string, uint16_t>& jointNameToIndexMap,
size_t vertexIndex) const
size_t vertexIndex,
bool& warnedExcessOfSkinInfluences) const
{
AZStd::vector<uint16_t>& skinJointIndices = productMesh.m_skinJointIndices;
AZStd::vector<float>& skinWeights = productMesh.m_skinWeights;
const auto& sourceMeshData = sourceMesh.m_meshData;
const SceneAPI::DataTypes::ISkinRule* skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get();
const size_t maxNumInfluences = ExtractMaxNumInfluencesPerVertex(skinRule);
const float weightThreshold = skinRule ? skinRule->GetWeightThreshold() : 0.0f;
size_t numInfluencesAdded = 0;
for (const auto& skinData : sourceMesh.m_skinData)
@@ -857,8 +899,9 @@ namespace AZ
const AZ::u32 controlPointIndex = sourceMeshData->GetControlPointIndex(vertexIndex);
const size_t numSkinInfluences = skinData->GetLinkCount(controlPointIndex);
const size_t numInfluencesToAdd = AZStd::min<size_t>(numSkinInfluences, maxNumInfluences - numInfluencesAdded);
for (size_t influenceIndex = 0; influenceIndex < numInfluencesToAdd; ++influenceIndex)
size_t numInfluencesExcess = 0;
for (size_t influenceIndex = 0; influenceIndex < numSkinInfluences; ++influenceIndex)
{
const AZ::SceneAPI::DataTypes::ISkinWeightData::Link& link = skinData->GetLink(controlPointIndex, influenceIndex);
@@ -874,30 +917,37 @@ namespace AZ
const AZ::u16 jointIndex = jointNameToIndexMap[boneName];
// Add skin influence
if (weight > weightThreshold)
if (weight > m_skinWeightThreshold)
{
skinJointIndices.push_back(jointIndex);
skinWeights.push_back(weight);
numInfluencesAdded++;
if (numInfluencesAdded < m_numSkinJointInfluencesPerVertex)
{
skinJointIndices.push_back(jointIndex);
skinWeights.push_back(weight);
numInfluencesAdded++;
}
else
{
numInfluencesExcess++;
}
}
}
if (numInfluencesAdded > maxNumInfluences)
if (numInfluencesExcess > 0)
{
AZ_WarningOnce(s_builderName, false, "More skin influences (%d) on data than supported (%d). Skinning influences won't be normalized.",
numSkinInfluences, maxNumInfluences);
AZ_Warning(s_builderName, warnedExcessOfSkinInfluences,
"Mesh %s has more skin influences (%d) than the maximum (%d). Skinning influences won't be normalized. Maximum number of skin influences can be increased with a Skin Modifier in FBX Settings.",
sourceMesh.m_name.GetCStr(),
m_numSkinJointInfluencesPerVertex + numInfluencesExcess,
m_numSkinJointInfluencesPerVertex);
warnedExcessOfSkinInfluences = true;
break;
}
}
if (!sourceMesh.m_skinData.empty() &&
numInfluencesAdded < maxNumInfluences)
for (size_t influenceIndex = numInfluencesAdded; influenceIndex < m_numSkinJointInfluencesPerVertex; ++influenceIndex)
{
for (size_t influenceIndex = numInfluencesAdded; influenceIndex < maxNumInfluences; ++influenceIndex)
{
skinJointIndices.push_back(0);
skinWeights.push_back(0.0f);
}
skinJointIndices.push_back(0);
skinWeights.push_back(0.0f);
}
}
@@ -914,7 +964,6 @@ namespace AZ
for (const ProductMeshContent& mesh : productMeshList)
{
// Disable mesh merging whenever a mesh is morphed.
if (mesh.CanBeMerged())
{
meshCountByMatUid[mesh.m_materialUid]++;
@@ -970,9 +1019,11 @@ namespace AZ
}
template<typename T>
void ModelAssetBuilderComponent::ValidateStreamSize([[maybe_unused]] size_t expectedVertexCount, const AZStd::vector<T>& bufferData, AZ::RHI::Format format, [[maybe_unused]] const char* streamName) const
void ModelAssetBuilderComponent::ValidateStreamSize([[maybe_unused]] size_t expectedVertexCount, [[maybe_unused]] const AZStd::vector<T>& bufferData, [[maybe_unused]] AZ::RHI::Format format, [[maybe_unused]] const char* streamName) const
{
#if defined(AZ_ENABLE_TRACING)
size_t actualVertexCount = (bufferData.size() * sizeof(T)) / RHI::GetFormatSize(format);
#endif
AZ_Error(s_builderName, expectedVertexCount == actualVertexCount, "VertexStream '%s' does not match the expected vertex count. This typically means multiple sub-meshes have mis-matched vertex stream layouts (such as one having more uv sets than the other) but are assigned the same material in the dcc tool so they were merged.", streamName);
}
@@ -999,9 +1050,21 @@ namespace AZ
{
ValidateStreamSize(expectedVertexCount, mesh.m_colorSets[i], ColorFormat, mesh.m_colorCustomNames[i].GetCStr());
}
if (!mesh.m_clothData.empty())
{
ValidateStreamSize(expectedVertexCount, mesh.m_clothData, ClothDataFormat, ShaderSemanticName_ClothData);
}
if (!mesh.m_skinJointIndices.empty())
{
ValidateStreamSize(expectedVertexCount * m_numSkinJointInfluencesPerVertex, mesh.m_skinJointIndices, AZ::RHI::Format::R16_UINT, ShaderSemanticName_SkinJointIndices);
}
if (!mesh.m_skinWeights.empty())
{
ValidateStreamSize(expectedVertexCount * m_numSkinJointInfluencesPerVertex, mesh.m_skinWeights, SkinWeightFormat, ShaderSemanticName_SkinWeights);
}
}
ModelAssetBuilderComponent::ProductMeshView ModelAssetBuilderComponent::CreateViewToEntireMesh(const ModelAssetBuilderContext& context, const ProductMeshContent& mesh)
ModelAssetBuilderComponent::ProductMeshView ModelAssetBuilderComponent::CreateViewToEntireMesh(const ProductMeshContent& mesh)
{
ProductMeshView meshView;
meshView.m_name = mesh.m_name.GetStringView();
@@ -1059,16 +1122,13 @@ namespace AZ
if (!mesh.m_skinJointIndices.empty() && !mesh.m_skinWeights.empty())
{
const SceneAPI::DataTypes::ISkinRule* skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get();
const AZ::u32 maxNumSkinInfluencesPerVertex = ExtractMaxNumInfluencesPerVertex(skinRule);
AZ_Assert(mesh.m_skinJointIndices.size() == mesh.m_skinWeights.size(),
"Number of skin influence joint indices (%d) should match the number of weights (%d).",
mesh.m_skinJointIndices.size(), mesh.m_skinWeights.size());
AZ_Assert(mesh.m_skinWeights.size() % maxNumSkinInfluencesPerVertex == 0,
AZ_Assert(mesh.m_skinWeights.size() % m_numSkinJointInfluencesPerVertex == 0,
"The number of skin influences per vertex (%d) is not a multiple of the total number of skinning weights (%d). This means that not every vertex has exactly (%d) skinning weights and invalidates the data.",
mesh.m_skinWeights.size(), maxNumSkinInfluencesPerVertex, maxNumSkinInfluencesPerVertex);
mesh.m_skinWeights.size(), m_numSkinJointInfluencesPerVertex, m_numSkinJointInfluencesPerVertex);
const size_t numSkinInfluences = mesh.m_skinWeights.size();
uint32_t jointIndicesSizeInBytes = numSkinInfluences * sizeof(uint16_t);
@@ -1082,13 +1142,25 @@ namespace AZ
meshView.m_morphTargetVertexDataView = RHI::BufferViewDescriptor::CreateStructured(0, numTotalVertices, sizeof(PackedCompressedMorphTargetDelta));
}
if (!mesh.m_clothData.empty())
{
auto meshClothDataFloatCount = static_cast<uint32_t>(mesh.m_clothData.size());
AZ_Assert((meshClothDataFloatCount % ClothDataFloatsPerVert) == 0,
"Unexpected number of cloth data elements (%d), it should contain a multiple of %d elements.", meshClothDataFloatCount, ClothDataFloatsPerVert);
auto meshClothDataCount = meshClothDataFloatCount / ClothDataFloatsPerVert;
AZ_Assert(meshClothDataCount == meshPositionCount,
"Number of cloth data elements (%d) does not match the number of positions (%d) in the mesh", meshClothDataCount, meshPositionCount);
meshView.m_clothDataView = RHI::BufferViewDescriptor::CreateTyped(0, meshClothDataCount, ClothDataFormat);
}
meshView.m_materialUid = mesh.m_materialUid;
return meshView;
}
void ModelAssetBuilderComponent::MergeMeshesToCommonBuffers(
const ModelAssetBuilderContext& context,
const ProductMeshContentList& lodMeshList,
ProductMeshContent& lodMeshContent,
ProductMeshViewList& meshViews)
@@ -1120,6 +1192,7 @@ namespace AZ
auto meshNormalsFloatCount = static_cast<uint32_t>(mesh.m_normals.size());
auto meshTangentsFloatCount = static_cast<uint32_t>(mesh.m_tangents.size());
auto meshBitangentsFloatCount = static_cast<uint32_t>(mesh.m_bitangents.size());
auto meshClothDataFloatCount = static_cast<uint32_t>(mesh.m_clothData.size());
// For each element we need to:
// record the offset for the view
@@ -1199,20 +1272,24 @@ namespace AZ
}
}
if (!mesh.m_clothData.empty())
{
const uint32_t elementOffset = static_cast<uint32_t>(lodBufferInfo.m_clothDataFloatCount) / ClothDataFloatsPerVert;
meshView.m_clothDataView = RHI::BufferViewDescriptor::CreateTyped(elementOffset, meshVertexCount, ClothDataFormat);
lodBufferInfo.m_clothDataFloatCount += meshClothDataFloatCount;
}
meshView.m_materialUid = mesh.m_materialUid;
if (!mesh.m_skinJointIndices.empty() && !mesh.m_skinWeights.empty())
{
const SceneAPI::DataTypes::ISkinRule* skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get();
const AZ::u32 maxNumSkinInfluencesPerVertex = ExtractMaxNumInfluencesPerVertex(skinRule);
AZ_Assert(mesh.m_skinJointIndices.size() == mesh.m_skinWeights.size(),
"Number of skin influence joint indices (%d) should match the number of weights (%d).",
mesh.m_skinJointIndices.size(), mesh.m_skinWeights.size());
AZ_Assert(mesh.m_skinWeights.size() % maxNumSkinInfluencesPerVertex == 0,
AZ_Assert(mesh.m_skinWeights.size() % m_numSkinJointInfluencesPerVertex == 0,
"The number of skin influences per vertex (%d) is not a multiple of the total number of skinning weights (%d). This means that not every vertex has exactly (%d) skinning weights and invalidates the data.",
mesh.m_skinWeights.size(), maxNumSkinInfluencesPerVertex, maxNumSkinInfluencesPerVertex);
mesh.m_skinWeights.size(), m_numSkinJointInfluencesPerVertex, m_numSkinJointInfluencesPerVertex);
const size_t numPrevSkinInfluences = lodBufferInfo.m_skinInfluencesCount;
const size_t numNewSkinInfluences = mesh.m_skinWeights.size();
@@ -1253,6 +1330,7 @@ namespace AZ
size_t normalCount = 0;
size_t tangentCount = 0;
size_t bitangentCount = 0;
size_t clothDataCount = 0;
AZStd::vector<size_t> uvSetCounts;
AZStd::vector<size_t> colorSetCounts;
@@ -1263,6 +1341,7 @@ namespace AZ
normalCount += mesh.m_normals.size();
tangentCount += mesh.m_tangents.size();
bitangentCount += mesh.m_bitangents.size();
clothDataCount += mesh.m_clothData.size();
if (mesh.m_uvSets.size() > uvSetCounts.size())
{
@@ -1290,6 +1369,7 @@ namespace AZ
mergedMesh.m_normals.reserve(normalCount);
mergedMesh.m_tangents.reserve(tangentCount);
mergedMesh.m_bitangents.reserve(bitangentCount);
mergedMesh.m_clothData.reserve(clothDataCount);
mergedMesh.m_uvCustomNames.resize(uvSetCounts.size());
for (auto& mesh : productMeshList)
@@ -1424,6 +1504,12 @@ namespace AZ
auto& mergedMorphTargetData = mergedMesh.m_morphTargetVertexData;
mergedMorphTargetData.insert(mergedMorphTargetData.end(), sourceMorphTargetData.begin(), sourceMorphTargetData.end());
}
if (!mesh.m_clothData.empty())
{
mergedMesh.m_clothData.insert(
mergedMesh.m_clothData.end(), mesh.m_clothData.begin(), mesh.m_clothData.end());
}
}
return mergedMesh;
@@ -1522,7 +1608,6 @@ namespace AZ
};
bool ModelAssetBuilderComponent::CreateModelLodBuffers(
const ModelAssetBuilderContext& context,
const ProductMeshContent& lodBufferContent,
BufferAssetView& outIndexBuffer,
AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo>& outStreamBuffers,
@@ -1537,6 +1622,7 @@ namespace AZ
const AZStd::vector<AZ::Name>& uvCustomNames = lodBufferContent.m_uvCustomNames;
const AZStd::vector<AZStd::vector<float>>& colorSets = lodBufferContent.m_colorSets;
const AZStd::vector<AZ::Name>& colorCustomNames = lodBufferContent.m_colorCustomNames;
const AZStd::vector<float>& clothData = lodBufferContent.m_clothData;
// Build Index Buffer ...
{
@@ -1598,10 +1684,8 @@ namespace AZ
const AZStd::vector<float>& skinWeights = lodBufferContent.m_skinWeights;
if (!skinJointIndices.empty() && !skinWeights.empty())
{
const SceneAPI::DataTypes::ISkinRule* skinRule = context.m_group.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get();
const AZ::u32 maxNumSkinInfluencesPerVertex = ExtractMaxNumInfluencesPerVertex(skinRule);
const size_t vertexCount = positions.size() / PositionFloatsPerVert;
const size_t numSkinInfluences = vertexCount * maxNumSkinInfluencesPerVertex;
const size_t numSkinInfluences = vertexCount * m_numSkinJointInfluencesPerVertex;
if (!BuildRawStreamBuffer<uint16_t>(outStreamBuffers, skinJointIndices, RHI::ShaderSemantic{ShaderSemanticName_SkinJointIndices}))
{
@@ -1625,6 +1709,14 @@ namespace AZ
}
}
if (!clothData.empty())
{
if (!BuildTypedStreamBuffer<float>(outStreamBuffers, clothData, ClothDataFormat, RHI::ShaderSemantic{ ShaderSemanticName_ClothData }))
{
return false;
}
}
lodAssetCreator.SetLodIndexBuffer(outIndexBuffer.GetBufferAsset());
for (const auto& streamBufferInfo : outStreamBuffers)
@@ -1758,6 +1850,15 @@ namespace AZ
}
}
// Set cloth data buffer
if (meshView.m_clothDataView.m_elementCount > 0)
{
if (!SetMeshStreamBufferById(RHI::ShaderSemantic{ ShaderSemanticName_ClothData }, AZ::Name(), meshView.m_clothDataView, lodStreamBuffers, lodAssetCreator))
{
return false;
}
}
lodAssetCreator.EndMesh();
return true;
@@ -2014,15 +2115,5 @@ namespace AZ
return transform;
}
AZ::u32 ModelAssetBuilderComponent::ExtractMaxNumInfluencesPerVertex(const SceneAPI::DataTypes::ISkinRule* skinRule) const
{
if (skinRule)
{
return skinRule->GetMaxWeightsPerVertex();
}
return DefaultSkinInfluencesPerVert;
}
} // namespace RPI
} // namespace AZ