老康教你做游戏(4)---图像生成->地图生成之LOD(Level of detail)算法


接下来我们来看方法

void CBFGroundDrawer::Draw(bool drawWaterReflection,bool drawUnitReflection,unsigned int overrideVP)
{
if (wireframe) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}

drawWater=drawWaterReflection;

int baseViewRadius=max(4,viewRadius);
if(drawUnitReflection)
viewRadius=(viewRadius/2)&0xfffffe;
float zoom=45/camera->fov;
viewRadius=(int)(viewRadius*sqrt(zoom));
viewRadius+=viewRadius%2; ---- viewRadius是观察半径

va=GetVertexArray();
va->Initialize();

textures->DrawUpdate();

int x,y;

int neededLod=int(gu->viewRange/8/viewRadius*2); -----镜头角度/8/镜头半径*2 这个什么意思呢?
UpdateCamRestraints(); -----更新镜头限制,获取边界值right,left

invMapSizeX=1.0f/gs->mapx; ----从全局变量获取X,Y
invMapSizeY=1.0f/gs->mapy;

glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
if(!overrideVP)
glEnable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

SetupTextureUnits(drawWaterReflection,overrideVP); -----载入单位质材
bool inStrip=false;

if(map->voidWater && !drawWater){
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0.9f);
}

float camxpart=0,oldcamxpart;
float camypart=0,oldcamypart;

for(int bty=0;bty<numBigTexY;++bty){ //循环画出质材的方块(128*128的方块)写这段地形算法的人是绝对的天才。。。。。


bigtexsuby=bty;

//only process the necessary big squares in the x direction
int sx=0;
int ex=numBigTexX;
float xtest,xtest2;
const int bigSquareSize=128;

std::vector<fline>::iterator fli;

-----迭代器里的fline等下用来历遍地图的边界,下面的left,和right用断点分析出来为一个left为个数为3的迭代器,而right个数为1,我们来查找它究竟是什么。请参照代码说明1

for(fli=left.begin();fli!=left.end();fli++){ left.begin() left.end()
xtest=((fli->base/SQUARE_SIZE+fli->dir*(bty*bigSquareSize)));
xtest2=((fli->base/SQUARE_SIZE+fli->dir*((bty*bigSquareSize)+bigSquareSize)));
if(xtest>xtest2)
xtest=xtest2;
xtest=xtest/bigSquareSize;
if(xtest>sx)
sx=(int) xtest; 取最大值储存入Sx中
}
for(fli=right.begin();fli!=right.end();fli++){
xtest=((fli->base/SQUARE_SIZE+fli->dir*(bty*bigSquareSize)))+bigSquareSize; 向量长度*方块个数+ 向量方向*方块编号*方块大小+方块大小

xtest2=((fli->base/SQUARE_SIZE+fli->dir*((bty*bigSquareSize)+bigSquareSize)))+bigSquareSize;

(向量长度*方块个数+ 向量方向*方块编号*方块大小+方块大小)+方块大小

if(xtest<xtest2)
xtest=xtest2;
xtest=xtest/bigSquareSize;
if(xtest<ex)
ex=(int) xtest; 取最小值存入ex中
}
// logOutput.Print("%i %i",sx,ex);
for(int btx=sx;btx<ex;++btx){
bigtexsubx=btx;

if(DrawExtraTex() || !shadowHandler->drawShadows){
textures->SetTexture(btx,bty);
SetTexGen(1.0f/1024,1.0f/1024,-btx,-bty);
if(overrideVP){
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,11, -btx,-bty,0,0);
}
} else {
textures->SetTexture(btx,bty);
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,11, -btx,-bty,0,0);
}

