//render height out
if (App::get()->clearMouseButtonState(App::BUTTON_LEFT))
{
Vec3 pos = Game::get()->getPlayer()->getWorldPosition();
vec3 dir = Game::get()->getPlayer()->getDirectionFromScreen();//拿到方向
double zfar = Game::get()->getPlayer()->getZFar();//拿到相机渲染的最长长度
Vec3 outPos;
GlobalPivot::get()->getIntersection(pos, pos + Vec3(dir)*zfar, outPos);//GlobalPivot是自定义的类,封装了geopivot对象和globalterrain对象,获取到与地形相交的点位置
Vec3 flatPos = GlobalPivot::get()->mapToFlat(translate(outPos));//将位置转为平铺坐标,这里有三种坐标请看其他博客
float size = GlobalPivot::get()->getHeightTileSize();
ivec2 c = ivec2((int)Math::floor(flatPos.x / size), (int)Math::floor((flatPos.y / size)));
worldPos = outPos;
if (coord != c) {
coords.clear();
coord = c;
GlobalPivot::get()->getTerrainHeightImage(c, timg);
flatPos.x = c.x*size;
flatPos.y = c.y*size;
flatPos.z = timg->get2D(0, 0).f.r;
for (int i = 0; i < 128; i++)
{
for (int j = 0; j < 128; j++)
{
GlobalPivot::get()->getWorldPos(Vec3(flatPos.x + i/128.0*size, flatPos.y + j / 128.0*size, timg->get2D(i, j).f.r), pos);
coords.append(pos);
}
}
}
}
for (int i = 0; i < coords.size(); i++)
{
Visualizer::get()->renderSphere(1, translate(coords[i]), vec4(1, 0, 0, 1));
}
ObjectTerrainGlobal是由如下几部分组装的:
virtual Ptr<TerrainGlobalLods> getHeightLods() = 0;
virtual Ptr<TerrainGlobalLods> getAlbedoLods() = 0;
virtual Ptr<TerrainGlobalLods> getNormalLods() = 0;
virtual Ptr<TerrainGlobalLods> getMaskLods() = 0;
每部分数据有多个lod
virtual const char *getName() const = 0;
virtual int getType() const = 0;
virtual int getDataType() const = 0;
virtual int getDataFormat() const = 0;
virtual int getMaskFormat() const = 0;
virtual void setNumLayers(int layers) = 0;
virtual int getNumLayers() const = 0;
virtual int getNumLods() const = 0;
virtual Ptr<TerrainGlobalLod> getLod(int num) const = 0;
virtual int addLod() = 0;
virtual void insertLod(int num) = 0;
virtual void removeLod(int num) = 0;
virtual void clearLods() = 0;
virtual String getVideoMemoryUsage() const = 0;
virtual int fetch(const BoundSphere & bs, const BoundBox & bb, int force = 0) = 0;
virtual int fetchData(double x, double y, Image::Pixel &ret_pixel, int layer, bool force) = 0;
每一个lof可以获取tileset(记录了地形的原始数据)
virtual Ptr<TerrainGlobalLod> getTerrainGlobalLod() const = 0;
virtual void setEnabled(int enabled) = 0;
virtual int isEnabled() const = 0;
virtual Ptr<Tileset> getTileset() const = 0;
virtual void setPath(const char *path) = 0;
virtual const char *getPath() const = 0;
virtual int renamePath(const char *new_path) = 0;
virtual void setTileDensity(float density) = 0;
virtual float getTileDensity() const = 0;
virtual void setViewportMask(int mask) = 0;
virtual int getViewportMask() const = 0;
virtual void setVisibleDistance(float distance) = 0;
virtual float getVisibleDistance() const = 0;
virtual void setLoadDistance(float distance) = 0;
virtual float getLoadDistance() const = 0;
virtual void setClearDistance(float distance) = 0;
virtual float getClearDistance() const = 0;
virtual void reload() = 0;
ObjectTerrainGlobalPtr terrain = ObjectTerrainGlobal::cast(Editor::get()->getNodeByName("Landscape"));
Vec3 rp;
vec3 normal, up;
terrain->fetchTopologyData(0, 0, rp, normal, up);
TilesetPtr tile = terrain->getHeightLods()->getLod(0)->getTileset();
float size = tile->getTileSize();//一张图像描述的大小,米为单位
int re = tile->getTileResolution();//图像的分辨率 一般是128
Vec2 p = tile->getTileFlatPosition(ivec2(0, 0));//获取该坐标为0,0的图像0,0的flat坐标
int t = tile->hasTile(ivec2(10, 10));
p = tile->getTileFlatPosition(ivec2(10, 10));
t = tile->hasTile(ivec2(128, 129));
p = tile->getTileFlatPosition(ivec2(128,129));
for (int i = 0; i < terrain->getAlbedoLods()->getNumLods(); i++)
{
tile = terrain->getAlbedoLods()->getLod(i)->getTileset();
size = tile->getTileSize();
re = tile->getTileResolution();
float d = terrain->getAlbedoLods()->getLod(i)->getVisibleDistance();
float de = terrain->getAlbedoLods()->getLod(i)->getTileDensity();
Log::message("%f,%d,%f,%f,%f\n", size, re,d,de,size/re);
}
Log::message("h:\n");
for (int i = 0; i < terrain->getHeightLods()->getNumLods(); i++)
{
tile = terrain->getHeightLods()->getLod(i)->getTileset();
size = tile->getTileSize();
re = tile->getTileResolution();
float d = terrain->getHeightLods()->getLod(i)->getVisibleDistance();
float de = terrain->getHeightLods()->getLod(i)->getTileDensity(); //密度,等于size/re
Log::message("%f,%d,%f,%f,%f\n", size, re, d, de, size / re);
}
ObjectTerrainGlobalPtr terrain = ObjectTerrainGlobal::cast(Editor::get()->getNodeByName("Landscape"));
testPos = terrain->getWorldPosition();
TilesetPtr tiles = terrain->getHeightLods()->getLod(0)->getTileset();
ImagePtr data = Image::create();
tiles->getTileData(ivec2(0, 0),data,1);
Vec3 wpos;
vec3 normal, up;
terrain->fetchTopologyData(0, 0, wpos, normal, up,1); //从terrian pos
GlobalPivot::get()->getWorldPos(wpos, testPos1);
terrain->fetchTopologyData(0, 10, wpos, normal, up, 1);
GlobalPivot::get()->getWorldPos(wpos, testPos2);
terrain->fetchTopologyData(10, 0, wpos, normal, up, 1);
GlobalPivot::get()->getWorldPos(wpos, testPos3);
Image::Pixel p = data->get2D(0, 0);
Log::message("r:%f\n", p.f.r);
testPos.z = p.f.r; //set the pos
tiles->setTileData(ivec2(0,0),timg); //当镜头转向后可能会被替换回来。
tiles->setLifeTime(ivec2(0, 0),10000 );//设置完后立马设置时间
int count = 0;
int ii = 0, jj=0; //获取tile的数量
for (int i = 0;; i++) //
{
bool havedata = false;
for (int j = 0;; j++)
{
if (tile->hasTile(ivec2(i, j)))
{
count++;
havedata = true;
}
else
{
if (jj < j) jj = j;
break;
}
}
if (!havedata)
{
if(ii<i) ii = i;
break;
}
}
count = ii*2*jj*2; //coordinate index range(-ii ~ ii , -jj ~ jj)
float size = tile->getTileSize(); //一张图片表示的实际大小
int re = tile->getTileResolution();//一张图片的分辨率
Vec2 p = tile->getTileFlatPosition(ivec2(0, 0)); //从纹理坐标转flat坐标
tile->getTileData(ivec2(10, 10), img); //获取tile,ivec需有效
Vec2 size = GlobalPivot::get()->getTSize();//(5786.2423553466797*2, 6453.8857040405273*2) //terrainsize
ivec2 isize = GlobalPivot::get()->getSize(); //(78*2,87*2) //terrain tilecount
Vec3 pos;
vec3 up, normal;
double t = Timer::getFloatTime();
for (int i = 0; i < 1000; i++) //time cost
{
//terrain->fetchTopologyData(Game::get()->getRandomDouble(-size.x, size.x), Game::get()->getRandomDouble(-size.y, size.y), pos, normal, up, 1); //1.64~2s
//terrain->fetchTopologyData(Game::get()->getRandomDouble(-1,1), Game::get()->getRandomDouble(-1,1),pos,normal,up,1);// 16~18 ms
terrain->fetchTopologyData(Game::get()->getRandomDouble(-100, 100), Game::get()->getRandomDouble(-100, 100), pos, normal, up, 1); //16~18ms
}
t = Timer::getFloatTime() - t;
地形坐标系与实际经纬度对齐问题
2.7.3中地形坐标系默认是在地形中心无高程的位置。从上面可以看出其tile的分布。如果没有高程数据也不使用geopivot,
那么地形中心刚好是地形坐标系的中心。加上高程后。会取对应位置的高程的高度,地形的坐标系位置在高度上也会偏离这个距离。
所以如果需要让现实坐标与场景的geodetic坐标对齐:首先让地形坐标系与pivot节点在同一个位置,找到地形中心对应的经纬度值,
设置geopivotaltitude 为地形中心点altitude 的负值。