法线,切线和副法线构成了所谓的切线空间(tangnet space),在Bump Mapping中,法线纹理中存储的法线值就是在切线空间内的。

从网上找了一段求切线和副法线的代码.
根据三个顶点的位置坐标和纹理坐标求面的副法线和正切

 1//let P = v1 - v0
 2D3DXVECTOR3 P = v1.pos - v0.pos;
 3//let Q = v2 - v0
 4D3DXVECTOR3 Q = v2.pos - v0.pos;
 5float s1 = v1.s - v0.s;
 6float t1 = v1.t - v0.t;
 7float s2 = v2.s - v0.s;
 8float t2 = v2.t - v0.t; 
 9
10//we need to solve the equation
11// P = s1*T + t1*B
12// Q = s2*T + t2*B
13// for T and B
14
15
16//this is a linear system with six unknowns and six equatinos, for TxTyTz BxByBz
17//[px,py,pz] = [s1,t1] * [Tx,Ty,Tz]
18// qx,qy,qz     s2,t2     Bx,By,Bz
19
20//multiplying both sides by the inverse of the s,t matrix gives
21//[Tx,Ty,Tz] = 1/(s1t2-s2t1) *  [t2,-t1] * [px,py,pz]
22// Bx,By,Bz                      -s2,s1     qx,qy,qz  
23
24//solve this for the unormalized T and B to get from tangent to object space
25
26
27float tmp = 0.0f;
28if(fabsf(s1*t2 - s2*t1) <= 0.0001f)
29{
30    tmp = 1.0f;
31}
32else
33{
34    tmp = 1.0f/(s1*t2 - s2*t1 );
35}
36
37tangent.x = (t2*P.x - t1*Q.x);
38tangent.y = (t2*P.y - t1*Q.y);
39tangent.z  = (t2*P.z - t1*Q.z);
40
41tangent = tmp * tangent;
42
43binormal.x = (s1*Q.x - s2*P.x);
44binormal.y = (s1*Q.y - s2*P.y);
45binormal.z = (s1*Q.z - s2*P.z);
46
47binormal = tmp * binormal;

根据Maya里面的资料写了一个求取tangent的函数,输入为3个顶点的位置,法线和纹理坐标,输出是切线值,副法线可以由切线和法线叉乘得到。

inline bool floatEqual(float a, float b)
{
    return abs(a-b) < 0.00001f;
}

HRESULT ComputerTangent(D3DXVECTOR3 position[3], D3DXVECTOR3 normal[3], D3DXVECTOR2 texcoord[3],D3DXVECTOR3 oTangent[3])
{
    D3DXVECTOR3 edge1;
    D3DXVECTOR3 edge2;
    D3DXVECTOR3 crossP;

     //==============================================
    // x, s, t
    // S & T vectors get used several times in this vector,
    // but are only computed once.
    //==============================================
    edge1.x = position[1].x - position[0].x;
    edge1.y = texcoord[1].x - texcoord[0].x;// s-vector - don't need to compute this multiple times
    edge1.z = texcoord[1].y - texcoord[0].y;// t-vector

    edge2.x = position[2].x - position[0].x;
    edge2.y = texcoord[2].x - texcoord[0].x;// another s-vector
    edge2.z = texcoord[2].y - texcoord[0].y;// another t-vector

    D3DXVec3Cross(&crossP,&edge1,&edge2);
    D3DXVec3Normalize(&crossP,&crossP);

    bool degnerateUVTangentPlane = floatEqual(crossP.x, 0.0f);
    if(degnerateUVTangentPlane)
        crossP.x = 1.0f;

    float tanX = -crossP.y / crossP.x;

    oTangent[0].x = tanX;
    oTangent[1].x = tanX;
    oTangent[2].x = tanX;

    //--------------------------------------------------------
    // y, s, t
    //--------------------------------------------------------
    edge1.x = position[1].y - position[0].y;

    edge2.x = position[2].y - position[0].y;
    edge2.y = texcoord[2].x - texcoord[0].x;// another s-vector
    edge2.z = texcoord[2].y - texcoord[0].y;// another t-vector

    D3DXVec3Cross(&crossP,&edge1,&edge2);
    D3DXVec3Normalize(&crossP,&crossP);

    degnerateUVTangentPlane = floatEqual(crossP.x, 0.0f);
    if(degnerateUVTangentPlane)
        crossP.x = 1.0f;

    float tanY = -crossP.y / crossP.x;

    oTangent[0].y = tanY;
    oTangent[1].y = tanY;
    oTangent[2].y = tanY;

     //------------------------------------------------------
    // z, s, t
    //------------------------------------------------------
    edge1.x = position[1].z - position[0].z;

    edge2.x = position[2].z - position[0].z;
    edge2.y = texcoord[2].x - texcoord[0].x;// another s-vector
    edge2.z = texcoord[2].y - texcoord[0].y;// another t-vector

    D3DXVec3Cross(&crossP,&edge1,&edge2);
    D3DXVec3Normalize(&crossP,&crossP);

    degnerateUVTangentPlane = floatEqual(crossP.x, 0.0f);
    if(degnerateUVTangentPlane)
        crossP.x = 1.0f;

    float tanZ = -crossP.y / crossP.x;

    oTangent[0].z = tanZ;
    oTangent[1].z = tanZ;
    oTangent[2].z = tanZ;

    //------------------------------------------------------
    for( int i = 0; i < 3; i++)
    {
        // Ortho-normalize to normal
        float dot = D3DXVec3Dot(&oTangent[i],&normal[i]);
        oTangent[i] -= normal[i] * dot;

        // Normalize tangents
        D3DXVec3Normalize(&oTangent[i],&oTangent[i]);
    }

    return S_OK;
}

