我的DirectX 9地形引擎出了问题。它工作正常,除了一件事,它没有以正确的方式加载高度图。 您可以在此处查看问题的屏幕截图:alt text http://img682.imageshack.us/img682/240/problemc.png 正如你所看到的那样,整个地图都有一个对角线裂缝......应该镜像一面以正确渲染地图。
我几乎可以肯定问题不在文件中,因为其他程序似乎没有问题。
我正在以这种方式加载我的高度图(首先是类头):
class Terrain
{
public:
Terrain(const char* fileName);
~Terrain();
void Update(int x, int y);
void Render(LPDIRECT3DDEVICE9 Device);
private:
float* Data;
int Width;
int TileWidth;
bool isRendering;
bool isSwapping;
std::vector<Chunk*> RenderChunks;
};
和构造函数:
Terrain::Terrain(const char* fileName)
{
std::fstream File(fileName, std::ios::in | std::ios::binary);
File.seekg(0, std::ios::end);
int Length = File.tellg();
File.seekg(0, std::ios::beg);
int w = (int)sqrt((float)Length/4.0)-1;
Data = new float[Length / 4];
File.read((char*)Data, Length);
File.close();
Width = w;
int dataWidth = w+1;
TileWidth = w/16;
for (int y=0; y<TileWidth; y++)
{
for (int x=0; x<TileWidth; x++)
{
Chunk* c = new Chunk(x*16, y*16, 16, 512, Data);
RenderChunks.push_back(c);
}
}
}
每当我在高度图上调用高度时,我就像这样使用它:Data [x + y * dataWidth](只是通常的方式) Chunk类是一个只渲染高度图的一部分的类,因此细节随着到摄像机的距离的增加而减少。
所以我的问题是:什么可能导致我的问题?
编辑:渲染代码:
void Terrain::Render(LPDIRECT3DDEVICE9 Device)
{
for (unsigned int i=0; i<RenderChunks.size(); ++i)
{
RenderChunks[i]->Render(Device);
}
}
Chunk::Chunk(int cX, int cY, int cW, int dW, float* Data):
Pos(cX, 0, cY)
{
Heights = new float[(cW + 1) * (cW + 1)];
ParentH = Data;
ParentOffset = cX + cY*dW;
ParentW = dW;
Width = cW + 1;
for (int y=0; y<Width; ++y)
{
memcpy(Heights + y*Width, Data + cX + (y+cY)*dW, sizeof(float)*Width);
}
Vertices = NULL;
Calculate(16, 16, 16, 16, 16);
}
void Chunk::Calculate(int L, int lod_L, int lod_R, int lod_U, int lod_D)
{
Detail = L;
if (Vertices) delete[] Vertices;
Vertices = new Vertex[(Width-1)*(Width-1)*6/(L*L)];
Count = (Width-1)*(Width-1)*2/(L*L);
float Height = 100.0f;
for (int y=0; y<Width-1; y += L)
{
for (int x=0; x<Width-1; x += L)
{
Vertex* thisQuad = Vertices + (y/L)*((Width-1)/L)*6 + (x/L)*6;
float heights[4] = {
Heights[(x ) + (y )*Width] * Height,
Heights[(x ) + (y + L)*Width] * Height,
Heights[(x + L) + (y )*Width] * Height,
Heights[(x + L) + (y + L)*Width] * Height};
float bonus[8] = {
heights[0],
heights[2],
heights[0],
heights[2],
heights[1],
heights[3],
heights[1],
heights[3]};
if (Pos.z + y > 0)
{
bonus[0] = ParentH[((int)Pos.x + x ) + ((int)Pos.z + y - L)*ParentW] * Height;
bonus[1] = ParentH[((int)Pos.x + x + L) + ((int)Pos.z + y - L)*ParentW] * Height;
}
if (Pos.x + x > 0)
{
bonus[2] = ParentH[((int)Pos.x + x - L) + ((int)Pos.z + y )*ParentW] * Height;
bonus[4] = ParentH[((int)Pos.x + x - L) + ((int)Pos.z + y + L)*ParentW] * Height;
}
if (Pos.x + x < ParentW-L-L)
{
bonus[3] = ParentH[((int)Pos.x + x+L+L) + ((int)Pos.z + y )*ParentW] * Height;
bonus[5] = ParentH[((int)Pos.x + x+L+L) + ((int)Pos.z + y + L)*ParentW] * Height;
}
if (Pos.z + y < ParentW-L-L)
{
bonus[6] = ParentH[((int)Pos.x + x ) + ((int)Pos.z + y+L+L)*ParentW] * Height;
bonus[7] = ParentH[((int)Pos.x + x + L) + ((int)Pos.z + y+L+L)*ParentW] * Height;
}
if (x == 0 && lod_L>L)
{
heights[0] = lerp(
Heights[(x ) + (((y )/lod_L)*lod_L )*Width],
Heights[(x ) + (((y )/lod_L)*lod_L + lod_L)*Width],
(float)((y ) % lod_L) / (float)lod_L) * Height;
heights[1] = lerp(
Heights[(x ) + (((y + L)/lod_L)*lod_L )*Width],
Heights[(x ) + (((y + L)/lod_L)*lod_L + lod_L)*Width],
(float)((y+L) % lod_L) / (float)lod_L) * Height;
}
if (x >= Width-2 && lod_R>L)
{
heights[2] = lerp(
Heights[(x + L) + (((y )/lod_R)*lod_R )*Width],
Heights[(x + L) + (((y )/lod_R)*lod_R + lod_R)*Width],
(float)((y ) % lod_R) / (float)lod_R) * Height;
heights[3] = lerp(
Heights[(x + L) + (((y + L)/lod_R)*lod_R )*Width],
Heights[(x + L) + (((y + L)/lod_R)*lod_R + lod_R)*Width],
(float)((y+L) % lod_R) / (float)lod_R) * Height;
}//*/
if (y == 0 && lod_U>L)
{
heights[0] = lerp(
Heights[(((x )/lod_U)*lod_U ) + (y )*Width],
Heights[(((x )/lod_U)*lod_U + lod_U) + (y )*Width],
(float)((x ) % lod_U) / (float)lod_U) * Height;
heights[2] = lerp(
Heights[(((x + L)/lod_U)*lod_U ) + (y )*Width],
Heights[(((x + L)/lod_U)*lod_U + lod_U) + (y )*Width],
(float)((x+L) % lod_U) / (float)lod_U) * Height;
}
if (y >= Width-2 && lod_D>L)
{
heights[1] = lerp(
Heights[(((x )/lod_D)*lod_D ) + (y + L)*Width],
Heights[(((x )/lod_D)*lod_D + lod_D) + (y + L)*Width],
(float)((x ) % lod_D) / (float)lod_D) * Height;
heights[3] = lerp(
Heights[(((x + L)/lod_D)*lod_D ) + (y + L)*Width],
Heights[(((x + L)/lod_D)*lod_D + lod_D) + (y + L)*Width],
(float)((x+L) % lod_D) / (float)lod_D) * Height;
}//*/
D3DXVECTOR3 fake(0,0,0);
Vertex p1(D3DXVECTOR3(x, heights[0], y ) + Pos, CalcNormal(bonus[2], heights[2], bonus[0], heights[1]));
Vertex p2(D3DXVECTOR3(x, heights[1], y + L) + Pos, CalcNormal(bonus[4], heights[3], heights[0], bonus[6]));
Vertex p3(D3DXVECTOR3(x + L, heights[2], y ) + Pos, CalcNormal(heights[0], bonus[3], bonus[1], heights[3]));
Vertex p4(D3DXVECTOR3(x + L, heights[3], y + L) + Pos, CalcNormal(heights[1], bonus[5], heights[2], bonus[7]));
thisQuad[0] = p1;
thisQuad[1] = p2;
thisQuad[2] = p3;
thisQuad[3] = p3;
thisQuad[4] = p2;
thisQuad[5] = p4;
}
}
}
void Chunk::Render(LPDIRECT3DDEVICE9 Device)
{
Device->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL);
Device->DrawPrimitiveUP(
D3DPT_TRIANGLELIST,
Count,
Vertices,
sizeof(Vertex));
}
答案 0 :(得分:2)
我猜你的问题是你的块类需要一个宽度(cW),然后你将该值+ 1分配给宽度。我进一步假设cW是高度图中的纹素的数量(即,在1024x1024高度图中,cW是1024)。如果那是正确的,那么每个后续行添加1将向左偏移1.当你继续时,你会使问题变得更糟,所以通过512行,你将在左边512(或从纹理的中间开始)。这将为您提供您所看到的对角剪切。
答案 1 :(得分:0)
它看起来很像你构建三角形条带的顺序(或者你使用的是其他类型的原语?)有一个问题。你可以发布渲染循环的相关部分吗?
编辑:我的直觉是,当你镜像你的地形数据时,你会在对角线上创建十字交叉的几何体,因为地形四边形的角落(如果你想象的那样)正对角地连接到角落跨越而不是直接跨越。我希望一些DirectX /渲染大师可以根据您发布的代码为您提供更准确的答案。
答案 2 :(得分:0)
它似乎是一个“off by 1”错误,但是帖子说这似乎被某种方式删除了.. 无论如何,这是正确的解决方案。