-
Notifications
You must be signed in to change notification settings - Fork 378
/
GenCylGenerators.cs
137 lines (115 loc) · 5.25 KB
/
GenCylGenerators.cs
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
135
136
137
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace g3
{
public class TubeGenerator : MeshGenerator
{
public List<Vector3d> Vertices;
public Polygon2d Polygon;
public bool Capped = true;
// [TODO] Frame3d ??
public Frame3f Frame = Frame3f.Identity;
// set to true if you are going to texture this or want sharp edges
public bool NoSharedVertices = true;
public int startCapCenterIndex = -1;
public int endCapCenterIndex = -1;
override public void Generate()
{
if (Polygon == null)
Polygon = Polygon2d.MakeCircle(1.0f, 8);
int Slices = Polygon.VertexCount;
int nRings = Vertices.Count;
int nRingSize = (NoSharedVertices) ? Slices + 1 : Slices;
int nCapVertices = (NoSharedVertices) ? Slices + 1 : 1;
if (Capped == false)
nCapVertices = 0;
vertices = new VectorArray3d(nRings * nRingSize + 2 * nCapVertices);
uv = new VectorArray2f(vertices.Count);
normals = new VectorArray3f(vertices.Count);
int nSpanTris = (Vertices.Count - 1) * (2 * Slices);
int nCapTris = (Capped) ? 2 * Slices : 0;
triangles = new IndexArray3i(nSpanTris + nCapTris);
Frame3f fCur = new Frame3f(Frame);
Vector3d dv = CurveUtils.GetTangent(Vertices, 0); ;
fCur.Origin = (Vector3f)Vertices[0];
fCur.AlignAxis(2, (Vector3f)dv);
Frame3f fStart = new Frame3f(fCur);
// generate tube
for (int ri = 0; ri < nRings; ++ri) {
// propagate frame
if (ri != 0) {
Vector3d tan = CurveUtils.GetTangent(Vertices, ri);
fCur.Origin = (Vector3f)Vertices[ri];
if (ri == 11)
dv = tan;
fCur.AlignAxis(2, (Vector3f)tan);
}
float uv_along = (float)ri / (float)(nRings - 1);
// generate vertices
int nStartR = ri * nRingSize;
for (int j = 0; j < nRingSize; ++j) {
float uv_around = (float)j / (float)(nRings);
int k = nStartR + j;
Vector2d pv = Polygon.Vertices[j % Slices];
Vector3d v = fCur.FromFrameP((Vector2f)pv, 2);
vertices[k] = v;
uv[k] = new Vector2f(uv_along, uv_around);
Vector3f n = (Vector3f)(v - fCur.Origin).Normalized;
normals[k] = n;
}
}
// generate triangles
int ti = 0;
for (int ri = 0; ri < nRings-1; ++ri) {
int r0 = ri * nRingSize;
int r1 = r0 + nRingSize;
for (int k = 0; k < nRingSize - 1; ++k) {
triangles.Set(ti++, r0 + k, r0 + k + 1, r1 + k + 1, Clockwise);
triangles.Set(ti++, r0 + k, r1 + k + 1, r1 + k, Clockwise);
}
if (NoSharedVertices == false) { // close disc if we went all the way
triangles.Set(ti++, r1 - 1, r0, r1, Clockwise);
triangles.Set(ti++, r1 - 1, r1, r1 + nRingSize - 1, Clockwise);
}
}
if (Capped) {
// add endcap verts
int nBottomC = nRings * nRingSize;
vertices[nBottomC] = fStart.Origin;
uv[nBottomC] = new Vector2f(0.5f, 0.5f);
normals[nBottomC] = -fStart.Z;
startCapCenterIndex = nBottomC;
int nTopC = nBottomC + 1;
vertices[nTopC] = fCur.Origin;
uv[nTopC] = new Vector2f(0.5f, 0.5f);
normals[nTopC] = fCur.Z;
endCapCenterIndex = nTopC;
if (NoSharedVertices) {
// duplicate first loop and make a fan w/ bottom-center
int nExistingB = 0;
int nStartB = nTopC + 1;
for (int k = 0; k < Slices; ++k) {
vertices[nStartB + k] = vertices[nExistingB + k];
uv[nStartB + k] = (Vector2f)Polygon.Vertices[k].Normalized;
normals[nStartB + k] = normals[nBottomC];
}
append_disc(Slices, nBottomC, nStartB, true, Clockwise, ref ti);
// duplicate second loop and make fan
int nExistingT = nRingSize * (nRings - 1);
int nStartT = nStartB + Slices;
for (int k = 0; k < Slices; ++k) {
vertices[nStartT + k] = vertices[nExistingT + k];
uv[nStartT + k] = (Vector2f)Polygon.Vertices[k].Normalized;
normals[nStartT + k] = normals[nTopC];
}
append_disc(Slices, nTopC, nStartT, true, !Clockwise, ref ti);
} else {
append_disc(Slices, nBottomC, 0, true, Clockwise, ref ti);
append_disc(Slices, nTopC, nRingSize * (nRings-1), true, !Clockwise, ref ti);
}
}
}
}
}