| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- #include "BsMeshUtility.h"
- #include "BsVector3.h"
- #include "BsVector2.h"
- namespace BansheeEngine
- {
- struct VertexFaces
- {
- UINT32* faces;
- UINT32 numFaces = 0;
- };
- struct VertexConnectivity
- {
- VertexConnectivity(UINT8* indices, UINT32 numVertices, UINT32 numFaces, UINT32 indexSize)
- :vertexFaces(nullptr), mMaxFacesPerVertex(0), mFaces(nullptr), mNumVertices(numVertices)
- {
- vertexFaces = bs_newN<VertexFaces>(numVertices);
- resizeFaceArray(10);
- for (UINT32 i = 0; i < numFaces; i++)
- {
- for (UINT32 j = 0; j < 3; j++)
- {
- UINT32 idx = i * 3 + j;
- UINT32 vertexIdx = 0;
- memcpy(&vertexIdx, indices + idx * indexSize, indexSize);
- VertexFaces& faces = vertexFaces[vertexIdx];
- if (faces.numFaces >= mMaxFacesPerVertex)
- resizeFaceArray(mMaxFacesPerVertex * 2);
- faces.faces[faces.numFaces] = i;
- faces.numFaces++;
- }
- }
- }
- ~VertexConnectivity()
- {
- if (vertexFaces != nullptr)
- bs_deleteN(vertexFaces, mNumVertices);
- if (mFaces != nullptr)
- bs_free(mFaces);
- }
- VertexFaces* vertexFaces;
- private:
- void resizeFaceArray(UINT32 numFaces)
- {
- UINT32* newFaces = (UINT32*)bs_alloc(numFaces * mNumVertices);
- if (mFaces != nullptr)
- {
- for (UINT32 i = 0; i < mNumVertices; i++)
- memcpy(newFaces + (i * numFaces), mFaces + (i * mMaxFacesPerVertex), mMaxFacesPerVertex * sizeof(UINT32));
- bs_free(mFaces);
- }
- for (UINT32 i = 0; i < mNumVertices; i++)
- vertexFaces[i].faces = newFaces + (i * numFaces);
- mFaces = newFaces;
- mMaxFacesPerVertex = numFaces;
- }
- UINT32 mMaxFacesPerVertex;
- UINT32 mNumVertices;
- UINT32* mFaces;
- };
- void MeshUtility::calculateNormals(Vector3* vertices, UINT8* indices, UINT32 numVertices,
- UINT32 numIndices, Vector3* normals, UINT32 indexSize)
- {
- UINT32 numFaces = numIndices / 3;
- Vector3* faceNormals = bs_newN<Vector3>(numFaces);
- for (UINT32 i = 0; i < numFaces; i++)
- {
- UINT32 triangle[3];
- memcpy(&triangle[0], indices + (i * 3 + 0) * indexSize, indexSize);
- memcpy(&triangle[1], indices + (i * 3 + 1) * indexSize, indexSize);
- memcpy(&triangle[2], indices + (i * 3 + 2) * indexSize, indexSize);
- Vector3 edgeA = vertices[triangle[1]] - vertices[triangle[0]];
- Vector3 edgeB = vertices[triangle[2]] - vertices[triangle[0]];
- faceNormals[i] = Vector3::normalize(Vector3::cross(edgeA, edgeB));
- // Note: Potentially don't normalize here in order to weigh the normals
- // by triangle size
- }
- VertexConnectivity connectivity(indices, numVertices, numFaces, indexSize);
- for (UINT32 i = 0; i < numVertices; i++)
- {
- VertexFaces& faces = connectivity.vertexFaces[i];
- for (UINT32 j = 0; j < faces.numFaces; j++)
- {
- UINT32 faceIdx = faces.faces[j];
- normals[i] += faceNormals[faceIdx];
- }
- normals[i].normalize();
- }
- bs_deleteN(faceNormals, numFaces);
- }
- void MeshUtility::calculateTangents(Vector3* vertices, Vector3* normals, Vector2* uv, UINT8* indices, UINT32 numVertices,
- UINT32 numIndices, Vector3* tangents, Vector3* bitangents, UINT32 indexSize)
- {
- UINT32 numFaces = numIndices / 3;
- Vector3* faceTangents = bs_newN<Vector3>(numFaces);
- Vector3* faceBitangents = bs_newN<Vector3>(numFaces);
- for (UINT32 i = 0; i < numFaces; i++)
- {
- UINT32 triangle[3];
- memcpy(&triangle[0], indices + (i * 3 + 0) * indexSize, indexSize);
- memcpy(&triangle[1], indices + (i * 3 + 1) * indexSize, indexSize);
- memcpy(&triangle[2], indices + (i * 3 + 2) * indexSize, indexSize);
- Vector3 p0 = vertices[triangle[0]];
- Vector3 p1 = vertices[triangle[1]];
- Vector3 p2 = vertices[triangle[2]];
- Vector2 uv0 = uv[triangle[0]];
- Vector2 uv1 = uv[triangle[1]];
- Vector2 uv2 = uv[triangle[2]];
- Vector3 q0 = p1 - p0;
- Vector3 q1 = p2 - p0;
- Vector2 s;
- s.x = uv1.x - uv0.x;
- s.y = uv2.x - uv0.x;
- Vector2 t;
- t.x = uv1.y - uv0.y;
- t.y = uv2.y - uv0.y;
- float denom = s.x*t.y - s.y * t.x;
- if (fabs(denom) >= 0e-8f)
- {
- float r = 1.0f / denom;
- s *= r;
- t *= r;
- faceTangents[i] = t.y * q0 - t.x * q1;
- faceBitangents[i] = s.x * q0 - s.y * q1;
- faceTangents[i].normalize();
- faceBitangents[i].normalize();
- }
- // Note: Potentially don't normalize here in order to weigh the normals
- // by triangle size
- }
- VertexConnectivity connectivity(indices, numVertices, numFaces, indexSize);
- for (UINT32 i = 0; i < numVertices; i++)
- {
- VertexFaces& faces = connectivity.vertexFaces[i];
- for (UINT32 j = 0; j < faces.numFaces; j++)
- {
- UINT32 faceIdx = faces.faces[j];
- tangents[i] += faceTangents[faceIdx];
- bitangents[i] += faceBitangents[faceIdx];
- }
- tangents[i].normalize();
- bitangents[i].normalize();
- // Orthonormalize
- float dot0 = normals[i].dot(tangents[i]);
- tangents[i] -= dot0*normals[i];
- tangents[i].normalize();
- float dot1 = tangents[i].dot(bitangents[i]);
- dot0 = normals[i].dot(bitangents[i]);
- bitangents[i] -= dot0*normals[i] + dot1*tangents[i];
- bitangents[i].normalize();
- }
- bs_deleteN(faceTangents, numFaces);
- bs_deleteN(faceBitangents, numFaces);
- // TODO - Consider weighing tangents by triangle size and/or edge angles
- }
- void MeshUtility::calculateTangentSpace(Vector3* vertices, Vector2* uv, UINT8* indices, UINT32 numVertices,
- UINT32 numIndices, Vector3* normals, Vector3* tangents, Vector3* bitangents, UINT32 indexSize)
- {
- calculateNormals(vertices, indices, numVertices, numIndices, normals, indexSize);
- calculateTangents(vertices, normals, uv, indices, numVertices, numIndices, tangents, bitangents, indexSize);
- }
- }
|