研发三维GIS系统笔记/实现wgs84投影-002
四叉树代码修改完善
原来的代码中,没有使用投影转换,直接使用的是世界坐标(单位是米),
CELLQuadTree::CELLQuadTree( CELLTerrainInterface* pInterface ,CELLQuadTree* parent ,const real2 vStart ,const real2 vEnd ,int level ,ChildId corner) { _terrain = pInterface; /// 这里使用y作为高度,因为如果是三维,后续初始化后应该使用高程数据填充
/// 初始化用0, _aabb.setExtents(vStart.x, 0, vStart.y, vEnd.x, 0, vEnd.y); real3 vXenter = _aabb.getCenter();
/// 这里计算经纬度,输入世界坐标转换成经纬度 real2 vLonLat = pInterface->spRef()->worldToLongLat(real2(vLonLat.x,vLonLat.z));
/// 调用接口根据经纬度计算出来瓦片的Id,加载瓦片会根据该id访问 网络/磁盘瓦片,例如 d:/data/vTileId.z/vTileId.x/vTileId.y.jpg int3 vTileId = pInterface->spRef()->getKey(level,vWorld.x,vWorld.y); _tileId._lev = level; _tileId._col = vTileId.x; _tileId._row = vTileId.y; _cornerId = corner; _parent = parent; _vStart = vStart; _vEnd = vEnd; _childs[0] = 0; _childs[1] = 0; _childs[2] = 0; _childs[3] = 0; _uvStart = float2(0.0f, 0.0f); _uvEnd = float2(1.0f, 1.0f); _terrain->getCounts()._nodes ++; _flag = 0; _flag &= ~FLAG_HAS_IMAGE;
/// 如果是没有父点,则说明是根节点,直接请求瓦片,不做处理 if (_parent == nullptr) { _terrain->request(this); return; }
/// 如果不是根节点,那么默认情况下是没有瓦片数据的,则使用父亲节点数据作为子节点的输入
/// 需要重新计算UV坐标,子节点的坐标应该是父节点的一半
float2 vHalf = (_parent->_uvEnd - _parent->_uvStart) * 0.5f; float2 vCenter = (_parent->_uvStart + _parent->_uvEnd) * 0.5f; _textureId = _parent->_textureId;
/// 不同的子节点,UV计算是不一样的 switch (corner) { case CHILD_LT: _uvStart = vCenter - float2(vHalf.x,0); _uvEnd = vCenter + float2(0,vHalf.y); break; case CHILD_RT: _uvStart = vCenter; _uvEnd = vCenter + vHalf; break; case CHILD_LB: _uvStart = vCenter - vHalf; _uvEnd = vCenter ; break; case CHILD_RB: _uvStart = vCenter - float2(0,vHalf.y); _uvEnd = vCenter + float2(vHalf.x,0); break; default: break; } if (_parent->hasFlag(FLAG_HAS_IMAGE)) { _flag |= FLAG_RENDER; }
/// 重点:引用父节点数据 _textureId = _parent->_textureId; _terrain->request(this); }
上图:
当一张瓦片被分裂成四张后,会存一个问题,瓦片是否有数据,默认情况下,使用父节点的书作为子节点输入
纹理坐标如下代码:
switch (corner) { case CHILD_LT: _uvStart = vCenter - float2(vHalf.x,0); _uvEnd = vCenter + float2(0,vHalf.y); break; case CHILD_RT: _uvStart = vCenter; _uvEnd = vCenter + vHalf; break; case CHILD_LB: _uvStart = vCenter - vHalf; _uvEnd = vCenter ; break; case CHILD_RB: _uvStart = vCenter - float2(0,vHalf.y); _uvEnd = vCenter + float2(vHalf.x,0); break; default: break; }
瓦片裂分流程代码:
1 vSize = _aabb.getHalfSize(); 2 _childs[CHILD_LT] = new CELLQuadTree( 3 _terrain 4 , this 5 ,real2(vCenter.x - vSize.x,vCenter.z) 6 ,real2(vCenter.x,vCenter.z + vSize.z) 7 ,(int)_tileId._lev + 1 8 ,CHILD_LT 9 ); 10 11 _childs[CHILD_RT] = new CELLQuadTree( 12 _terrain 13 ,this 14 , real2(vCenter.x, vCenter.z) 15 , real2(vCenter.x + vSize.x, vCenter.z + vSize.z) 16 , (int)_tileId._lev + 1 17 , CHILD_RT 18 ); 19 20 _childs[CHILD_LB] = new CELLQuadTree( 21 _terrain 22 , this 23 , real2(vCenter.x - vSize.x, vCenter.z - vSize.z) 24 , real2(vCenter.x, vCenter.z) 25 , (int)_tileId._lev + 1 26 , CHILD_LB 27 ); 28 _childs[CHILD_RB] = new CELLQuadTree( 29 _terrain 30 , this 31 , real2(vCenter.x, vCenter.z - vSize.z) 32 , real2(vCenter.x + vSize.x, vCenter.z) 33 , (int)_tileId._lev + 1 34 , CHILD_RB 35 );