第二人生的源码分析(100)雷达地图详细显示

系统 1639 0
前面已经介绍雷达地图的类声明,现在就来仔细分析一下雷达地图是怎么样显示出来的。雷达地图显示函数 LLNetMap::draw代码如下:
#001 void LLNetMap::draw()
#002 {
#003     static LLFrameTimer map_timer;
#004 
 
判断是否显示雷达地图。
#005     if (!getVisible() || !gWorldPointer)
#006     {
#007         return;
#008     }
 
创建对象图片。
#009     if (mObjectImagep.isNull())
#010     {
#011         createObjectImage();
#012     }
#013    
#014     mCurPanX = lerp(mCurPanX, mTargetPanX, LLCriticalDamp::getInterpolant(0.1f));
#015     mCurPanY = lerp(mCurPanY, mTargetPanY, LLCriticalDamp::getInterpolant(0.1f));
#016  
#017     // Prepare a scissor region
#018      F32 rotation = 0;
#019 
#020     {
#021         LLGLEnable scissor(GL_SCISSOR_TEST);
#022        
#023         {
#024             LLGLSNoTexture no_texture;
 
取得窗口显示的大小。
#025             LLLocalClipRect clip(getLocalRect());
#026 
 
设置 GL显示的模式。
#027             glMatrixMode(GL_MODELVIEW);
#028 
 
显示背景方框。
#029             // Draw background rectangle
#030             gGL.color4fv( mBackgroundColor.mV );
#031             gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0);
#032         }
#033 
 
计算中心位置。
#034         // region 0,0 is in the middle
#035         S32 center_sw_left = getRect().getWidth() / 2 + llfloor(mCurPanX);
#036         S32 center_sw_bottom = getRect().getHeight() / 2 + llfloor(mCurPanY);
#037 
#038         gGL.pushMatrix();
#039 
#040         gGL.translatef( (F32) center_sw_left, (F32) center_sw_bottom, 0.f);
#041 
 
判断是否旋转显示地图。
#042         if( LLNetMap::sRotateMap )
#043         {
#044             // rotate subsequent draws to agent rotation
#045             rotation = atan2( gCamera->getAtAxis().mV[VX], gCamera->getAtAxis().mV[VY] );
#046             glRotatef( rotation * RAD_TO_DEG, 0.f, 0.f, 1.f);
#047         }
#048  
#049         // figure out where agent is
#050         S32 region_width = llround(gWorldPointer->getRegionWidthInMeters());
#051 
#052         for (LLWorld::region_list_t::iterator iter = gWorldp->mActiveRegionList.begin();
#053              iter != gWorldp->mActiveRegionList.end(); ++iter)
#054         {
 
计算以当前摄像机为中心的地图位置。
#055             LLViewerRegion* regionp = *iter;
#056             // Find x and y position relative to camera's center.
#057             LLVector3 origin_agent = regionp->getOriginAgent();
#058             LLVector3 rel_region_pos = origin_agent - gAgent.getCameraPositionAgent();
#059              F32 relative_x = (rel_region_pos.mV[0] / region_width) * gMiniMapScale;
#060              F32 relative_y = (rel_region_pos.mV[1] / region_width) * gMiniMapScale;
#061 
#062             // background region rectangle
#063              F32 bottom =    relative_y;
#064              F32 left =      relative_x;
#065              F32 top =       bottom + gMiniMapScale ;
#066              F32 right =     left + gMiniMapScale ;
#067 
#068             if (regionp == gAgent.getRegion())
#069             {
#070                 gGL.color4f(1.f, 1.f, 1.f, 1.f);
#071             }
#072             else
#073             {
#074                 gGL.color4f(0.8f, 0.8f, 0.8f, 1.f);
#075             }
#076 
#077             if (!regionp->mAlive)
#078             {
#079                 gGL.color4f(1.f, 0.5f, 0.5f, 1.f);
#080             }
#081 
#082 
 
