扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
在室外场境的实现中,有很多植物是需要显示出来的,比如树和花草是最常见的植物。下面就来看看第二人生里树显示的实现,如下图所示:
蔡军生
看到如此优美的画面,让人感觉就是身临其境,快活如神仙一般。这样才提供给人们快乐的环境,度过美好的人生。那么这么优美的树是怎么样实现的呢?现在就来分析一下第二人生里树显示的实现,跟前面地面和天空一样,都是先创建网格,然再加上合适的纹理来实现的,代码如下:
#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 =
#008 const F32 LEAF_RIGHT =
#009 const F32 LEAF_TOP =
#010 const F32 LEAF_BOTTOM =
#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(
#063 vertex_count++;
#064
#065 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
#066 *(vertices++) = LLVector3(
#067 vertex_count++;
#068
#069 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
#070 *(vertices++) = LLVector3(
#071 vertex_count++;
#072
#073 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
#074 *(vertices++) = LLVector3(
#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(
#100 vertex_count++;
#101
#102 //*(tex_coords++) = LLVector2(1.f,
#103 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
#104 *(vertices++) = LLVector3(
#105 vertex_count++;
#106
#107 //*(tex_coords++) = LLVector2(
#108 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
#109 *(vertices++) = LLVector3(
#110 vertex_count++;
#111
#112 //*(tex_coords++) = LLVector2(1.f,
#113 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
#114 *(vertices++) = LLVector3(
#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,
#139 vertex_count++;
#140
#141 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
#142 *(vertices++) = LLVector3(0.f,
#143 vertex_count++;
#144
#145 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
#146 *(vertices++) = LLVector3(0.f,
#147 vertex_count++;
#148
#149 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
#150 *(vertices++) = LLVector3(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,
#174 vertex_count++;
#175
#176 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
#177 *(vertices++) = LLVector3(0.f,
#178 vertex_count++;
#179
#180 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
#181 *(vertices++) = LLVector3(0.f,
#182 vertex_count++;
#183
#184 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
#185 *(vertices++) = LLVector3(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];
#
#
#215 //llinfos << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << llendl;
#216 //llinfos << "Droop " << mDroop << ", branchlength: " << mBranchLength << llendl;
#
#
#
#
#221 if (slices > 3)
#222 {
#223 z_inc = 1.f/(slices - 3);
#224 }
#
#226
#
#
#229 LLVector3 nvec;
#230
#231 const F32 cap_nudge =
#232
#233 const S32 fractal_depth = 5;
#
#
#236
#
#238
#
#
#
#
#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 +
#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(
#291 }
#292 else
#293 {
#294 tc = LLVector2((angle/360.f)*
#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
这段代码是先生成四个叶子平面,也就是八个三角形,接着再生成树干的顶点和纹理坐标。这样就可以通过不同的纹理图片显示出来就是不同的种类的树了。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者