具有平均法线的高度场
Posted
技术标签:
【中文标题】具有平均法线的高度场【英文标题】:Height Field with average normals 【发布时间】:2020-10-22 13:35:13 【问题描述】:我正在创建高度场并且我想创建它的法线(面/顶点),我正在使用三角形来创建网格。我已经计算了 GL 四边形法线,但在这里混淆了三角形而不是四边形。 我搜索了互联网,发现存在两种类型的法线,例如每个面和每个顶点,但没有找到任何与我的代码相关的帮助。 这是我现在正在做的创建高度场。
int average_normal()
glPushMatrix();
GLfloat xdelta=xsize/xsteps;
GLfloat zdelta=zsize/zsteps;
glNormal3f(0,1,0);
for (int x=0; x<xsteps-1; x++)
for (int z=0; z<zsteps-1; z++)
glBegin(GL_TRIANGLES);
setMaterialHeight(map[x][z]);
glNormal3f(0, 0, 1);
glVertex3f(xdelta*x,map[x][z],zdelta*z);
setMaterialHeight(map[x+1][z]);
glNormal3f(0, 0, 1);
glVertex3f(xdelta*x+xdelta,map[x+1][z],zdelta*z);
setMaterialHeight(map[x][z+1]);
glNormal3f(0, 0, 1);
glVertex3f(xdelta*x,map[x][z+1],zdelta*z+zdelta);
glEnd();
glBegin(GL_TRIANGLES);
setMaterialHeight(map[x+1][z+1]);
glNormal3f(0, 0, 1);
glVertex3f(xdelta*x+xdelta,map[x+1][z+1],zdelta*z+zdelta);
setMaterialHeight(map[x][z+1]);
glNormal3f(0, 0, 1);
glVertex3f(xdelta*x,map[x][z+1],zdelta*z+zdelta);
setMaterialHeight(map[x+1][z]);
glNormal3f(0, 0, 1);
glVertex3f(xdelta*x+xdelta,map[x+1][z],zdelta*z);
glEnd();
glPopMatrix();
return true;
如何计算它的法线?
【问题讨论】:
【参考方案1】:法线向量可以通过2个向量的Cross product来计算。创建一个函数,计算叉积并设置法线向量属性:
void set_normal_from_cross_product(
float x1, float y1, float z1,
float x2, float y2, float z2)
float nx = y1*z2 - z1*y2;
float ny = z1*x2 - x1*z2;
float nz = x1*y2 - y1*x2;
float len = sqrt(nx*nx + ny*ny + nz*nz);
if (len != 0.0f)
glNormal3f(nx/len, ny/len, nz/len);
在网格中,法线向量可以通过相邻顶点之间的向量来计算。编写函数计算相邻顶点之间的向量并调用set_normal_from_cross_product
:
void set_grid_normal(int x, int z)
int prev_x = x > 0 ? x - 1 : x;
int next_x = x < xsteps - 1 ? x + 1 : x;
int prev_z = z > 0 ? z - 1 : z;
int next_z = z < zsteps - 1 ? z + 1 : z;
set_normal_from_cross_product(
xdelta * 2, map[next_x][z]-map[prev_x][z], 0,
0, map[x][next_z]-map[x][prev_z], zdelta * 2);
使用函数设置法向量:
void set_attributes(int x, int z)
setMaterialHeight(map[x][z]);
set_grid_normal(x, z);
glVertex3f(xdelta*x,map[x][z],zdelta*z);
for (int x=0; x<xsteps-1; x++)
for (int z=0; z<zsteps-1; z++)
glBegin(GL_TRIANGLES);
set_attributes(x, z);
set_attributes(x+1, z);
set_attributes(x, z+1);
glEnd();
glBegin(GL_TRIANGLES);
set_attributes(x+1, z+1);
set_attributes(x, z+1);
set_attributes(x+1, z);
glEnd();
【讨论】:
什么是 prev_x_z ?没有定义? 明白了!!!但是当我按下按键时什么都没有显示:( @Struggler 可能法线向量必须反转glNormal3f(-nx/len, -ny/len, -nz/len)
。
让我们continue this discussion in chat。
@Struggler 我的代码中的另一个错字:sqrt(nx*nx + ny*ny * nz*nz)
-> sqrt(nx*nx + ny*ny + nz*nz)
以上是关于具有平均法线的高度场的主要内容,如果未能解决你的问题,请参考以下文章