18 "title" :
"VuoMeshUtility",
28 #define PI 3.14159265359
33 static inline VuoPoint4d
VuoPoint4d_min(
const VuoPoint4d lhs,
const VuoPoint4d rhs)
46 static inline VuoPoint4d
VuoPoint4d_max(
const VuoPoint4d lhs,
const VuoPoint4d rhs)
64 VUserLog(
"VuoMeshUtility_calculateNormals() requires element assembly method VuoMesh_IndividualTriangles.");
70 const unsigned int* elements = submesh->
elements;
71 const VuoPoint4d* vertices = submesh->
positions;
73 VuoPoint4d* normals = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * vertexCount);
74 unsigned int* normalsAverage = (
unsigned int*)malloc(
sizeof(
unsigned int) * vertexCount);
77 for(
unsigned int i = 0; i < vertexCount; i++)
80 normalsAverage[i] = 0;
85 for (
unsigned int i = 0; i < elementCount; i += 3)
87 unsigned int i0 = elements[i + 0];
88 unsigned int i1 = elements[i + 1];
89 unsigned int i2 = elements[i + 2];
91 VuoPoint4d a = vertices[i0];
92 VuoPoint4d b = vertices[i1];
93 VuoPoint4d c = vertices[i2];
101 normalsAverage[i0]++;
102 normalsAverage[i1]++;
103 normalsAverage[i2]++;
106 for (
unsigned int i = 0; i < vertexCount; i += 3)
108 unsigned int i0 = i + 0;
109 unsigned int i1 = i + 1;
110 unsigned int i2 = i + 2;
112 VuoPoint4d a = vertices[i0];
113 VuoPoint4d b = vertices[i1];
114 VuoPoint4d c = vertices[i2];
122 normalsAverage[i0]++;
123 normalsAverage[i1]++;
124 normalsAverage[i2]++;
128 for(
unsigned int i = 0; i < vertexCount; i++)
133 free(normalsAverage);
148 const VuoPoint4d *vertex = submesh->
positions;
149 const VuoPoint4d *normal = submesh->
normals;
152 const unsigned int *triangle = submesh->
elements;
156 VUserLog(
"VuoMeshUtility_calculateNormals() requires element assembly method VuoMesh_IndividualTriangles.");
160 VuoPoint4d *tangent = submesh->
tangents != NULL ? submesh->
tangents : (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * vertexCount);
161 VuoPoint4d *bitangent = submesh->
bitangents != NULL ? submesh->
bitangents : (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * vertexCount);
163 int tan1count = vertexCount * 2;
164 VuoPoint4d *tan1 =
new VuoPoint4d[tan1count];
165 VuoPoint4d *tan2 = tan1 + vertexCount;
167 for(
int i = 0; i < tan1count; i++)
168 tan1[i] = (VuoPoint4d) {0,0,0,0};
171 for (
int a = 0; a < triangleCount; a += 3)
173 long i1 = triangle[a + 0];
174 long i2 = triangle[a + 1];
175 long i3 = triangle[a + 2];
177 if (i1 > vertexCount || i2 > vertexCount || i3 > vertexCount)
179 VUserLog(
"Skipping tangent generation for triangle: (%lu, %lu, %lu) because it references out of bounds vertices.", i1, i2, i3);
183 const VuoPoint4d &v1 = vertex[i1];
184 const VuoPoint4d &v2 = vertex[i2];
185 const VuoPoint4d &v3 = vertex[i3];
187 const VuoPoint4d &w1 = texcoord[i1];
188 const VuoPoint4d &w2 = texcoord[i2];
189 const VuoPoint4d &w3 = texcoord[i3];
191 float x1 = v2.x - v1.x;
192 float x2 = v3.x - v1.x;
193 float y1 = v2.y - v1.y;
194 float y2 = v3.y - v1.y;
195 float z1 = v2.z - v1.z;
196 float z2 = v3.z - v1.z;
198 float s1 = w2.x - w1.x;
199 float s2 = w3.x - w1.x;
200 float t1 = w2.y - w1.y;
201 float t2 = w3.y - w1.y;
203 float r = 1.0 / (s1 * t2 - s2 * t1);
204 VuoPoint4d sdir = (VuoPoint4d){
205 (t2 * x1 - t1 * x2) * r,
206 (t2 * y1 - t1 * y2) * r,
207 (t2 * z1 - t1 * z2) * r,
211 VuoPoint4d tdir = (VuoPoint4d){
212 (s1 * x2 - s2 * x1) * r,
213 (s1 * y2 - s2 * y1) * r,
214 (s1 * z2 - s2 * z1) * r,
227 for (
int a = 0; a < vertexCount; a += 3)
233 const VuoPoint4d &v1 = vertex[i1];
234 const VuoPoint4d &v2 = vertex[i2];
235 const VuoPoint4d &v3 = vertex[i3];
237 const VuoPoint4d &w1 = texcoord[i1];
238 const VuoPoint4d &w2 = texcoord[i2];
239 const VuoPoint4d &w3 = texcoord[i3];
241 float x1 = v2.x - v1.x;
242 float x2 = v3.x - v1.x;
243 float y1 = v2.y - v1.y;
244 float y2 = v3.y - v1.y;
245 float z1 = v2.z - v1.z;
246 float z2 = v3.z - v1.z;
248 float s1 = w2.x - w1.x;
249 float s2 = w3.x - w1.x;
250 float t1 = w2.y - w1.y;
251 float t2 = w3.y - w1.y;
253 float r = 1.0 / (s1 * t2 - s2 * t1);
254 VuoPoint4d sdir = (VuoPoint4d){
255 (t2 * x1 - t1 * x2) * r,
256 (t2 * y1 - t1 * y2) * r,
257 (t2 * z1 - t1 * z2) * r,
261 VuoPoint4d tdir = (VuoPoint4d){
262 (s1 * x2 - s2 * x1) * r,
263 (s1 * y2 - s2 * y1) * r,
264 (s1 * z2 - s2 * z1) * r,
278 for (
long a = 0; a < vertexCount; a++)
280 VuoPoint3d n = (VuoPoint3d){ normal[a].x, normal[a].y, normal[a].z };
281 VuoPoint3d t = (VuoPoint3d){ tan1[a].x, tan1[a].y, tan1[a].z };
282 VuoPoint3d t2 = (VuoPoint3d){ tan2[a].x, tan2[a].y, tan2[a].z };
288 tangent[a] = (VuoPoint4d){tan.x, tan.y, tan.z, 0.};
289 bitangent[a] = (VuoPoint4d){ bitan.x, bitan.y, bitan.z, 0. };
307 const VuoPoint4d* vertices = mesh.
positions;
334 unsigned int dup_vertex_start = submesh->
vertexCount;
339 const VuoPoint4d* vertices = submesh->
positions;
353 textures[i] = (VuoPoint4d)
355 (float)(1 - (.5 + (atan2(v.z, v.x) / (2 *
PI)))),
356 (float)(1. - (.5 - (asin(v.y) /
PI))),
361 if(i >= dup_vertex_start)
370 min.x = fmin(min.x, textures[i].x);
371 min.y = fmin(min.y, textures[i].y);
373 max.x = fmax(max.x, textures[i].x);
374 max.y = fmax(max.y, textures[i].y);
377 VuoPoint2d scale = { 1 / (max.x - min.x), 1 / (max.y - min.y) };
381 textures[i].x -= min.x;
382 textures[i].y -= min.y;
383 textures[i].x *= scale.x;
384 textures[i].y *= scale.y;
412 float x = fabs(normal.x),
416 if( x > y && x > z ) {
417 return normal.x < 0 ? PlaneNegX : PlaneX;
418 }
else if( y > x && y > z ) {
419 return normal.y < 0 ? PlaneNegY : PlaneY;
421 return normal.z < 0 ? PlaneNegZ : PlaneZ;
431 (a.y + b.y + c.y) / 3.,
432 (a.z + b.z + c.z) / 3.,
445 const VuoPoint4d* positions = submesh->
positions;
446 const VuoPoint4d* normals = submesh->
normals;
451 for(
unsigned int i = 0; i < submesh->
vertexCount; i++)
453 VuoPoint4d p = positions[i];
456 uv.x = uv.x / range.x;
457 uv.y = uv.y / range.y;
458 uv.z = uv.z / range.z;
489 const VuoPoint4d* positions = submesh->
positions;
490 const VuoPoint4d* normals = submesh->
normals;
495 for(
unsigned int i = 0; i < submesh->
elementCount; i+=3)
497 unsigned int a = submesh->
elements[i+0],
505 uv_a.x = uv_a.x / range.x;
506 uv_b.x = uv_b.x / range.x;
507 uv_c.x = uv_c.x / range.x;
508 uv_a.y = uv_a.y / range.y;
509 uv_b.y = uv_b.y / range.y;
510 uv_c.y = uv_c.y / range.y;
511 uv_a.z = uv_a.z / range.z;
512 uv_b.z = uv_b.z / range.z;
513 uv_c.z = uv_c.z / range.z;
544 static float dot(
const VuoPoint4d lhs,
const VuoPoint4d rhs)
546 return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
554 const float epsilon = .00001f;
556 return fabs(a.x-b.x) < epsilon &&
557 fabs(a.y-b.y) < epsilon &&
558 fabs(a.z-b.z) < epsilon;
566 const VuoPoint4d* positions = submesh->
positions;
567 const VuoPoint4d* normals = submesh->
normals;
568 const VuoPoint4d* tangents = submesh->
tangents;
569 const VuoPoint4d* bitangents = submesh->
bitangents;
572 const unsigned int* indices = submesh->
elements;
573 unsigned int* seam_indices = (
unsigned int*)malloc(
sizeof(
unsigned int) * submesh->
elementCount);
574 memcpy(seam_indices, indices,
sizeof(
unsigned int) * submesh->
elementCount);
577 std::vector<VuoPoint4d> seam_positions = std::vector<VuoPoint4d>(positions != NULL ? vertexCount : 0);
578 if(positions) std::copy(positions, positions + vertexCount, seam_positions.begin());
579 std::vector<VuoPoint4d> seam_normals = std::vector<VuoPoint4d>(normals != NULL ? vertexCount : 0);
580 if(normals) std::copy(normals, normals + vertexCount, seam_normals.begin());
581 std::vector<VuoPoint4d> seam_tangents = std::vector<VuoPoint4d>(tangents != NULL ? vertexCount : 0);
582 if(tangents) std::copy(tangents, tangents + vertexCount, seam_tangents.begin());
583 std::vector<VuoPoint4d> seam_bitangents = std::vector<VuoPoint4d>(bitangents != NULL ? vertexCount : 0);
584 if(bitangents) std::copy(bitangents, bitangents + vertexCount, seam_bitangents.begin());
585 std::vector<VuoPoint4d> seam_textures = std::vector<VuoPoint4d>(textures != NULL ? vertexCount : 0);
586 if(textures) std::copy(textures, textures + vertexCount, seam_textures.begin());
599 for(
unsigned int i = 0; i < submesh->
elementCount; i+=3)
601 if(indices[i] > vertexCount || indices[i+1] > vertexCount || indices[i+2] > vertexCount)
603 VUserLog(
"Triangle indices are referencing out of bounds vertices. (%u, %u, %u) Vertex Count: %u", indices[i], indices[i+1], indices[i+2], vertexCount);
607 for(
int n = 0; n < 3; n++)
609 unsigned int x = i + n;
610 unsigned int y = i + (n == 2 ? 0 : n+1);
621 if(
dot(v0, left) > 0 &&
dot(v0, forward) < 0 &&
dot(v1, forward) >= 0 )
624 seam_positions.push_back(positions[indices[x]]);
626 seam_normals.push_back(normals[indices[x]]);
628 seam_tangents.push_back(tangents[indices[x]]);
630 seam_bitangents.push_back(bitangents[indices[x]]);
632 seam_textures.push_back(textures[indices[x]]);
634 seam_indices[x] = seam_positions.size() - 1;
638 if(
dot(v1, left) > 0 &&
dot(v1, forward) < 0 &&
dot(v0, forward) >= 0 )
641 seam_positions.push_back(positions[indices[y]]);
643 seam_normals.push_back(normals[indices[y]]);
645 seam_tangents.push_back(tangents[indices[y]]);
647 seam_bitangents.push_back(bitangents[indices[y]]);
649 seam_textures.push_back(textures[indices[y]]);
651 seam_indices[y] = seam_positions.size() - 1;
656 unsigned int seam_vertexCount = seam_positions.size();
658 if(positions != NULL)
661 submesh->
positions = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * seam_vertexCount);
662 std::copy(seam_positions.begin(), seam_positions.end(), submesh->
positions);
668 submesh->
normals = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * seam_vertexCount);
669 std::copy(seam_normals.begin(), seam_normals.end(), submesh->
normals);
675 submesh->
tangents = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * seam_vertexCount);
676 std::copy(seam_tangents.begin(), seam_tangents.end(), submesh->
tangents);
679 if(bitangents != NULL)
682 submesh->
bitangents = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * seam_vertexCount);
683 std::copy(seam_bitangents.begin(), seam_bitangents.end(), submesh->
bitangents);
689 submesh->
textureCoordinates = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * seam_vertexCount);
702 static int compare(
const void* lhs,
const void* rhs)
704 return ( *(
int*)lhs - *(
int*)rhs );
715 unsigned int* sortedTriangles = (
unsigned int*)malloc(
sizeof(
unsigned int) * elementCount);
716 memcpy(sortedTriangles, mesh->
elements,
sizeof(
unsigned int) * elementCount);
719 qsort(sortedTriangles, elementCount,
sizeof(
unsigned int),
compare);
722 unsigned int last = elementCount-1;
724 while( sortedTriangles[last] > vertexCount )
728 if(last < elementCount-1)
730 unsigned int* pruned_elements = (
unsigned int*)malloc(
sizeof(
unsigned int) * (last+1));
734 for(
unsigned int i = 0; i < elementCount; i++)
737 pruned_elements[n++] = mesh->
elements[i];
740 elementCount = last+1;
747 std::vector<unsigned int> unused;
750 for(
int i = 0; i < elementCount && sortedTriangles[i] < elementCount; i++)
752 for(
int n = lastVal+1; n < sortedTriangles[i]; n++)
757 lastVal = sortedTriangles[i];
759 free(sortedTriangles);
763 int unusedCount = unused.size();
764 for(
int i = 0; i < elementCount; i++)
766 unsigned int vertex = mesh->
elements[i];
768 if(vertex > vertexCount)
773 for(
auto& val : unused)
786 std::vector<VuoPoint4d> new_positions = std::vector<VuoPoint4d>(mesh->
positions == NULL ? 0 : vertexCount);
787 std::vector<VuoPoint4d> new_normals = std::vector<VuoPoint4d>(mesh->
normals == NULL ? 0 : vertexCount);
788 std::vector<VuoPoint4d> new_tangents = std::vector<VuoPoint4d>(mesh->
tangents == NULL ? 0 : vertexCount);
789 std::vector<VuoPoint4d> new_bitangents = std::vector<VuoPoint4d>(mesh->
bitangents == NULL ? 0 : vertexCount);
790 std::vector<VuoPoint4d> new_textureCoordinates = std::vector<VuoPoint4d>(mesh->
textureCoordinates == NULL ? 0 : vertexCount);
792 unsigned int curIndex = 0, n = 0;
793 for(
int i = 0; i < vertexCount; i++)
795 if(curIndex >= unusedCount || i < unused[curIndex])
800 new_normals[n] = mesh->
normals[i];
802 new_tangents[n] = mesh->
tangents[i];
814 }
while(curIndex < unusedCount && unused[curIndex] <= i);
819 unsigned int culledVertexCount = new_positions.size();
824 mesh->
positions = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * culledVertexCount);
825 std::copy(new_positions.begin(), new_positions.end(), mesh->
positions);
831 mesh->
normals = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * culledVertexCount);
832 std::copy(new_normals.begin(), new_normals.end(), mesh->
normals);
838 mesh->
tangents = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * culledVertexCount);
839 std::copy(new_tangents.begin(), new_tangents.end(), mesh->
tangents);
845 mesh->
bitangents = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * culledVertexCount);
846 std::copy(new_bitangents.begin(), new_bitangents.end(), mesh->
bitangents);
852 mesh->
textureCoordinates = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d) * culledVertexCount);
853 std::copy(new_textureCoordinates.begin(), new_textureCoordinates.end(), mesh->
textureCoordinates);