Skip to content

Commit

Permalink
#5746: Implement face vertex manipulation for two selected vertices
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Sep 22, 2021
1 parent 8fa388f commit 050e3b7
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 9 deletions.
44 changes: 43 additions & 1 deletion radiantcore/selection/textool/FaceNode.h
Expand Up @@ -74,7 +74,7 @@ class FaceNode :
auto selectionCount = selectedIndices.size();

Vector3 vertices[3];
Vector2 texcoords[2];
Vector2 texcoords[3];
const auto& winding = _face.getWinding();

if (selectionCount >= 3)
Expand All @@ -87,6 +87,23 @@ class FaceNode :
texcoords[i] = _vertices[selectedIndices[i]].getTexcoord();
}

_face.setTexDefFromPoints(vertices, texcoords);
}
else if (selectionCount == 2)
{
// Calculate the center point of the selection and pick the vertex that is farthest from it
auto selectionBounds = getSelectedComponentBounds();
auto farthestIndex = findIndexFarthestFrom({ selectionBounds.origin.x(), selectionBounds.origin.y() });

for (std::size_t i = 0; i < 2; ++i)
{
vertices[i] = _vertices[selectedIndices[i]].getVertex();
texcoords[i] = _vertices[selectedIndices[i]].getTexcoord();
}

vertices[2] = _vertices[farthestIndex].getVertex();
texcoords[2] = _vertices[farthestIndex].getTexcoord();

_face.setTexDefFromPoints(vertices, texcoords);
}
}
Expand Down Expand Up @@ -164,6 +181,31 @@ class FaceNode :
renderComponents();
}
}

private:
// Locates the index of the unselected vertex that is farthest away from the given texcoord
std::size_t findIndexFarthestFrom(const Vector2& texcoord)
{
assert(!_vertices.empty());

std::size_t farthestIndex = 0;
double largestDistanceSquared = 0;

for (std::size_t i = 0; i < _vertices.size(); ++i)
{
if (_vertices[i].isSelected()) continue;

auto candidateDistanceSquared = (_vertices[i].getTexcoord() - texcoord).getLengthSquared();

if (candidateDistanceSquared > largestDistanceSquared)
{
farthestIndex = i;
largestDistanceSquared = candidateDistanceSquared;
}
}

return farthestIndex;
}
};

}
19 changes: 11 additions & 8 deletions test/TextureTool.cpp
Expand Up @@ -1036,24 +1036,27 @@ TEST_F(TextureToolTest, DragManipulateSingleFaceVertex)
// Dragging two selected vertices chooses the one vertex as anchor point which is farthest away from the clicked vertex
TEST_F(TextureToolTest, DragManipulateTwoFaceVertices)
{
// Vertices 0 and 2 are opposite of each other, but 0 takes the lead
// Vertices 0 and 2 are opposite of each other
std::size_t firstVertex = 0;
std::size_t secondVertex = 2;
performFaceVertexManipulationTest(false, { firstVertex, secondVertex }, [&](IFace& face,
const std::vector<Vector2>& oldTexcoords, const std::vector<Vector2>& changedTexcoords)
{
// Find out which face vertex was the farthest away from the first one
int farthestIndex = 1;
double largestDistance = 0;
for (int i = 0; i < oldTexcoords.size(); ++i)
auto center = (changedTexcoords[firstVertex] + changedTexcoords[secondVertex]) * 0.5;
// Find out which face vertex was the farthest away from the bounds center of the selection
std::size_t farthestIndex = 0;
double largestDistanceSquared = 0;

for (std::size_t i = 0; i < changedTexcoords.size(); ++i)
{
if (i == firstVertex || i == secondVertex) continue;

auto candidateDistance = (oldTexcoords[i] - oldTexcoords[firstVertex]).getLengthSquared();
if (candidateDistance > largestDistance)
auto candidateDistanceSquared = (changedTexcoords[i] - center).getLengthSquared();

if (candidateDistanceSquared > largestDistanceSquared)
{
farthestIndex = i;
largestDistance = candidateDistance;
largestDistanceSquared = candidateDistanceSquared;
}
}

Expand Down

0 comments on commit 050e3b7

Please sign in to comment.