C++ OpenGL 地形生成
c++ OpenGL terrain generation
我正在尝试从顶点网格制作地形,但我有一个错误,只是找不到 it.Im 使用 C++ 坚持了 3 hours.Im 并且 opengl.Im 计划使用混合贴图和高度贴图 later.Anyway 这里是代码:
它应该是这样的:http://postimg.org/image/9431kcvy7/
外观如下:
http://postimg.org/image/xxsoesqkp/
如您所见,三角形由 1 个单位的矩形分隔,看起来所有底部点都形成一个三角形,该点的坐标为 (0,0,0)
我知道这个问题看起来很容易解决,但我已经浪费了 3 个小时 trying.Please 求助:)
Map.h
#ifndef MAP_H
#define MAP_H
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics.hpp>
#include <windows.h>
using namespace std;
struct coordinate{
float x,y,z;
};
struct face{
int v[3];
int n[3];
};
struct uv{
float x;
float y;
};
class Map
{
private:
int mapX,mapY;
vector<coordinate> vertex;
vector<uv>textureCoordinates;
vector<coordinate>normals;
vector< vector<face> > faces;
string fileNameString;
sf::Image image[5];
sf::Color faceColor,blendPixel,p0,p1,p2;
sf::Image texture;
sf::Uint8 pixels[256*256*4];
unsigned int imageID[3],textureID;
public:
void load(const char *fileName);
void draw();
};
#endif // MAP_H
和Map.cpp
#include "Map.h"
#define blendMap 3
#define heightMap 4
void Map::load(const char *fileName)
{
int i,j;
fileNameString=fileName;
vector<face> F;
coordinate v;
face f;
image[0].loadFromFile(fileNameString+"/0.png");
image[1].loadFromFile(fileNameString+"/1.png");
image[2].loadFromFile(fileNameString+"/2.png");
image[blendMap].loadFromFile(fileNameString+"/blendMap.png");
image[heightMap].loadFromFile(fileNameString+"/heightMap.png");
mapX=image[blendMap].getSize().x;
mapY=image[blendMap].getSize().y;
for(i=-mapY/2;i<mapY/2;i++)
for(j=-mapX/2;j<mapX/2;j++)
{
v.x=j*0.5;
v.z=i*0.5;
vertex.push_back(v);
}
for(i=0;i<mapY-1;i++)
{
for(j=0;j<2*(mapX-1);j++)
F.push_back(f);
faces.push_back(F);
}
for(i=0;i<mapY-1;i++)
for(j=0;j<(mapX-1)*2;j+=2)
{
faces[i][j].v[0]=i*mapX+j;
faces[i][j].v[1]=i*mapX+j+1;
faces[i][j].v[2]=(i+1)*mapX+j;
faces[i][j+1].v[0]=i*mapX+j+1;
faces[i][j+1].v[1]=(i+1)*mapX+j+1;
faces[i][j+1].v[2]=(i+1)*mapX+j;
}
for(i=0;i<mapX*mapY;i++)
{
color=image[heightMap].getPixel(i/mapX,i%mapX);
vertex[i].y=0;//(float)color.r/25.5-10;
}
}
void Map::draw()
{
unsigned int i,j;
for(i=0;i<mapY-1;i++)
for(j=0;j<(mapX-1)*2;j+=2)
{
glBindTexture(GL_TEXTURE_2D,imageID[0]);
glBegin(GL_TRIANGLES);
glTexCoord2f (0,0);
glVertex3f(vertex[faces[i][j].v[0]].x , vertex[faces[i][j].v[0]].y , vertex[faces[i][j].v[0]].z);
glTexCoord2f (1,0);
glVertex3f(vertex[faces[i][j].v[1]].x , vertex[faces[i][j].v[1]].y , vertex[faces[i][j].v[1]].z);
glTexCoord2f (0,1);
glVertex3f(vertex[faces[i][j].v[2]].x , vertex[faces[i][j].v[2]].y , vertex[faces[i][j].v[2]].z);
glTexCoord2f (0,0);
glVertex3f(vertex[faces[i][j+1].v[0]].x , vertex[faces[i][j+1].v[0]].y , vertex[faces[i][j+1].v[0]].z);
glTexCoord2f (1,0);
glVertex3f(vertex[faces[i][j+1].v[1]].x , vertex[faces[i][j+1].v[1]].y , vertex[faces[i][j+1].v[1]].z);
glTexCoord2f (0,1);
glVertex3f(vertex[faces[i][j+1].v[2]].x , vertex[faces[i][j+1].v[2]].y , vertex[faces[i][j+1].v[2]].z);
glEnd();
}
}
一些事情:
for(i=-mapY/2;i<mapY/2;i++)
这很危险,而且可能不是循环的意图。你想循环 mapY
次。但是,如果 mapY
是奇数,您将只循环 mapY - 1
次。例如。如果 mapY = 3
,则 -mapY / 2 = -1; mapY / 2 = 1
。因此,您将使用值 -1
和 0
进行循环。这是第一个问题,它会导致缓冲区中的顶点太少(这可能是主要问题)。而是在坐标级别上进行移动:
for(i = 0; i < mapY; i++)
for(j = 0; j < mapX; j++)
{
v.x = j * 0.5 - mapY / 2.0;
v.z = i * 0.5 - mapX / 2.0;
vertex.push_back(v);
}
你用 vector<vector<...>>
作为面孔有什么原因吗?正如您已经注意到的那样,它会给您带来关于索引的各种问题。只需使用 vector<Face>
并将您所有的面孔都放在那里。通常,您创建此结构一次,就再也不会碰它了。所以二维索引可能不是必需的。如果你想继续使用 2D 索引,这个循环有错误的边界:
for(j=0;j<(mapX-1)*2;j+=2)
这个上限是一个包含边界。因此,使用
for(j = 0; j <= (mapX - 1) * 2; j += 2)
我正在尝试从顶点网格制作地形,但我有一个错误,只是找不到 it.Im 使用 C++ 坚持了 3 hours.Im 并且 opengl.Im 计划使用混合贴图和高度贴图 later.Anyway 这里是代码:
它应该是这样的:http://postimg.org/image/9431kcvy7/
外观如下: http://postimg.org/image/xxsoesqkp/
如您所见,三角形由 1 个单位的矩形分隔,看起来所有底部点都形成一个三角形,该点的坐标为 (0,0,0)
我知道这个问题看起来很容易解决,但我已经浪费了 3 个小时 trying.Please 求助:)
Map.h
#ifndef MAP_H
#define MAP_H
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics.hpp>
#include <windows.h>
using namespace std;
struct coordinate{
float x,y,z;
};
struct face{
int v[3];
int n[3];
};
struct uv{
float x;
float y;
};
class Map
{
private:
int mapX,mapY;
vector<coordinate> vertex;
vector<uv>textureCoordinates;
vector<coordinate>normals;
vector< vector<face> > faces;
string fileNameString;
sf::Image image[5];
sf::Color faceColor,blendPixel,p0,p1,p2;
sf::Image texture;
sf::Uint8 pixels[256*256*4];
unsigned int imageID[3],textureID;
public:
void load(const char *fileName);
void draw();
};
#endif // MAP_H
和Map.cpp
#include "Map.h"
#define blendMap 3
#define heightMap 4
void Map::load(const char *fileName)
{
int i,j;
fileNameString=fileName;
vector<face> F;
coordinate v;
face f;
image[0].loadFromFile(fileNameString+"/0.png");
image[1].loadFromFile(fileNameString+"/1.png");
image[2].loadFromFile(fileNameString+"/2.png");
image[blendMap].loadFromFile(fileNameString+"/blendMap.png");
image[heightMap].loadFromFile(fileNameString+"/heightMap.png");
mapX=image[blendMap].getSize().x;
mapY=image[blendMap].getSize().y;
for(i=-mapY/2;i<mapY/2;i++)
for(j=-mapX/2;j<mapX/2;j++)
{
v.x=j*0.5;
v.z=i*0.5;
vertex.push_back(v);
}
for(i=0;i<mapY-1;i++)
{
for(j=0;j<2*(mapX-1);j++)
F.push_back(f);
faces.push_back(F);
}
for(i=0;i<mapY-1;i++)
for(j=0;j<(mapX-1)*2;j+=2)
{
faces[i][j].v[0]=i*mapX+j;
faces[i][j].v[1]=i*mapX+j+1;
faces[i][j].v[2]=(i+1)*mapX+j;
faces[i][j+1].v[0]=i*mapX+j+1;
faces[i][j+1].v[1]=(i+1)*mapX+j+1;
faces[i][j+1].v[2]=(i+1)*mapX+j;
}
for(i=0;i<mapX*mapY;i++)
{
color=image[heightMap].getPixel(i/mapX,i%mapX);
vertex[i].y=0;//(float)color.r/25.5-10;
}
}
void Map::draw()
{
unsigned int i,j;
for(i=0;i<mapY-1;i++)
for(j=0;j<(mapX-1)*2;j+=2)
{
glBindTexture(GL_TEXTURE_2D,imageID[0]);
glBegin(GL_TRIANGLES);
glTexCoord2f (0,0);
glVertex3f(vertex[faces[i][j].v[0]].x , vertex[faces[i][j].v[0]].y , vertex[faces[i][j].v[0]].z);
glTexCoord2f (1,0);
glVertex3f(vertex[faces[i][j].v[1]].x , vertex[faces[i][j].v[1]].y , vertex[faces[i][j].v[1]].z);
glTexCoord2f (0,1);
glVertex3f(vertex[faces[i][j].v[2]].x , vertex[faces[i][j].v[2]].y , vertex[faces[i][j].v[2]].z);
glTexCoord2f (0,0);
glVertex3f(vertex[faces[i][j+1].v[0]].x , vertex[faces[i][j+1].v[0]].y , vertex[faces[i][j+1].v[0]].z);
glTexCoord2f (1,0);
glVertex3f(vertex[faces[i][j+1].v[1]].x , vertex[faces[i][j+1].v[1]].y , vertex[faces[i][j+1].v[1]].z);
glTexCoord2f (0,1);
glVertex3f(vertex[faces[i][j+1].v[2]].x , vertex[faces[i][j+1].v[2]].y , vertex[faces[i][j+1].v[2]].z);
glEnd();
}
}
一些事情:
for(i=-mapY/2;i<mapY/2;i++)
这很危险,而且可能不是循环的意图。你想循环 mapY
次。但是,如果 mapY
是奇数,您将只循环 mapY - 1
次。例如。如果 mapY = 3
,则 -mapY / 2 = -1; mapY / 2 = 1
。因此,您将使用值 -1
和 0
进行循环。这是第一个问题,它会导致缓冲区中的顶点太少(这可能是主要问题)。而是在坐标级别上进行移动:
for(i = 0; i < mapY; i++)
for(j = 0; j < mapX; j++)
{
v.x = j * 0.5 - mapY / 2.0;
v.z = i * 0.5 - mapX / 2.0;
vertex.push_back(v);
}
你用 vector<vector<...>>
作为面孔有什么原因吗?正如您已经注意到的那样,它会给您带来关于索引的各种问题。只需使用 vector<Face>
并将您所有的面孔都放在那里。通常,您创建此结构一次,就再也不会碰它了。所以二维索引可能不是必需的。如果你想继续使用 2D 索引,这个循环有错误的边界:
for(j=0;j<(mapX-1)*2;j+=2)
这个上限是一个包含边界。因此,使用
for(j = 0; j <= (mapX - 1) * 2; j += 2)