游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2252|回复: 2

有关求vertex tangent

[复制链接]

31

主题

257

帖子

1752

积分

金牌会员

申城谍影

Rank: 6Rank: 6

积分
1752
QQ
发表于 2016-5-25 17:53:11 | 显示全部楼层 |阅读模式
提个小问题,

在OpenGL应用法线贴图时,

需要CPU计算法线,切线,副法线,作为VS的输入。

顶点法线比较好求,

有关顶点切线的求法,

网上给出的公式是这样:

    p1 = pos2-pos1;
    p2 = pos3-pos1;
    s1 = uv2 - uv1;
    s2 = uv3 - uv1;

    float t = 1.0f / (s1.x * s2.y - s1.y*s2.x);
   Tangent = (p1 * s2.y - p2 * s1.y) * t;
   Binormal = (p2*s1.x - p1 * s2.x) * t;

这好像是面切线的求法吧,
要得到顶点切线,是不是要和求法线一样,把每个面加起来?

不过,如果已经有了顶点法线
应该有更快的方式求切线吧?

求解法。

31

主题

257

帖子

1752

积分

金牌会员

申城谍影

Rank: 6Rank: 6

积分
1752
QQ
 楼主| 发表于 2016-5-26 13:33:06 | 显示全部楼层
这里找到了一种解法,
确实是把面切线累加,得到顶点切线。。。

不过用累加的方法,同时求法线和切线,
好像有点浪费,

如果已经求了法线,应该有更简单的方法,求切线。。。
  1. #include "Vector4D.h"


  2. struct Triangle
  3. {
  4.     unsigned short  index[3];
  5. };


  6. void CalculateTangentArray(long vertexCount, const Point3D *vertex, const Vector3D *normal,
  7.         const Point2D *texcoord, long triangleCount, const Triangle *triangle, Vector4D *tangent)
  8. {
  9.     Vector3D *tan1 = new Vector3D[vertexCount * 2];
  10.     Vector3D *tan2 = tan1 + vertexCount;
  11.     ZeroMemory(tan1, vertexCount * sizeof(Vector3D) * 2);

  12.     for (long a = 0; a < triangleCount; a++)
  13.     {
  14.         long i1 = triangle->index[0];
  15.         long i2 = triangle->index[1];
  16.         long i3 = triangle->index[2];

  17.         const Point3D& v1 = vertex[i1];
  18.         const Point3D& v2 = vertex[i2];
  19.         const Point3D& v3 = vertex[i3];

  20.         const Point2D& w1 = texcoord[i1];
  21.         const Point2D& w2 = texcoord[i2];
  22.         const Point2D& w3 = texcoord[i3];

  23.         float x1 = v2.x - v1.x;
  24.         float x2 = v3.x - v1.x;
  25.         float y1 = v2.y - v1.y;
  26.         float y2 = v3.y - v1.y;
  27.         float z1 = v2.z - v1.z;
  28.         float z2 = v3.z - v1.z;

  29.         float s1 = w2.x - w1.x;
  30.         float s2 = w3.x - w1.x;
  31.         float t1 = w2.y - w1.y;
  32.         float t2 = w3.y - w1.y;

  33.         float r = 1.0F / (s1 * t2 - s2 * t1);
  34.         Vector3D sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
  35.                 (t2 * z1 - t1 * z2) * r);
  36.         Vector3D tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
  37.                 (s1 * z2 - s2 * z1) * r);

  38.         tan1[i1] += sdir;
  39.         tan1[i2] += sdir;
  40.         tan1[i3] += sdir;

  41.         tan2[i1] += tdir;
  42.         tan2[i2] += tdir;
  43.         tan2[i3] += tdir;

  44.         triangle++;
  45.     }

  46.     for (long a = 0; a < vertexCount; a++)
  47.     {
  48.         const Vector3D& n = normal[a];
  49.         const Vector3D& t = tan1[a];

  50.         // Gram-Schmidt orthogonalize
  51.         tangent[a] = (t - n * Dot(n, t)).Normalize();

  52.         // Calculate handedness
  53.         tangent[a].w = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F;
  54.     }

  55.     delete[] tan1;
  56. }
复制代码

31

主题

257

帖子

1752

积分

金牌会员

申城谍影

Rank: 6Rank: 6

积分
1752
QQ
 楼主| 发表于 2016-5-26 14:03:52 | 显示全部楼层
哈,找到了一个用法线求切线的方法,
给大家参考吧。。。。。。。。。
  1. Vec3 tangent;

  2. Vec3 c1 = cross(normal, Vec3(0.0, 0.0, 1.0));
  3. Vec3 c2 = cross(normal, Vec3(0.0, 1.0, 0.0));

  4. if( len(c1) > len(c2) )
  5. {
  6. tangent = c1;       
  7. }
  8. else
  9. {
  10. tangent = c2;       
  11. }

  12. normalizeSelfFAST(tangent);
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-5-15 23:43

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表