猿问

计算三角形网格中的法线

我绘制了一个具有10000个顶点(100x100)的三角形网格,它将成为草地。我使用了gldrawelements()。我整天看了看,仍然不明白该如何计算法线。每个顶点都有自己的法线还是每个三角形都有自己的法线?有人可以为我指出如何编辑代码以合并法线的正确方向吗?


struct vertices {

    GLfloat x;

    GLfloat y;

    GLfloat z;

}vertices[10000];


GLuint indices[60000];


/*

99..9999

98..9998

........

01..9901

00..9900

*/


void CreateEnvironment() {

    int count=0;

    for (float x=0;x<10.0;x+=.1) {

        for (float z=0;z<10.0;z+=.1) {

            vertices[count].x=x;

            vertices[count].y=0;

            vertices[count].z=z;

            count++;

        }

    }

    count=0;

    for (GLuint a=0;a<99;a++){

        for (GLuint b=0;b<99;b++){

            GLuint v1=(a*100)+b;indices[count]=v1;count++;

            GLuint v2=(a*100)+b+1;indices[count]=v2;count++;

            GLuint v3=(a*100)+b+100;indices[count]=v3;count++;

        }

    }

    count=30000;

    for (GLuint a=0;a<99;a++){

        for (GLuint b=0;b<99;b++){

            indices[count]=(a*100)+b+100;count++;//9998

            indices[count]=(a*100)+b+1;count++;//9899

            indices[count]=(a*100)+b+101;count++;//9999

        }

    }

}


void ShowEnvironment(){

    //ground

    glPushMatrix();

    GLfloat GroundAmbient[]={0.0,0.5,0.0,1.0};

    glMaterialfv(GL_FRONT,GL_AMBIENT,GroundAmbient);

    glEnableClientState(GL_VERTEX_ARRAY);

    glIndexPointer( GL_UNSIGNED_BYTE, 0, indices );

    glVertexPointer(3,GL_FLOAT,0,vertices);

    glDrawElements(GL_TRIANGLES,60000,GL_UNSIGNED_INT,indices);

    glDisableClientState(GL_VERTEX_ARRAY);

    glPopMatrix();

}


温温酱
浏览 1196回答 3
3回答

宝慕林4294392

