37 VUserLog(
"VuoMeshUtility_calculateNormals() requires element assembly method VuoMesh_IndividualTriangles.");
41 unsigned int vertexCount, elementCount, *elements;
42 float *vertices, *textureCoordinates, *colors;
43 VuoMesh_getCPUBuffers(mesh, &vertexCount, &vertices,
nullptr, &textureCoordinates, &colors, &elementCount, &elements);
47 float *normals = (
float *)malloc(
sizeof(
float) * 3 * vertexCount);
48 unsigned int* normalsAverage = (
unsigned int*)malloc(
sizeof(
unsigned int) * vertexCount);
51 for(
unsigned int i = 0; i < vertexCount; i++)
54 normals[i * 3 + 1] = 0;
55 normals[i * 3 + 2] = 0;
56 normalsAverage[i] = 0;
61 for (
unsigned int i = 0; i < elementCount; i += 3)
63 unsigned int i0 = elements[i + 0];
64 unsigned int i1 = elements[i + 1];
65 unsigned int i2 = elements[i + 2];
87 for (
unsigned int i = 0; i < vertexCount; i += 3)
89 unsigned int i0 = i + 0;
90 unsigned int i1 = i + 1;
91 unsigned int i2 = i + 2;
108 normalsAverage[i0]++;
109 normalsAverage[i1]++;
110 normalsAverage[i2]++;
114 for (
unsigned int i = 0; i < vertexCount; i++)
116 normals[i * 3 ] /= normalsAverage[i];
117 normals[i * 3 + 1] /= normalsAverage[i];
118 normals[i * 3 + 2] /= normalsAverage[i];
121 free(normalsAverage);
123 VuoMesh_setCPUBuffers(mesh, vertexCount, vertices, normals, textureCoordinates, colors, elementCount, elements);
158 unsigned int vertexCount, elementCount, *elements;
159 float *vertices, *normals, *colors;
160 VuoMesh_getCPUBuffers(mesh, &vertexCount, &vertices, &normals,
nullptr, &colors, &elementCount, &elements);
164 unsigned int dup_vertex_start = vertexCount;
166 float *textureCoordinates = (
float *)malloc(
sizeof(
float) * 2 * vertexCount);
172 center = (min + max) / 2.f;
176 for (
unsigned int i = 0; i < vertexCount; i++)
180 VuoPoint2d tc = (VuoPoint2d){
181 1.f - (.5f + (atan2f(v.z, v.x) / (2.f *
PI))),
182 1.f - (.5f - (asinf(v.y) /
PI))};
184 if(i >= dup_vertex_start)
193 min.x = fmin(min.x, tc.x);
194 min.y = fmin(min.y, tc.y);
196 max.x = fmax(max.x, tc.x);
197 max.y = fmax(max.y, tc.y);
199 textureCoordinates[i * 2 ] = tc.x;
200 textureCoordinates[i * 2 + 1] = tc.y;
203 VuoPoint2d scale = { 1 / (max.x - min.x), 1 / (max.y - min.y) };
205 for (
unsigned int i = 0; i < vertexCount; i++)
207 textureCoordinates[i * 2 ] -= min.x;
208 textureCoordinates[i * 2 + 1] -= min.y;
209 textureCoordinates[i * 2 ] *= scale.x;
210 textureCoordinates[i * 2 + 1] *= scale.y;
213 VuoMesh_setCPUBuffers(mesh, vertexCount, vertices, normals, textureCoordinates, colors, elementCount, elements);
270 VuoPoint3d range = max - min;
272 unsigned int vertexCount, elementCount, *elements;
273 float *positions, *normals, *colors;
274 VuoMesh_getCPUBuffers(mesh, &vertexCount, &positions, &normals,
nullptr, &colors, &elementCount, &elements);
275 if (!vertexCount || !normals)
278 float *textureCoordinates = (
float *)malloc(
sizeof(
float) * 2 * vertexCount);
280 for (
unsigned int i = 0; i < vertexCount; i++)
284 VuoPoint3d uv = p - min;
286 uv.x = uv.x / range.x;
287 uv.y = uv.y / range.y;
288 uv.z = uv.z / range.z;
294 textureCoordinates[i * 2 ] = uv.z;
295 textureCoordinates[i * 2 + 1] = uv.y;
300 textureCoordinates[i * 2 ] = uv.x;
301 textureCoordinates[i * 2 + 1] = uv.z;
306 textureCoordinates[i * 2 ] = uv.x;
307 textureCoordinates[i * 2 + 1] = uv.y;
312 VuoMesh_setCPUBuffers(mesh, vertexCount, positions, normals, textureCoordinates, colors, elementCount, elements);
322 VuoPoint3d range = max - min;
324 unsigned int vertexCount, elementCount, *elements;
325 float *positions, *normals, *colors;
326 VuoMesh_getCPUBuffers(mesh, &vertexCount, &positions, &normals,
nullptr, &colors, &elementCount, &elements);
327 if (!vertexCount || !normals || !elementCount)
330 float *textureCoordinates = (
float *)malloc(
sizeof(
float) * 2 * vertexCount);
332 for (
unsigned int i = 0; i < elementCount; i+=3)
334 unsigned int a = elements[i+0],
342 VuoPoint3d uv_a = pa - min;
343 VuoPoint3d uv_b = pb - min;
344 VuoPoint3d uv_c = pc - min;
346 uv_a.x = uv_a.x / range.x;
347 uv_b.x = uv_b.x / range.x;
348 uv_c.x = uv_c.x / range.x;
349 uv_a.y = uv_a.y / range.y;
350 uv_b.y = uv_b.y / range.y;
351 uv_c.y = uv_c.y / range.y;
352 uv_a.z = uv_a.z / range.z;
353 uv_b.z = uv_b.z / range.z;
354 uv_c.z = uv_c.z / range.z;
360 textureCoordinates[a * 2 ] = uv_a.z;
361 textureCoordinates[a * 2 + 1] = uv_a.y;
362 textureCoordinates[b * 2 ] = uv_b.z;
363 textureCoordinates[b * 2 + 1] = uv_b.y;
364 textureCoordinates[c * 2 ] = uv_c.z;
365 textureCoordinates[c * 2 + 1] = uv_c.y;
370 textureCoordinates[a * 2 ] = uv_a.x;
371 textureCoordinates[a * 2 + 1] = uv_a.z;
372 textureCoordinates[b * 2 ] = uv_b.x;
373 textureCoordinates[b * 2 + 1] = uv_b.z;
374 textureCoordinates[c * 2 ] = uv_c.x;
375 textureCoordinates[c * 2 + 1] = uv_c.z;
380 textureCoordinates[a * 2 ] = uv_a.x;
381 textureCoordinates[a * 2 + 1] = uv_a.y;
382 textureCoordinates[b * 2 ] = uv_b.x;
383 textureCoordinates[b * 2 + 1] = uv_b.y;
384 textureCoordinates[c * 2 ] = uv_c.x;
385 textureCoordinates[c * 2 + 1] = uv_c.y;
390 VuoMesh_setCPUBuffers(mesh, vertexCount, positions, normals, textureCoordinates, colors, elementCount, elements);
398 unsigned int vertexCount, elementCount, *indices;
399 float *positions, *normals, *textures;
400 VuoMesh_getCPUBuffers(mesh, &vertexCount, &positions, &normals, &textures,
nullptr, &elementCount, &indices);
401 if (!vertexCount || !elementCount)
404 unsigned int *seam_indices = (
unsigned int *)malloc(
sizeof(
unsigned int) * elementCount);
405 memcpy(seam_indices, indices,
sizeof(
unsigned int) * elementCount);
407 std::vector<float> seam_positions = std::vector<float>(positions != NULL ? vertexCount * 3 : 0);
408 if(positions) std::copy(positions, positions + vertexCount * 3, seam_positions.begin());
409 std::vector<float> seam_normals = std::vector<float>(normals != NULL ? vertexCount * 3 : 0);
410 if(normals) std::copy(normals, normals + vertexCount * 3, seam_normals.begin());
411 std::vector<float> seam_textures = std::vector<float>(textures != NULL ? vertexCount * 2 : 0);
412 if(textures) std::copy(textures, textures + vertexCount * 2, seam_textures.begin());
414 const VuoPoint3d left = (VuoPoint3d){-1., 0., 0.};
415 const VuoPoint3d forward = (VuoPoint3d){ 0., 0., 1.};
416 const VuoPoint3d up = (VuoPoint3d){ 0., 1., 0.};
417 const VuoPoint3d down = (VuoPoint3d){ 0., -1., 0.};
422 VuoPoint3d center = (max + min) / 2.f;
425 for (
unsigned int i = 0; i < elementCount; i+=3)
427 if(indices[i] > vertexCount || indices[i+1] > vertexCount || indices[i+2] > vertexCount)
429 VUserLog(
"Triangle indices are referencing out of bounds vertices. (%u, %u, %u) Vertex Count: %u", indices[i], indices[i+1], indices[i+2], vertexCount);
433 for(
int n = 0; n < 3; n++)
435 unsigned int x = i + n;
436 unsigned int y = i + (n == 2 ? 0 : n+1);
455 seam_positions.push_back(positions[indices[x] * 3 ]);
456 seam_positions.push_back(positions[indices[x] * 3 + 1]);
457 seam_positions.push_back(positions[indices[x] * 3 + 2]);
461 seam_normals.push_back(normals[indices[x] * 3 ]);
462 seam_normals.push_back(normals[indices[x] * 3 + 1]);
463 seam_normals.push_back(normals[indices[x] * 3 + 2]);
467 seam_textures.push_back(textures[indices[x] * 2 ]);
468 seam_textures.push_back(textures[indices[x] * 2 + 1]);
471 seam_indices[x] = seam_positions.size() / 3 - 1;
481 seam_positions.push_back(positions[indices[y] * 3 ]);
482 seam_positions.push_back(positions[indices[y] * 3 + 1]);
483 seam_positions.push_back(positions[indices[y] * 3 + 2]);
487 seam_normals.push_back(normals[indices[y] * 3 ]);
488 seam_normals.push_back(normals[indices[y] * 3 + 1]);
489 seam_normals.push_back(normals[indices[y] * 3 + 2]);
493 seam_textures.push_back(textures[indices[y] * 2 ]);
494 seam_textures.push_back(textures[indices[y] * 2 + 1]);
497 seam_indices[y] = seam_positions.size() / 3 - 1;
502 float *newPositions = (
float *)malloc(
sizeof(
float) * seam_positions.size());
503 std::copy(seam_positions.begin(), seam_positions.end(), newPositions);
505 float *newNormals =
nullptr;
508 newNormals = (
float *)malloc(
sizeof(
float) * seam_normals.size());
509 std::copy(seam_normals.begin(), seam_normals.end(), newNormals);
512 float *newTextureCoordinates =
nullptr;
515 newTextureCoordinates = (
float *)malloc(
sizeof(
float) * seam_textures.size());
516 std::copy(seam_textures.begin(), seam_textures.end(), newTextureCoordinates);
520 newPositions, newNormals, newTextureCoordinates,
nullptr,
521 elementCount, seam_indices);
537 unsigned int vertexCount, elementCount, *elements;
538 float *positions, *normals, *textureCoordinates;
539 VuoMesh_getCPUBuffers(mesh, &vertexCount, &positions, &normals, &textureCoordinates,
nullptr, &elementCount, &elements);
540 if (!vertexCount || !elementCount)
543 unsigned int* sortedTriangles = (
unsigned int*)malloc(
sizeof(
unsigned int) * elementCount);
544 memcpy(sortedTriangles, elements,
sizeof(
unsigned int) * elementCount);
547 qsort(sortedTriangles, elementCount,
sizeof(
unsigned int),
compare);
550 unsigned int last = elementCount-1;
552 while( sortedTriangles[last] > vertexCount )
556 if(last < elementCount-1)
558 unsigned int* pruned_elements = (
unsigned int*)malloc(
sizeof(
unsigned int) * (last+1));
562 for(
unsigned int i = 0; i < elementCount; i++)
564 if (elements[i] < vertexCount)
565 pruned_elements[n++] = elements[i];
568 elementCount = last+1;
569 elements = pruned_elements;
573 std::vector<unsigned int> unused;
576 for(
int i = 0; i < elementCount && sortedTriangles[i] < elementCount; i++)
578 for(
int n = lastVal+1; n < sortedTriangles[i]; n++)
583 lastVal = sortedTriangles[i];
585 free(sortedTriangles);
589 int unusedCount = unused.size();
590 for(
int i = 0; i < elementCount; i++)
592 unsigned int vertex = elements[i];
594 if(vertex > vertexCount)
599 for(
auto& val : unused)
612 std::vector<float> new_positions = std::vector<float>(vertexCount * 3);
613 std::vector<float> new_normals = std::vector<float>(normals ? vertexCount * 3 : 0);
614 std::vector<float> new_textureCoordinates = std::vector<float>(textureCoordinates ? vertexCount * 2 : 0);
616 unsigned int curIndex = 0, n = 0;
617 for(
int i = 0; i < vertexCount; i++)
619 if(curIndex >= unusedCount || i < unused[curIndex])
621 new_positions[n * 3 ] = positions[i * 3 ];
622 new_positions[n * 3 + 1] = positions[i * 3 + 1];
623 new_positions[n * 3 + 2] = positions[i * 3 + 2];
626 new_normals[n * 3 ] = normals[i * 3 ];
627 new_normals[n * 3 + 1] = normals[i * 3 + 1];
628 new_normals[n * 3 + 2] = normals[i * 3 + 2];
630 if (textureCoordinates)
632 new_textureCoordinates[n * 2 ] = textureCoordinates[i * 2 ];
633 new_textureCoordinates[n * 2 + 1] = textureCoordinates[i * 2 + 1];
642 }
while(curIndex < unusedCount && unused[curIndex] <= i);
647 unsigned int culledVertexCount = new_positions.size();
649 float *newPositions = (
float *)malloc(
sizeof(
float) * 3 * culledVertexCount);
650 std::copy(new_positions.begin(), new_positions.end(), newPositions);
652 float *newNormals =
nullptr;
655 newNormals = (
float *)malloc(
sizeof(
float) * 3 * culledVertexCount);
656 std::copy(new_normals.begin(), new_normals.end(), newNormals);
659 float *newTextureCoordinates =
nullptr;
660 if (textureCoordinates)
662 newTextureCoordinates = (
float *)malloc(
sizeof(
float) * 2 * culledVertexCount);
663 std::copy(new_textureCoordinates.begin(), new_textureCoordinates.end(), newTextureCoordinates);
667 newPositions, newNormals, newTextureCoordinates,
nullptr,
668 elementCount, elements);