Pertama-tama, untuk setiap titik 3D ada vektor garis singgung dan bi-tangen tak terbatas. Gambar di bawah ini menjelaskan mengapa ada jumlah ruang singgung yang tak terbatas untuk setiap titik, garis singgung dan bitangen dapat memiliki arah apa pun di bidang yang ditampilkan.
Jadi, inorder untuk menghitung dengan benar ruang tangen 1 yang paling berguna , kami ingin ruang tangen kami disejajarkan sedemikian rupa sehingga sumbu x (garis singgung) sesuai dengan arah u dalam peta bump dan sumbu y (bitangent) sesuai dengan arah v dalam peta benjolan, kita seharusnya sudah memiliki normal dari simpul yang sudah sesuai dengan arah Z dalam ruang singgung.
(1) paling berguna karena pada akhirnya kami ingin vektor normal disampel dari tekstur
Yang terbaik dijelaskan dengan gambar, kami ingin ruang singgung kami selaras seperti yang (u, v)
ditunjukkan di bawah ini.
Sumber gambar meskipun tidak sepenuhnya terkait dengan grafik komputer
Di komputer, pengembang grafis biasanya menggunakan (u,v)
juga dikenal sebagai koordinat tekstur. Kami akan menganggap T adalah garis singgung dan B adalah bitangent, dan P0
merupakan simpul target kami, yang merupakan bagian dari segitiga (P0,P1,P2)
.
Pertama ingat apa yang ingin kita lakukan, adalah menghitung tangen dan bitanget yang:
- T sejajar dengan u dan B sejajar dengan v.
- T dan B terletak pada bidang dengan titik normal (bidang ditunjukkan pada gambar di atas).
Intinya adalah kita sudah mengasumsikan bahwa T dan B terletak pada bidang yang sama dan berkorespondensi dengan U dan V sekarang jika kita dapat mengetahui nilai-nilainya, kita dapat melintasi produk dan vektor ketiga untuk membangun matriks transformasi dari dunia ke ruang singgung.
Mengingat bahwa kita tahu bahwa setiap vektor 2D dapat ditulis sebagai kombinasi linear dari dua vektor independen 2 dan karena kita sudah memiliki titik-titik segitiga (tepi), ditunjukkan pada gambar di atas. Kita bisa menulis:
E1 = (u1-u0) T + (v1-v0) B
E2 = (u2-u0) T + (v2-v0) B
(2) sebenarnya itulah bagaimana basis matriks diturunkan
Persamaan di atas dapat ditulis dalam bentuk matriks,
| E1x E1y E1z | | deltaU1 deltaV1 | * | Tx Ty Tz |
| E2x E2y E2z | = | deltaU2 deltaV2 | | Bx By Bz |
Dengan menyelesaikan persamaan matriks kita dapat menentukan nilai T dan B kita dapat membangun matriks transformasi.
Kode sumber lengkap dalam C ++
#include "Vector4D.h"
struct Triangle
{
unsigned short index[3];
};
void CalculateTangentArray(long vertexCount, const Point3D *vertex, const Vector3D *normal,
const Point2D *texcoord, long triangleCount, const Triangle *triangle, Vector4D *tangent)
{
Vector3D *tan1 = new Vector3D[vertexCount * 2];
Vector3D *tan2 = tan1 + vertexCount;
ZeroMemory(tan1, vertexCount * sizeof(Vector3D) * 2);
for (long a = 0; a < triangleCount; a++)
{
long i1 = triangle->index[0];
long i2 = triangle->index[1];
long i3 = triangle->index[2];
const Point3D& v1 = vertex[i1];
const Point3D& v2 = vertex[i2];
const Point3D& v3 = vertex[i3];
const Point2D& w1 = texcoord[i1];
const Point2D& w2 = texcoord[i2];
const Point2D& w3 = texcoord[i3];
float x1 = v2.x - v1.x;
float x2 = v3.x - v1.x;
float y1 = v2.y - v1.y;
float y2 = v3.y - v1.y;
float z1 = v2.z - v1.z;
float z2 = v3.z - v1.z;
float s1 = w2.x - w1.x;
float s2 = w3.x - w1.x;
float t1 = w2.y - w1.y;
float t2 = w3.y - w1.y;
float r = 1.0F / (s1 * t2 - s2 * t1);
Vector3D sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
(t2 * z1 - t1 * z2) * r);
Vector3D tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
(s1 * z2 - s2 * z1) * r);
tan1[i1] += sdir;
tan1[i2] += sdir;
tan1[i3] += sdir;
tan2[i1] += tdir;
tan2[i2] += tdir;
tan2[i3] += tdir;
triangle++;
}
for (long a = 0; a < vertexCount; a++)
{
const Vector3D& n = normal[a];
const Vector3D& t = tan1[a];
// Gram-Schmidt orthogonalize
tangent[a] = (t - n * Dot(n, t)).Normalize();
// Calculate handedness
tangent[a].w = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F;
}
delete[] tan1;
}
Kode sumber dan derivasi lengkap dapat ditemukan di sini .