平面法向量的计算

2020-04-17  本文已影响0人  tp夕阳武士

重点:计算法线向量是使用光照的必要步骤

图1-1.png
1.什么叫做法向量?

法向量与几何学中的法线有点类似;
如上图1-1,我们已知三个顶点:
A:(0.0,0.0,0.0)
B:(0.0,1.0,0.0)
C:(0.0,0.0,1.0)
那么平面ABC的发线是垂直于这个面的;

我们又知道两个向量是可以确定一个面的;
那么向量Vab 与向量Vac 的法向量 normal1 也是同事垂直于这两个向量的;

2.法线数据是如何与顶点数据匹配的?
typedef struct {
    GLKVector3  position; //顶点向量
    GLKVector3  normal;   //法线向量
    GLKVector2  texture;  //纹理坐标
}
SceneVertex;

从上面这个数据结构的定义我们可以了解到,法线量与顶点数据是一一对应的;

3.GLKit提供的计算方法:
//已知两个点,求两点组成的向量;
GLKVector3 v = GLKVector3Subtract(GLKVector3 point1, GLKVector3 point2);

// 已知两个向量 Vab ,Vca, 求着两个向量的法向量
GLKVector3 normal = GLKVector3Normalize(GLKVector3CrossProduct(Vab, Vac));

//根据这个方法,我们可以求图1-1中的normal1
GLKVector3 normal = GLKVector3Normalize(GLKVector3CrossProduct(Vab, Vca));

//normal1的最终结果应该是等于{0.0,1.0,0.0}

//因为三角形的三个顶点都是属于一个平面的,所以它三个顶点对应的法向量都是相等的
//再结合上文中的内容2:法线数据是如何与顶点数据匹配的
//我们就可以直接把求得的normal配置给三角形的每一个顶点就可以了.
代码测试结果.png
4.自定义方法修改三角形顶点数据的法向量数据
//顶点数据结构
typedef struct {
    GLKVector3  position; //顶点向量
    GLKVector3  normal;   //法线向量
    GLKVector2  texture;  //纹理坐标
}
SceneVertex;

//三角形数据结构
typedef struct {
    SceneVertex vertices[3];
}
SceneTriangle;

//NUM_FACES 表示有多少个三角形 是一个常量 根据实际开发情况设定.
//录入一个正方形,就有两个三角形,那么NUM_FACES = 2;
//在传参数的时候,这个数不用管,因为传入的是数据的地址;
void SceneTrianglesUpdateFaceNormals(SceneTriangle someTriangles[NUM_FACES])
{
    int I;
    
    for (i=0; i<NUM_FACES; I++)
    {
        //计算平面法向量
        GLKVector3 faceNormal = SceneTriangleFaceNormal(someTriangles[I]);
        
        //更新每个点的平面法向量
        someTriangles[i].vertices[0].normal = faceNormal;
        someTriangles[i].vertices[1].normal = faceNormal;
        someTriangles[i].vertices[2].normal = faceNormal;
    }
}

GLKVector3 SceneTriangleFaceNormal(const SceneTriangle triangle)
{
    //vectorA =  v1 - v0
    GLKVector3 vectorA = GLKVector3Subtract(triangle.vertices[1].position,
                                            triangle.vertices[0].position);
    //vectorB =  v2 - v0
    GLKVector3 vectorB = GLKVector3Subtract(triangle.vertices[2].position,
                                            triangle.vertices[0].position);
    
    GLKVector3 normal = GLKVector3Normalize(GLKVector3CrossProduct(vectorA, vectorB));
    
    //通过 向量A和向量B的叉积求出平面法向量,单元化后返回
//    return SceneVector3UnitNormal(vectorA,vectorB);
    return normal;
}
上一篇 下一篇

猜你喜欢

热点阅读