显示背景边框。
#083             // Draw using texture.
#084             LLViewerImage::bindTexture(regionp->getLand().getSTexture());
#085             gGL.begin(GL_QUADS);
#086                 gGL.texCoord2f(0.f, 1.f);
#087                 gGL.vertex2f(left, top);
#088                 gGL.texCoord2f(0.f, 0.f);
#089                 gGL.vertex2f(left, bottom);
#090                 gGL.texCoord2f(1.f, 0.f);
#091                 gGL.vertex2f(right, bottom);
#092                 gGL.texCoord2f(1.f, 1.f);
#093                 gGL.vertex2f(right, top);
#094             gGL.end();
#095 
 
显示水所在的区域。
#096             // Draw water
#097             glAlphaFunc(GL_GREATER, ABOVE_WATERLINE_ALPHA / 255.f );
#098             {
#099                 if (regionp->getLand().getWaterTexture())
#100                 {
#101                     LLViewerImage::bindTexture(regionp->getLand().getWaterTexture());
#102                     gGL.begin(GL_QUADS);
#103                         gGL.texCoord2f(0.f, 1.f);
#104                         gGL.vertex2f(left, top);
#105                         gGL.texCoord2f(0.f, 0.f);
#106                         gGL.vertex2f(left, bottom);
#107                         gGL.texCoord2f(1.f, 0.f);
#108                         gGL.vertex2f(right, bottom);
#109                         gGL.texCoord2f(1.f, 1.f);
#110                         gGL.vertex2f(right, top);
#111                     gGL.end();
#112                 }
#113             }
#114             glAlphaFunc(GL_GREATER,0.01f);
#115         }
#116        
#117 
#118         LLVector3d old_center = mObjectImageCenterGlobal;
#119         LLVector3d new_center = gAgent.getCameraPositionGlobal();
#120 
#121         new_center.mdV[0] = (5.f/mObjectMapTPM)*floor(0.2f*mObjectMapTPM*new_center.mdV[0]);
#122         new_center.mdV[1] = (5.f/mObjectMapTPM)*floor(0.2f*mObjectMapTPM*new_center.mdV[1]);
#123         new_center.mdV[2] = 0.f;
#124 
#125         if (mUpdateNow || (map_timer.getElapsedTimeF32() > 0.5f))
#126         {
#127             mUpdateNow = FALSE;
#128             mObjectImageCenterGlobal = new_center;
#129 
#130             // Center moved enough.
#131             // Create the base texture.
#132             U8 *default_texture = mObjectRawImagep->getData();
#133             memset( default_texture, 0, mObjectImagep->getWidth() * mObjectImagep->getHeight() * mObjectImagep->getComponents() );
#134 
 
显示建筑物,根据水平面的高度来显示不同的颜色。
#135             // Draw buildings
#136             gObjectList.renderObjectsForMap(*this);
#137 
#138             mObjectImagep->setSubImage(mObjectRawImagep, 0, 0, mObjectImagep->getWidth(), mObjectImagep->getHeight());
#139            
#140             map_timer.reset();
#141         }
#142 
#143         LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal);
#144         map_center_agent -= gAgent.getCameraPositionAgent();
#145         map_center_agent.mV[VX] *= gMiniMapScale/region_width;
#146         map_center_agent.mV[VY] *= gMiniMapScale/region_width;
#147 
#148         LLViewerImage::bindTexture(mObjectImagep);
#149          F32 image_half_width = 0.5f*mObjectMapPixels;
#150          F32 image_half_height = 0.5f*mObjectMapPixels;
#151 
#152         gGL.begin(GL_QUADS);
#153             gGL.texCoord2f(0.f, 1.f);
#154             gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, image_half_height + map_center_agent.mV[VY]);
#155             gGL.texCoord2f(0.f, 0.f);
#156             gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, map_center_agent.mV[VY] - image_half_height);
#157             gGL.texCoord2f(1.f, 0.f);
#158             gGL.vertex2f(image_half_width + map_center_agent.mV[VX], map_center_agent.mV[VY] - image_half_height);
#159             gGL.texCoord2f(1.f, 1.f);
#160             gGL.vertex2f(image_half_width + map_center_agent.mV[VX], image_half_height + map_center_agent.mV[VY]);
#161         gGL.end();
#162 
#163         gGL.popMatrix();
#164 
#165         LLVector3d pos_global;
#166         LLVector3 pos_map;
#167 
 
 
下面开始显示整个地图上所有玩家。
#168         // Draw avatars
#169         for (LLWorld::region_list_t::iterator iter = gWorldp->mActiveRegionList.begin();
#170              iter != gWorldp->mActiveRegionList.end(); ++iter)
#171         {
 
