明论  

 前两章的涉及一些很表面的东西,这一节开始我们要慢慢进入游戏的核心技术拉     

 

我们先从图像生成这一个方向入手,我们可以看到CGame中有两个与图形生成有关的方法:bool Draw();  和   bool DrawWorld();

我们先来看 bool DrawWorld();

bool CGame::DrawWorld()
{
    START_TIME_PROFILE("Draw world");

    CBaseGroundDrawer* gd = readmap->GetGroundDrawer();

    sky->Draw();
    gd->UpdateExtraTexture();
    gd->Draw();
                                                            ----------------该章就讲解这生成地图图像两句话,其他不用管
    if(!readmap->voidWater && water->drawSolid)
         water->Draw();

    selectedUnits.Draw();
    luaCallIns.DrawWorldPreUnit();
    unitDrawer->Draw(false);
    featureHandler->Draw();
    if(gu->drawdebug && gs->cheatEnabled)
        pathManager->Draw();
    //transparent stuff
    glEnable(GL_BLEND);
    glDepthFunc(GL_LEQUAL);
    if(treeDrawer->drawTrees)
        treeDrawer->DrawGrass();
    if(!readmap->voidWater && !water->drawSolid)
        water->Draw();
    unitDrawer->DrawCloakedUnits();
    ph->Draw(false);
    sky->DrawSun();

    luaCallIns.DrawWorld();

    lineDrawer.UpdateLineStipple();
    LuaUnsyncedCtrl::DrawUnitCommandQueues();
    if (cmdColors.AlwaysDrawQueue() || guihandler->GetQueueKeystate()) {
        selectedUnits.DrawCommands();
    }
    cursorIcons.Draw();
    cursorIcons.Clear();

    mouse->Draw();

    guihandler->DrawMapStuff(0);

    inMapDrawer->Draw();

    // underwater overlay
    if (camera->pos.y < 0.0f) {
        const float3& cpos = camera->pos;
        const float vr = gu->viewRange * 0.5f;
        glDisable(GL_TEXTURE_2D);
        glColor4f(0.0f, 0.5f, 0.3f, 0.50f);
        glBegin(GL_QUADS);
        glVertex3f(cpos.x - vr, 0.0f, cpos.z - vr);
        glVertex3f(cpos.x - vr, 0.0f, cpos.z + vr);
        glVertex3f(cpos.x + vr, 0.0f, cpos.z + vr);
        glVertex3f(cpos.x + vr, 0.0f, cpos.z - vr);
        glEnd();
        glBegin(GL_QUAD_STRIP);
        glVertex3f(cpos.x - vr, 0.0f, cpos.z - vr);
        glVertex3f(cpos.x - vr,  -vr, cpos.z - vr);
        glVertex3f(cpos.x - vr, 0.0f, cpos.z + vr);
        glVertex3f(cpos.x - vr,  -vr, cpos.z + vr);
        glVertex3f(cpos.x + vr, 0.0f, cpos.z + vr);
        glVertex3f(cpos.x + vr,  -vr, cpos.z + vr);
        glVertex3f(cpos.x + vr, 0.0f, cpos.z - vr);
        glVertex3f(cpos.x + vr,  -vr, cpos.z - vr);
        glVertex3f(cpos.x - vr, 0.0f, cpos.z - vr);
        glVertex3f(cpos.x - vr,  -vr, cpos.z - vr);
        glEnd();
    }

    glLoadIdentity();
    glDisable(GL_DEPTH_TEST);

    //reset fov
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0,1,0,1);
    glMatrixMode(GL_MODELVIEW);

    if (shadowHandler->drawShadows && shadowHandler->showShadowMap) {
        shadowHandler->DrawShadowTex();
    }

    glEnable(GL_BLEND);
    glDisable(GL_DEPTH_TEST );
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glLoadIdentity();

    // underwater overlay, part 2
    if (camera->pos.y < 0.0f) {
        glDisable(GL_TEXTURE_2D);
        glColor4f(0.0f, 0.2f, 0.8f, 0.333f);
        glRectf(0.0f, 0.0f, 1.0f, 1.0f);
    }

    END_TIME_PROFILE("Draw world");

    return true;

}

一开始我们就看到一个类叫CBaseGroundDrawer 这个类是干什么的呢?它就是本节的主角生成地图。分析他先上代码:

我们可以看到CBaseGroundDrawer* gd = readmap->GetGroundDrawer();

从readmap读出存有CBaseGroundDrawer的指针后进行了如下方法调用:gd->UpdateExtraTexture();gd->Draw();

那我们来先来看 gd->UpdateExtraTexture();方法是在干什么的

