2006年8月28日

简单的三维树生成及渲染


这个暑假写的学的东西,最近整理起来,刚刚学OpenGL,很多方面做得都不好。
压缩包里有介绍
DEMO下载
源文件下载

pre: 先反省一下,以前写的确实过于简略,代码又没有设么注释。感谢EmilMatthew的话,让更多人受益 源代码正在改写,以前变量命名很随意,反正很不清晰,更提不上elegant了。另一方面也在进行优化
核心算法描述:(实际上并不算是什么算法) 树主要分两部分:树枝和树干。树干使用二次曲面圆柱(gluCylinder,注意这个圆柱是可以上下半径不等的)近似,树叶就贴一片纹理。 树的绘制是递归进行的,也就是说:在一段树桩上接上三段树枝所形成的东西仍然叫做树(DEMO里每一段树枝上都有三段小树枝 ,递归的深度是四,可以自己调整)。用代码来写的话:


void DrawTree(int depth)
{
DrawStem(); //绘制树桩
if (2 < m_ndepthtop ="=">

//未绘制到顶层的话继续递归绘制
MoveToStemTop(); //移动到树桩顶部(注意圆柱体是没有上下表面的,所以要用树枝挡住)
DrawTree(depth + 1); //绘制第一个树枝

MoveToProperPos(); //移动到适当位置(glPushMatrix();glRotatef();glTranlatef();...)
DrawTree(depth + 1); //绘制第二个树枝
MoveToProperPos(); //移动到适当位置
DrawTree(depth + 1); //绘制第三个树枝
}


绘制函数可以这样被调用:DrawTree(1); m_nDepth指的是树的递归层数,加深一层速度会慢三倍,但是可以得到更繁茂的树。 DEMO里只有四层,只是用了很大的叶子去掩盖,并且一片纹理图上就有五片叶子。不过总比一棵树上贴五片树枝纹理图,然后用billboard 好的多,很多著名游戏都是这么干的。
post: 还有一点别的事情,树的顶端树枝很细,所以我并没有使用二次曲面进行模拟,而是使用了长方体。这样会稍微快一点。 比较粗的树干上通常是没有叶子的,所以绘制的过程中有相关的判断,地层的树枝上不会有叶子。 我用AMD CodeAnalyst 对程序进行了分析,可惜并没有找到真正的热点。对于代码优化来讲,算法上的优化通常会更优。 在我的机器(AMD Sempron 2800+ 1.6G,512MB,6600LE 128MB)上,把绘制树的过程做成显示列表后,调用一次列表的时间大约为0.85ms ,使用近似之后可以节约大约0.04ms。目前对我来说主要问题还是效率,我希望效率可以提升一倍,反正要比导入模型更快。 最近主要针对的是消除递归,树是递归定义的,希望消除递归能提高效率。主要方法还是用栈,二叉树和三叉树消除递归好像差不多。 还有隐藏面消除,显卡也会完成隐藏面消除,我希望要的结果是不需要绘制的面(或者点)的信息就不要传给显卡,估计自己做可能倒不如传给显卡。 还有更快的圆柱体绘制方法。 还有使用更小更精巧的纹理,看WAR3的纹理图给了我一点启发,一张256X256的图片巧妙的交错存储了两种植物的纹理。30多个面,50多个顶点 做出来的植物也是非常逼真,不过WAR3并不是以真实感为卖点的游戏,其实树做的就很搓,实时性可能更重要一些。 如果有人对这个感兴趣的话可以在我的blog上留言。
注:递归消除部分的代码已经写完,但是效率并没有得到提高

没有评论: