科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道第二人生的源码分析(13)树显示的实现

第二人生的源码分析(13)树显示的实现

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在室外场境的实现中,有很多植物是需要显示出来的,比如树和花草是最常见的植物。下面就来看看第二人生里树显示的实现,如下图所示

作者:第二人生 来源:blog【原创】 2008年1月14日

关键字: C++ caimouse Second Life 第二人生 软件

  • 评论
  • 分享微博
  • 分享邮件

在室外场境的实现中,有很多植物是需要显示出来的,比如树和花草是最常见的植物。下面就来看看第二人生里树显示的实现,如下图所示:

 

蔡军生  2008/01/13 QQ:9073204 深圳

看到如此优美的画面,让人感觉就是身临其境,快活如神仙一般。这样才提供给人们快乐的环境,度过美好的人生。那么这么优美的树是怎么样实现的呢?现在就来分析一下第二人生里树显示的实现,跟前面地面和天空一样,都是先创建网格,然再加上合适的纹理来实现的,代码如下:

#001  BOOL LLVOTree::updateGeometry(LLDrawable *drawable)

#002  {

#003       LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TREE);

#004       U32 i, j;

#005       const S32 MAX_SLICES = 32;

#006 

#007       const F32 LEAF_LEFT = 0.52f;

#008       const F32 LEAF_RIGHT = 0.98f;

#009       const F32 LEAF_TOP = 1.0f;

#010       const F32 LEAF_BOTTOM = 0.52f;

#011 

#012       const F32 LEAF_WIDTH = 1.f;

#013 

#014 

#015       U32 slices = MAX_SLICES;

#016 

#017       S32 max_indices = LEAF_INDICES;

#018       S32 max_vertices = LEAF_VERTICES;

#019       S32 lod;

#020 

#021       LLFace *face = drawable->getFace(0);

#022 

获取树显示的表面。

 

#023       face->mCenterAgent = getPositionAgent();

#024       face->mCenterLocal = face->mCenterAgent;

#025 

#026       for (lod = 0; lod < 4; lod++)

#027       {

#028              slices = sLODSlices[lod];

#029              sLODVertexOffset[lod] = max_vertices;

#030              sLODVertexCount[lod] = slices*slices;

#031              sLODIndexOffset[lod] = max_indices;

#032              sLODIndexCount[lod] = (slices-1)*(slices-1)*6;

#033              max_indices += sLODIndexCount[lod];

#034              max_vertices += sLODVertexCount[lod];

#035       }

#036 

计算有多少顶点实现树网格。

 

#037       LLStrider<LLVector3> vertices;

#038       LLStrider<LLVector3> normals;

#039       LLStrider<LLVector2> tex_coords;

#040       LLStrider<U32> indicesp;

#041 

#042       face->setSize(max_vertices, max_indices);

设置表面的顶点个数和索引个数。

 

#043 

#044       face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);

#045       face->mVertexBuffer->allocateBuffer(max_vertices, max_indices, TRUE);

分配表面的顶点和索引内存缓冲区。

 

#046       face->setGeomIndex(0);

#047       face->setIndicesIndex(0);

#048 

#049       face->getGeometry(vertices, normals, tex_coords, indicesp);

获取顶点、法线、纹理、索引的保存数组开始位置。

 

#050      

#051 

#052       S32 vertex_count = 0;

#053       S32 index_count = 0;

#054      

#055       // First leaf

#056       for (i = 0; i < 4; i++)

#057       {

#058              *(normals++) =            LLVector3(0.f, 0.f, 1.f);

#059       }

#060 

#061       *(tex_coords++) =       LLVector2(LEAF_LEFT, LEAF_BOTTOM);

#062       *(vertices++) =            LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f);

#063       vertex_count++;

#064 

#065       *(tex_coords++) =       LLVector2(LEAF_RIGHT, LEAF_TOP);

#066       *(vertices++) =            LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);

#067       vertex_count++;

#068 

#069      *(tex_coords++) =     LLVector2(LEAF_LEFT, LEAF_TOP);

#070       *(vertices++) =            LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);

#071       vertex_count++;

#072 

#073       *(tex_coords++) =       LLVector2(LEAF_RIGHT, LEAF_BOTTOM);

#074       *(vertices++) =            LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f);

#075       vertex_count++;

#076 

#077 

#078       *(indicesp++) = 0;

#079       index_count++;

#080       *(indicesp++) = 1;

#081       index_count++;

#082       *(indicesp++) = 2;

#083       index_count++;

#084 

#085       *(indicesp++) = 0;

#086       index_count++;

#087       *(indicesp++) = 3;

#088       index_count++;

#089       *(indicesp++) = 1;

#090       index_count++;

上面计算第一个叶子平面的四个顶点和纹理坐标。

 

#091 

#092       // Same leaf, inverse winding/normals

#093       for (i = 0; i < 4; i++)

#094       {

#095              *(normals++) =            LLVector3(0.f, 0.f, 1.f);

#096       }

#097 

#098       *(tex_coords++) =       LLVector2(LEAF_LEFT, LEAF_BOTTOM);

#099       *(vertices++) =            LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f);

#100       vertex_count++;

#101 

#102       //*(tex_coords++) =     LLVector2(1.f, 1.0f);

#103       *(tex_coords++) =       LLVector2(LEAF_RIGHT, LEAF_TOP);

#104       *(vertices++) =            LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);

#105       vertex_count++;

#106 

#107       //*(tex_coords++) =     LLVector2(0.52f, 1.0f);

#108       *(tex_coords++) =       LLVector2(LEAF_LEFT, LEAF_TOP);

#109       *(vertices++) =            LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);

#110       vertex_count++;

#111 

#112       //*(tex_coords++) =     LLVector2(1.f, 0.52f);

#113       *(tex_coords++) =       LLVector2(LEAF_RIGHT, LEAF_BOTTOM);

#114       *(vertices++) =            LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f);

#115       vertex_count++;

#116 

#117       *(indicesp++) = 4;

#118       index_count++;

#119       *(indicesp++) = 6;

#120       index_count++;

#121       *(indicesp++) = 5;

#122       index_count++;

#123 

#124       *(indicesp++) = 4;

#125       index_count++;

#126       *(indicesp++) = 5;

#127       index_count++;

#128       *(indicesp++) = 7;

#129       index_count++;

#130 

#131 

#132       for (i = 0; i < 4; i++)

#133       {

#134              *(normals++) =            LLVector3(0.f, 0.f, 1.f);

#135       }

#136 

#137       *(tex_coords++) =       LLVector2(LEAF_LEFT, LEAF_BOTTOM);

#138       *(vertices++) =            LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f);

#139       vertex_count++;

#140 

#141       *(tex_coords++) =       LLVector2(LEAF_RIGHT, LEAF_TOP);

#142       *(vertices++) =            LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);

#143       vertex_count++;

#144 

#145      *(tex_coords++) =     LLVector2(LEAF_LEFT, LEAF_TOP);

#146       *(vertices++) =            LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);

#147       vertex_count++;

#148 

#149       *(tex_coords++) =       LLVector2(LEAF_RIGHT, LEAF_BOTTOM);

#150       *(vertices++) =            LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f);

#151       vertex_count++;

#152 

#153       *(indicesp++) = 8;

#154       index_count++;

#155       *(indicesp++) = 9;

#156       index_count++;

#157       *(indicesp++) = 10;

#158       index_count++;

#159 

#160       *(indicesp++) = 8;

#161       index_count++;

#162       *(indicesp++) = 11;

#163       index_count++;

#164       *(indicesp++) = 9;

#165       index_count++;

#166 

#167       for (i = 0; i < 4; i++)

#168       {

#169              *(normals++) =            LLVector3(0.f, 0.f, 1.f);

#170       }

#171 

#172       *(tex_coords++) =       LLVector2(LEAF_LEFT, LEAF_BOTTOM);

#173       *(vertices++) =            LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f);

#174       vertex_count++;

#175 

#176       *(tex_coords++) =       LLVector2(LEAF_RIGHT, LEAF_TOP);

#177       *(vertices++) =            LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);

#178       vertex_count++;

#179 

#180      *(tex_coords++) =     LLVector2(LEAF_LEFT, LEAF_TOP);

#181       *(vertices++) =            LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);

#182       vertex_count++;

#183 

#184       *(tex_coords++) =       LLVector2(LEAF_RIGHT, LEAF_BOTTOM);

#185       *(vertices++) =            LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f);

#186       vertex_count++;

#187 

#188 

#189       *(indicesp++) = 12;

#190       index_count++;

#191       *(indicesp++) = 14;

#192       index_count++;

#193       *(indicesp++) = 13;

#194       index_count++;

#195 

#196       *(indicesp++) = 12;

#197       index_count++;

#198       *(indicesp++) = 13;

#199       index_count++;

#200       *(indicesp++) = 15;

#201       index_count++;

#202 

#203       // Generate geometry for the cylinders

#204 

#205       // Different LOD's

#206 

#207       // Generate the vertices

#208       // Generate the indices

#209 

 

下面生成4个级别的树形显示。

#210       for (lod = 0; lod < 4; lod++)

#211       {

#212              slices = sLODSlices[lod];

#213              F32 base_radius = 0.65f;

#214              F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper;

#215              //llinfos << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << llendl;

#216              //llinfos << "Droop " << mDroop << ", branchlength: " << mBranchLength << llendl;

#217              F32 angle = 0;

#218              F32 angle_inc = 360.f/(slices-1);

#219              F32 z = 0.f;

#220              F32 z_inc = 1.f;

#221              if (slices > 3)

#222              {

#223                     z_inc = 1.f/(slices - 3);

#224              }

#225              F32 radius = base_radius;

#226 

#227              F32 x1,y1;

#228              F32 noise_scale = sSpeciesTable[mSpecies]->mNoiseMag;

#229              LLVector3 nvec;

#230 

#231              const F32 cap_nudge = 0.1f;                  // Height to 'peak' the caps on top/bottom of branch

#232 

#233              const S32 fractal_depth = 5;

#234              F32 nvec_scale = 1.f * sSpeciesTable[mSpecies]->mNoiseScale;

#235              F32 nvec_scalez = 4.f * sSpeciesTable[mSpecies]->mNoiseScale;

#236 

#237              F32 tex_z_repeat = sSpeciesTable[mSpecies]->mRepeatTrunkZ;

#238 

#239              F32 start_radius;

#240              F32 nangle = 0;

#241              F32 height = 1.f;

#242              F32 r0;

#243 

 

下面生成圆柱形状树形顶点和纹理坐标.

#244              for (i = 0; i < slices; i++)

#245              {

#246                     if (i == 0)

#247                     {

#248                            z = - cap_nudge;

#249                            r0 = 0.0;

#250                     }

#251                     else if (i == (slices - 1))

#252                     {

#253                            z = 1.f + cap_nudge;//((i - 2) * z_inc) + cap_nudge;

#254                            r0 = 0.0;

#255                     }

#256                     else 

#257                     {

#258                            z = (i - 1) * z_inc;

#259                            r0 = base_radius + (top_radius - base_radius)*z;

#260                     }

#261 

#262                     for (j = 0; j < slices; j++)

#263                     {

#264                            if (slices - 1 == j)

#265                            {

#266                                   angle = 0.f;

#267                            }

#268                            else

#269                            {

#270                                   angle =  j*angle_inc;

#271                            }

#272                    

#273                            nangle = angle;

#274                           

#275                            x1 = cos(angle * DEG_TO_RAD);

#276                            y1 = sin(angle * DEG_TO_RAD);

#277                            LLVector2 tc;

#278                            // This isn't totally accurate.  Should compute based on slope as well.

#279                            start_radius = r0 * (1.f + 1.2f*fabs(z - 0.66f*height)/height);

#280                            nvec.setVec( cos(nangle * DEG_TO_RAD)*start_radius*nvec_scale,

#281                                                        sin(nangle * DEG_TO_RAD)

#282  *start_radius*nvec_scale,

#283                                                        z*nvec_scalez);

#284                            // First and last slice at 0 radius (to bring in top/bottom of structure)

#285                            radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale;

#286 

#287                            if (slices - 1 == j)

#288                            {

#289                                   // Not 0.5 for slight slop factor to avoid edges on leaves

#290                                   tc = LLVector2(0.490f, (1.f - z/2.f)*tex_z_repeat);

#291                            }

#292                            else

#293                            {

#294                                   tc = LLVector2((angle/360.f)*0.5f, (1.f - z/2.f)*tex_z_repeat);

#295                            }

#296 

#297                            *(vertices++) =            LLVector3(x1*radius, y1*radius, z);

#298                            *(normals++) =            LLVector3(x1, y1, 0.f);

#299                            *(tex_coords++) = tc;

#300                            vertex_count++;

#301                     }

#302              }

#303 

#304              for (i = 0; i < (slices - 1); i++)

#305              {

#306                     for (j = 0; j < (slices - 1); j++)

#307                     {

#308                            S32 x1_offset = j+1;

#309                            if ((j+1) == slices)

#310                            {

#311                                   x1_offset = 0;

#312                            }

#313                            // Generate the matching quads

#314                            *(indicesp) = j + (i*slices) + sLODVertexOffset[lod];

#315                            llassert(*(indicesp) < (U32)max_vertices);

#316                            indicesp++;

#317                            index_count++;

#318                            *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod];

#319                            llassert(*(indicesp) < (U32)max_vertices);

#320                            indicesp++;

#321                            index_count++;

#322                            *(indicesp) = j + ((i+1)*slices) + sLODVertexOffset[lod];

#323                            llassert(*(indicesp) < (U32)max_vertices);

#324                            indicesp++;

#325                            index_count++;

#326 

#327                            *(indicesp) = j + (i*slices) + sLODVertexOffset[lod];

#328                            llassert(*(indicesp) < (U32)max_vertices);

#329                            indicesp++;

#330                            index_count++;

#331                            *(indicesp) = x1_offset + (i*slices) + sLODVertexOffset[lod];

#332                            llassert(*(indicesp) < (U32)max_vertices);

#333                            indicesp++;

#334                            index_count++;

#335                            *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod];

#336                            llassert(*(indicesp) < (U32)max_vertices);

#337                            indicesp++;

#338                            index_count++;

#339                     }

#340              }

#341              slices /= 2;

#342       }

#343 

#344       llassert(vertex_count == max_vertices);

#345       llassert(index_count == max_indices);

#346 

#347       return TRUE;

#348  }

#349 

 

这段代码是先生成四个叶子平面,也就是八个三角形,接着再生成树干的顶点和纹理坐标。这样就可以通过不同的纹理图片显示出来就是不同的种类的树了。

原文链接:http://blog.csdn.net/caimouse/archive/2008/01/13/2042474.aspx

 
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章