Skip to content

Commit

Permalink
#5382: Make sure the merged patches are facing the same direction
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Dec 13, 2020
1 parent 8a91501 commit fa02e0a
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 6 deletions.
2 changes: 1 addition & 1 deletion include/version.h
Expand Up @@ -2,7 +2,7 @@
#include <config.h>
#define RADIANT_VERSION PACKAGE_VERSION
#else
#define RADIANT_VERSION "2.10.0pre1"
#define RADIANT_VERSION "2.10.0pre2"
#endif

#define RADIANT_APPNAME "DarkRadiant"
Expand Down
35 changes: 33 additions & 2 deletions radiantcore/patch/algorithm/General.cpp
Expand Up @@ -166,6 +166,8 @@ void bulge(const cmd::ArgumentList& args)
namespace
{

constexpr double WELD_EPSILON = 0.001;

// Returns true if <num> elements in the given sequences are equal
inline bool firstNItemsAreEqual(const PatchControlIterator& sequence1,
const PatchControlIterator& sequence2, std::size_t num, double epsilon)
Expand Down Expand Up @@ -215,12 +217,39 @@ struct PatchEdge
EdgeType edgeType;
};

void correctPatchOrientation(const IPatch& originalPatch, IPatch& mergedPatch)
{
auto refVertex = originalPatch.getTesselatedPatchMesh().vertices[0];
auto mergedMesh = mergedPatch.getTesselatedPatchMesh();
bool vertexFound = false;

// Find a matching 3D vertex and compare its normals, they should match
for (auto h = 0; h < mergedMesh.height; ++h)
{
for (auto w = 0; w < mergedMesh.width; ++w)
{
const auto& mergedVertex = mergedMesh.vertices[h * mergedMesh.width + w];

if (!mergedVertex.vertex.isEqual(refVertex.vertex, WELD_EPSILON))
{
continue;
}

// Found a matching vertex, its normal might have changed after merging,
// but the overall direction its facing should be ok, so assume they're equal +/-half_pi
if (std::abs(mergedVertex.normal.angle(refVertex.normal)) > c_half_pi)
{
rMessage() << "Reversing patch matrix" << std::endl;
mergedPatch.invertMatrix();
}
}
}
}

}

scene::INodePtr createdMergedPatch(const PatchNodePtr& patchNode1, const PatchNodePtr& patchNode2)
{
constexpr double WELD_EPSILON = 0.001;

auto& patch1 = patchNode1->getPatch();
auto& patch2 = patchNode2->getPatch();

Expand Down Expand Up @@ -294,6 +323,8 @@ scene::INodePtr createdMergedPatch(const PatchNodePtr& patchNode1, const PatchNo

newPatch.controlPointsChanged();

correctPatchOrientation(patch1, newPatch);

return newPatchNode; // success
}
}
Expand Down
33 changes: 30 additions & 3 deletions test/PatchWelding.cpp
Expand Up @@ -42,10 +42,37 @@ scene::INodePtr performPatchWelding(const std::string& number1, const std::strin
EXPECT_FALSE(firstPatch->getParent());
EXPECT_FALSE(secondPatch->getParent());

// Check patch orientation
auto& refPatch = std::dynamic_pointer_cast<IPatchNode>(firstPatch)->getPatch();

auto mergedPatchNode = GlobalSelectionSystem().ultimateSelected();
auto& mergedPatch = std::dynamic_pointer_cast<IPatchNode>(mergedPatchNode)->getPatch();

auto refVertex = refPatch.getTesselatedPatchMesh().vertices[0];
auto mergedMesh = mergedPatch.getTesselatedPatchMesh();
bool vertexFound = false;

// Find a matching 3D vertex and compare its normals, they should match
for (auto h = 0; h < mergedMesh.height; ++h)
{
for (auto w = 0; w < mergedMesh.width; ++w)
{
const auto& mergedVertex = mergedMesh.vertices[h * mergedMesh.width + w];

if (mergedVertex.vertex.isEqual(refVertex.vertex, 0.01))
{
vertexFound = true;
EXPECT_LT(std::abs(mergedVertex.normal.angle(refVertex.normal)), c_half_pi);
}
}
}

EXPECT_TRUE(vertexFound) << "Didn't find a matching vertex to compare the normals.";

return GlobalSelectionSystem().ultimateSelected();
}

void verifyPatchDimensions(const scene::INodePtr& mergedPatchNode, int expectedRows, int expectedCols)
void verifyMergedPatch(const scene::INodePtr& mergedPatchNode, int expectedRows, int expectedCols)
{
auto merged = std::dynamic_pointer_cast<IPatchNode>(mergedPatchNode);
EXPECT_EQ(merged->getPatch().getHeight(), expectedRows);
Expand Down Expand Up @@ -84,7 +111,7 @@ TEST_P(PatchWelding3x3, WeldWithOther3x3Patch)
auto expectedRows = std::get<2>(GetParam());
auto expectedColumns = std::get<3>(GetParam());

verifyPatchDimensions(performPatchWelding(firstPatch, secondPatch), expectedRows, expectedColumns);
verifyMergedPatch(performPatchWelding(firstPatch, secondPatch), expectedRows, expectedColumns);
}

// Patch 1 is sharing its first row
Expand Down Expand Up @@ -154,7 +181,7 @@ TEST_F(PatchWeldingTest, WeldStackedCylinders)
loadMap("weld_patches.mapx");

// Welding the two cylinders produce a 5rows x 9cols patch
verifyPatchDimensions(performPatchWelding("11", "12"), 5, 9);
verifyMergedPatch(performPatchWelding("11", "12"), 5, 9);
}

TEST_F(PatchWeldingTest, WeldedPatchInheritsLayers)
Expand Down

0 comments on commit fa02e0a

Please sign in to comment.