for(int lod=1;lod<neededLod;lod*=2){

------ 这个地方超级不好理解,我也是看了半天才弄懂一点 在这个lod的循环中,我们可以看到lod是1,也就是说,在第一次循环中

if(!inStrip){
DrawVertexA(x,y);
DrawVertexA(x,y+lod);
inStrip=true;
}
DrawVertexA(x+lod,y);

DrawVertexA(x+lod,y+lod);

是一点连着一点的画的

当我们跟踪成寻随lod变化所话出来的图形时,我们可以看到lod的大小是与焦点到物体的距离成正比的

随着lod的变化,程序描绘的图形越来越远->越来越小。随着距离越远,程序描绘物体也就越小

而我们也越不需要更细致的描绘他,从而优化了图形的生成


int cx=(int)(cam2->pos.x/(SQUARE_SIZE));
int cy=(int)(cam2->pos.z/(SQUARE_SIZE));

cx=(cx/lod)*lod;
cy=(cy/lod)*lod;
int hlod=lod>>1;
int ysquaremod=((cy)%(2*lod))/lod;
int xsquaremod=((cx)%(2*lod))/lod;

oldcamxpart=camxpart;
float cx2=(cx/(2*lod))*lod*2;
camxpart=(cam2->pos.x/(SQUARE_SIZE)-cx2)/(lod*2);

oldcamypart=camypart;
float cy2=(cy/(2*lod))*lod*2;
camypart=(cam2->pos.z/(SQUARE_SIZE)-cy2)/(lod*2);

int minty=bty*128;
int maxty=(bty+1)*128;
int mintx=btx*128;
int maxtx=(btx+1)*128;

int minly=cy+(-viewRadius+3-ysquaremod)*lod;
int maxly=cy+(viewRadius-1-ysquaremod)*lod;
int minlx=cx+(-viewRadius+3-xsquaremod)*lod;
int maxlx=cx+(viewRadius-1-xsquaremod)*lod;

int xstart=max(minlx,mintx);
int xend=min(maxlx,maxtx);
int ystart=max(minly,minty);
int yend=min(maxly,maxty);

for(y=ystart;y<yend;y+=lod){
int xs=xstart;
int xe=xend;
int xtest,xtest2;
std::vector<fline>::iterator fli;
for(fli=left.begin();fli!=left.end();fli++){
xtest=((int)(fli->base/(SQUARE_SIZE)+fli->dir*y))/lod*lod-lod;
xtest2=((int)(fli->base/(SQUARE_SIZE)+fli->dir*(y+lod)))/lod*lod-lod;
if(xtest>xtest2)
xtest=xtest2;
if(xtest>xs)
xs=xtest;
}
for(fli=right.begin();fli!=right.end();fli++){
xtest=((int)(fli->base/(SQUARE_SIZE)+fli->dir*y))/lod*lod+lod;
xtest2=((int)(fli->base/(SQUARE_SIZE)+fli->dir*(y+lod)))/lod*lod+lod;
if(xtest<xtest2)
xtest=xtest2;
if(xtest<xe)
xe=xtest;
}

for(x=xs;x<xe;x+=lod){
if((lod==1) ||
(x>(cx)+viewRadius*hlod) || (x<(cx)-viewRadius*hlod) ||
(y>(cy)+viewRadius*hlod) || (y<(cy)-viewRadius*hlod)){ //normal terr锟絞
if(!inStrip){
DrawVertexA(x,y);
DrawVertexA(x,y+lod);
inStrip=true;
}
DrawVertexA(x+lod,y);
DrawVertexA(x+lod,y+lod);
} else { //inre begr锟絪ning mot f锟絜g锟絥de lod
if((x>=(cx)+viewRadius*hlod)){
float h1=(heightData[(y)*heightDataX+x]+heightData[(y+lod)*heightDataX+x])*0.5f*(1-oldcamxpart)+heightData[(y+hlod)*heightDataX+x]*(oldcamxpart);
float h2=(heightData[(y)*heightDataX+x]+heightData[(y)*heightDataX+x+lod])*0.5f*(1-oldcamxpart)+heightData[(y)*heightDataX+x+hlod]*(oldcamxpart);
float h3=(heightData[(y+lod)*heightDataX+x]+heightData[(y)*heightDataX+x+lod])*0.5f*(1-oldcamxpart)+heightData[(y+hlod)*heightDataX+x+hlod]*(oldcamxpart);
float h4=(heightData[(y+lod)*heightDataX+x]+heightData[(y+lod)*heightDataX+x+lod])*0.5f*(1-oldcamxpart)+heightData[(y+lod)*heightDataX+x+hlod]*(oldcamxpart);

if(inStrip){
EndStrip();
inStrip=false;
}
DrawVertexA(x,y);
DrawVertexA(x,y+hlod,h1);
DrawVertexA(x+hlod,y,h2);
DrawVertexA(x+hlod,y+hlod,h3);
EndStrip();
DrawVertexA(x,y+hlod,h1);
DrawVertexA(x,y+lod);
DrawVertexA(x+hlod,y+hlod,h3);
DrawVertexA(x+hlod,y+lod,h4);
EndStrip();
DrawVertexA(x+hlod,y+lod,h4);
DrawVertexA(x+lod,y+lod);
DrawVertexA(x+hlod,y+hlod,h3);
DrawVertexA(x+lod,y);
DrawVertexA(x+hlod,y,h2);
EndStrip();
}
if((x<=(cx)-viewRadius*hlod)){
float h1=(heightData[(y)*heightDataX+x+lod]+heightData[(y+lod)*heightDataX+x+lod])*0.5f*(oldcamxpart)+heightData[(y+hlod)*heightDataX+x+lod]*(1-oldcamxpart);
float h2=(heightData[(y)*heightDataX+x]+heightData[(y)*heightDataX+x+lod])*0.5f*(oldcamxpart)+heightData[(y)*heightDataX+x+hlod]*(1-oldcamxpart);
float h3=(heightData[(y+lod)*heightDataX+x]+heightData[(y)*heightDataX+x+lod])*0.5f*(oldcamxpart)+heightData[(y+hlod)*heightDataX+x+hlod]*(1-oldcamxpart);
float h4=(heightData[(y+lod)*heightDataX+x]+heightData[(y+lod)*heightDataX+x+lod])*0.5f*(oldcamxpart)+heightData[(y+lod)*heightDataX+x+hlod]*(1-oldcamxpart);

if(inStrip){
EndStrip();
inStrip=false;
}
DrawVertexA(x+lod,y+hlod,h1);
DrawVertexA(x+lod,y);
DrawVertexA(x+hlod,y+hlod,h3);
DrawVertexA(x+hlod,y,h2);
EndStrip();
DrawVertexA(x+lod,y+lod);
DrawVertexA(x+lod,y+hlod,h1);
DrawVertexA(x+hlod,y+lod,h4);
DrawVertexA(x+hlod,y+hlod,h3);
EndStrip();
DrawVertexA(x+hlod,y,h2);
DrawVertexA(x,y);
DrawVertexA(x+hlod,y+hlod,h3);
DrawVertexA(x,y+lod);
DrawVertexA(x+hlod,y+lod,h4);
EndStrip();
}
if((y>=(cy)+viewRadius*hlod)){
float h1=(heightData[(y)*heightDataX+x]+heightData[(y)*heightDataX+x+lod])*0.5f*(1-oldcamypart)+heightData[(y)*heightDataX+x+hlod]*(oldcamypart);
float h2=(heightData[(y)*heightDataX+x]+heightData[(y+lod)*heightDataX+x])*0.5f*(1-oldcamypart)+heightData[(y+hlod)*heightDataX+x]*(oldcamypart);
float h3=(heightData[(y+lod)*heightDataX+x]+heightData[(y)*heightDataX+x+lod])*0.5f*(1-oldcamypart)+heightData[(y+hlod)*heightDataX+x+hlod]*(oldcamypart);
float h4=(heightData[(y+lod)*heightDataX+x+lod]+heightData[(y)*heightDataX+x+lod])*0.5f*(1-oldcamypart)+heightData[(y+hlod)*heightDataX+x+lod]*(oldcamypart);

if(inStrip){
EndStrip();
inStrip=false;
}
DrawVertexA(x,y);
DrawVertexA(x,y+hlod,h2);
DrawVertexA(x+hlod,y,h1);
DrawVertexA(x+hlod,y+hlod,h3);
DrawVertexA(x+lod,y);
DrawVertexA(x+lod,y+hlod,h4);
EndStrip();
DrawVertexA(x,y+hlod,h2);
DrawVertexA(x,y+lod);
DrawVertexA(x+hlod,y+hlod,h3);
DrawVertexA(x+lod,y+lod);
DrawVertexA(x+lod,y+hlod,h4);
EndStrip();
}
if((y<=(cy)-viewRadius*hlod)){
float h1=(heightData[(y+lod)*heightDataX+x]+heightData[(y+lod)*heightDataX+x+lod])*0.5f*(oldcamypart)+heightData[(y+lod)*heightDataX+x+hlod]*(1-oldcamypart);
float h2=(heightData[(y)*heightDataX+x]+heightData[(y+lod)*heightDataX+x])*0.5f*(oldcamypart)+heightData[(y+hlod)*heightDataX+x]*(1-oldcamypart);
float h3=(heightData[(y+lod)*heightDataX+x]+heightData[(y)*heightDataX+x+lod])*0.5f*(oldcamypart)+heightData[(y+hlod)*heightDataX+x+hlod]*(1-oldcamypart);
float h4=(heightData[(y+lod)*heightDataX+x+lod]+heightData[(y)*heightDataX+x+lod])*0.5f*(oldcamypart)+heightData[(y+hlod)*heightDataX+x+lod]*(1-oldcamypart);

if(inStrip){
EndStrip();
inStrip=false;
}
DrawVertexA(x,y+hlod,h2);
DrawVertexA(x,y+lod);
DrawVertexA(x+hlod,y+hlod,h3);
DrawVertexA(x+hlod,y+lod,h1);
DrawVertexA(x+lod,y+hlod,h4);
DrawVertexA(x+lod,y+lod);
EndStrip();
DrawVertexA(x+lod,y+hlod,h4);
DrawVertexA(x+lod,y);
DrawVertexA(x+hlod,y+hlod,h3);
DrawVertexA(x,y);
DrawVertexA(x,y+hlod,h2);
EndStrip();
}
}
}
if(inStrip){
EndStrip();
inStrip=false;
}
}
//rita yttre begr锟絪nings yta mot n锟絫a lod
if(maxlx<maxtx && maxlx>=mintx){
x=maxlx;
for(y=max(ystart-lod,minty);y<min(yend+lod,maxty);y+=lod){
DrawVertexA(x,y);
DrawVertexA(x,y+lod);
if(y%(lod*2)){
float h=((heightData[(y-lod)*heightDataX+x+lod]+heightData[(y+lod)*heightDataX+x+lod])*0.5f)*(1-camxpart)+heightData[(y)*heightDataX+x+lod]*(camxpart);
DrawVertexA(x+lod,y,h);
DrawVertexA(x+lod,y+lod);
} else {
DrawVertexA(x+lod,y);
float h=(heightData[(y)*heightDataX+x+lod]+heightData[(y+lod*2)*heightDataX+x+lod])*0.5f*(1-camxpart)+heightData[(y+lod)*heightDataX+x+lod]*(camxpart);
DrawVertexA(x+lod,y+lod,h);
}
EndStrip();
}
}
if(minlx>mintx && minlx<maxtx){
x=minlx-lod;
for(y=max(ystart-lod,minty);y<min(yend+lod,maxty);y+=lod){
if(y%(lod*2)){
float h=((heightData[(y-lod)*heightDataX+x]+heightData[(y+lod)*heightDataX+x])*0.5f)*(camxpart)+heightData[(y)*heightDataX+x]*(1-camxpart);
DrawVertexA(x,y,h);
DrawVertexA(x,y+lod);
} else {
DrawVertexA(x,y);
float h=(heightData[(y)*heightDataX+x]+heightData[(y+lod*2)*heightDataX+x])*0.5f*(camxpart)+heightData[(y+lod)*heightDataX+x]*(1-camxpart);
DrawVertexA(x,y+lod,h);
}
DrawVertexA(x+lod,y);
DrawVertexA(x+lod,y+lod);
EndStrip();
}
}
if(maxly<maxty && maxly>minty){
y=maxly;
int xs=max(xstart-lod,mintx);
int xe=min(xend+lod,maxtx);
int xtest,xtest2;
std::vector<fline>::iterator fli;
for(fli=left.begin();fli!=left.end();fli++){
xtest=((int)(fli->base/(SQUARE_SIZE)+fli->dir*y))/lod*lod-lod;
xtest2=((int)(fli->base/(SQUARE_SIZE)+fli->dir*(y+lod)))/lod*lod-lod;
if(xtest>xtest2)
xtest=xtest2;
if(xtest>xs)
xs=xtest;
}
for(fli=right.begin();fli!=right.end();fli++){
xtest=((int)(fli->base/(SQUARE_SIZE)+fli->dir*y))/lod*lod+lod;
xtest2=((int)(fli->base/(SQUARE_SIZE)+fli->dir*(y+lod)))/lod*lod+lod;
if(xtest<xtest2)
xtest=xtest2;
if(xtest<xe)
xe=xtest;
}
if(xs<xe){
x=xs;
if(x%(lod*2)){
DrawVertexA(x,y);
float h=((heightData[(y+lod)*heightDataX+x-lod]+heightData[(y+lod)*heightDataX+x+lod])*0.5f)*(1-camypart)+heightData[(y+lod)*heightDataX+x]*(camypart);
DrawVertexA(x,y+lod,h);
} else {
DrawVertexA(x,y);
DrawVertexA(x,y+lod);
}
for(x=xs;x<xe;x+=lod){
if(x%(lod*2)){
DrawVertexA(x+lod,y);
DrawVertexA(x+lod,y+lod);
} else {
DrawVertexA(x+lod,y);
float h=(heightData[(y+lod)*heightDataX+x+2*lod]+heightData[(y+lod)*heightDataX+x])*0.5f*(1-camypart)+heightData[(y+lod)*heightDataX+x+lod]*(camypart);
DrawVertexA(x+lod,y+lod,h);
}
}
EndStrip();
}
}
if(minly>minty && minly<maxty){
y=minly-lod;
int xs=max(xstart-lod,mintx);
int xe=min(xend+lod,maxtx);
int xtest,xtest2;
std::vector<fline>::iterator fli;
for(fli=left.begin();fli!=left.end();fli++){
xtest=((int)(fli->base/(SQUARE_SIZE)+fli->dir*y))/lod*lod-lod;
xtest2=((int)(fli->base/(SQUARE_SIZE)+fli->dir*(y+lod)))/lod*lod-lod;
if(xtest>xtest2)
xtest=xtest2;
if(xtest>xs)
xs=xtest;
}
for(fli=right.begin();fli!=right.end();fli++){
xtest=((int)(fli->base/(SQUARE_SIZE)+fli->dir*y))/lod*lod+lod;
xtest2=((int)(fli->base/(SQUARE_SIZE)+fli->dir*(y+lod)))/lod*lod+lod;
if(xtest<xtest2)
xtest=xtest2;
if(xtest<xe)
xe=xtest;
}
if(xs<xe){
x=xs;
if(x%(lod*2)){
float h=((heightData[(y)*heightDataX+x-lod]+heightData[(y)*heightDataX+x+lod])*0.5f)*(camypart)+heightData[(y)*heightDataX+x]*(1-camypart);
DrawVertexA(x,y,h);
DrawVertexA(x,y+lod);
} else {
DrawVertexA(x,y);
DrawVertexA(x,y+lod);
}
for(x=xs;x<xe;x+=lod){
if(x%(lod*2)){
DrawVertexA(x+lod,y);
DrawVertexA(x+lod,y+lod);
} else {
float h=(heightData[(y)*heightDataX+x+2*lod]+heightData[(y)*heightDataX+x])*0.5f*(camypart)+heightData[(y)*heightDataX+x+lod]*(1-camypart);
DrawVertexA(x+lod,y,h);
DrawVertexA(x+lod,y+lod);
}
}
EndStrip();
}
}
}
DrawGroundVertexArray();
}
}
ResetTextureUnits(drawWaterReflection,overrideVP);
glDisable(GL_CULL_FACE);