获取所在区域。
#172             LLViewerRegion* regionp = *iter;
#173             const LLVector3d& origin_global = regionp->getOriginGlobal();
#174 
 
获取当前玩家的人数。
#175             S32 count = regionp->mMapAvatars.count();
#176             S32 i;
#177             LLVector3 pos_local;
#178             U32 compact_local;
#179             U8 bits;
#180             // TODO: it'd be very cool to draw these in sorted order from lowest Z to highest.
#181             // just be careful to sort the avatar IDs along with the positions. –MG
 
开始在地图上显示所有玩家。
#182             for (i = 0; i < count; i++)
#183             {
#184                 compact_local = regionp->mMapAvatars.get(i);
#185 
#186                 bits = compact_local & 0xFF;
#187                 pos_local.mV[VZ] = F32(bits) * 4.f;
#188                 compact_local >>= 8;
#189 
#190                 bits = compact_local & 0xFF;
#191                 pos_local.mV[VY] = (F32)bits;
#192                 compact_local >>= 8;
#193 
#194                 bits = compact_local & 0xFF;
#195                 pos_local.mV[VX] = (F32)bits;
#196 
#197                 pos_global.setVec( pos_local );
#198                 pos_global += origin_global;
#199 
 
从全局坐标转换为地图坐标。
#200                 pos_map = globalPosToView(pos_global);
#201 
#202                 BOOL show_as_friend = FALSE;
#203                 if( i < regionp->mMapAvatarIDs.count())
#204                 {
#205                     show_as_friend = is_agent_friend(regionp->mMapAvatarIDs.get(i));
#206                 }
 
在地图坐标上显示玩家。
#207                 LLWorldMapView::drawAvatar(
#208                     pos_map.mV[VX], pos_map.mV[VY],
#209                     show_as_friend ? gFriendMapColor : gAvatarMapColor,
#210                     pos_map.mV[VZ]);
#211             }
#212         }
#213 
#214         // Draw dot for autopilot target
#215         if (gAgent.getAutoPilot())
#216         {
#217             drawTracking( gAgent.getAutoPilotTargetGlobal(), gTrackColor );
#218         }
#219         else
#220         {
#221             LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
#222             if ( LLTracker::TRACKING_AVATAR == tracking_status )
#223             {
#224                 drawTracking( LLAvatarTracker::instance().getGlobalPos(), gTrackColor );
#225             }
#226             else if ( LLTracker::TRACKING_LANDMARK == tracking_status
#227                     || LLTracker::TRACKING_LOCATION == tracking_status )
#228             {
#229                 drawTracking( LLTracker::getTrackedPositionGlobal(), gTrackColor );
#230             }
#231         }
#232 
#233         // Draw dot for self avatar position
#234         //drawTracking( gAgent.getPosGlobalFromAgent(gAgent.getFrameAgent().getCenter()), gSelfMapColor );
#235         pos_global = gAgent.getPositionGlobal();
#236         pos_map = globalPosToView(pos_global);
#237         gl_draw_image(llround(pos_map.mV[VX]) - 4,
#238                     llround(pos_map.mV[VY]) - 4,
#239                     LLWorldMapView::sAvatarYouSmallImage,
#240                     LLColor4::white);
#241 
 
