| 
				 摘  要:本文作者利用OpenGL的图形功能和VC++的编程功能,通过“贴图法”较好地实现了树木的三维可视化建模,运用此法实现树木建模要比直接创建三维的物体要快得多,在视觉上亦可取得较好的效果。 
关键词:OpenGL,建模,VC++,三维可视化 
  
一、引言 
景观可视化建模是当前3DGIS、虚拟现实等领域研究的热点之一,其核心技术是计算机图形学。树木无疑是自然场景的重要构成因素,树木种类繁多,形态各异,复杂的结构使其无论在造型、存储还是在绘制上都存在相当的困难。 
OpenGL作为一种三维工具软件包,在交互式三维图形建模能力和编程方面有无可比拟的优越性。OpenGL灵活方便地实现了二维和三维的高级图形技术,在性能上表现得异常优越。它具有建模、变换、光线处理、色彩处理、动画以及更先进的能力,如纹理映射、物体运动模糊效果、雾化效果等。OpenGL为实现逼真的三维绘制效果,建立交互的三维场景提供了优秀的软件工具。 
在计算机中,图形纹理映射技术是计算机图形学中用于构建真实图形环境的最常用的方法,它把一个地物的影像映射在表达地物的几何模型表面,从而构成直观形象的图形对象。曾经有学者通过使用单张经过处理的真实树木的照片,经过映射到一个多边形上,在具体应用中,根据视点的变化,对该多边形进行绕某一轴线转动,来进行树木的三维建模,但是这样会增加应用系统环境图像生成的工作量,影响显示效果。也曾有学者使用基于表面剖分的空间数据模型构建实体型的树木模型(如图1所示)。 
 
图1 基于表面剖分数据模型构造的树木模型 
本文作者从视觉的角度来考虑,利用两个垂直交叉的多边形来代替以上视点计算,一方面在视觉上起弥补了单张固定照片的缺陷,同时又降低了因图像转动而需要的计算量。下面具体讲述一下树木建模实验。 
二、树木建模实验 
2.1获取树木的真实图像 
对要建模的树种,我们首先拍摄一张真实的树木的照片,假如用数码相机的话,就可以直接将采集的图像转入到计算机中进行处理,对于用光学照相机拍摄的照片,可通过扫描获取数字图像。处理主要的工作是,对图像进行旋转使树木的树干尽量呈垂直方向,另外就是用图像处理软件,如Photoshop,将图像周围的颜色进行处理,使树木周围的颜色变成单一的颜色如纯黑色或纯白色。 
2.2纹理实时处理 
把第一步获取的真实图像载入应用程序,装载的时候先将图像的三色(RGB)扩展成四色(RGBA),当判断遇到背景色时,分配其alpha值为完全透明,来创建非矩形光栅图像效果,此处理步骤由函数LoadTextureImage()来完成。 
void CRenderView::LoadTextureImage(CString strFilepath) 
{ 
AUX_RGBImageRec *image; 
    unsigned char *myimage; 
    GLint m_TreeTexwidth=256,m_TreeTexheight=256; 
    image=auxDIBImageLoad(strFilepath);  
//strFilePath为纹理图像文件所在路径 
    if(image){ 
        m_TreeTexwidth=image->sizeX; 
        m_TreeTexheight=image->sizeY; 
    } 
    myimage=(unsigned char *)malloc(m_TreeTexwidth*m_TreeTexheight*3); 
    glPixelStorei(GL_UNPACK_ALIGNMENT,1); 
    gluScaleImage(GL_RGB,image->sizeX,image->sizeY,GL_UNSIGNED_BYTE, 
                image->data,m_TreeTexwidth,m_TreeTexheight,GL_UNSIGNED_BYTE,myimage); 
    unsigned char *rgba=(unsigned char  
*)malloc(m_TreeTexwidth*m_TreeTexheight*4); 
    unsigned char *rgbaptr,*ptr; 
    int i; 
        for (i = m_TreeTexwidth * m_TreeTexheight, 
       rgbaptr = rgba, ptr = myimage; 
            i > 0; 
         i --, rgbaptr += 4, ptr += 3) 
{ 
        rgbaptr[0] = ptr[0]; 
        rgbaptr[1] = ptr[1]; 
            rgbaptr[2] = ptr[2]; 
        if((rgbaptr[0]==255&&rgbaptr[1]==255&&rgbaptr[2]==255)|| 
            (rgbaptr[0]==0&&rgbaptr[1]==0&&rgbaptr[2]==0)) 
            rgbaptr[3] = 0; 
        else 
            rgbaptr[3] = 255; 
    } 
    glTexImage2D(GL_TEXTURE_2D, 0, 4, m_TreeTexwidth, m_TreeTexheight, 0, GL_RGBA,  
                 GL_UNSIGNED_BYTE, rgba); 
} 
2.3 纹理贴图的实现 
    假如知道每株树的坐标位置(m_fCenter[3])、树高(m_fTreeHeight)、冠幅(m_fTreeWidth),并设原型木的树高和冠幅分别为平均树高和平均冠幅,则可根据这些数据在相应位置建立两个大小相同的交叉多边行,一般来说,是选择最简单的空间四边形来进行建模。 
