【问题标题】:Normals for height map data高度图数据的法线
【发布时间】:2012-12-15 04:59:47
【问题描述】:

我想找到高度图数据的法线。我在我的代码中使用 gl_triangles 作为索引。我如何找到这个的法线?

【问题讨论】:

    标签: opengl normals


    【解决方案1】:

    给定一个三角形(vert1, vert2, vert3),它的法线是((vert2 - vert1).cross(vert3 - vert1)).normalize()

    对于平滑的逐顶点法线:对于每个顶点,将顶点所属的每个三角形的面法线相加,然后对总和进行归一化。

    编辑:示例:

    #include <GL/glut.h>
    #include <vector>
    #include <cmath>
    #include <Eigen/Core>
    #include <Eigen/Geometry>
    
    using namespace std;
    using namespace Eigen;
    
    typedef Matrix< Vector3f, Dynamic, Dynamic > VecMat;
    
    // given a matrix of heights returns a matrix of vertices
    VecMat GetVerts( const MatrixXf& hm )
    {
        VecMat verts( hm.rows(), hm.cols() );
        for( int col = 0; col < hm.cols(); ++col )
            for( int row = 0; row < hm.rows(); ++row )
                verts( row, col ) = Vector3f( col, row, hm( row, col ) );
        return verts;
    }
    
    VecMat GetNormals( const VecMat& hm )
    {
        VecMat normals( hm );
        for( int col = 0; col < hm.cols(); ++col )
            for( int row = 0; row < hm.rows(); ++row )
            {
                Vector3f sum( Vector3f::Zero() );
                const Vector3f& cur = hm( row, col );
                if( row+1 < hm.rows() && col+1 < hm.cols() )
                    sum += ( hm( row+0, col+1 ) - cur ).cross( hm( row+1, col+0 ) - cur ).normalized();
                if( row+1 < hm.rows() && col > 0 )
                    sum += ( hm( row+1, col+0 ) - cur ).cross( hm( row+0, col-1 ) - cur ).normalized();
                if( row > 0 && col > 0 )
                    sum += ( hm( row+0, col-1 ) - cur ).cross( hm( row-1, col+0 ) - cur ).normalized();
                if( row > 0 && col+1 < hm.cols() )
                    sum += ( hm( row-1, col+0 ) - cur ).cross( hm( row+0, col+1 ) - cur ).normalized();
                normals( row, col ) = sum.normalized();
            }
        return normals;
    }
    
    // returns an index array for a GL_TRIANGLES heightmap
    vector< unsigned int > GetIndices( int rows, int cols )
    {
        vector< unsigned int > indices;
        for( int col = 1; col < cols; ++col )
            for( int row = 1; row < rows; ++row )
            {
                // Eigen default storage order is column-major
                // lower triangle
                indices.push_back( (col-1) * rows + (row-1) );
                indices.push_back( (col-0) * rows + (row-1) );
                indices.push_back( (col-1) * rows + (row-0) );
                // upper triangle
                indices.push_back( (col-1) * rows + (row-0) );
                indices.push_back( (col-0) * rows + (row-1) );
                indices.push_back( (col-0) * rows + (row-0) );
            }
        return indices;
    }
    
    VecMat heightmap;
    VecMat normals;
    vector< unsigned int > indices;
    void init()
    {
        // wavy heightmap
        MatrixXf hm( 64, 64 );
        for( int col = 1; col < hm.cols(); ++col )
            for( int row = 1; row < hm.rows(); ++row )
            {
                float x = ( col - ( hm.cols() / 2.0f ) ) / 2.0f;
                float y = ( row - ( hm.rows() / 2.0f ) ) / 2.0f;
                hm( row, col ) = cos( sqrt( x * x + y * y ) );
            }
    
        heightmap = GetVerts( hm );
        heightmap.array() -= Vector3f( hm.cols() / 2.0f, hm.rows() / 2.0f, 0 );
        for( int col = 0; col < hm.cols(); ++col )
            for( int row = 0; row < hm.rows(); ++row )
                heightmap( row, col ).array() *= Vector3f( 1 / 4.0f, 1 / 4.0f, 1.0f ).array();
    
        normals = GetNormals( heightmap );
        indices = GetIndices( heightmap.rows(), heightmap.cols() );
    }
    
    void display()
    {
        glEnable( GL_DEPTH_TEST );
        glEnable( GL_CULL_FACE );
        glShadeModel( GL_SMOOTH );
    
        glEnable( GL_LIGHTING );
        GLfloat global_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
        glLightModelfv( GL_LIGHT_MODEL_AMBIENT, global_ambient );
        glEnable( GL_COLOR_MATERIAL );
        glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
    
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
        double w = glutGet( GLUT_WINDOW_WIDTH );
        double h = glutGet( GLUT_WINDOW_HEIGHT );
        gluPerspective( 60, w / h, 1, 100 );
    
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();
        gluLookAt( 8, 8, 8, 0, 0, 0, 0, 0, 1 );
    
        // spinning light
        glEnable( GL_LIGHT0 );
        float angle = 20 * ( glutGet( GLUT_ELAPSED_TIME ) / 1000.0f ) * (3.14159f / 180.0f);
        float x = cos( -angle ) * 6;
        float y = sin( -angle ) * 6;
        GLfloat light_position[] = { x, y, 2, 1.0 };
        glLightfv( GL_LIGHT0, GL_POSITION, light_position );    
        glDisable( GL_LIGHTING );
        glPointSize( 5 );
        glBegin(GL_POINTS);
        glColor3ub( 255, 255, 255 );
        glVertex3fv( light_position );
        glEnd();
        glEnable( GL_LIGHTING );
    
        glColor3ub(255,0,0);
        glEnableClientState( GL_VERTEX_ARRAY );
        glEnableClientState( GL_NORMAL_ARRAY );
        glVertexPointer( 3, GL_FLOAT, sizeof( Vector3f ), heightmap(0,0).data() );
        glNormalPointer( GL_FLOAT, sizeof( Vector3f ), normals(0,0).data() );
        glDrawElements( GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, &indices[0] );
        glDisableClientState( GL_VERTEX_ARRAY );
        glDisableClientState( GL_NORMAL_ARRAY );
    
        glutSwapBuffers();
    }
    
    void timer( int extra )
    {
        glutPostRedisplay();
        glutTimerFunc( 16, timer, 0 );
    }
    
    int main( int argc, char **argv )
    {
        glutInit( &argc, argv );
        glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
        glutInitWindowSize( 640, 480 );
        glutCreateWindow( "Heightmap" );
        init();
        glutDisplayFunc( display );
        glutTimerFunc( 0, timer, 0 );
        glutMainLoop();
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-02-17
      • 1970-01-01
      • 1970-01-01
      • 2012-05-12
      • 1970-01-01
      • 2013-02-17
      • 2017-11-18
      • 2013-12-18
      • 1970-01-01
      相关资源
      最近更新 更多