if (wireframe) {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

if(map->voidWater && !drawWater){
glDisable(GL_ALPHA_TEST);
}

if(map->hasWaterPlane)
{
glDisable(GL_TEXTURE_2D);
glColor3f(map->waterPlaneColor.x, map->waterPlaneColor.y, map->waterPlaneColor.z);
glBegin(GL_QUADS);//water color edge of map <0
if(!drawWaterReflection){
float xsize=gs->mapx*SQUARE_SIZE/4;
float ysize=gs->mapy*SQUARE_SIZE/4;
for(y=-4;y<8;++y)
for(int x=-4;x<8;++x)
if(x>3 || x<0 || y>3 || y<0 || camera->pos.x<0 || camera->pos.z<0 || camera->pos.x>float3::maxxpos || camera->pos.z>float3::maxzpos){
glVertex3f(x*xsize,-200,y*ysize);
glVertex3f((x+1)*xsize,-200,y*ysize);
glVertex3f((x+1)*xsize,-200,(y+1)*ysize);
glVertex3f(x*xsize,-200,(y+1)*ysize);
}
}
glEnd();
}

if(groundDecals && !(drawWaterReflection || drawUnitReflection))
groundDecals->Draw();

glEnable(GL_ALPHA_TEST);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

// sky->SetCloudShadow(1);
// if(drawWaterReflection)
// treeDistance*=0.5f;

ph->DrawGroundFlashes();
if(treeDrawer->drawTrees){
if(DrawExtraTex()){
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_ADD_SIGNED_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ALPHA_ARB,GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_ALPHA_ARB,GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_ALPHA_ARB,GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
glBindTexture(GL_TEXTURE_2D, infoTex);
SetTexGen(1.0f/(gs->pwr2mapx*SQUARE_SIZE),1.0f/(gs->pwr2mapy*SQUARE_SIZE),0,0);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
treeDrawer->Draw(drawWaterReflection || drawUnitReflection);
if(DrawExtraTex()){
glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
}

glDisable(GL_ALPHA_TEST);

glDisable(GL_TEXTURE_2D);
viewRadius=baseViewRadius;

}

又是一个吐血加头晕的方法, 其实这个方法的关键地方就是DrawVertexA()这个方法,这个方法有两个重载:

inline void CBFGroundDrawer::DrawVertexA(int x,int y)
{
float height=heightData[y*heightDataX+x];
if(drawWater && height<0){
height*=2;
}

va->AddVertex0(float3(x*SQUARE_SIZE,height,y*SQUARE_SIZE));
}

inline void CBFGroundDrawer::DrawVertexA(int x,int y,float height)
{
if(drawWater && height<0){
height*=2;
}
va->AddVertex0(float3(x*SQUARE_SIZE,height,y*SQUARE_SIZE));

}

画图的关键地方就是找出正确的x,y,height ,然后一点一点的画出来,我们再看va->AddVerterx0()这个方法

void CVertexArray::AddVertex0(const float3& pos)
{
if(drawIndex>drawArraySize-10)
EnlargeDrawArray();

drawArray[drawIndex++]=pos.x;
drawArray[drawIndex++]=pos.y;
drawArray[drawIndex++]=pos.z;
}

意思很明显,就是将x,y,z的坐标存入一个叫drawArray的数列之中。然后。。。。

void CVertexArray::DrawArray0(int drawType,int stride)
{
if(stripIndex==0 || stripArray[stripIndex-1]!=drawIndex)
EndStrip();
glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
glEnableClientState(GL_VERTEX_ARRAY);
int oldIndex=0;
for(int a=0;a<stripIndex;a++){
glDrawArrays(drawType,oldIndex*4/stride,stripArray[a]*4/stride-oldIndex*4/stride);
oldIndex=stripArray[a];
}
glDisableClientState(GL_VERTEX_ARRAY);

}

调用glDrawArrays将这些点画出来。

现在我们反过来考察,前面的传入x,y,z究竟是什么东西。大家现在可以回过头看我前面的注释。

*代码说明1--------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------

要了接left,和right的作用,我们要看看以下这两个方法

void CBFGroundDrawer::UpdateCamRestraints(void)
{
left.clear();
right.clear();

//Add restraints for camera sides
AddFrustumRestraint(cam2->bottom);
AddFrustumRestraint(cam2->top);
AddFrustumRestraint(cam2->rightside);
AddFrustumRestraint(cam2->leftside);

//Add restraint for maximum view distance
fline temp;
float3 up(0,1,0);
float3 side=cam2->forward;
float3 camHorizontal=cam2->forward;
camHorizontal.y=0;
camHorizontal.Normalize();
float3 b=up.cross(camHorizontal); //get vector for collision between frustum and horizontal plane
if(fabs(b.z)>0.0001f){
temp.dir=b.x/b.z; //set direction to that
float3 c=b.cross(camHorizontal); //get vector from camera to collision line
float3 colpoint; //a point on the collision line

if(side.y>0)
colpoint=cam2->pos+camHorizontal*gu->viewRange*1.05f-c*(cam2->pos.y/c.y);
else
colpoint=cam2->pos+camHorizontal*gu->viewRange*1.05f-c*((cam2->pos.y-255/3.5f)/c.y);


temp.base=colpoint.x-colpoint.z*temp.dir; //get intersection between colpoint and z axis
if(b.z>0){
left.push_back(temp);
}else{
right.push_back(temp);
}

}

}

void CBFGroundDrawer::AddFrustumRestraint(float3 side)
{
fline temp;
float3 up(0,1,0);

float3 b=up.cross(side); //get vector for collision between frustum and horizontal plane (计算side和y轴的垂线)
if(fabs(b.z)<0.0001f) fabs为取绝对值
b.z=0.0001f;
{
temp.dir=b.x/b.z; //set direction to that 计算向量方向值

float3 c=b.cross(side); //get vector from camera to collision line 这里其实是进行 (y1*z2-z1*y2,z1*x2-x1*z2,x1*y2-y1*x2) 这样的计算

这是什么意思?这是计算正交向量的意思(x1,y1,z1)(x2,y2,z2)计算他的垂直变量

float3 colpoint; //a point on the collision line

if(side.y>0)
colpoint=cam2->pos-c*((cam2->pos.y-(readmap->minheight-100))/c.y);
else
colpoint=cam2->pos-c*((cam2->pos.y-(readmap->maxheight+30))/c.y);


temp.base=colpoint.x-colpoint.z*temp.dir; //get intersection between colpoint and z axis 与Z轴的X方向的距离
if(b.z>0){
left.push_back(temp);
}else{
right.push_back(temp);
}
}

}

关键我们看 UpdateCamRestraints(void)这个方法,在这方法中一个temp的数据被添加left和right迭代器中。我们来考察得出temp的这一段算法

*代码说明1完--------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------


优质内容筛选与推荐>>
1、预测:2015年美国医疗保健市场五大变化
2、MySQL对CREATETABLEIFNOTEXISTSSELECT的处理
3、VMwarevSAN架构解析及存储策略
4、高效沟通的秘籍-沟通视窗
5、数据科学家可能成为2015年最热门职业


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号