Skip to content

Commit

Permalink
#5622: Implement fingerprinting of brush nodes (layer or grouping inf…
Browse files Browse the repository at this point in the history
…ormation are disregarded)
  • Loading branch information
codereader committed May 22, 2021
1 parent d70645d commit f27c073
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
37 changes: 37 additions & 0 deletions radiantcore/brush/BrushNode.cpp
Expand Up @@ -7,6 +7,7 @@
#include "iclipper.h"
#include "ientity.h"
#include "math/Frustum.h"
#include "math/Hash.h"
#include <functional>

// Constructor
Expand Down Expand Up @@ -60,6 +61,42 @@ const AABB& BrushNode::localAABB() const {
return m_brush.localAABB();
}

std::size_t BrushNode::getFingerprint()
{
constexpr std::size_t SignificantDigits = 6;

if (m_brush.getNumFaces() == 0)
{
return 0; // empty brushes produce a zero fingerprint
}

auto hash = static_cast<std::size_t>(m_brush.getDetailFlag() + 1);

math::combineHash(hash, m_brush.getNumFaces());

// Combine all face plane equations
for (const auto& face : m_brush)
{
// Plane equation
math::combineHash(hash, math::hashVector3(face->getPlane3().normal(), SignificantDigits));
math::combineHash(hash, math::hashDouble(face->getPlane3().dist(), SignificantDigits));

// Material Name
math::combineHash(hash, std::hash<std::string>()(face->getShader()));

// Texture Matrix
auto texdef = face->getTexDefMatrix();
math::combineHash(hash, math::hashDouble(texdef.xx(), SignificantDigits));
math::combineHash(hash, math::hashDouble(texdef.yx(), SignificantDigits));
math::combineHash(hash, math::hashDouble(texdef.tx(), SignificantDigits));
math::combineHash(hash, math::hashDouble(texdef.xy(), SignificantDigits));
math::combineHash(hash, math::hashDouble(texdef.yy(), SignificantDigits));
math::combineHash(hash, math::hashDouble(texdef.ty(), SignificantDigits));
}

return hash;
}

// Snappable implementation
void BrushNode::snapto(float snap) {
m_brush.snapto(snap);
Expand Down
9 changes: 7 additions & 2 deletions radiantcore/brush/BrushNode.h
Expand Up @@ -4,6 +4,7 @@
#include "ibrush.h"
#include "itraceable.h"
#include "iscenegraph.h"
#include "icomparablenode.h"

#include "Brush.h"
#include "scene/SelectableNode.h"
Expand All @@ -29,7 +30,8 @@ class BrushNode :
public PlaneSelectable,
public LitObject,
public Transformable,
public ITraceable
public ITraceable,
public scene::IComparableNode
{
// The actual contained brush (NO reference)
Brush m_brush;
Expand Down Expand Up @@ -71,7 +73,7 @@ class BrushNode :

virtual ~BrushNode();

// IBrushNode implementtation
// IBrushNode implementation
virtual Brush& getBrush() override;
virtual IBrush& getIBrush() override;

Expand All @@ -82,6 +84,9 @@ class BrushNode :

Type getNodeType() const override;

// IComparable implementation
std::size_t getFingerprint() override;

// Bounded implementation
virtual const AABB& localAABB() const override;

Expand Down
6 changes: 3 additions & 3 deletions radiantcore/map/algorithm/Import.cpp
Expand Up @@ -376,18 +376,18 @@ void importFromStream(std::istream& stream)
using Fingerprints = std::map<std::size_t, scene::INodePtr>;
using FingerprintsByType = std::map<scene::INode::Type, Fingerprints>;

FingerprintsByType collectFingerprints(const scene::INodePtr& node)
FingerprintsByType collectFingerprints(const scene::INodePtr& root)
{
FingerprintsByType result;

node->foreachNode([&](const scene::INodePtr& node)
root->foreachNode([&](const scene::INodePtr& node)
{
auto comparable = std::dynamic_pointer_cast<scene::IComparableNode>(node);

if (!comparable) return true; // skip

// Find or insert the map for this node type
auto fingerprints = result.try_emplace(comparable->getNodeType()).first->second;
auto& fingerprints = result.try_emplace(comparable->getNodeType()).first->second;

// Store the fingerprint and check for collisions
auto insertResult = fingerprints.try_emplace(comparable->getFingerprint(), node);
Expand Down

0 comments on commit f27c073

Please sign in to comment.