计算当前摄像机观看的视角。
#242         // Draw frustum
#243          F32 meters_to_pixels = gMiniMapScale/ gWorldPointer->getRegionWidthInMeters();
#244 
#245          F32 horiz_fov = gCamera->getView() * gCamera->getAspect();
#246          F32 far_clip_meters = gCamera->getFar();
#247          F32 far_clip_pixels = far_clip_meters * meters_to_pixels;
#248 
#249          F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 );
#250          F32 half_width_pixels = half_width_meters * meters_to_pixels;
#251        
#252          F32 ctr_x = (F32)center_sw_left;
#253          F32 ctr_y = (F32)center_sw_bottom;
#254 
#255 
#256         LLGLSNoTexture no_texture;
#257 
 
旋转地图的显示。
#258         if( LLNetMap::sRotateMap )
#259         {
#260             gGL.color4fv(gFrustumMapColor.mV);
#261 
#262             gGL.begin( GL_TRIANGLES );
#263                 gGL.vertex2f( ctr_x, ctr_y );
#264                 gGL.vertex2f( ctr_x - half_width_pixels, ctr_y + far_clip_pixels );
#265                 gGL.vertex2f( ctr_x + half_width_pixels, ctr_y + far_clip_pixels );
#266             gGL.end();
#267         }
#268         else
#269         {
#270             gGL.color4fv(gRotatingFrustumMapColor.mV);
#271            
#272             // If we don't rotate the map, we have to rotate the frustum.
#273             gGL.pushMatrix();
#274                 gGL.translatef( ctr_x, ctr_y, 0 );
#275                 glRotatef( atan2( gCamera->getAtAxis().mV[VX], gCamera->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f);
#276                 gGL.begin( GL_TRIANGLES );
#277                     gGL.vertex2f( 0, 0 );
#278                     gGL.vertex2f( -half_width_pixels, far_clip_pixels );
#279                     gGL.vertex2f( half_width_pixels, far_clip_pixels );
#280                 gGL.end();
#281             gGL.popMatrix();
#282         }
#283     }
#284    
 
下面显示 8个方向的文字提示。
#285     // Rotation of 0 means that North is up
#286     setDirectionPos( mTextBoxEast,  rotation );
#287     setDirectionPos( mTextBoxNorth, rotation + F_PI_BY_TWO );
#288     setDirectionPos( mTextBoxWest, rotation + F_PI );
#289     setDirectionPos( mTextBoxSouth, rotation + F_PI + F_PI_BY_TWO );
#290 
#291     setDirectionPos( mTextBoxNorthEast, rotation +                      F_PI_BY_TWO / 2);
#292     setDirectionPos( mTextBoxNorthWest, rotation + F_PI_BY_TWO +        F_PI_BY_TWO / 2);
#293     setDirectionPos( mTextBoxSouthWest, rotation + F_PI +               F_PI_BY_TWO / 2);
#294     setDirectionPos( mTextBoxSouthEast, rotation + F_PI + F_PI_BY_TWO + F_PI_BY_TWO / 2);
#295 
#296     LLUICtrl::draw();
#297 }
 
从上面的函数可以看到,先显示底层的边框,然后在上面显示水区域,接着显示建筑物层,最后在上面显示玩家所在的地方。当然还显示当前玩家所能看到的视角平面,显示地图八个方向的文字显示。

第二人生开发包提供,价格 198 / 套(含邮费)。

包括内容如下:

1.     《第二人生的源码分析》 PDF 文档。

2.     第二人生客户端源程序。

3.     2G U 盘一个,主要用来拷贝源程序以及相关开发工具。

 

提供三个月的技术服务,

提供快速编译指导,比如通过 QQ 远程编译操作。

提供完整的书参考。

 

联系方式:

QQ:              9073204

MSN:             caimouse1976@sina.com

EMAIL:           ccaimouse@gmail.com

第二人生的源码分析(100)雷达地图详细显示


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论