MFC环境下实现旋转星空效果,以及在这之中遇到的一些问题。(COPY NEHELESSON9)...

NEHE,估计知道OpenGL的人应该都会了解那么一些的。虽然导师让我们从OpenGL转向用VTK实现三维显示,不过这两个的原理其实差不多,因为都是基于计算机图形学的嘛。

Moving Bitmaps In 3D Space,其实实现这个“旋转星空”的效果(这个是我自己命名的,哈哈)主要就是以下步骤:

1.读入BMP图像,这里就是一个星星的图像;

2.将其变为二维纹理;

3.设置混合模式,因为BMP图像是四四方方的,要想弄出个星星的效果,必须让一部分变得透明;

4.0K,接下来就是在虚拟的三维空间里,在虚拟的矩形上贴这个星星生成的二维纹理了。

 

下面是详细的步骤说明,一起说说NEHE所使用的“算法”(姑且用算法吧,其实也够不上,因为星星移动其实不复杂的):

在实现以下4步之前,还是像往常一样啦,去洞庭散人的博客里,按照《基于MFC的OpenGL编程》Part 2 Setting up OpenGL on Windows把基本的东西先弄弄好。

1.好了,可以读BMP了,这是NEHE写的,感觉很严谨,或者说程序的健壮性比较好吧。

AUX_RGBImageRec * COpenglDemoView::LoadBMP( char * Filename)
{
FILE
* File = NULL;
if ( ! Filename)
{
return NULL;
}

File
= fopen(Filename, " r " );
if (File)
{
fclose(File);
return auxDIBImageLoad(Filename);
}
return NULL;
}

 

2.可以开始生成纹理的工作了,这个其实也没什么可说的,除了本人菜鸟,刚开始不知道怎么把CString转化为char*,呵呵,后来百度了下,用了其中最简单的一个方法,const char* ch = (LPCTSTR)Picname

BOOL COpenglDemoView::LoadGLTextures(CString Picname)
{
bool Status = FALSE;
AUX_RGBImageRec
* TextureImage[ 1 ];
memset(TextureImage,
0 , sizeof ( void * ) * 1 );
const char * ch = (LPCTSTR)Picname;
if (TextureImage[ 0 ] = LoadBMP(( char * )ch))
{
Status
= TRUE;
glGenTextures(
1 ,texture);
glBindTexture(GL_TEXTURE_2D,texture[
0 ]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
0 , 3 ,TextureImage[ 0 ] -> sizeX,
TextureImage[
0 ] -> sizeY, 0 ,GL_RGB,GL_UNSIGNED_BYTE,
TextureImage[
0 ] -> data);
}
if (TextureImage[ 0 ])
{
if (TextureImage[ 0 ] -> data)
{
free(TextureImage[
0 ] -> data);
}
free(TextureImage[
0 ]);
}
return Status;
}

 

3.\(^o^)/,设置混合模式啦,搞出个透明的效果的代码就在这里啦。貌似在NEHE的教程中没有glDepthMask(GL_FALSE)这一句,结果就不透明了,呵呵,但是它的程序直接拷贝到一个win32 console application里编译运行的时候又是一切OK的,不过这个没什么关系,参考了下红宝书,找出上面这句话添上,就没问题了。

BOOL COpenglDemoView::InitTex( void )
{
if ( ! LoadGLTextures( " Star.bmp " )) // Jump To Texture Loading Routine
{
return FALSE; // If Texture Didn't Load Return FALSE
}

glEnable(GL_TEXTURE_2D);
// Enable Texture Mapping
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set The Blending Function For Translucency
glEnable(GL_BLEND);
glDepthMask (GL_FALSE);

for ( int loop = 0 ; loop < num; loop ++ )
{
star[loop].angle
= 0.0f ;
star[loop].dist
= ( float (loop) / num) * 5.0f ;
star[loop].r
= rand() % 256 ;
star[loop].g
= rand() % 256 ;
star[loop].b
= rand() % 256 ;
}
return TRUE; // Initialization Went OK
}

4.在做显示在前嘛,先看看其中使用的数据结构吧。旁边的注释说得很清楚了。

typedef struct // Create A Structure For Star
{
int r, g, b; // Stars Color
GLfloat dist, // Stars Distance From Center
angle; // Stars Current Angle
}
stars;

进入正题吧,显示之。我觉得他用的显示过程还是应该说一下的。首先,glLoadIdentity(),这个函数,我以前都是不注意的,虽然很多地方都出现过,都没有去查,这个函数其实相当于初始化,将表示坐标的那个Matrix变成对角线为1,其余为0的4X4矩阵;然后转到屏幕后深度15的地方;接着绕X轴旋转tilt = 90°,绕Y轴旋转,这个角度,是各个STAR随机生成的。角度转好了之后再移动,距离dist也因星星而异,因为图片是片面的所以角度需要转回去。dist是从5.0递减到0,然后再重复。为了显示旋转的效果,坐标又绕Z轴旋转spin度,这个参数的设置时让所有的星星都旋转起来,即星星旋转的角速度。然后画星星。这部分的代码的功能,就是让星星从距离(0,0,-15)为5的地方向(0,0,-15)移动。在这个代码后面贴上运动控制和随机数生成的代码吧。

代码
glBindTexture(GL_TEXTURE_2D, texture[ 0 ]); // Select Our Texture

for ( int loop = 0 ; loop < num; loop ++ ) // Loop Through All The Stars
{
glLoadIdentity();
// Reset The View Before We Draw Each Star
glTranslatef( 0.0f , 0.0f , - 15.0f ); // Zoom Into The Screen (Using The Value In 'zoom')
glRotatef(tilt, 1.0f , 0.0f , 0.0f ); // Tilt The View (Using The Value In 'tilt')
glRotatef(star[loop].angle, 0.0f , 1.0f , 0.0f ); // Rotate To The Current Stars Angle
glTranslatef(star[loop].dist, 0.0f , 0.0f ); // Move Forward On The X Plane
glRotatef( - star[loop].angle, 0.0f , 1.0f , 0.0f ); // Cancel The Current Stars Angle
glRotatef( - tilt, 1.0f , 0.0f , 0.0f ); // Cancel The Screen Tilt


glRotatef(spin,
0.0f , 0.0f , 1.0f );
glColor4ub(star[loop].r,star[loop].g,star[loop].b,
255 );
glBegin(GL_QUADS);
glTexCoord2f(
0.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , 0.0f );
glTexCoord2f(
1.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , 0.0f );
glTexCoord2f(
1.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , 0.0f );
glTexCoord2f(
0.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , 0.0f );
glEnd();
}

NEHE所写的程序并不是基于MFC的,我在这里把变量的变化放在OnTimer里面,这样的话程序可以正常运行。如果照搬NEHE,写在上面的代码后面,图像是动不了的。

 

void COpenglDemoView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
for ( int loop = 0 ; loop < num; loop ++ )
{
spin
+= 0.01f ;
star[loop].angle
+= float (loop) / num;
star[loop].dist
-= 0.01f ;
if (star[loop].dist < 0.0f )
{
star[loop].dist
+= 5.0f ;
star[loop].r
= rand() % 256 ;
star[loop].g
= rand() % 256 ;
star[loop].b
= rand() % 256 ;
}
}
InvalidateRect(NULL,FALSE);
CView::OnTimer(nIDEvent);
}

 

效果图也贴上吧,和NEHE的其实一样。

 

转载于:https://www.cnblogs.com/unsigned/archive/2010/03/27/1698520.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值