• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            麒麟子

            ~~

            導(dǎo)航

            <2010年12月>
            2829301234
            567891011
            12131415161718
            19202122232425
            2627282930311
            2345678

            統(tǒng)計(jì)

            常用鏈接

            留言簿(12)

            隨筆分類

            隨筆檔案

            Friends

            WebSites

            積分與排名

            最新隨筆

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            Computing Tangent Space Basis Vectors for an Arbitrary Mesh

            原文地址:http://www.terathon.com/code/tangent.html

            為一個(gè)任意網(wǎng)格模型計(jì)算其切線空間的基本向量(即切線空間的T B N三個(gè)向量)

            Modern bump mapping (also known as normal mapping) requires that tangent plane basis vectors be calculated for each vertex in a mesh. This article presents the theory behind the computation of per-vertex tangent spaces for an arbitrary triangle mesh and provides source code that implements the proper mathematics.

            現(xiàn)在的bump mapping(或者normal mapping)需要每個(gè)頂點(diǎn)的切面的基本向量。這篇文章描述了逐頂點(diǎn)計(jì)算任意三角模型的切線空間原理,并且提供了實(shí)現(xiàn)這個(gè)數(shù)學(xué)理論的源代碼。

             

            Mathematical Derivation 數(shù)學(xué)來(lái)源

            [This derivation also appears in Mathematics for 3D Game Programming and Computer Graphics, 2nd ed., Section 6.8.]

             

            We want our tangent space to be aligned such that the x axis corresponds to the u direction in the bump map and the y axis corresponds to the v direction in the bump map. That is, if Q represents a point inside the triangle, we would like to be able to write

            我們想我們的切線空間像這樣對(duì)齊,比如; X軸相當(dāng)于bump圖中的U方向,而Y軸相當(dāng)于bump圖中的V方向。于是,如果Q表示三角形上的一點(diǎn),則我們可以得出如下等式

            QP0 = (uu0)T + (vv0)B,

             

            where T and B are tangent vectors aligned to the texture map, P0 is the position of one of the vertices of the triangle, and (u0, v0) are the texture coordinates at that vertex. The letter B stands for bitangent, but in many places it is stilled called binormal because of a mix-up in terms when tangent-space bump mapping first became widespread. (See “Bitangent versus Binormal” below.)

            等式中的T是與紋理對(duì)應(yīng)的切線向量,P0 是三角形的其中一個(gè)頂點(diǎn)。(u0, v0) 是對(duì)應(yīng)頂點(diǎn)的紋理坐標(biāo)。 B表示副(雙)切線(bitangent),但是由于在切線空間的bump mapping第一次被傳播開來(lái)的時(shí)候,有人混淆這個(gè)定義,所以在許多地方它始終被稱為副法線(binormal )。(參見下面的Bitangent VS Binormal)

             

            Suppose that we have a triangle whose vertex positions are given by the points P0, P1, and P2, and whose corresponding texture coordinates are given by (u0, v0), (u1, v1), and (u2, v2). Our calculations can be made much simpler by working relative to the vertex P0, so we let

            假設(shè)三角形的三個(gè)頂點(diǎn)分別為P0, P1, and P2, 其分別對(duì)應(yīng)的紋理坐標(biāo)為(u0, v0), (u1, v1), and (u2, v2). 。那我們的計(jì)算就可以簡(jiǎn)化下為下面的方程式組

            Q1 = P1P0
            Q2 = P2P0

            設(shè)

            (s1, t1) = (u1u0, v1v0)
            (s2, t2) = (u2u0, v2v0).

            We need to solve the following equations for T and B.

            于是,我們最終要解決的就是下面這個(gè)方程式

            Q1 = s1T + t1B
            Q2 = s2T + t2B

            This is a linear system with six unknowns (three for each T and B) and six equations (the x, y, and z components of the two vector equations). We can write this in matrix form as follows.

            這個(gè)有著6個(gè)未知數(shù)的線性方程組(T,B是向量,每個(gè)有三個(gè)量)。我們可以把它寫成如下的矩陣方式

            image

            Multiplying both sides by the inverse of the (s, t) matrix, we have

            兩邊都乘以(s,t)的逆矩陣

            image .

             

            This gives us the (unnormalized) T and B tangent vectors for the triangle whose vertices are P0, P1, and P2. To find the tangent vectors for a single vertex, we average the tangents for all triangles sharing that vertex in a manner similar to the way in which vertex normals are commonly calculated. In the case that neighboring triangles have discontinuous texture mapping, vertices along the border are generally already duplicated since they have different mapping coordinates anyway. We do not average tangents from such triangles because the result would not accurately represent the orientation of the bump map for either triangle.

            由此,我們解出等式后,就得到了未單位化的T和B。 為了找到單個(gè)頂點(diǎn)的切線向量,我們平均共享這個(gè)頂點(diǎn)的所有切三角形的的切線。法線也可以通過類似的方式計(jì)算出來(lái)。 而在這種情況下,相鄰的兩個(gè)三角形則會(huì)形成不連續(xù)的紋理映射,處于邊緣的頂點(diǎn)由于有不同的紋理坐標(biāo)而經(jīng)常被復(fù)制。我們沒有平均這些三角形的切線,因?yàn)槲覀兊挠?jì)算結(jié)果就可以不精確地描述每個(gè)三角形的切線朝向。

             

            Once we have the normal vector N and the tangent vectors T and B for a vertex, we can transform from tangent space into object space using the matrix

            一旦我們得到了一個(gè)頂點(diǎn)的法向量N和切線T和B。我們就可以用它們來(lái)構(gòu)造一個(gè)由正切空間到對(duì)象空間的矩陣。

            image

            To transform in the opposite direction (from object space to tangent space—what we want to do to the light direction), we can simply use the inverse of this matrix. It is not necessarily true that the tangent vectors are perpendicular to each other or to the normal vector, so the inverse of this matrix is not generally equal to its transpose. It is safe to assume, however, that the three vectors will at least be close to orthogonal, so using the Gram-Schmidt algorithm to orthogonalize them should not cause any unacceptable distortions. Using this process, new (still unnormalized) tangent vectors T′ and B′ are given by

            為了向反方向變換(從對(duì)象空間變換到正切空間,[法線貼圖時(shí)]我們需這樣處理光照方向),我們可以簡(jiǎn)單地使用這個(gè)矩陣的逆矩陣。 但我們要注意切線向量并非總是與其它兩個(gè)向量,或法向量垂直的。于是,我們的逆矩陣并非總是等于其轉(zhuǎn)置矩陣。但是,可以安全地認(rèn)為,這三個(gè)向量是非常接近正交關(guān)系的。 所以使用我們可以使用Gram-Schmidt算法來(lái)對(duì)其進(jìn)行正交化,就不會(huì)出現(xiàn)不可接受的誤差了。

            T′ = T − (N · T)N
            B′ = B − (N · B)N − (T′ · B)T′/T2

            Normalizing these vectors and storing them as the tangent and bitangent for a vertex lets us use the matrixto transform the direction to light from object space into tangent space. Taking the dot product of the transformed light direction with a sample from the bump map then produces the correct Lambertian diffuse lighting value.

            單位化這些向量并將其存為一個(gè)頂點(diǎn)的tangent 和bitangent 。

            于是,我們可以用下面這個(gè)矩陣將光方向從對(duì)象空間轉(zhuǎn)換到切線空間。然后將轉(zhuǎn)換后的光照方向和bump圖中的采樣值點(diǎn)乘,然后再處理某些矯正因子就可以完成光照的計(jì)算。

            image

            It is not necessary to store an extra array containing the per-vertex bitangent since the cross product N × T′ can be used to obtain mB′, where m = ±1 represents the handedness of the tangent space. The handedness value must be stored per-vertex since the bitangent B′ obtained from N × T′ may point in the wrong direction. The value of m is equal to the determinant of the matrix in Equation (*). One may find it convenient to store the per-vertex tangent vector T′ as a four-dimensional entity whose w coordinate holds the value of m. Then the bitangent B′ can be computed using the formula

            我們也不必要存儲(chǔ)bitangent這個(gè)值。因?yàn)?strong>N × T′可以得出我們的mB′,這里的m = ±1,表示切空間的左右手坐標(biāo)系習(xí)慣。表示左右手坐標(biāo)系習(xí)慣的這個(gè)值必須逐頂點(diǎn)存儲(chǔ)。因?yàn)閎itangent B′ 是由N × T′計(jì)算得來(lái),就可能指向錯(cuò)誤的方向。m的值必須要和(*)中的決定保持一致。 所以我們可以用T′的w分量來(lái)存儲(chǔ)m值。最后B′的值就可以向下面一樣計(jì)算

            B′ = T’(N × T′),

             

            where the cross product ignores the w coordinate. This works nicely for vertex programs by avoiding the need to specify an additional array containing the per-vertex m values.

            向量的叉乘忽略了w分量,因此不會(huì)造成任何影響。這樣就可以很好地寫頂點(diǎn)程序,而不用另外用空間來(lái)存儲(chǔ)m值。

             

            Bitangent versus Binormal

            The term binormal is commonly used as the name of the second tangent direction (that is perpendicular to the surface normal and u-aligned tangent direction). This is a misnomer. The term binormal pops up in the study of curves and completes what is known as a Frenet frame about a particular point on a curve. Curves have a single tangent direction and two orthogonal normal directions, hence the terms normal and binormal. When discussing a coordinate frame at a point on a surface, there is one normal direction and two tangent directions, which should be called the tangent and bitangent.

            (上面講的就是binormalbitangent的區(qū)別)。

            Source Code

            The code below generates a four-component tangent T in which the handedness of the local coordinate system is stored as ±1 in the w-coordinate. The bitangent vector B is then given by B = (N × T) · Tw.

            下面的代碼產(chǎn)生了一個(gè)4維的T,其第4個(gè)分量用于存儲(chǔ)左右手坐標(biāo)系習(xí)慣。B 是由 B = (N × T) · Tw.計(jì)算而來(lái)。

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


            How to cite this article

            Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html

            posted on 2010-12-20 23:17 麒麟子 閱讀(1848) 評(píng)論(0)  編輯 收藏 引用 所屬分類: GPU and Graphic

            99久久香蕉国产线看观香| 麻豆精品久久久一区二区| 久久影院午夜理论片无码| 伊人伊成久久人综合网777| 亚洲日韩中文无码久久| 精品久久香蕉国产线看观看亚洲 | 思思久久99热免费精品6| 亚洲国产日韩欧美综合久久| 亚洲人成伊人成综合网久久久 | 亚洲欧美日韩久久精品第一区| 久久精品天天中文字幕人妻| 狠狠色综合久久久久尤物| 中文字幕精品无码久久久久久3D日动漫| 亚洲AV乱码久久精品蜜桃| 久久高潮一级毛片免费| 99精品国产在热久久| 中文字幕久久久久人妻| 久久99亚洲综合精品首页| 国产Av激情久久无码天堂| 精产国品久久一二三产区区别| 久久91亚洲人成电影网站| 亚洲国产美女精品久久久久∴| 精品综合久久久久久88小说 | 国产精品久久久久影院嫩草 | 18岁日韩内射颜射午夜久久成人| 偷偷做久久久久网站| 久久97久久97精品免视看| 91久久精一区二区三区大全| 久久人人爽人人爽人人片av麻烦 | 久久亚洲高清综合| 丁香久久婷婷国产午夜视频| 久久久久久九九99精品| 无码人妻久久一区二区三区免费 | 99久久综合狠狠综合久久| 久久久精品人妻一区二区三区蜜桃 | 91性高湖久久久久| 99久久国产综合精品网成人影院| 99久久99久久精品免费看蜜桃 | 久久影院午夜理论片无码 | 久久婷婷午色综合夜啪| 合区精品久久久中文字幕一区|