/
PatchNode.h
134 lines (108 loc) · 3.31 KB
/
PatchNode.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#pragma once
#include "ipatch.h"
#include "itextstream.h"
#include "NodeBase.h"
namespace textool
{
class PatchNode :
public NodeBase
{
private:
IPatch& _patch;
mutable AABB _bounds;
public:
PatchNode(IPatch& patch) :
_patch(patch)
{}
void beginTransformation() override
{
// We call undoSave() here for consistency, but technically it's too early -
// the undo operation hasn't started yet
_patch.undoSave();
}
void revertTransformation() override
{
_patch.revertTransform();
_patch.updateTesselation();
}
void applyTransformToSelected(const Matrix3& transform) override
{
foreachVertex([&](PatchControl& vertex)
{
vertex.texcoord = transform * vertex.texcoord;
});
// We have to force the patch to update its tesselation since
// modifying the "transformed" control point set won't trigger this
_patch.updateTesselation(true);
}
void commitTransformation() override
{
// Patch::freezeTransform will call undoSave() before overwriting
// the control point set with the transformed ones
_patch.freezeTransform();
}
const AABB& localAABB() const
{
_bounds = AABB();
foreachVertex([&](PatchControl& vertex)
{
_bounds.includePoint({ vertex.texcoord.x(), vertex.texcoord.y(), 0 });
});
return _bounds;
}
void testSelect(Selector& selector, SelectionTest& test) override
{
test.BeginMesh(Matrix4::getIdentity(), true);
foreachVertex([&](PatchControl& vertex)
{
SelectionIntersection intersection;
test.TestPoint(Vector3(vertex.texcoord.x(), vertex.texcoord.y(), 0), intersection);
if (intersection.isValid())
{
Selector_add(selector, *this);
}
});
}
void render() override
{
glEnable(GL_BLEND);
glBlendColor(0, 0, 0, 0.3f);
glBlendFunc(GL_CONSTANT_ALPHA_EXT, GL_ONE_MINUS_CONSTANT_ALPHA_EXT);
if (isSelected())
{
glColor3f(1, 0.5f, 0);
}
else
{
glColor3f(0.8f, 0.8f, 0.8f);
}
// Get the tesselation and the first
auto tess = _patch.getTesselatedPatchMesh();
auto renderInfo = _patch.getRenderIndices();
auto* strip_indices = &renderInfo.indices.front();
for (std::size_t i = 0; i < renderInfo.numStrips; i++, strip_indices += renderInfo.lenStrips)
{
glBegin(GL_QUAD_STRIP);
for (std::size_t offset = 0; offset < renderInfo.lenStrips; offset++)
{
// Retrieve the mesh vertex from the line strip
auto& meshVertex = tess.vertices[*(strip_indices + offset)];
glVertex2d(meshVertex.texcoord[0], meshVertex.texcoord[1]);
}
glEnd();
}
glDisable(GL_BLEND);
}
private:
void foreachVertex(const std::function<void(PatchControl&)>& functor) const
{
for (std::size_t col = 0; col < _patch.getWidth(); ++col)
{
for (std::size_t row = 0; row < _patch.getHeight(); ++row)
{
functor(_patch.getTransformedCtrlAt(row, col));
}
}
}
};
}