ProtoTracer  1.0
Real-time 3D rendering and animation engine
Loading...
Searching...
No Matches
PixelGroup.tpp
Go to the documentation of this file.
1#pragma once
2
3template<size_t pixelCount>
4PixelGroup<pixelCount>::PixelGroup(Vector2D size, Vector2D position, uint16_t rowCount){
5 this->size = size;
6 this->position = position;
7 this->rowCount = rowCount;
8 this->colCount = pixelCount / rowCount;
9
10 isRectangular = true;
11
12 bounds.UpdateBounds(position);
13 bounds.UpdateBounds(position + size);
14
15 for(uint16_t i = 0; i < pixelCount; i++){
16 pixelColors[i] = RGBColor();
17 pixelBuffer[i] = RGBColor();
18
19 up[i] = 65535;
20 down[i] = 65535;
21 left[i] = 65535;
22 right[i] = 65535;
23 }
24
25 GridSort();
26}
27
28template<size_t pixelCount>
29PixelGroup<pixelCount>::PixelGroup(const Vector2D* pixelLocations, Direction direction){
30 this->direction = direction;
31 pixelPositions = pixelLocations;
32
33 for(uint16_t i = 0; i < pixelCount; i++){
34 pixelColors[i] = RGBColor();
35 pixelBuffer[i] = RGBColor();
36
37 bounds.UpdateBounds(pixelLocations[i]);
38
39 up[i] = 65535;
40 down[i] = 65535;
41 left[i] = 65535;
42 right[i] = 65535;
43 }
44
45 GridSort();
46}
47
48template<size_t pixelCount>
49PixelGroup<pixelCount>::~PixelGroup(){}
50
51template<size_t pixelCount>
52Vector2D PixelGroup<pixelCount>::GetCenterCoordinate(){
53 return (bounds.GetMaximum() + bounds.GetMinimum()) / 2.0f;
54}
55
56template<size_t pixelCount>
57Vector2D PixelGroup<pixelCount>::GetSize(){
58 return bounds.GetMaximum() - bounds.GetMinimum();
59}
60
61template<size_t pixelCount>
62Vector2D PixelGroup<pixelCount>::GetCoordinate(uint16_t count){
63 count = Mathematics::Constrain<int>(count, 0, pixelCount);
64
65 if (isRectangular){
66 float row = count % rowCount;
67 float col = (count - row) / rowCount;
68
69 tempLocation.X = Mathematics::Map(row, 0.0f, float(rowCount), position.X, position.X + size.X);
70 tempLocation.Y = Mathematics::Map(col, 0.0f, float(colCount), position.Y, position.Y + size.Y);
71
72 return tempLocation;
73 }
74 else{
75 if(direction == ZEROTOMAX){
76 return pixelPositions[count];
77 }
78 else{
79 return pixelPositions[pixelCount - count - 1];
80 }
81 }
82}
83
84template<size_t pixelCount>
85int PixelGroup<pixelCount>::GetPixelIndex(Vector2D location){
86 float row = Mathematics::Map(location.X, position.X, position.X + size.X, 0.0f, float(rowCount));
87 float col = Mathematics::Map(location.Y, position.Y, position.Y + size.Y, 0.0f, float(colCount));
88
89 uint16_t count = row + col * rowCount;
90
91 if (count < pixelCount && count > 0 && row > 0 && row < rowCount && col > 0 && col < colCount){
92 return count;
93 }
94 else{
95 return -1;
96 }
97}
98
99template<size_t pixelCount>
100RGBColor* PixelGroup<pixelCount>::GetColor(uint16_t count){
101 return &pixelColors[count];
102}
103
104template<size_t pixelCount>
105RGBColor* PixelGroup<pixelCount>::GetColors(){
106 return &pixelColors[0];
107}
108
109template<size_t pixelCount>
110RGBColor* PixelGroup<pixelCount>::GetColorBuffer(){
111 return &pixelBuffer[0];
112}
113
114template<size_t pixelCount>
115uint16_t PixelGroup<pixelCount>::GetPixelCount(){
116 return pixelCount;
117}
118
119template<size_t pixelCount>
120bool PixelGroup<pixelCount>::Overlaps(BoundingBox2D* box){
121 return bounds.Overlaps(box);
122}
123
124template<size_t pixelCount>
125bool PixelGroup<pixelCount>::ContainsVector2D(Vector2D v){
126 return v.CheckBounds(bounds.GetMinimum(), bounds.GetMaximum());
127}
128
129template<size_t pixelCount>
130bool PixelGroup<pixelCount>::GetUpIndex(uint16_t count, uint16_t* upIndex){
131 *upIndex = up[count];
132
133 return up[count] < 65535;
134}
135
136template<size_t pixelCount>
137bool PixelGroup<pixelCount>::GetDownIndex(uint16_t count, uint16_t* downIndex){
138 *downIndex = down[count];
139
140 return down[count] < 65535;
141}
142
143template<size_t pixelCount>
144bool PixelGroup<pixelCount>::GetLeftIndex(uint16_t count, uint16_t* leftIndex){
145 *leftIndex = left[count];
146
147 return left[count] < 65535;
148}
149
150template<size_t pixelCount>
151bool PixelGroup<pixelCount>::GetRightIndex(uint16_t count, uint16_t* rightIndex){
152 *rightIndex = right[count];
153
154 return right[count] < 65535;
155}
156
157template<size_t pixelCount>
158bool PixelGroup<pixelCount>::GetAlternateXIndex(uint16_t count, uint16_t* index){
159 uint16_t tempIndex = count;
160 bool isEven = count % 2;
161 bool valid = true;
162
163 for(uint16_t i = 0; i < count / 2; i++){
164 if (isEven){
165 valid = GetRightIndex(tempIndex, &tempIndex);
166 }
167 else{
168 valid = GetLeftIndex(tempIndex, &tempIndex);
169 }
170
171 if (!valid) break;
172 }
173
174 *index = tempIndex;
175
176 return valid;
177}
178
179template<size_t pixelCount>
180bool PixelGroup<pixelCount>::GetAlternateYIndex(uint16_t count, uint16_t* index){
181 uint16_t tempIndex = count;
182 bool isEven = count % 2;
183 bool valid = true;
184
185 for(uint16_t i = 0; i < count / 2; i++){
186 if (isEven){
187 valid = GetUpIndex(tempIndex, &tempIndex);
188 }
189 else{
190 valid = GetDownIndex(tempIndex, &tempIndex);
191 }
192
193 if (!valid) break;
194 }
195
196 *index = tempIndex;
197
198 return valid;
199}
200
201template<size_t pixelCount>
202bool PixelGroup<pixelCount>::GetOffsetXIndex(uint16_t count, uint16_t* index, int x1){
203 uint16_t tempIndex = count;
204 bool valid = true;
205
206 for(int i = 0; i < x1; i++){
207 if (x1 > 0) valid = GetRightIndex(tempIndex, &tempIndex);
208 else if (x1 < 0) valid = GetLeftIndex(tempIndex, &tempIndex);
209 else break;
210
211 if (!valid) break;
212 }
213
214 *index = tempIndex;
215
216 return valid;
217}
218
219template<size_t pixelCount>
220bool PixelGroup<pixelCount>::GetOffsetYIndex(uint16_t count, uint16_t* index, int y1){
221 uint16_t tempIndex = count;
222 bool valid = true;
223
224 for(int i = 0; i < y1; i++){
225 if (y1 > 0) valid = GetUpIndex(tempIndex, &tempIndex);
226 else if (y1 < 0) valid = GetDownIndex(tempIndex, &tempIndex);
227 else break;
228
229 if (!valid) break;
230 }
231
232 *index = tempIndex;
233
234 return valid;
235}
236
237template<size_t pixelCount>
238bool PixelGroup<pixelCount>::GetOffsetXYIndex(uint16_t count, uint16_t* index, int x1, int y1){
239 uint16_t tempIndex = count;
240 bool valid = true;
241
242 for(int i = 0; i < abs(x1); i++){
243 if (x1 > 0) valid = GetRightIndex(tempIndex, &tempIndex);
244 else if (x1 < 0) valid = GetLeftIndex(tempIndex, &tempIndex);
245 else break;
246
247 if (!valid) break;
248 }
249
250 for(int i = 0; i < abs(y1); i++){
251 if (y1 > 0) valid = GetUpIndex(tempIndex, &tempIndex);
252 else if (y1 < 0) valid = GetDownIndex(tempIndex, &tempIndex);
253 else break;
254
255 if (!valid) break;
256 }
257
258 *index = tempIndex;
259
260 return valid;
261}
262
263template<size_t pixelCount>
264bool PixelGroup<pixelCount>::GetRadialIndex(uint16_t count, uint16_t* index, int pixels, float angle){//walks in the direction of the angle to a target pixel to grab an index
265 int x1 = int(float(pixels) * cosf(angle * Mathematics::MPID180));
266 int y1 = int(float(pixels) * sinf(angle * Mathematics::MPID180));
267
268 uint16_t tempIndex = count;
269 bool valid = true;
270
271 int previousX = 0;
272 int previousY = 0;
273
274 int x = 0;
275 int y = 0;
276
277 for(int i = 0; i < pixels; i++){
278 x = Mathematics::Map(i, 0, pixels, 0, x1);
279 y = Mathematics::Map(i, 0, pixels, 0, y1);
280
281 for (int k = 0; k < abs(x - previousX); k++){
282 if (x > previousX) valid = GetRightIndex(tempIndex, &tempIndex);
283 else if (x < previousX) valid = GetLeftIndex(tempIndex, &tempIndex);
284 if (!valid) break;
285 }
286
287 if (!valid) break;
288
289 for (int k = 0; k < abs(y - previousY); k++){
290 if (y > previousY) valid = GetUpIndex(tempIndex, &tempIndex);
291 else if (y < previousY) valid = GetDownIndex(tempIndex, &tempIndex);
292 if (!valid) break;
293 }
294
295 if (!valid) break;
296
297 previousX = x;
298 previousY = y;
299 }
300
301 *index = tempIndex;
302
303 return valid;
304}
305
306template<size_t pixelCount>
307void PixelGroup<pixelCount>::GridSort(){
308 if(!isRectangular){
309 // Loop through all pixels
310 for (uint16_t i = 0; i < pixelCount; i++) {
311 Vector2D currentPos;
312
313 if(!isRectangular) currentPos = direction == ZEROTOMAX ? pixelPositions[i] : pixelPositions[pixelCount - i - 1];
314 else currentPos = direction == ZEROTOMAX ? GetCoordinate(i) : GetCoordinate(pixelCount - i - 1);
315
316 // Initialize the minimum distances and indices to the first pixel
317 float minUp = Mathematics::FLTMAX, minDown = Mathematics::FLTMAX, minLeft = Mathematics::FLTMAX, minRight = Mathematics::FLTMAX;
318 int minUpIndex = -1, minDownIndex = -1, minLeftIndex = -1, minRightIndex = -1;
319
320 // Loop through all other pixels
321 for (uint16_t j = 0; j < pixelCount; j++) {
322 if (i == j) { continue; } // Skip the current pixel
323
324 Vector2D neighborPos;
325
326 if(!isRectangular) neighborPos = direction == ZEROTOMAX ? pixelPositions[j] : pixelPositions[pixelCount - j - 1];
327 else currentPos = direction == ZEROTOMAX ? GetCoordinate(j) : GetCoordinate(pixelCount - j - 1);
328
329 // Calculate the distances between the current pixel and the other pixel
330 float dist = currentPos.CalculateEuclideanDistance(neighborPos);
331
332 // Check if the other pixel is above or below the current pixel
333 if (Mathematics::IsClose(currentPos.X, neighborPos.X, 1.0f)) {
334 if (currentPos.Y < neighborPos.Y && dist < minUp) {
335 minUp = dist;
336 minUpIndex = j;
337 }
338 else if (currentPos.Y > neighborPos.Y && dist < minDown) {
339 minDown = dist;
340 minDownIndex = j;
341 }
342 }
343
344 // Check if the other pixel is to the left or right of the current pixel
345 if (Mathematics::IsClose(currentPos.Y, neighborPos.Y, 1.0f)) {
346 if (currentPos.X > neighborPos.X && dist < minLeft) {
347 minLeft = dist;
348 minLeftIndex = j;
349 }
350 else if (currentPos.X < neighborPos.X && dist < minRight) {
351 minRight = dist;
352 minRightIndex = j;
353 }
354 }
355 }
356
357 // Set the indices of the neighboring pixels
358 if (minUpIndex != -1) up[i] = minUpIndex;
359 if (minDownIndex != -1) down[i] = minDownIndex;
360
361 if (minLeftIndex != -1) left[i] = minLeftIndex;
362 if (minRightIndex != -1) right[i] = minRightIndex;
363 }
364 }
365 else {//optimized algorithm for rectangular matrices
366 for (int i = 0; i < int(pixelCount); i++) {
367 if (i + int(rowCount) < int(pixelCount) - 1) up[i] = uint16_t(i) + rowCount;//up
368 if (i - int(rowCount) > 1) down[i] = uint16_t(i) - rowCount;//down
369
370 if (!(i % rowCount == 0) && i > 1) left[i] = uint16_t(i) - 1;//left
371 if (!(i % rowCount + 1 == 0) && i < int(pixelCount) - 1) right[i] = uint16_t(i) + 1;//right
372 }
373 }
374}