unsigned

以后要是一事无成,还娶了个很龊的老婆,这些年的书都白读了啊!

导航

飘动的风景画(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.好了,运行程序。效果如下:

 纹理贴在正面,背面是由线组成的,所以能看到正面的内容。
 

posted on 2010-04-02 20:35  unsigned  阅读(672)  评论(0编辑  收藏  举报