• 飘动的风景画(NEHE经典教程MFC下的实现:LESSON11)


    不再多说,首先按《基于MFCOpenGL编程》Part 2 Setting up OpenGL on Windows中的介绍,把所有该做的东西都先做好。

    1.增加变量

    float points[45][45][3]; // The Array For The Points On The Grid Of Our "Wave"
    int wiggle_count; // Counter Used To Control How Fast Flag Waves

    GLfloat xrot;
    // X Rotation ( NEW )
    GLfloat yrot; // Y Rotation ( NEW )
    GLfloat zrot; // Z Rotation ( NEW )
    GLfloat hold; // Temporarily Holds A Floating Point Value

    GLuint texture[
    1]; // Storage For One Texture ( NEW )

     本例虽然只有一幅图片来作为纹理,但是为了让他看起来能动。不是把它整个的贴在一个矩形里面,而是放到44X44个矩阵里面,所以设置了points这个数组来存储各个顶点的x,y,z值。其它的变量就不解释了。

    2.这是用来读入BMP图像的函数,关键代码其实就auxDIBImageLoad(Filename),其它的都是用来防止出错的,程序的健壮性相当的好啊。

    AUX_RGBImageRec* CdemoView::LoadBMP(char* Filename)
    {
    FILE
    *File=NULL; // File Handle

    if (!Filename) // Make Sure A Filename Was Given
    {
    return NULL; // If Not Return NULL
    }

    File
    =fopen(Filename,"r"); // Check To See If The File Exists

    if (File) // Does The File Exist?
    {
    fclose(File);
    // Close The Handle
    return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer
    }

    return NULL; // If Load Failed Return NULL

    }

    3.载入纹理:GenT -> BindT ->TImg -> TParameter。这个过程如果熟悉的话,是个很简单的过程,主要参数的意义需要理清楚。NEHE的程序总是很完美,该释放的变量和空间绝不保留。

    int CdemoView::LoadGLTextures(void)
    {
    int Status=FALSE; // Status Indicator

    AUX_RGBImageRec
    *TextureImage[1]; // Create Storage Space For The Texture

    memset(TextureImage,
    0,sizeof(void*)*1); // Set The Pointer To NULL

    // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
    if (TextureImage[0]=LoadBMP("Data/Tim.bmp"))
    {
    Status
    =TRUE; // Set The Status To TRUE

    glGenTextures(
    1, &texture[0]); // Create The Texture

    // Typical Texture Generation Using Data From The Bitmap
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    glTexImage2D(GL_TEXTURE_2D,
    0, 3, TextureImage[0]->sizeX,
           TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    }

    if (TextureImage[0]) // If Texture Exists
    {
    if (TextureImage[0]->data) // If Texture Image Exists
    {
    free(TextureImage[
    0]->data); // Free The Texture Image Memory
    }

    free(TextureImage[
    0]); // Free The Image Structure
    }

    return Status; // Return The Status

    }

    4.InitializeOpenGL函数需要做一些改动,我把整个函数都贴上来了。主要就是加了对二维纹理映射和数组(即各个矩形顶点)的初始化。

    BOOL CdemoView::InitializeOpenGL(void)
    {
    //Get a DC for the Client Area
    m_pDC =new CClientDC(this);
    //Failure to Get DC
    if(m_pDC == NULL)
    {
    MessageBox(
    "Error Obtaining DC");
    return FALSE;
    }
    //Failure to set the pixel format
    if(!SetupPixelFormat())
    {
    return FALSE;
    }
    //Create Rendering Context
    m_hRC = ::wglCreateContext (m_pDC->GetSafeHdc ());
    //Failure to Create Rendering Context
    if(m_hRC ==0)
    {
    MessageBox(
    "Error Creating RC");
    return FALSE;
    }
    //Make the RC Current
    if(::wglMakeCurrent (m_pDC->GetSafeHdc (), m_hRC)==FALSE)
    {
    MessageBox(
    "Error making RC Current");
    return FALSE;
    }

    if (!LoadGLTextures()) // Jump To Texture Loading Routine ( NEW )
    {
    return FALSE; // If Texture Didn't Load Return FALSE
    }

    glEnable(GL_TEXTURE_2D);
    // Enable Texture Mapping ( NEW )
    glShadeModel(GL_SMOOTH); // Enable Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
    glClearDepth(1.0f); // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST); // Enables Depth Testing
    glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
    glPolygonMode( GL_BACK, GL_FILL ); // Back Face Is Solid
    glPolygonMode( GL_FRONT, GL_LINE ); // Front Face Is Made Of Lines

    for(int x=0; x<45; x++)
    {
    for(int y=0; y<45; y++)
    {
    points[x][y][
    0]=float((x/5.0f)-4.5f);
    points[x][y][
    1]=float((y/5.0f)-4.5f);
    points[x][y][
    2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));
    }
    }

    return TRUE;
    }

    5.渲染函数了,RenderScene,这个程序的精华也就在这里了。

    void CdemoView::RenderScene(void)
    {
    int x, y;
    float float_x, float_y, float_xb, float_yb;

    glClear(GL_COLOR_BUFFER_BIT
    | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
    glLoadIdentity(); // Reset The View

    glTranslatef(
    0.0f,0.0f,-12.0f);

    分别以x,y,z轴为中心就行旋转,这样图像作为一个整体会有动态的效果。

    glRotatef(xrot,1.0f,0.0f,0.0f);
    glRotatef(yrot,
    0.0f,1.0f,0.0f);
    glRotatef(zrot,
    0.0f,0.0f,1.0f);

    下面这段要仔细看看,如何把纹理贴到这个44X44的网格上面去。

    glBindTexture(GL_TEXTURE_2D, texture[0]);

    glBegin(GL_QUADS);
    for( x =0; x <44; x++ )
    {
    for( y =0; y <44; y++ )
    {
    float_x
    =float(x)/44.0f;
    float_y
    =float(y)/44.0f;
    float_xb
    =float(x+1)/44.0f;
    float_yb
    =float(y+1)/44.0f;

    glTexCoord2f( float_x, float_y);
    glVertex3f( points[x][y][
    0], points[x][y][1], points[x][y][2] );

    glTexCoord2f( float_x, float_yb );
    glVertex3f( points[x][y
    +1][0], points[x][y+1][1], points[x][y+1][2] );

    glTexCoord2f( float_xb, float_yb );
    glVertex3f( points[x
    +1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2] );

    glTexCoord2f( float_xb, float_y );
    glVertex3f( points[x
    +1][y][0], points[x+1][y][1], points[x+1][y][2] );
    }
    }
    glEnd();

    撇开图像整体沿x,y,z轴的旋转,飘动的效果是由下面的代码完成的。

    if( wiggle_count ==2 )
    {
    for( y =0; y <45; y++ )
    {
    hold
    =points[0][y][2];
    for( x =0; x <44; x++)
    {
    points[x][y][
    2] = points[x+1][y][2];
    }
    points[
    44][y][2]=hold;
    }
    wiggle_count
    =0;
    }
    }

    6.记得在ONCREATE函数下面加上SetTimer这个函数。

    void CdemoView::OnTimer(UINT_PTR nIDEvent)
    {
    // TODO: Add your message handler code here and/or call default
    wiggle_count++;

    xrot
    +=0.3f;
    yrot
    +=0.2f;
    zrot
    +=0.4f;
    InvalidateRect(NULL,FALSE);
    CView::OnTimer(nIDEvent);
    }

    7.好了,运行程序。效果如下:

     纹理贴在正面,背面是由线组成的,所以能看到正面的内容。
     
  • 相关阅读:
    nodejs内存控制
    nodejs的Buffer解析
    基于Yeoman实现自定义脚手架
    基于node实现一个简单的脚手架工具(node控制台交互项目)
    nodeJs入门的第一节课
    手动封装一个node命令集工具
    [转载] 如何掌握所有的程序语言 —— 王垠
    Kubernetes:服务与负载均衡
    Zabbix 6.0:原生高可用(HA)方案部署
    Kubernetes:健康检查
  • 原文地址:https://www.cnblogs.com/unsigned/p/1703402.html
Copyright © 2020-2023  润新知