bool CBaseGroundDrawer::UpdateExtraTexture()
{
    if(drawMode == drawNormal)
        return true;

    unsigned short* myLos=&loshandler->losMap[gu->myAllyTeam].front();
    unsigned short* myAirLos=&loshandler->airLosMap[gu->myAllyTeam].front();
    unsigned short* myRadar=&radarhandler->radarMaps[gu->myAllyTeam].front();
    unsigned short* myJammer=&radarhandler->jammerMaps[gu->myAllyTeam].front();
    if(updateTextureState<50){                   ---50的意思是分50次加载
        int starty;
        int endy;
        if(highResInfoTexWanted){
            starty=updateTextureState*gs->mapy/50;
            endy=(updateTextureState+1)*gs->mapy/50;
        } else {
            starty=updateTextureState*gs->hmapy/50;
            endy=(updateTextureState+1)*gs->hmapy/50;    ---将地图的X,Y分为50块
        }

        switch(drawMode) {
            case drawPath: {
                if (guihandler->inCommand > 0 && guihandler->inCommand < guihandler->commands.size() &&
                        guihandler->commands[guihandler->inCommand].type == CMDTYPE_ICON_BUILDING) {              ---如果当前命令为建造
                    // use the current build order
                    for (int y = starty; y < endy; ++y) {
                        for (int x = 0; x < gs->hmapx; ++x) {
                            float m;
                            if (!loshandler->InLos(float3(x*16+8, 0, y*16+8), gu->myAllyTeam)) {
                                m = 0.25f;
                            } else {
                                const UnitDef* unitdef = unitDefHandler->GetUnitByID(-guihandler->commands[guihandler->inCommand].id);
                                CFeature* f;
                                if(uh->TestUnitBuildSquare(BuildInfo(unitdef, float3(x*16+8, 0, y*16+8), guihandler->buildFacing), f, gu->myAllyTeam)) {
                                    if (f) {
                                        m = 0.5f;
                                    } else {
                                        m = 1.0f;
                                    }
                                } else {
                                    m = 0.0f;
                                }
                            }
                            const int a=y*gs->pwr2mapx/2+x;
                            infoTexMem[a*4+0]=255-int(m*255.0f);
                            infoTexMem[a*4+1]=int(m*255.0f);
                            infoTexMem[a*4+2]=0;                                   ---- 计算缓冲区大小填入缓冲区
                        }
                    }
                }
                else {
                    // use the first selected unit
                    if (selectedUnits.selectedUnits.empty()) {
                        return true;
                    }
                    const MoveData* md = (*selectedUnits.selectedUnits.begin())->unitDef->movedata;
                    if (md == NULL) {
                        return true;
                    }
                    for (int y = starty; y < endy; ++y) {
                        for (int x = 0; x < gs->hmapx; ++x) {
                            float m = md->moveMath->SpeedMod(*md, x*2, y*2);
                            if (gs->cheatEnabled && md->moveMath->IsBlocked2(*md, x*2+1, y*2+1) & (CMoveMath::BLOCK_STRUCTURE | CMoveMath::BLOCK_TERRAIN)) {
                                m = 0.0f;
                            }
                            m = min(1.0f, (float)sqrt(m));
                            const int a=y*gs->pwr2mapx/2+x;
                            infoTexMem[a*4+0]=255-int(m*255.0f);
                            infoTexMem[a*4+1]=int(m*255.0f);
                            infoTexMem[a*4+2]=0;                                      ---- 计算缓冲区大小填入缓冲区
                        }
                    }
                }
                break;
            }
            case drawMetal: {
                for(int y=starty;y<endy;++y){
                    for(int x=0;x<gs->hmapx;++x){
                        int a=y*gs->pwr2mapx/2+x;
                        if(myAirLos[((y*2)>>loshandler->airMipLevel)*loshandler->airSizeX+((x*2)>>loshandler->airMipLevel)]) {
                            float extractDepth = extractDepthMap[y*gs->hmapx+x];
                            infoTexMem[a*4]=(unsigned char)min(255.0f,(float)sqrt(sqrt(extractDepth))*900);
                        } else {
                            infoTexMem[a*4]=0;
                        }
                        infoTexMem[a*4+1]=(extraTexPal[extraTex[y*gs->hmapx+x]*3+1]);
                        infoTexMem[a*4+2]=(extraTexPal[extraTex[y*gs->hmapx+x]*3+2]);              ---- 计算缓冲区大小填入缓冲区
                    }
                }
                break;
            }
            case drawHeight: {
                extraTexPal=readmap->heightLinePal;
                for(int y=starty;y<endy;++y){
                    for(int x=0;x<gs->mapx;++x){
                        int a=y*gs->pwr2mapx+x;
                        float height=readmap->centerheightmap[y*gs->mapx+x];
                        unsigned char value=(unsigned char)(height*8);
                        infoTexMem[a*4]=64+(extraTexPal[value*3]>>1);
                        infoTexMem[a*4+1]=64+(extraTexPal[value*3+1]>>1);
                        infoTexMem[a*4+2]=64+(extraTexPal[value*3+2]>>1);                   ---- 计算缓冲区大小填入缓冲区
                    }
                }
                break;
            }
            case drawLos: {
                int lowRes = highResInfoTexWanted ? 0 : -1;
                int endx = highResInfoTexWanted ? gs->mapx : gs->hmapx;
                int pwr2mapx = gs->pwr2mapx >> (-lowRes);
                for(int y=starty;y<endy;++y){
                    for(int x=0;x<endx;++x){
                        int a=y*pwr2mapx+x;
                        int inRadar=0;
                        int inJam=0;
                        if (drawRadarAndJammer){
                            inRadar = InterpolateLos(myRadar,  radarhandler->xsize, radarhandler->ysize, 3+lowRes, 50, x, y);
                            inJam   = InterpolateLos(myJammer, radarhandler->xsize, radarhandler->ysize, 3+lowRes, 50, x, y);
                        }
                        int inLos = InterpolateLos(myLos,    loshandler->losSizeX, loshandler->losSizeY, loshandler->losMipLevel+lowRes, 32, x, y);
                        int inAir = InterpolateLos(myAirLos, loshandler->airSizeX, loshandler->airSizeY, loshandler->airMipLevel+lowRes, 32, x, y);
                        infoTexMem[a*4] = 64+inLos+inAir+inJam;
                        infoTexMem[a*4+1] = 64+inLos+inAir+inRadar;
                        infoTexMem[a*4+2] = 64+inLos+inAir;                                   ---- 计算缓冲区大小填入缓冲区
                    }
                }
                break;
            }
            case drawNormal:
                break;
        } // switch (drawMode)
    } // if (updateTextureState < 50)

    if(updateTextureState==50){
        if(infoTex!=0 && highResInfoTexWanted!=highResInfoTex){
            glDeleteTextures(1,&infoTex);
            infoTex=0;
        }
        if(infoTex==0){
            glGenTextures(1,&infoTex);
            glBindTexture(GL_TEXTURE_2D, infoTex);

            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
            if(highResInfoTexWanted)
                glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8, gs->pwr2mapx, gs->pwr2mapy,0,GL_RGBA, GL_UNSIGNED_BYTE, infoTexMem);
            else
                glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8, gs->pwr2mapx>>1, gs->pwr2mapy>>1,0,GL_RGBA, GL_UNSIGNED_BYTE, infoTexMem);
            highResInfoTex=highResInfoTexWanted;
            updateTextureState=0;
            return true;
        }

    }
    if(updateTextureState>=50){
        glBindTexture(GL_TEXTURE_2D, infoTex);
        if(highResInfoTex)
            glTexSubImage2D(GL_TEXTURE_2D,0, 0,(updateTextureState-50)*(gs->pwr2mapy/8),gs->pwr2mapx, (gs->pwr2mapy/8),GL_RGBA, GL_UNSIGNED_BYTE, &infoTexMem[(updateTextureState-50)*(gs->pwr2mapy/8)*gs->pwr2mapx*4]);
        else
            glTexSubImage2D(GL_TEXTURE_2D,0, 0,(updateTextureState-50)*(gs->pwr2mapy/16),gs->pwr2mapx>>1, (gs->pwr2mapy/16),GL_RGBA, GL_UNSIGNED_BYTE, &infoTexMem[(updateTextureState-50)*(gs->pwr2mapy/16)*(gs->pwr2mapx>>1)*4]);
        if(updateTextureState==57){
            updateTextureState=0;
            return true;
        }
    }
    updateTextureState++;
    return false;

}

恩,这个方法让我们看到头晕,不知所云,跟载入地图有什么关系呢, 给大家提醒下,这是在更新地图质材的方法

  updateTextureState < 50:   计算质材的颜色值,填入缓冲区
  updateTextureState >= 50:  从缓冲区填入质材

  updateTextureState = 57:   重设updateTextureState为0,重新更新

想知道他们各自做了什么呢,看看我上面为他们做的注释。


 

 


 

 


   
posted on 2008-08-06 14:35  konyel  阅读(598)  评论(0)    收藏  举报