|
@@ -24,9 +24,17 @@ namespace SurfaceData
|
|
using SurfaceTagVector = AZStd::vector<SurfaceTag>;
|
|
using SurfaceTagVector = AZStd::vector<SurfaceTag>;
|
|
|
|
|
|
//! SurfaceTagWeights stores a collection of surface tags and weights.
|
|
//! SurfaceTagWeights stores a collection of surface tags and weights.
|
|
|
|
+ //! A surface tag can only appear once in the collection. Attempting to add it multiple times will always preserve the
|
|
|
|
+ //! highest weight value.
|
|
class SurfaceTagWeights
|
|
class SurfaceTagWeights
|
|
{
|
|
{
|
|
public:
|
|
public:
|
|
|
|
+ //! The maximum number of surface weights that we can store.
|
|
|
|
+ //! For performance reasons, we want to limit this so that we can preallocate the max size in advance.
|
|
|
|
+ //! The current number is chosen to be higher than expected needs, but small enough to avoid being excessively wasteful.
|
|
|
|
+ //! (Dynamic structures would end up taking more memory than what we're preallocating)
|
|
|
|
+ static inline constexpr size_t MaxSurfaceWeights = 16;
|
|
|
|
+
|
|
SurfaceTagWeights() = default;
|
|
SurfaceTagWeights() = default;
|
|
|
|
|
|
//! Construct a collection of SurfaceTagWeights from the given SurfaceTagWeightList.
|
|
//! Construct a collection of SurfaceTagWeights from the given SurfaceTagWeightList.
|
|
@@ -45,42 +53,68 @@ namespace SurfaceData
|
|
//! @param weight - The weight to assign to each tag.
|
|
//! @param weight - The weight to assign to each tag.
|
|
void AssignSurfaceTagWeights(const SurfaceTagVector& tags, float weight);
|
|
void AssignSurfaceTagWeights(const SurfaceTagVector& tags, float weight);
|
|
|
|
|
|
- //! Add a surface tag weight to this collection.
|
|
|
|
- //! @param tag - The surface tag.
|
|
|
|
- //! @param weight - The surface tag weight.
|
|
|
|
- void AddSurfaceTagWeight(const AZ::Crc32 tag, const float weight);
|
|
|
|
-
|
|
|
|
- //! Replace the surface tag weight with the new one if it's higher, or add it if the tag isn't found.
|
|
|
|
|
|
+ //! Add a surface tag weight to this collection. If the tag already exists, the higher weight will be preserved.
|
|
//! (This method is intentionally inlined for its performance impact)
|
|
//! (This method is intentionally inlined for its performance impact)
|
|
//! @param tag - The surface tag.
|
|
//! @param tag - The surface tag.
|
|
//! @param weight - The surface tag weight.
|
|
//! @param weight - The surface tag weight.
|
|
- void AddSurfaceWeightIfGreater(const AZ::Crc32 tag, const float weight)
|
|
|
|
|
|
+ void AddSurfaceTagWeight(const AZ::Crc32 tag, const float weight)
|
|
{
|
|
{
|
|
- const auto maskItr = m_weights.find(tag);
|
|
|
|
- const float previousValue = maskItr != m_weights.end() ? maskItr->second : 0.0f;
|
|
|
|
- m_weights[tag] = AZ::GetMax(weight, previousValue);
|
|
|
|
|
|
+ for (auto weightItr = m_weights.begin(); weightItr != m_weights.end(); ++weightItr)
|
|
|
|
+ {
|
|
|
|
+ // Since we need to scan for duplicate surface types, store the entries sorted by surface type so that we can
|
|
|
|
+ // early-out once we pass the location for the entry instead of always searching every entry.
|
|
|
|
+ if (weightItr->m_surfaceType > tag)
|
|
|
|
+ {
|
|
|
|
+ if (m_weights.size() != MaxSurfaceWeights)
|
|
|
|
+ {
|
|
|
|
+ // We didn't find the surface type, so add the new entry in sorted order.
|
|
|
|
+ m_weights.insert(weightItr, { tag, weight });
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ AZ_Assert(false, "SurfaceTagWeights has reached max capacity, it cannot add a new tag / weight.");
|
|
|
|
+ }
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ else if (weightItr->m_surfaceType == tag)
|
|
|
|
+ {
|
|
|
|
+ // We found the surface type, so just keep the higher of the two weights.
|
|
|
|
+ weightItr->m_weight = AZ::GetMax(weight, weightItr->m_weight);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // We didn't find the surface weight, and the sort order for it is at the end, so add it to the back of the list.
|
|
|
|
+ if (m_weights.size() != MaxSurfaceWeights)
|
|
|
|
+ {
|
|
|
|
+ m_weights.emplace_back(tag, weight);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ AZ_Assert(false, "SurfaceTagWeights has reached max capacity, it cannot add a new tag / weight.");
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- //! Replace the surface tag weight with the new one if it's higher, or add it if the tag isn't found.
|
|
|
|
|
|
+ //! Add surface tags and weights to this collection. If a tag already exists, the higher weight will be preserved.
|
|
//! (This method is intentionally inlined for its performance impact)
|
|
//! (This method is intentionally inlined for its performance impact)
|
|
//! @param tags - The surface tags to replace/add.
|
|
//! @param tags - The surface tags to replace/add.
|
|
//! @param weight - The surface tag weight to use for each tag.
|
|
//! @param weight - The surface tag weight to use for each tag.
|
|
- void AddSurfaceWeightsIfGreater(const SurfaceTagVector& tags, const float weight)
|
|
|
|
|
|
+ void AddSurfaceTagWeights(const SurfaceTagVector& tags, const float weight)
|
|
{
|
|
{
|
|
for (const auto& tag : tags)
|
|
for (const auto& tag : tags)
|
|
{
|
|
{
|
|
- AddSurfaceWeightIfGreater(tag, weight);
|
|
|
|
|
|
+ AddSurfaceTagWeight(tag, weight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- //! Replace the surface tag weight with the new one if it's higher, or add it if the tag isn't found.
|
|
|
|
|
|
+ //! Add surface tags and weights to this collection. If a tag already exists, the higher weight will be preserved.
|
|
//! (This method is intentionally inlined for its performance impact)
|
|
//! (This method is intentionally inlined for its performance impact)
|
|
//! @param weights - The surface tags and weights to replace/add.
|
|
//! @param weights - The surface tags and weights to replace/add.
|
|
- void AddSurfaceWeightsIfGreater(const SurfaceTagWeights& weights)
|
|
|
|
|
|
+ void AddSurfaceTagWeights(const SurfaceTagWeights& weights)
|
|
{
|
|
{
|
|
for (const auto& [tag, weight] : weights.m_weights)
|
|
for (const auto& [tag, weight] : weights.m_weights)
|
|
{
|
|
{
|
|
- AddSurfaceWeightIfGreater(tag, weight);
|
|
|
|
|
|
+ AddSurfaceTagWeight(tag, weight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -125,7 +159,7 @@ namespace SurfaceData
|
|
//! Check to see if the collection contains the given tag.
|
|
//! Check to see if the collection contains the given tag.
|
|
//! @param sampleTag - The tag to look for.
|
|
//! @param sampleTag - The tag to look for.
|
|
//! @return True if the tag is found, false if it isn't.
|
|
//! @return True if the tag is found, false if it isn't.
|
|
- bool HasMatchingTag(const AZ::Crc32& sampleTag) const;
|
|
|
|
|
|
+ bool HasMatchingTag(AZ::Crc32 sampleTag) const;
|
|
|
|
|
|
//! Check to see if the collection contains the given tag with the given weight range.
|
|
//! Check to see if the collection contains the given tag with the given weight range.
|
|
//! The range check is inclusive on both sides of the range: [weightMin, weightMax]
|
|
//! The range check is inclusive on both sides of the range: [weightMin, weightMax]
|
|
@@ -133,7 +167,7 @@ namespace SurfaceData
|
|
//! @param weightMin - The minimum weight for this tag.
|
|
//! @param weightMin - The minimum weight for this tag.
|
|
//! @param weightMax - The maximum weight for this tag.
|
|
//! @param weightMax - The maximum weight for this tag.
|
|
//! @return True if the tag is found, false if it isn't.
|
|
//! @return True if the tag is found, false if it isn't.
|
|
- bool HasMatchingTag(const AZ::Crc32& sampleTag, float weightMin, float weightMax) const;
|
|
|
|
|
|
+ bool HasMatchingTag(AZ::Crc32 sampleTag, float weightMin, float weightMax) const;
|
|
|
|
|
|
//! Check to see if the collection contains any of the given tags.
|
|
//! Check to see if the collection contains any of the given tags.
|
|
//! @param sampleTags - The tags to look for.
|
|
//! @param sampleTags - The tags to look for.
|
|
@@ -149,7 +183,12 @@ namespace SurfaceData
|
|
bool HasAnyMatchingTags(const SurfaceTagVector& sampleTags, float weightMin, float weightMax) const;
|
|
bool HasAnyMatchingTags(const SurfaceTagVector& sampleTags, float weightMin, float weightMax) const;
|
|
|
|
|
|
private:
|
|
private:
|
|
- AZStd::unordered_map<AZ::Crc32, float> m_weights;
|
|
|
|
|
|
+ //! Search for the given tag entry.
|
|
|
|
+ //! @param tag - The tag to search for.
|
|
|
|
+ //! @return The pointer to the tag that's found, or end() if it wasn't found.
|
|
|
|
+ const AzFramework::SurfaceData::SurfaceTagWeight* FindTag(AZ::Crc32 tag) const;
|
|
|
|
+
|
|
|
|
+ AZStd::fixed_vector<AzFramework::SurfaceData::SurfaceTagWeight, MaxSurfaceWeights> m_weights;
|
|
};
|
|
};
|
|
|
|
|
|
//! SurfacePointList stores a collection of surface point data, which consists of positions, normals, and surface tag weights.
|
|
//! SurfacePointList stores a collection of surface point data, which consists of positions, normals, and surface tag weights.
|