1#include "ConstructTangentSpace.h"
5 IMPLEMENT_CLASS(ConstructTangentSpace)
7 ConstructTangentSpace::ConstructTangentSpace()
9 this->outNormal()->allocate();
10 this->outTangent()->allocate();
11 this->outBitangent()->allocate();
14 ConstructTangentSpace::~ConstructTangentSpace()
18 template<typename TriangleIndex>
19 __global__ void CTS_AccumulateTangentSpace(
20 DArray<Vec3f> tangent,
21 DArray<Vec3f> bitangent,
24 DArray<Vec2f> texCoord,
25 DArray<TriangleIndex> vIndex,
26 DArray<TriangleIndex> nIndex,
27 DArray<TriangleIndex> tIndex)
29 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
30 if (tId >= vIndex.size()) return;
32 TriangleIndex vIdx = vIndex[tId];
33 TriangleIndex nIdx = nIndex[tId];
34 TriangleIndex tIdx = tIndex[tId];
36 Vec3f v0 = vertex[vIdx[0]];
37 Vec3f v1 = vertex[vIdx[1]];
38 Vec3f v2 = vertex[vIdx[2]];
40 Vec2f uv0 = texCoord[tIdx[0]];
41 Vec2f uv1 = texCoord[tIdx[1]];
42 Vec2f uv2 = texCoord[tIdx[2]];
44 // Edges of the triangle : position delta
45 Vec3f deltaPos1 = v1 - v0;
46 Vec3f deltaPos2 = v2 - v0;
49 Vec2f deltaUV1 = uv1 - uv0;
50 Vec2f deltaUV2 = uv2 - uv0;
52 float r = 1.0 / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
53 Vec3f tangent_i = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r;
54 Vec3f bitangent_i = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r;
57 atomicAdd(&tangent[nIdx[0]].x, tangent_i.x);
58 atomicAdd(&tangent[nIdx[0]].y, tangent_i.y);
59 atomicAdd(&tangent[nIdx[0]].z, tangent_i.z);
61 atomicAdd(&tangent[nIdx[1]].x, tangent_i.x);
62 atomicAdd(&tangent[nIdx[1]].y, tangent_i.y);
63 atomicAdd(&tangent[nIdx[1]].z, tangent_i.z);
65 atomicAdd(&tangent[nIdx[2]].x, tangent_i.x);
66 atomicAdd(&tangent[nIdx[2]].y, tangent_i.y);
67 atomicAdd(&tangent[nIdx[2]].z, tangent_i.z);
69 //Accumulate bitangent
70 atomicAdd(&bitangent[nIdx[0]].x, bitangent_i.x);
71 atomicAdd(&bitangent[nIdx[0]].y, bitangent_i.y);
72 atomicAdd(&bitangent[nIdx[0]].z, bitangent_i.z);
74 atomicAdd(&bitangent[nIdx[1]].x, bitangent_i.x);
75 atomicAdd(&bitangent[nIdx[1]].y, bitangent_i.y);
76 atomicAdd(&bitangent[nIdx[1]].z, bitangent_i.z);
78 atomicAdd(&bitangent[nIdx[2]].x, bitangent_i.x);
79 atomicAdd(&bitangent[nIdx[2]].y, bitangent_i.y);
80 atomicAdd(&bitangent[nIdx[2]].z, bitangent_i.z);
83 __global__ void CTS_NormalizeTangentSpace(
84 DArray<Vec3f> tangent,
85 DArray<Vec3f> bitangent,
86 DArray<Vec3f> normals)
88 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
89 if (tId >= tangent.size()) return;
91 Vec3f normal_i = normals[tId];
92 Vec3f tangent_i = tangent[tId];
93 Vec3f bitangent_i = bitangent[tId];
95 tangent_i = tangent_i - tangent_i.dot(normal_i) * normal_i;
96 bitangent_i = bitangent_i - bitangent_i.dot(normal_i) * normal_i;
98 tangent[tId] = tangent_i.normalize();
99 bitangent[tId] = bitangent_i.normalize();
102 void ConstructTangentSpace::compute()
104 auto mesh = this->inTextureMesh()->constDataPtr();
106 auto& inVertex = mesh->vertices();
107 auto& inNormal = mesh->normals();
108 auto& inTexCoord = mesh->texCoords();
109 auto& inShapes = mesh->shapes();
111 if (this->outNormal()->size() != inNormal.size()) {
112 auto totalNum = inNormal.size();
113 this->outNormal()->resize(totalNum);
114 this->outTangent()->resize(totalNum);
115 this->outBitangent()->resize(totalNum);
118 auto& outNormal = this->outNormal()->getData();
119 auto& outTangent = this->outTangent()->getData();
120 auto& outBitangent = this->outBitangent()->getData();
124 outBitangent.reset();
126 for (auto i = 0; i < inShapes.size(); i++)
128 auto& shape = inShapes[i];
130 auto& vIndex = shape->vertexIndex;
131 auto& nIndex = shape->normalIndex;
132 auto& tIndex = shape->texCoordIndex;
134 cuExecute(nIndex.size(),
135 CTS_AccumulateTangentSpace,
146 cuExecute(outTangent.size(),
147 CTS_NormalizeTangentSpace,
152 outNormal.assign(inNormal);