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

来源:互联网 发布:编程唯快不破 编辑:程序博客网 时间:2024/04/29 08:52
前面已经介绍雷达地图的类声明,现在就来仔细分析一下雷达地图是怎么样显示出来的。雷达地图显示函数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 }