高度图的正态平均
Normal averaging of heightmap
本文关键字:高度 更新时间:2023-10-16
我有以下代码来计算高度贴图法线
void CalcMapNormals(HeightMap * map, Vec3f normals[])
{
int dst, i, j, right, bottom;
Vec3f p0, p1, p2;
Vec3f n0;
/* Avoid writing map->rows|cols - 1 all the time */
right = map->cols - 1;
bottom = map->rows - 1;
dst = 0;
for (i = 0; i < map->rows; i++) {
for (j = 0; j < map->cols; j++) {
Vec3Set(normals[dst], 0, 0, 0);
/* Vertex can have 2, 3, or 4 neighbours horizontally and vertically */
if (i < bottom && j < right) {
/* Right and below */
GetHeightPoint(map, i, j, p0);
GetHeightPoint(map, i + 1, j, p1);
GetHeightPoint(map, i + 1, j + 1, p2);
CalcTriNormal(n0, p0, p1, p2);
VecAdd(normals[dst], normals[dst], n0);
}
/* TODO: the other three possibilities */
VecNormalize(normals[dst]);
dst += 1;
}
}
/* Sanity check */
if (dst != map->rows * map->cols)
Fail("Internal error in CalcMapNormals: normals count mismatch");
}
我知道代码获取三角形的三个顶点,计算其法线,然后将它们相加并规范化它们以获得平均正态。但我不知道你如何获得其他三种可能性,我一直在做如下的事情:
void CalcMapNormals(HeightMap * map, Vec3f normals[])
{
int dst, i, j, right, bottom;
Vec3f p0, p1, p2;
Vec3f n0;
Vec3f p3, p4, p5;
Vec3f n1;
Vec3f p6, p7, p8;
Vec3f n2;
Vec3f p9, p10, p11;
Vec3f n3;
/* Avoid writing map->rows|cols - 1 all the time */
right = map->cols - 1;
bottom = map->rows - 1;
dst = 0;
for (i = 0; i < map->rows; i++) {
for (j = 0; j < map->cols; j++) {
Vec3Set(normals[dst], 0, 0, 0);
/* Vertex can have 2, 3, or 4 neighbours horizontally and vertically */
if (i < bottom && j < right) {
/* Right and below */
GetHeightPoint(map, i, j, p0);
GetHeightPoint(map, i + 1, j, p1);
GetHeightPoint(map, i + 1, j + 1, p2);
CalcTriNormal(n0, p0, p1, p2);
VecAdd(normals[dst], normals[dst], n0);
}
if ( i > bottom && j > 0)
{
GetHeightPoint(map, i, j, p3);
GetHeightPoint(map, i + 1, j, p4);
GetHeightPoint(map, i, j -1, p5);
CalcTriNormal(n1, p3, p4, p5);
VecAdd(normals[dst], normals[dst], n1);
}
if ( i > 0 && j > 0)
{
GetHeightPoint(map, i, j, p6);
GetHeightPoint(map, i, j - 1, p7);
GetHeightPoint(map, i - 1, j, p8);
CalcTriNormal(n2, p6, p7, p8);
VecAdd(normals[dst], normals[dst], n2);
}
if ( i > bottom && j < right)
{
GetHeightPoint(map, i, j, p9);
GetHeightPoint(map, i-1, j, p10);
GetHeightPoint(map, i, j+1, p11);
CalcTriNormal(n3, p9, p10, p11);
VecAdd(normals[dst], normals[dst], n3);
}
/* TODO: the other three possibilities */
VecNormalize(normals[dst]);
dst += 1;
}
}
/* Sanity check */
if (dst != map->rows * map->cols)
Fail("Internal error in CalcMapNormals: normals count mismatch");
}
但我不认为它给了我想要的结果,我得到了正态平均的概念,但无法弄清楚代码。
嗨,
Yzwboy 这是我尝试制作"平滑"法线(基于相邻三角形平均)的一种方法:
为了计算"平滑"法线,您需要为每个顶点分配一个法线,该法线在与顶点相邻的三角形的法线上取平均值。
我会根据与所讨论的顶点相邻的两条边之间的角度计算加权平均值(交叉乘积,这是一个简单的计算):
伪代码:
Vec3F faceNormal(int face_id, int vertex_id) // assumes C-->B-->A is clockwise
{
Vec3f A = triangleMesh.face[face_id].vertex[vertex_id]; // A
Vec3f B = triangleMesh.face[face_id].vertex[(vertex_id+1)%3]; // B
Vec3f C = triangleMesh.face[face_id].vertex[(vertex_id+2)%3]; // C
Vec3f BA = B-A;
Vec3f CA = C-A;
Vec3f Normal = BA.cross(CA);
float sin_alpha = length(Normal) / (BA.len() * CA.len() ); // depending on your implementation of Vec3f it could be .magnitude() or .length() instead of .len()
return (Normal.normalize() * asin(sin_alpha);)
}
然后通过顶点改变法线:
void computeNormals() {
for (vertex v in triangleMesh)
{
Vec3f Normal (0,0,0);
for (int i = 0;i < TriangleCount;i++)
if (triangleMesh.face[i].contains(v) )
{
int vertID = vertexPositionInTriangle(i,v); //Can be 0,1 or 2. Use an enum to make A = 0, B=1, C=2 if that is easier to read:)
Normal = Normal + faceNormal(i,vertID);
}
addNormalToVertexV(Normal.normalize(),v); // this is a function to set the normal for a vertex, the vertex class must have a member for normal though and the arguments for the function are Vec3f, Vec3f
}
}
您还可以计算每个三角形的面积以用作权重,尽管我发现大多数时候使用角度最适合外观。
我尝试使用与 Vec3f 规范匹配的名称以及内置函数来保存工作,但您需要进行一些编码才能使伪代码正常工作(我无法访问这里的 GL 测试环境)。
希望这对:)有所帮助
相关文章:
- C++:如何根据地形高度更新玩家身高?
- 如何更改QComboBox项目的高度大小?
- 更改高度贴图,使其在 4x4 网格上显示 16 个 hieghtmap
- 我试图用这段代码找到二叉树的高度,但它一直返回 0,有人可以告诉我为什么吗?
- C++:如何计算二叉树中其值模块高度小于 2 的节点数?
- 如何使用 C++ gdal 库将栅格地理从 EGM96 转换为 WGS84 椭球体高度基准面
- 从具有父指针和左子树和右子树高度的树中删除
- 程序输入名称和高度并显示它。我不知道如何显示列表中最高人的姓名和身高
- 我正在尝试创建一个 C++ 贪吃蛇游戏,但我似乎无法绘制第二个高度边框,我该如何解决这个问题?
- 计算树高度的函数
- 尝试创建一个程序来查找非二叉树的高度.最终得到一个很长的循环,没有答案
- 计算BST返回-1的高度混淆
- 使用递归计算一个函数中的高度和大小
- 如何从2D数组为QHeightMapSurfaceDataProxy创建高度图以显示2D傅立叶变换结果
- 接受来自键盘的树节点以确定其高度
- 在 C++ 中使用平展数组语法,崩溃取决于宽度/高度
- 在一行中初始化指针(新uint8_t[高度*宽度*3])
- 在高度模板化的库中进行代码混淆
- ID3DXFont :文本被拉伸,如何获取字体的宽度和高度?
- C ,二进制树的高度,而不是检查我的子树是否为空,而是在检查我的子树是否是叶子节点.抛出分割故障