Teğet ve bitanjant vektörler nasıl hesaplanır


9

Üç dokuda yüklü bir doku var, sonra gölgelendiricilere geçti. Köşe gölgelendiricisinde normali hesaplıyorum ve değişkene uv vektörünü kaydediyorum.

<script id="vertexShader" type="x-shader/x-vertex">

                varying vec3 N,P;
                varying vec2 UV;

                void main() {
                    gl_Position= projectionMatrix * modelViewMatrix * vec4(position,1.0);
                    P= position;
                    N= normalMatrix * vec3(normal);
                    UV= uv;
                }
            </script>
            <script id="fragmentShader" type="x-shader/x-fragment">

                varying vec3 N,P;
                varying vec2 UV;
                uniform sampler2D texture;

                void main() {
                    gl_FragColor= texture2D(texture,UV);
                }

            </script>

T ve B vektörlerini nasıl hesaplayabilirim?


2
algoritmayı genel olarak mı yoksa özellikle seçtiğiniz kütüphaneniz için mi istiyorsunuz?
concept3d

Eğer bunu üç.js ile hesaplayabilirsem daha iyi olur.
Ramy Al Zuhouri

Yanıtlar:


26

Her şeyden önce, her 3D tepe noktası için sonsuz teğet ve iki teğet vektörler vardır. Aşağıdaki görüntü, her köşe için neden sonsuz sayıda teğet boşluğunun olduğunu açıklar, teğet ve bitanjant, gösterilen düzlemde herhangi bir yöne sahip olabilir.

Her köşe için sonsuz sayıda tanget alanı

Bu nedenle, en kullanışlı 1 teğet boşluğunu doğru bir şekilde hesaplamak için , teğet alanımızın x ekseni (teğet) yumru haritasındaki u yönüne ve y ekseni (bitanjant) v yönüne karşılık gelecek şekilde hizalanmasını istiyoruz yumru haritasında, teğet uzaydaki Z yönüne zaten karşılık gelen tepe noktasının normaline sahip olmalıyız.

(1) en kullanışlı çünkü sonunda normal vektörlerin dokudan örneklenmesini istiyoruz

En iyi resimlerle açıklanabilir, teğet alanımızın (u, v)aşağıda gösterildiği gibi hizalanmasını istiyoruz .

resim açıklamasını buraya girin

Bilgisayar grafikleri ile tam olarak ilgili olmasa da görüntünün kaynağı

Bilgisayar grafiklerinde geliştiriciler genellikle (u,v)doku koordinatları olarak da bilinir. T'nin tanjant olduğunu ve B'nin bitanjant P0olduğunu ve üçgenin bir parçası olan hedef tepe noktamız olduğunu varsayacağız (P0,P1,P2).

Öncelikle ne yapmak istediğimizi hatırlayın, tanjant hesaplamak ve bunu iki noktadan ayırmaktır:

  1. T u ile hizalıdır ve B v ile hizalıdır.
  2. T ve B düzlemde tepe noktası normal şekilde (yukarıdaki görüntüde gösterilen düzlem) yer alır.

Mesele şu ki, T ve B'nin aynı düzlemde bulunduğunu ve şimdi U ve V'ye karşılık geldiğini varsaydık, eğer değerlerini bilebilirsek, dünyadan teğet uzaya bir dönüşüm matrisi oluşturmak için ürünü ve üçüncü vektörü geçebiliriz.

resim açıklamasını buraya girin

Herhangi bir 2D vektörün iki bağımsız vektörün 2 doğrusal bir kombinasyonu olarak yazılabileceğini bildiğimiz ve yukarıdaki resimde gösterildiği gibi üçgen noktalara (kenarlara) sahip olduğumuz göz önüne alındığında . Yazabiliriz:

E1 = (u1-u0) T + (v1-v0) B

E2 = (u2-u0) T + (v2-v0) B

(2) aslında temel matris böyle elde edilir

Yukarıdaki denklem bir matris biçiminde yazılabilir,

| E1x E1y E1z |   | deltaU1 deltaV1 | * | Tx Ty Tz |
| E2x E2y E2z | = | deltaU2 deltaV2 |   | Bx By Bz |

Matris denklemini çözerek T ve B değerlerini belirleyebiliriz, bir dönüşüm matrisi oluşturabiliriz.

C ++ 'da tam kaynak kodu

#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;
}

Tam kaynak kodu ve türetme burada bulunabilir .


Bir üçgenim yoksa ne olur? Benim durumumda, bir küreye uygulanması gereken bir doku var. Bu duruma nasıl uyarlanır?
Ramy Al Zuhouri

@RamyAlZuhouri küre üçgenlerden oluşmuyor mu? Sadece kodda olduğu gibi köşe noktaları üzerinde döngü. Küreniz üçgen tabanlı değilse, bu tamamen farklı bir hikaye.
concept3d

Three.js SphereGeometry (javascript içinde) kullanıyorum. Belki de yüz özelliğini gölgelendiricilere iletmeliyim? Çizdiğim kürenin 1089 köşesi ve 1084 yüzü var.
Ramy Al Zuhouri

1
teğet alanını hesaplar ve ardından teğetleri gölgelendiricilere geçirirsiniz. Teğet alanı hesaplamak için yüze / köşelere erişiminiz olmalıdır.
concept3d

Benim durumumda 1084 teğetim olacak, tanjantları köşelerle nasıl eşleyebilirim?
Ramy Al Zuhouri
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.