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

前面已经介绍雷达地图的类声明,现在就来仔细分析一下雷达地图是怎么样显示出来的。雷达地图显示函数 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

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
随着大数据、云计算、物联网的诞生、大量的设备数据、传感器数据、行为数据、日志数据、基础画像数据、运行数据等等都对传统的数据展现提出了新的要求 。随着前端技术的不断成熟,客户对业务系统的要求也由原来的简单实现功能上升到,漂亮、直观、易用、有科技未来感。因此系统的可视化难度加大,我们大多数客户的业务系统都需要可视化大屏的统计分析,甚至部分管理系统也被要求做成图表、地图、三维可视化,VR、AR,三维仿真、地理信息系统等等被要求深度结合业务,这在设计上有一定的难度,而且设计完成了大部分开发难度非常大,不过好在得益于技术的日渐进步,已经有大部分优秀的开源项目和插件可以实现和满足部分可视化的要求。数据分析的需求猛增,那么我们分析后的数据展示也成为目前比较热门的方向。数据可视化,我们常见的有表格、图标、图表、柱状图、折线图、雷达图、漏斗图、等值面图、等值线图、GIS地图、蜂窝图、格点数据、热力图、柱状图、饼图、散点图、地理坐标/地图、K 线图、雷达图、盒须图、热力图、关系图、路径图、树图、矩形树图、旭日图、平行坐标系、桑基图、漏斗图,三维模型可视化等等展现方式。本节课我们主要以百度地图结合mapv进行课程演示讲解,并且使用gis绘图生成等值面直接叠加地图。 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caimouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值