竖起大拇指给datenwolf!我完全同意他的方法。要为每个顶点添加相邻三角形的法线向量,然后进行归一化。我只想稍微介绍一下答案,并仔细研究具有x / y步长不变的矩形,平滑网格的特殊但很常见的情况。换句话说,每个点的高度都可变的矩形x / y网格。这种网格是通过在x和y上循环并为z设置一个值来创建的,并且可以表示类似山丘的表面。因此,网格的每个点都由一个向量表示P = (x, y, f(x,y))&nbsp;其中f(x,y)是给出网格上每个点的z的函数。通常要绘制这样的网格,我们使用TriangleStrip或TriangleFan,但是任何技术都应为生成的三角形提供相似的形貌。&nbsp; &nbsp; &nbsp;|/&nbsp; &nbsp;|/&nbsp; &nbsp;|/&nbsp; &nbsp;|/...--+----U----UR---+--...&nbsp; &nbsp; /|&nbsp; &nbsp;/| 2 /|&nbsp; &nbsp;/|&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Y&nbsp; &nbsp;/ |&nbsp; / |&nbsp; / |&nbsp; / |&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;^&nbsp; &nbsp; &nbsp;| /&nbsp; | /&nbsp; | /&nbsp; | /&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;|/ 1 |/ 3 |/&nbsp; &nbsp;|/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |...--L----P----R----+--...&nbsp; &nbsp; &nbsp; +-----> X&nbsp; &nbsp; /| 6 /| 4 /|&nbsp; &nbsp;/|&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;/ |&nbsp; / |&nbsp; / |&nbsp; / |&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;| /5 | /&nbsp; | /&nbsp; | /&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;|/&nbsp; &nbsp;|/&nbsp; &nbsp;|/&nbsp; &nbsp;|/...--DL---D----+----+--...&nbsp; &nbsp; /|&nbsp; &nbsp;/|&nbsp; &nbsp;/|&nbsp; &nbsp;/|对于atriangleStrip,每个顶点P =(x0,y0,z0)具有6个相邻顶点,表示为up&nbsp; &nbsp; &nbsp; &nbsp;= (x0&nbsp; &nbsp; &nbsp;, y0 + ay, Zup)upright&nbsp; = (x0 + ax, y0 + ay, Zupright)&nbsp;right&nbsp; &nbsp; = (x0 + ax, y0&nbsp; &nbsp; &nbsp;, Zright)&nbsp;down&nbsp; &nbsp; &nbsp;= (x0&nbsp; &nbsp; &nbsp;, y0 - ay, Zdown)downleft = (x0 - ax, y0 - ay, Zdownleft)&nbsp;left&nbsp; &nbsp; &nbsp;= (x0 - ax, y0&nbsp; &nbsp; &nbsp;, Zleft)其中ax / ay分别是x / y轴上的恒定网格步长。在正方形网格上,ax = ay。ax = width / (nColumns - 1)ay = height / (nRows - 1)因此,每个顶点都有6个相邻的三角形,每个三角形都有自己的法向矢量(表示为N1至N6)。可以使用定义三角形边的两个向量的叉积来计算这些值,并小心执行叉积的顺序。如果法向矢量指向您的Z方向:N1 = up x left =&nbsp; &nbsp;= (Yup*Zleft - Yleft*Zup, Xleft*Zup - Xup*ZLeft, Xleft*Yup - Yleft*Xup)&nbsp;&nbsp; &nbsp;=( (y0 + ay)*Zleft - y0*Zup,&nbsp;&nbsp; &nbsp; &nbsp; (x0 - ax)*Zup&nbsp; &nbsp;- x0*Zleft,&nbsp;&nbsp; &nbsp; &nbsp; x0*y0 - (y0 + ay)*(x0 - ax) )&nbsp;N2 = upright&nbsp; x upN3 = right&nbsp; &nbsp; x uprightN4 = down&nbsp; &nbsp; &nbsp;x rightN5 = downleft x downN6 = left&nbsp; &nbsp; &nbsp;x downleft每个点P的最终法向矢量为N1至N6之和。我们求和后归一化。创建循环,计算每个法线向量的值,将它们相加然后进行归一化非常容易。但是,正如Shickadance先生所指出的那样,这可能会花费相当长的时间,尤其是对于大型网格物体和/或在嵌入式设备上。如果我们仔细观察并手动执行计算,我们将发现大多数项相互抵消,从而为我们得出的向量N提供了非常优雅且易于计算的最终解决方案。避免计算N1到N6的坐标,从而对每个点进行6个叉积和6个加法运算,从而加快了计算速度。代数帮助我们直接跳到解决方案,使用更少的内存和更少的CPU时间。我将不显示计算的详细信息,因为它很长但是很简单,并且会跳到网格上任何点的法线向量的最终表达式。为了清楚起见,仅分解了N1,其他向量看起来相似。求和后,我们得到尚未归一化的N:N = N1 + N2 + ... + N6&nbsp; = .... (long but easy algebra) ...&nbsp; = ( (2*(Zleft - Zright) - Zupright + Zdownleft + Zup - Zdown) / ax,&nbsp; &nbsp; &nbsp; (2*(Zdown - Zup)&nbsp; &nbsp; + Zupright + Zdownleft - Zup - Zleft) / ay,&nbsp; &nbsp; &nbsp; &nbsp;6 )你去!只要标准化此向量,就可以知道网格上任何点的法线向量,只要您知道其周围点的Z值以及网格的水平/垂直步长即可。请注意,这是周围三角形法线向量的加权平均值。权重是三角形的面积,并且已经包含在叉积中。您甚至可以只考虑四个周围点(上,下,左和右)的Z值来进一步简化它。在这种情况下,您会得到:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; &nbsp;\|/&nbsp; &nbsp;|N = N1 + N2 + N3 + N4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ..--+----U----+--..&nbsp; = ( (Zleft - Zright) / ax,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; &nbsp;/|\&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp; (Zdown -&nbsp; Zup&nbsp; ) / ay,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; / | \&nbsp; |&nbsp; &nbsp; &nbsp; &nbsp;2 )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\ | / 1|2 \ | /&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \|/&nbsp; &nbsp;|&nbsp; &nbsp;\|/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;..--L----P----R--...&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /|\&nbsp; &nbsp;|&nbsp; &nbsp;/|\&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/ | \ 4|3 / | \&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; \ | /&nbsp; |&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; &nbsp;\|/&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;..--+----D----+--..&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; &nbsp;/|\&nbsp; &nbsp;|这更加优雅,计算速度更快。希望这可以使一些网格更快。干杯
随时随地看视频慕课网APP
我要回答