18 "title" :
"VuoMeshUtility",
28 #define PI 3.14159265359f
38 VUserLog(
"VuoMeshUtility_calculateNormals() requires element assembly method VuoMesh_IndividualTriangles.");
42 unsigned int vertexCount, elementCount, *elements;
43 float *vertices, *textureCoordinates, *colors;
44 VuoMesh_getCPUBuffers(mesh, &vertexCount, &vertices,
nullptr, &textureCoordinates, &colors, &elementCount, &elements);
48 float *normals = (
float *)malloc(
sizeof(
float) * 3 * vertexCount);
49 unsigned int* normalsAverage = (
unsigned int*)malloc(
sizeof(
unsigned int) * vertexCount);
52 for(
unsigned int i = 0; i < vertexCount; i++)
55 normals[i * 3 + 1] = 0;
56 normals[i * 3 + 2] = 0;
57 normalsAverage[i] = 0;
62 for (
unsigned int i = 0; i < elementCount; i += 3)
64 unsigned int i0 = elements[i + 0];
65 unsigned int i1 = elements[i + 1];
66 unsigned int i2 = elements[i + 2];
88 for (
unsigned int i = 0; i < vertexCount; i += 3)
90 unsigned int i0 = i + 0;
91 unsigned int i1 = i + 1;
92 unsigned int i2 = i + 2;
109 normalsAverage[i0]++;
110 normalsAverage[i1]++;
111 normalsAverage[i2]++;
115 for (
unsigned int i = 0; i < vertexCount; i++)
117 normals[i * 3 ] /= normalsAverage[i];
118 normals[i * 3 + 1] /= normalsAverage[i];
119 normals[i * 3 + 2] /= normalsAverage[i];
122 free(normalsAverage);
124 VuoMesh_setCPUBuffers(mesh, vertexCount, vertices, normals, textureCoordinates, colors, elementCount, elements);
132 unsigned int vertexCount;
141 for (
unsigned int i = 1; i < vertexCount; i++)
159 unsigned int vertexCount, elementCount, *elements;
160 float *vertices, *normals, *colors;
161 VuoMesh_getCPUBuffers(mesh, &vertexCount, &vertices, &normals,
nullptr, &colors, &elementCount, &elements);
165 unsigned int dup_vertex_start = vertexCount;
167 float *textureCoordinates = (
float *)malloc(
sizeof(
float) * 2 * vertexCount);
173 center = (min + max) / 2.f;
177 for (
unsigned int i = 0; i < vertexCount; i++)
181 VuoPoint2d tc = (VuoPoint2d){
182 1.f - (.5f + (atan2f(v.z, v.x) / (2.f *
PI))),
183 1.f - (.5f - (asinf(v.y) /
PI))};
185 if(i >= dup_vertex_start)
194 min.x = fmin(min.x, tc.x);
195 min.y = fmin(min.y, tc.y);
197 max.x = fmax(max.x, tc.x);
198 max.y = fmax(max.y, tc.y);
200 textureCoordinates[i * 2 ] = tc.x;
201 textureCoordinates[i * 2 + 1] = tc.y;
204 VuoPoint2d scale = { 1 / (max.x - min.x), 1 / (max.y - min.y) };
206 for (
unsigned int i = 0; i < vertexCount; i++)
208 textureCoordinates[i * 2 ] -= min.x;
209 textureCoordinates[i * 2 + 1] -= min.y;
210 textureCoordinates[i * 2 ] *= scale.x;
211 textureCoordinates[i * 2 + 1] *= scale.y;
214 VuoMesh_setCPUBuffers(mesh, vertexCount, vertices, normals, textureCoordinates, colors, elementCount, elements);
241 float x = fabs(normal.x),
245 if( x > y && x > z ) {
246 return normal.x < 0 ? PlaneNegX : PlaneX;
247 }
else if( y > x && y > z ) {
248 return normal.y < 0 ? PlaneNegY : PlaneY;
250 return normal.z < 0 ? PlaneNegZ : PlaneZ;
259 return (VuoPoint3d){(a.x + b.x + c.x) / 3.f,
260 (a.y + b.y + c.y) / 3.f,
261 (a.z + b.z + c.z) / 3.f};
271 VuoPoint3d range = max - min;
273 unsigned int vertexCount, elementCount, *elements;
274 float *positions, *normals, *colors;
275 VuoMesh_getCPUBuffers(mesh, &vertexCount, &positions, &normals,
nullptr, &colors, &elementCount, &elements);
276 if (!vertexCount || !normals)
279 float *textureCoordinates = (
float *)malloc(
sizeof(
float) * 2 * vertexCount);
281 for (
unsigned int i = 0; i < vertexCount; i++)
285 VuoPoint3d uv = p - min;
287 uv.x = uv.x / range.x;
288 uv.y = uv.y / range.y;
289 uv.z = uv.z / range.z;
295 textureCoordinates[i * 2 ] = uv.z;
296 textureCoordinates[i * 2 + 1] = uv.y;
301 textureCoordinates[i * 2 ] = uv.x;
302 textureCoordinates[i * 2 + 1] = uv.z;
307 textureCoordinates[i * 2 ] = uv.x;
308 textureCoordinates[i * 2 + 1] = uv.y;
313 VuoMesh_setCPUBuffers(mesh, vertexCount, positions, normals, textureCoordinates, colors, elementCount, elements);
323 VuoPoint3d range = max - min;
325 unsigned int vertexCount, elementCount, *elements;
326 float *positions, *normals, *colors;
327 VuoMesh_getCPUBuffers(mesh, &vertexCount, &positions, &normals,
nullptr, &colors, &elementCount, &elements);
328 if (!vertexCount || !normals || !elementCount)
331 float *textureCoordinates = (
float *)malloc(
sizeof(
float) * 2 * vertexCount);
333 for (
unsigned int i = 0; i < elementCount; i+=3)
335 unsigned int a = elements[i+0],
343 VuoPoint3d uv_a = pa - min;
344 VuoPoint3d uv_b = pb - min;
345 VuoPoint3d uv_c = pc - min;
347 uv_a.x = uv_a.x / range.x;
348 uv_b.x = uv_b.x / range.x;
349 uv_c.x = uv_c.x / range.x;
350 uv_a.y = uv_a.y / range.y;
351 uv_b.y = uv_b.y / range.y;
352 uv_c.y = uv_c.y / range.y;
353 uv_a.z = uv_a.z / range.z;
354 uv_b.z = uv_b.z / range.z;
355 uv_c.z = uv_c.z / range.z;
361 textureCoordinates[a * 2 ] = uv_a.z;
362 textureCoordinates[a * 2 + 1] = uv_a.y;
363 textureCoordinates[b * 2 ] = uv_b.z;
364 textureCoordinates[b * 2 + 1] = uv_b.y;
365 textureCoordinates[c * 2 ] = uv_c.z;
366 textureCoordinates[c * 2 + 1] = uv_c.y;
371 textureCoordinates[a * 2 ] = uv_a.x;
372 textureCoordinates[a * 2 + 1] = uv_a.z;
373 textureCoordinates[b * 2 ] = uv_b.x;
374 textureCoordinates[b * 2 + 1] = uv_b.z;
375 textureCoordinates[c * 2 ] = uv_c.x;
376 textureCoordinates[c * 2 + 1] = uv_c.z;
381 textureCoordinates[a * 2 ] = uv_a.x;
382 textureCoordinates[a * 2 + 1] = uv_a.y;
383 textureCoordinates[b * 2 ] = uv_b.x;
384 textureCoordinates[b * 2 + 1] = uv_b.y;
385 textureCoordinates[c * 2 ] = uv_c.x;
386 textureCoordinates[c * 2 + 1] = uv_c.y;
391 VuoMesh_setCPUBuffers(mesh, vertexCount, positions, normals, textureCoordinates, colors, elementCount, elements);
399 unsigned int vertexCount, elementCount, *indices;
400 float *positions, *normals, *textures;
401 VuoMesh_getCPUBuffers(mesh, &vertexCount, &positions, &normals, &textures,
nullptr, &elementCount, &indices);
402 if (!vertexCount || !elementCount)
405 unsigned int *seam_indices = (
unsigned int *)malloc(
sizeof(
unsigned int) * elementCount);
406 memcpy(seam_indices, indices,
sizeof(
unsigned int) * elementCount);
408 std::vector<float> seam_positions = std::vector<float>(positions != NULL ? vertexCount * 3 : 0);
409 if(positions) std::copy(positions, positions + vertexCount * 3, seam_positions.begin());
410 std::vector<float> seam_normals = std::vector<float>(normals != NULL ? vertexCount * 3 : 0);
411 if(normals) std::copy(normals, normals + vertexCount * 3, seam_normals.begin());
412 std::vector<float> seam_textures = std::vector<float>(textures != NULL ? vertexCount * 2 : 0);
413 if(textures) std::copy(textures, textures + vertexCount * 2, seam_textures.begin());
415 const VuoPoint3d left = (VuoPoint3d){-1., 0., 0.};
416 const VuoPoint3d forward = (VuoPoint3d){ 0., 0., 1.};
417 const VuoPoint3d up = (VuoPoint3d){ 0., 1., 0.};
418 const VuoPoint3d down = (VuoPoint3d){ 0., -1., 0.};
423 VuoPoint3d center = (max + min) / 2.f;
426 for (
unsigned int i = 0; i < elementCount; i+=3)
428 if(indices[i] > vertexCount || indices[i+1] > vertexCount || indices[i+2] > vertexCount)
430 VUserLog(
"Triangle indices are referencing out of bounds vertices. (%u, %u, %u) Vertex Count: %u", indices[i], indices[i+1], indices[i+2], vertexCount);
434 for(
int n = 0; n < 3; n++)
436 unsigned int x = i + n;
437 unsigned int y = i + (n == 2 ? 0 : n+1);
456 seam_positions.push_back(positions[indices[x] * 3 ]);
457 seam_positions.push_back(positions[indices[x] * 3 + 1]);
458 seam_positions.push_back(positions[indices[x] * 3 + 2]);
462 seam_normals.push_back(normals[indices[x] * 3 ]);
463 seam_normals.push_back(normals[indices[x] * 3 + 1]);
464 seam_normals.push_back(normals[indices[x] * 3 + 2]);
468 seam_textures.push_back(textures[indices[x] * 2 ]);
469 seam_textures.push_back(textures[indices[x] * 2 + 1]);
472 seam_indices[x] = seam_positions.size() / 3 - 1;
482 seam_positions.push_back(positions[indices[y] * 3 ]);
483 seam_positions.push_back(positions[indices[y] * 3 + 1]);
484 seam_positions.push_back(positions[indices[y] * 3 + 2]);
488 seam_normals.push_back(normals[indices[y] * 3 ]);
489 seam_normals.push_back(normals[indices[y] * 3 + 1]);
490 seam_normals.push_back(normals[indices[y] * 3 + 2]);
494 seam_textures.push_back(textures[indices[y] * 2 ]);
495 seam_textures.push_back(textures[indices[y] * 2 + 1]);
498 seam_indices[y] = seam_positions.size() / 3 - 1;
503 float *newPositions = (
float *)malloc(
sizeof(
float) * seam_positions.size());
504 std::copy(seam_positions.begin(), seam_positions.end(), newPositions);
506 float *newNormals =
nullptr;
509 newNormals = (
float *)malloc(
sizeof(
float) * seam_normals.size());
510 std::copy(seam_normals.begin(), seam_normals.end(), newNormals);
513 float *newTextureCoordinates =
nullptr;
516 newTextureCoordinates = (
float *)malloc(
sizeof(
float) * seam_textures.size());
517 std::copy(seam_textures.begin(), seam_textures.end(), newTextureCoordinates);
521 newPositions, newNormals, newTextureCoordinates,
nullptr,
522 elementCount, seam_indices);
528 static int compare(
const void* lhs,
const void* rhs)
530 return ( *(
int*)lhs - *(
int*)rhs );
538 unsigned int vertexCount, elementCount, *elements;
539 float *positions, *normals, *textureCoordinates;
540 VuoMesh_getCPUBuffers(mesh, &vertexCount, &positions, &normals, &textureCoordinates,
nullptr, &elementCount, &elements);
541 if (!vertexCount || !elementCount)
544 unsigned int* sortedTriangles = (
unsigned int*)malloc(
sizeof(
unsigned int) * elementCount);
545 memcpy(sortedTriangles, elements,
sizeof(
unsigned int) * elementCount);
548 qsort(sortedTriangles, elementCount,
sizeof(
unsigned int),
compare);
551 unsigned int last = elementCount-1;
553 while( sortedTriangles[last] > vertexCount )
557 if(last < elementCount-1)
559 unsigned int* pruned_elements = (
unsigned int*)malloc(
sizeof(
unsigned int) * (last+1));
563 for(
unsigned int i = 0; i < elementCount; i++)
565 if (elements[i] < vertexCount)
566 pruned_elements[n++] = elements[i];
569 elementCount = last+1;
570 elements = pruned_elements;
574 std::vector<unsigned int> unused;
577 for(
int i = 0; i < elementCount && sortedTriangles[i] < elementCount; i++)
579 for(
int n = lastVal+1; n < sortedTriangles[i]; n++)
584 lastVal = sortedTriangles[i];
586 free(sortedTriangles);
590 int unusedCount = unused.size();
591 for(
int i = 0; i < elementCount; i++)
593 unsigned int vertex = elements[i];
595 if(vertex > vertexCount)
600 for(
auto& val : unused)
613 std::vector<float> new_positions = std::vector<float>(vertexCount * 3);
614 std::vector<float> new_normals = std::vector<float>(normals ? vertexCount * 3 : 0);
615 std::vector<float> new_textureCoordinates = std::vector<float>(textureCoordinates ? vertexCount * 2 : 0);
617 unsigned int curIndex = 0, n = 0;
618 for(
int i = 0; i < vertexCount; i++)
620 if(curIndex >= unusedCount || i < unused[curIndex])
622 new_positions[n * 3 ] = positions[i * 3 ];
623 new_positions[n * 3 + 1] = positions[i * 3 + 1];
624 new_positions[n * 3 + 2] = positions[i * 3 + 2];
627 new_normals[n * 3 ] = normals[i * 3 ];
628 new_normals[n * 3 + 1] = normals[i * 3 + 1];
629 new_normals[n * 3 + 2] = normals[i * 3 + 2];
631 if (textureCoordinates)
633 new_textureCoordinates[n * 2 ] = textureCoordinates[i * 2 ];
634 new_textureCoordinates[n * 2 + 1] = textureCoordinates[i * 2 + 1];
643 }
while(curIndex < unusedCount && unused[curIndex] <= i);
648 unsigned int culledVertexCount = new_positions.size();
650 float *newPositions = (
float *)malloc(
sizeof(
float) * 3 * culledVertexCount);
651 std::copy(new_positions.begin(), new_positions.end(), newPositions);
653 float *newNormals =
nullptr;
656 newNormals = (
float *)malloc(
sizeof(
float) * 3 * culledVertexCount);
657 std::copy(new_normals.begin(), new_normals.end(), newNormals);
660 float *newTextureCoordinates =
nullptr;
661 if (textureCoordinates)
663 newTextureCoordinates = (
float *)malloc(
sizeof(
float) * 2 * culledVertexCount);
664 std::copy(new_textureCoordinates.begin(), new_textureCoordinates.end(), newTextureCoordinates);
668 newPositions, newNormals, newTextureCoordinates,
nullptr,
669 elementCount, elements);