Cogs.Core
LoftedCrossSectionsSystemShell.cpp
1#include <glm/gtc/type_ptr.hpp>
2#include "LoftedCrossSectionsSystem.h"
3#define COGS_TABLE_SHELL
4#include "LoftedCrossSectionsSystem_tables.h"
5
6using glm::vec2;
7using glm::vec3;
8using glm::dot;
9using glm::mix;
10using glm::make_vec2;
11using glm::make_vec3;
12using glm::normalize;
13
14using std::abs;
15using std::vector;
16
17void Cogs::Core::LoftedCrossSectionsSystem::shellInitialize()
18{
19 shellCellClassCounts.resize(16);
20 for (int code = 0; code < 16; code++) {
21 CellClassCounts counts = { 0, 0, 0, 0 };
22
23 int N = triangle_table_shell[code].n;
24 unsigned char* indices = triangle_table_shell[code].indices;
25 for (int l = 0; l < N; l++) {
26 int ix_a = indices[l] & 0x3;
27 int ix_b = (indices[l] >> 4) & 0x3;
28 if (ix_a == ix_b) {
29 counts.outIndices++;
30 }
31 else {
32 counts.newVertices++;
33 counts.outIndices++;
34 }
35 }
36 shellCellClassCounts[code] = counts;
37 }
38}
39
40
41void Cogs::Core::LoftedCrossSectionsSystem::shellOpenAlignedClassifySamples(vector<uint8_t>& inside,
42 const float* pos, const size_t pos_stride,
43 const vector<vec3>& spine,
44 const vec3& viewer,
45 const int slices, const int samples)
46{
47 inside.resize(slices*samples);
48 for (int j = 0; j < slices; j++) {
49 for (int i = 0; i < samples; i++) {
50 const vec3 p = make_vec3(pos + pos_stride*(j*samples + i));
51 inside[j*samples + i] = dot(viewer - p, p - spine[j]) <= 0.0f;
52 }
53 }
54}
55
56void Cogs::Core::LoftedCrossSectionsSystem::shellOpenAlignedCountCellResources(size_t& newVertices,
57 size_t& outIndices,
58 vector<uint8_t>& classification,
59 const vector<vec3>& /*spine*/,
60 const vector<uint8_t>& inside,
61 const vec3& /*viewer*/,
62 const int slices, const int samples, const bool doubleSeam)
63{
64 classification.resize(slices*samples);
65 newVertices = 0;
66 outIndices = 0;
67
68 for (int k = 0; k < slices - 1; k++) {
69 for (int i = 0; i < (doubleSeam ? samples - 1 : samples); i++) {
70 int ii = (i + 1) % samples;
71 uint8_t code = ((inside[(k + 0)*samples + i] ? 1 : 0) |
72 (inside[(k + 0)*samples + ii] ? 2 : 0) |
73 (inside[(k + 1)*samples + i] ? 4 : 0) |
74 (inside[(k + 1)*samples + ii] ? 8 : 0));
75
76 classification[k*samples + i] = code;
77 const CellClassCounts& counts = shellCellClassCounts[code];
78 outIndices += counts.outIndices;
79 newVertices += counts.newVertices;
80 }
81 }
82}
83
84
85void Cogs::Core::LoftedCrossSectionsSystem::shellOpenAlignedSkin(vector<unsigned int>& outSurface,
86 float* pos, const size_t pos_stride,
87 float* tex, const size_t tex_stride,
88 float* nrm, const size_t nrm_stride,
89 const vector<uint8_t>& classification,
90 const vector<vec3>& spine,
91 const vec3& viewer,
92 const int slices, const int samples, const bool doubleSeam)
93{
94 unsigned int newVertex = samples * slices;
95 unsigned int outIndex = 0;
96
97 for (int k = 0; k < slices - 1; k++) {
98 for (int i = 0; i < (doubleSeam ? samples - 1 : samples); i++) {
99 int ii = (i + 1) % samples;
100 int ix[4] = {
101 (k + 0)*samples + i, (k + 0)*samples + ii,
102 (k + 1)*samples + i, (k + 1)*samples + ii,
103 };
104
105 int code = classification[k*samples + i];
106
107 int N = triangle_table_shell[code].n;
108 unsigned char* indices = triangle_table_shell[code].indices;
109 for (int l = 0; l < N; l++) {
110 int ix_a = indices[l] & 0x3;
111 int ix_b = (indices[l] >> 4) & 0x3;
112 if (ix_a == ix_b) {
113 outSurface[outIndex++] = ix[ix_a];
114 }
115 else {
116 int a = ix[ix_a];
117 int b = ix[ix_b];
118 int a_j = k + ((ix_a & 0x2) == 0 ? 0 : 1);
119 int b_j = k + ((ix_b & 0x2) == 0 ? 0 : 1);
120
121 const vec3 ap = make_vec3(pos + pos_stride*a);
122 const vec3 bp = make_vec3(pos + pos_stride*b);
123
124 vec3 va = normalize(viewer - ap);
125 vec3 vb = normalize(viewer - bp);
126 vec3 na = normalize(ap - spine[a_j]);
127 vec3 nb = normalize(bp - spine[b_j]);
128#if 0
129 float fa = std::acos(glm::dot(va, na)) - float(M_PI_2);
130 float fb = std::acos(glm::dot(vb, nb)) - float(M_PI_2);
131#else
132 float fa = dot(va, na);
133 float fb = dot(vb, nb);
134#endif
135 const float t = fa*fb < 0.f ? fa / (fa - fb) : (abs(fa) < abs(fb) ? 0.f : 1.f);
136
137 const vec3 p = mix(ap, bp, t);
138 *reinterpret_cast<vec3*>(pos + pos_stride*newVertex) = p;
139
140 if (tex_stride) {
141 const vec2 at = make_vec2(tex + tex_stride*a);
142 const vec2 bt = make_vec2(tex + tex_stride*b);
143 *reinterpret_cast<vec2*>(tex + tex_stride*newVertex) = mix(at, bt, t);
144 }
145 if (nrm_stride) {
146 const vec3 an = make_vec3(nrm + nrm_stride*a);
147 const vec3 bn = make_vec3(nrm + nrm_stride*b);
148 *reinterpret_cast<vec3*>(nrm + nrm_stride*newVertex) = mix(an, bn, t);
149 }
150
151 outSurface[outIndex++] = newVertex++;
152 }
153 }
154 }
155 }
156}
157
158void Cogs::Core::LoftedCrossSectionsSystem::shellOpenCountCellResources(size_t& outIndices,
159 const int slices, const int samples,
160 const bool doubleSeam)
161{
162 int cN = (samples - (doubleSeam ? 1 : 0)) / 2;
163 outIndices = 6 * cN*(slices - 1);
164}
165
166
167void Cogs::Core::LoftedCrossSectionsSystem::shellOpenSkin(vector<unsigned int>& outSurface,
168 const int slices,
169 const int samples,
170 const bool doubleSeam)
171{
172 int cN = (samples - (doubleSeam ? 1 : 0)) / 2;
173 unsigned int outIndex = 0;
174 for (int k = 0; k < slices - 1; k++) {
175 for (int i = 0; i < cN; i++) {
176 int ii = (i + 1) % samples;
177
178 outSurface[outIndex++] = (k + 0)*samples + i; // Outer skin triangle 1
179 outSurface[outIndex++] = (k + 0)*samples + ii;
180 outSurface[outIndex++] = (k + 1)*samples + i;
181
182 outSurface[outIndex++] = (k + 1)*samples + ii; // Outer skin triangle 2
183 outSurface[outIndex++] = (k + 1)*samples + i;
184 outSurface[outIndex++] = (k + 0)*samples + ii;
185 }
186 }
187}
188
189void Cogs::Core::LoftedCrossSectionsSystem::shellClosedCountCellResources(size_t& outIndices,
190 const int slices, const int samples,
191 const bool doubleSeam)
192{
193 int cN = (samples - (doubleSeam ? 1 : 0));
194 outIndices = 6 * cN*(slices - 1);
195}
196
197
198void Cogs::Core::LoftedCrossSectionsSystem::shellClosedSkin(vector<unsigned int>& outSurface,
199 const int slices,
200 const int samples,
201 const bool doubleSeam)
202{
203 int cN = (samples - (doubleSeam ? 1 : 0));
204 unsigned int outIndex = 0;
205 for (int k = 0; k < slices - 1; k++) {
206 for (int i = 0; i < cN; i++) {
207 int ii = (i + 1) % samples;
208
209 outSurface[outIndex++] = (k + 0)*samples + i; // Outer skin triangle 1
210 outSurface[outIndex++] = (k + 0)*samples + ii;
211 outSurface[outIndex++] = (k + 1)*samples + i;
212
213 outSurface[outIndex++] = (k + 1)*samples + ii; // Outer skin triangle 2
214 outSurface[outIndex++] = (k + 1)*samples + i;
215 outSurface[outIndex++] = (k + 0)*samples + ii;
216 }
217 }
218}