forked from WWU-cptr143-sprouts/sprouts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
generate.cpp
94 lines (86 loc) · 3.13 KB
/
generate.cpp
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
#include "generate.h"
namespace
{
struct Edge
{
VectorF p1, p2;
float distance;
Edge(VectorF p1, VectorF p2, float distance)
: p1(p1), p2(p2), distance(distance)
{
}
};
Edge makeStartEdge(VectorF startPoint, VectorF otherPoint, float distance, float lineWidth)
{
VectorF tangent = normalize(otherPoint - startPoint);
VectorF edgeDir = normalize(cross(tangent, VectorF(0, 0, 1)));
return Edge(startPoint - edgeDir * lineWidth, startPoint + edgeDir * lineWidth, distance);
}
Edge makeEndEdge(VectorF otherPoint, VectorF endPoint, float distance, float lineWidth)
{
VectorF tangent = normalize(endPoint - otherPoint);
VectorF edgeDir = normalize(cross(tangent, VectorF(0, 0, 1)));
return Edge(endPoint - edgeDir * lineWidth, endPoint + edgeDir * lineWidth, distance);
}
Edge makeMiddleEdge(VectorF p1, VectorF p2, VectorF p3, float distance, float lineWidth)
{
VectorF delta1 = normalize(p2 - p1);
VectorF delta2 = normalize(p2 - p3);
VectorF edgeDir = delta1 + delta2;
if(absSquared(edgeDir) < eps * eps)
{
edgeDir = normalize(cross(delta1, VectorF(0, 0, 1)));
}
else
{
edgeDir = normalize(edgeDir);
if(dot(edgeDir, cross(delta1, VectorF(0, 0, 1))) < 0)
{
edgeDir = -edgeDir;
}
}
return Edge(p2 - edgeDir * lineWidth, p2 + edgeDir * lineWidth, distance);
}
}
Mesh Generate::line(const vector<VectorF> &linePointsIn, TextureDescriptor texture, Color color,
float lineWidth)
{
if(linePointsIn.size() < 2) // if less than 2 points then we can't have a line
{
return Mesh(new Mesh_t());
}
vector<VectorF> linePoints;
linePoints.reserve(linePointsIn.size());
linePoints.push_back(linePointsIn[0]);
for(size_t i = 1; i < linePointsIn.size(); i++)
{
if(absSquared(linePointsIn[i] - linePoints.back()) >= eps * eps) // remove duplicates
linePoints.push_back(linePointsIn[i]);
}
if(linePoints.size() < 2) // if less than 2 points then we can't have a line
{
return Mesh(new Mesh_t());
}
vector<Edge> edges;
edges.reserve(linePoints.size());
float distance = 0;
edges.push_back(makeStartEdge(linePoints[0], linePoints[1], distance, lineWidth));
distance += abs(linePoints[1] - linePoints[0]);
for(size_t i = 2; i < linePoints.size(); i++)
{
edges.push_back(makeMiddleEdge(linePoints[i - 2], linePoints[i - 1], linePoints[i], distance, lineWidth));
distance += abs(linePoints[i - 1] - linePoints[i]);
}
edges.push_back(makeEndEdge(linePoints[linePoints.size() - 2], linePoints[linePoints.size() - 1], distance, lineWidth));
Mesh retval = nullptr;
for(size_t i = 1; i < edges.size(); i++)
{
TextureDescriptor currentTexture = texture.subTexture(edges[i - 1].distance / distance, edges[i].distance / distance, 0, 1);
Mesh mesh = Generate::quadrilateral(currentTexture, edges[i - 1].p2, color, edges[i].p2, color, edges[i].p1, color, edges[i - 1].p1, color);
if(retval == nullptr)
retval = mesh;
else
retval->add(mesh);
}
return retval;
}