副法线和正切是什么?相关推荐

  1. 神经正切核,深度学习理论研究的最新热点?

    2020-01-15 13:03:42 选自Rajat's Blog 作者:Rajat Vadiraj Dwaraknath 机器之心编译 参与:魔王 想理解神经网络的训练动态过程,不妨从「神经正切核 ...

  2. c语言函数编正切余切运算,浅谈正切函数与余切函数的应用

    九年义务教育三年制初级中学"数学"课本中,对正切函数和余切函数的定义是这样下的:在RtABC中,∠C=90°,a,b,c分别是∠A,∠B,∠C所对的边,那么tanA==或tanB= ...

  3. 图象:sine(正弦)、cosine(余弦)与Tangent(正切)

    对于小于90度的角,增加角A的度数,也会增加该角对边的长度(假设斜边的长度保持不变),因此角A的正弦值也会随着增大,同时角A的临边将变短,同样角A的余弦值也会减小. 对于大于90度的角,可以理解为将相 ...

  4. OpenJudge百炼-1183-反正切函数的应用-C语言-简单计算

    描述: 反正切函数可展开成无穷级数,有如下公式 (其中0 <= x <= 1) 公式(1) 使用反正切函数计算PI是一种常用的方法.例如,最简单的计算PI的方法: PI=4arctan(1 ...

  5. 初三数学——正弦值,余弦值和正切值

    原文出处: https://jingyan.baidu.com/article/ed2a5d1f3c9bdc09f6be17ee.html 无法区分正弦值,余弦值和正切值?现在,就有此文来给你补补课 ...

  6. 两角和与差的正弦、余弦、正切公式推导

    啥也不说,咱们先上公式: 乍一看,这啥呀这是!不过别紧张,任何公式都是可以推导的,为了方便我们先从余弦公式开始推: 两角和与差的余弦公式 推导过程: 得到这个公式: 公式助记:coco sinsin, ...

  7. 法线向量扰动、副法线

    3D数学 学习笔记(9)凹凸映射(bump mapping)和切线空间(tangent space) 凹凸映射和切线空间在图形学中也是用的较多的,下面给大家介绍下凹凸映射和切线空间,并和大家说下凹凸映 ...

  8. houdini 求出曲线的法向 切线以及副法线

    首先使用polyframe节点,Style有多种选择,Two Edges为前后两个点生成,如果设置Frist Edges,它的朝向将为朝向前一个点. 这里注释写错了,把叉乘写成了点积,大家注意一下. ...

  9. UG\NX二次开发 获取曲线上某个位置的点坐标、切线矢量、主法线矢量、副法线矢量 UF_MODL_ask_curve_props

    文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan 简介: UG\NX二次开发 获取曲线上某个位置的点坐标.切线矢量.主法线矢量.副法线矢量 U ...

最新文章

  1. android wear换表盘,Ticwear系统使用watchmaker更换表盘教程
  2. MySQL字段类型与Java数据类型的对应关系
  3. 为什么要用MyBatis-JDBC 连接数据库
  4. Sniffer Pro 教程
  5. 设计模式(5)--工厂模式
  6. 【One by One系列】IdentityServer4(三)使用用户名和密码
  7. Linux shell - 重命名文件和文件夹(mv)
  8. webrtc在远程助手应用的实践
  9. 数据结构笔记(十五)-- 数组原理
  10. 售票统计表表格模板_财务常用四大报表模板,共二十张,会计小白入职有它被高看一眼...
  11. Druid 在有赞的实践
  12. 洛谷2863 [Usaco06JAN]牛的舞会
  13. php 写入txt换行_php是如何向文件中写入换行
  14. 矢量地图自定义切片样式
  15. linux电容触摸屏驱动参数,linux 电容触摸屏驱动-1
  16. cmos与非门电路、或非门电路
  17. 其实读一读,真的安静了
  18. 科学计算机计算二进制,科学计算器如何调成二进制计算
  19. CSU 1506 酷酷的单词
  20. 在Word中为标题样式添加自动编号功能

热门文章

  1. centos7全盘备份到本地_CentOS7 系统盘迁移案例【大硬盘迁移到小硬盘,新思路】...
  2. java 观察者模式_设计模式:全面通晓23种设计模式(典藏查阅)-第三部分
  3. createprocess重启程序_win32取CreateProcess启动程序的返回值
  4. django2连接mysql_django2连接mysql
  5. 3_python基础—运算符 1
  6. printf输出字符串_c语言入门 第十二章 字符串
  7. 用硬盘安装linux物理机,老爷机安装UBUNTU的悲剧之旅(附用GRUB2硬盘安装ubuntu教程)...
  8. tomcat中间件的默认端口号_Tomcat下载安装及配置
  9. vscode css提示_lt;css-doodle/gt;让你成为CSS艺术家
  10. java 调用casperjs_Java程序去调用并执行shell脚本及问题总结(推荐)