在建立交叉多边形时,将第二步处理的纹理映射到多边形中。这种方法有时叫做“贴图法”,同时利用OpenGL融合函数设置适当的融合参数,并启用融合。纹理贴图通过函数DrawTree()来实现。 
void CRenderView::DrawTree() 
{ 
    glEnable(GL_BLEND); 
    glEnable(GL_TEXTURE_2D); 
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); 
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); 
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); 
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 
    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); 
    // 
    glPushMatrix(); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    //XOY 
    glBegin(GL_POLYGON); 
    glTexCoord2f(1.0f,0.0f); 
    glVertex3f(m_fCenter[0]+m_fTreeWidth/2,m_fCenter[1],m_fCenter[2]); 
    glTexCoord2f(0.0f,0.0f); 
    glVertex3f(m_fCenter[0]-m_fTreeWidth/2,m_fCenter[1],m_fCenter[2]); 
    glTexCoord2f(0.0f,1.0f); 
    glVertex3f(m_fCenter[0]-m_fTreeWidth/2,m_fCenter[1],m_fCenter[2]+m_fTreeHeight); 
    glTexCoord2f(1.0f,1.0f); 
    glVertex3f(m_fCenter[0]+m_fTreeWidth/2,m_fCenter[1],m_fCenter[2]+m_fTreeHeight); 
    glEnd(); 
    //YOZ 
    glBegin(GL_POLYGON); 
    glTexCoord2f(0.0f,1.0f); 
    glVertex3f(m_fCenter[0],m_fCenter[1]+m_fTreeWidth/2,m_fCenter[2]+m_fTreeHeight); 
    glTexCoord2f(1.0f,1.0f); 
    glVertex3f(m_fCenter[0],m_fCenter[1]-m_fTreeWidth/2,m_fCenter[2]+m_fTreeHeight); 
    glTexCoord2f(1.0f,0.0f); 
    glVertex3f(m_fCenter[0],m_fCenter[1]-m_fTreeWidth/2,m_fCenter[2]); 
    glTexCoord2f(0.0f,0.0f); 
    glVertex3f(m_fCenter[0],m_fCenter[1]+m_fTreeWidth/2,m_fCenter[2]); 
    glEnd(); 
    glPopMatrix(); 
    // 
    glDisable(GL_TEXTURE_2D); 
    glDisable(GL_BLEND); 
} 
这样便可以形成非常逼真的树木景观,从不同的角度观察均可获得树木的较为完整的图像(如图2所示),它比直接创建三维的物体要快捷得多;但是,可能由于默认的多边形光照效果不能和环境的光照协调,需要进行进一步的设置。 
 
图2 贴图法构建的树木 
  
2.4设置光照效果 
经过上面三步我们可以把三维植物的模型建立起来,但是为了和外界的环境光照等条件进行融合,必须对第三步生成的多边形表面光照效果进行设置,使生成的三维树木的显示效果更加逼真。 
三、结束语 
本文作者通过简单的建模,利用“贴图法”构建了具有真实感的树木。本文构建的树木虽然在视觉上能达到一定的三维效果,在游戏、虚拟现实等领域也能满足一定的应用要求,但是本文构建的树木并非真正意义上的三维树木,要构建真三维树木,还有待人们在对景观数据模型的研究较富成果的基础上再去讨论。 
参考文献 
1. Richard S.Wright,Jr. Michael Sweet. OpenGL超级宝典.北京:人民邮电出版社,2001.6. 
2. 向南平、江资斌等. VC++6.0中利用OpenGL实现3DS模型的交互控制.北京:电脑编程技巧与维护,2003年第3期. 
3. 孙敏. 三维城市模型的数据建模研究.中南大学博士学位论文,2000,4. 
  			
				 |