예제 #1
0
void Cterrain::getBlocks(int jmin,int jmax,int imin,int imax,int curDepth)
{
    //检查当前节点是否与视截体相交--abc
    //求节点p所表示区域的保守包围盒--abc
    //    上面--abc
    //    p[0]--p[3]
    //     |     |
    //    p[1]--p[2]
    //    下面--abc
    //    p[4]--p[7]
    //     |     |
    //    p[5]--p[6]
    float xmin=m_range.getMinX()+gridSize*jmin;
    float xmax=m_range.getMinX()+gridSize*jmax;
    float zmin=m_range.getMinZ()+gridSize*imin;
    float zmax=m_range.getMinZ()+gridSize*imax;
    float ymin=m_range.getMinY();
    float ymax=m_range.getMaxY();
    float c[3]={(xmax+xmin)/2,(ymin+ymax)/2,(zmin+zmax)/2};
    float r=max(xmax-xmin,ymax-ymin)*0.86602540378443864676372317075294;//由于zmax-zmin与xmax-xmin相等,所以不用考虑--abc
    //看球体(c,r)是否都在planeList中某个面的反面,如果是则可剔除--abc
    bool visible=true;
    for(int i=0;i<5;i++){//不考虑远平面--abc
        const Cc3dPlane&plane=this->getMesh()->getSubMeshByIndex(0)->getCamera()->getFrustum().getPlaneByIndex(i);
        //看球体(c,r)是否在plane的背面--abc
        float PND=directedDistanceFromPointToPlane(plane, c);
        if(PND<-r){//如果在背面--abc
            //断定为不可见,不用再继续检测--abc
            visible=false;
            break;
        }
    }//得到visible
    if(visible){//如果可见--abc
        bool needDiv=false;//是否需要再分--abc
        //求needDiv
        if(imin+1==imax){//无须再分,因为已经无法再分--abc
            needDiv=false;
        }else{//进一步判断--abc
            //求c到视点的距离--abc
            float d2=square(this->getMesh()->getSubMeshByIndex(0)->getCamera()->getEyePos().x()-c[0])
         ///   +square(this->getMesh()->getSubMeshByIndex(0)->getCamera()->getEyePos().y()-c[1])
            +square(this->getMesh()->getSubMeshByIndex(0)->getCamera()->getEyePos().z()-c[2]);
            float e=xmax-xmin;//边长--abc
            if(d2<square(e*reso))needDiv=true;
        }//得到needDiv
        if(needDiv){//继续分--abc
            int imid=(imin+imax)>>1;//除2
            int jmid=(jmin+jmax)>>1;
            markmat[imid][jmid]=true;
            markedElementIndexList.push_back(Cij(imid,jmid));
            //对四个孩子继续递归--abc
            getBlocks(jmin,jmid,imin,imid,curDepth+1);
            getBlocks(jmin,jmid,imid,imax,curDepth+1);
            getBlocks(jmid,jmax,imid,imax,curDepth+1);
            getBlocks(jmid,jmax,imin,imid,curDepth+1);
        }else{//不分--abc
			CterrainBlock block(imin,imax,jmin,jmax);
			m_blockList.push_back(block);
   
        }
    }
void Cterrain::showAndMark(int jmin,int jmax,int imin,int imax,int curDepth)
{
    //检查当前节点是否与视截体相交
    //求节点p所表示区域的保守包围盒
    //    上面
    //    p[0]--p[3]
    //     |     |
    //    p[1]--p[2]
    //    下面
    //    p[4]--p[7]
    //     |     |
    //    p[5]--p[6]
    float xmin=m_range.getMinX()+gridSize*jmin;
    float xmax=m_range.getMinX()+gridSize*jmax;
    float zmin=m_range.getMinZ()+gridSize*imin;
    float zmax=m_range.getMinZ()+gridSize*imax;
    float ymin=m_range.getMinY();
    float ymax=m_range.getMaxY();
    float c[3]={(xmax+xmin)/2,(ymin+ymax)/2,(zmin+zmax)/2};
    float r=max(xmax-xmin,ymax-ymin)*0.86602540378443864676372317075294;//由于zmax-zmin与xmax-xmin相等,所以不用考虑
    //看球体(c,r)是否都在planeList中某个面的反面,如果是则可剔除
    bool visible=true;
    for(int i=0;i<5;i++){//不考虑远平面
        const Cc3dPlane&plane=this->getModel()->getMeshByIndex(0)->getCamera()->getFrustum().getPlaneByIndex(i);
        //看球体(c,r)是否在plane的背面
        float PND=directedDistanceFromPointToPlane(plane, c);
        if(PND<-r){//如果在背面
            //断定为不可见,不用再继续检测
            visible=false;
            break;
        }
    }//得到visible
    if(visible){//如果可见
        bool needDiv=false;//是否需要再分
        //求needDiv
        if(imin+1==imax){//无须再分,因为已经无法再分
            needDiv=false;
        }else{//进一步判断
            //求c到视点的距离
            //指数值越大,LOD效应越明显
            float d=square(this->getModel()->getMeshByIndex(0)->getCamera()->getEyePos().x()-c[0])
            +square(minf(0.6*(this->getModel()->getMeshByIndex(0)->getCamera()->getEyePos().y()-c[1]),700))//Y乘以一个比1小的系数是为了让LOD对高度变化不敏感
            +square(this->getModel()->getMeshByIndex(0)->getCamera()->getEyePos().z()-c[2]);
            float e=xmax-xmin;//边长
            if(d<e*reso)needDiv=true;
        }//得到needDiv
        if(needDiv){//继续分
            int imid=(imin+imax)>>1;//除2
            int jmid=(jmin+jmax)>>1;
            markmat[imid][jmid]=true;
            markedElementIndexList.push_back(Cij(imid,jmid));
            //对四个孩子继续递归
            showAndMark(jmin,jmid,imin,imid,curDepth+1);
            showAndMark(jmin,jmid,imid,imax,curDepth+1);
            showAndMark(jmid,jmax,imid,imax,curDepth+1);
            showAndMark(jmid,jmax,imin,imid,curDepth+1);
        }else{//不分
            const int vIDMat_imin=(int)markmat[0].size()*imin;//vIDMat[imin];
            const int vIDMat_imax=(int)markmat[0].size()*imax;//vIDMat[imax];
            const int ID0=vIDMat_imin+jmin;
            const int ID1=vIDMat_imax+jmin;
            const int ID2=vIDMat_imax+jmax;
            const int ID3=vIDMat_imin+jmax;
            this->getModel()->getMeshByIndex(0)->addIDtri(ID0, ID1, ID2);
            this->getModel()->getMeshByIndex(0)->addIDtri(ID0, ID2, ID3);
        }
    }