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); } }