标签: normals

计算三角形网格中的法线

我画了一个有10000个顶点(100x100)的三角形网格,它将是一个草地.我使用了gldrawelements().我看了一整天,仍然无法理解如何计算这个法线.每个顶点是否有自己的法线或每个三角形都有自己的法线?有人能指出我正确的方向如何编辑我的代码以合并法线?

struct vertices {
    GLfloat x;
    GLfloat y;
    GLfloat z;
}vertices[10000];

GLuint indices[60000];

/*
99..9999
98..9998
........
01..9901
00..9900
*/

void CreateEnvironment() {
    int count=0;
    for (float x=0;x<10.0;x+=.1) {
        for (float z=0;z<10.0;z+=.1) {
            vertices[count].x=x;
            vertices[count].y=0;
            vertices[count].z=z;
            count++;
        }
    }
    count=0;
    for (GLuint a=0;a<99;a++){
        for (GLuint b=0;b<99;b++){
            GLuint v1=(a*100)+b;indices[count]=v1;count++;
            GLuint v2=(a*100)+b+1;indices[count]=v2;count++;
            GLuint v3=(a*100)+b+100;indices[count]=v3;count++;
        }
    }
    count=30000;
    for (GLuint a=0;a<99;a++){
        for (GLuint b=0;b<99;b++){
            indices[count]=(a*100)+b+100;count++;//9998
            indices[count]=(a*100)+b+1;count++;//9899
            indices[count]=(a*100)+b+101;count++;//9999
        }
    }
}

void ShowEnvironment(){
    //ground
    glPushMatrix();
    GLfloat GroundAmbient[]={0.0,0.5,0.0,1.0};
    glMaterialfv(GL_FRONT,GL_AMBIENT,GroundAmbient);
    glEnableClientState(GL_VERTEX_ARRAY);
    glIndexPointer( GL_UNSIGNED_BYTE, 0, indices ); …
Run Code Online (Sandbox Code Playgroud)

c++ opengl normals computational-geometry

43
推荐指数
4
解决办法
5万
查看次数

OpenGL - 如何计算地形高度网格中的法线?

我的方法是分别计算平行于轴X和Y的两个切向量.然后计算叉积以找到法向量.

切线向量由两条最近段上的中点交叉的线给出,如下图所示.

在此输入图像描述

我想知道是否有更直接的计算,或者在CPU周期方面更便宜.

opengl grid performance terrain normals

21
推荐指数
1
解决办法
9974
查看次数

使用相邻像素交叉乘积从深度图像计算表面法线

正如标题所说,我想通过使用相邻像素的叉积来计算给定深度图像的表面法线.我想使用Opencv并避免使用PCL,但是我并不真正理解这个过程,因为我的知识在这个主题上非常有限.因此,如果有人可以提供一些提示,我将不胜感激.这里要提到的是除了深度图像和相应的rgb图像之外我没有任何其他信息,所以没有K相机矩阵信息.

因此,假设我们有以下深度图像:

在此输入图像描述

并且我想在相应的点找到具有相应深度值的法向量,如下图所示:

在此输入图像描述

如何使用相邻像素的叉积来做到这一点?我不介意法线是否高度准确.

谢谢.


更新:

好吧,我试图关注@ timday的答案并将他的代码移植到Opencv.使用以下代码:

Mat depth = <my_depth_image> of type CV_32FC1
Mat normals(depth.size(), CV_32FC3);

for(int x = 0; x < depth.rows; ++x)
{
    for(int y = 0; y < depth.cols; ++y)
    {

        float dzdx = (depth.at<float>(x+1, y) - depth.at<float>(x-1, y)) / 2.0;
        float dzdy = (depth.at<float>(x, y+1) - depth.at<float>(x, y-1)) / 2.0;

        Vec3f d(-dzdx, -dzdy, 1.0f);
        Vec3f n = normalize(d);

        normals.at<Vec3f>(x, y) = n;
    }
}

imshow("depth", depth / 255);
imshow("normals", normals);
Run Code Online (Sandbox Code Playgroud)

我得到正确的结果如下(我不得不更换double …

c++ opencv normals depth cross-product

21
推荐指数
1
解决办法
1万
查看次数

我的法线贴图有什么问题?我认为这是我的切线

编辑:你可能想从"编辑3"开始,因为我已经解决了很多这个问题

这是我应用于icosphere的普通立方体贴图的屏幕截图:

在此输入图像描述

我的立方体贴图icosphere的切线是使用以下代码生成的.m_indices在一个std::vector索引中std::vector的顶点m_vertices.

std::vector<glm::vec3> storedTan(m_vertices.size(),glm::vec3(0,0,0));

// tangents
for(int i = 0; i < m_indices.size(); i+=3)
{
    int i1 = m_indices[i];
    int i2 = m_indices[i+1];
    int i3 = m_indices[i+2];

    VertexData v1 = m_vertices[i1];
    VertexData v2 = m_vertices[i2];
    VertexData v3 = m_vertices[i3];

    glm::vec3 p1 = glm::vec3(v1.position[0],v1.position[1],v1.position[2]);
    glm::vec3 p2 = glm::vec3(v2.position[0],v2.position[1],v2.position[2]);
    glm::vec3 p3 = glm::vec3(v3.position[0],v3.position[1],v3.position[2]);

    glm::vec3 t1 = glm::vec3(v1.tcoords[0],v1.tcoords[1],v1.tcoords[2]);
    glm::vec3 t2 = glm::vec3(v2.tcoords[0],v2.tcoords[1],v2.tcoords[2]);
    glm::vec3 t3 = glm::vec3(v3.tcoords[0],v3.tcoords[1],v3.tcoords[2]);

    std::function<glm::vec2(glm::vec3)> get_uv = [=](glm::vec3 STR)
    {
        float sc, …
Run Code Online (Sandbox Code Playgroud)

c++ opengl normals bump-mapping

18
推荐指数
1
解决办法
1680
查看次数

OpenGL中的常态是什么?

我听说我应该使用法线而不是颜色,因为颜色已被弃用.(这是真的吗?)法线与光的反射有关,但我找不到清晰直观的解释.什么是正常的?

opengl colors light normals

16
推荐指数
2
解决办法
2万
查看次数

计算在接缝处结束的2个网格之间的法线

我的任务

我目前正在为Unity3D创建一个地形,专门用于运行应用程序的内存不足的移动设备.允许大小为15.000 x 15.000千米且高度为-1.000米到10.000米的地形,并且它的唯一限制是硬盘上的空间.

情况

现在一切都运行正常,除了不正确地计算不同网格之间的法线(每个网格具有细分级别).这是两张可视化问题的图片:

带有显示三角形的网格 仅与法线网格

问题仅发生在从一个细分级别到另一个细分级别的转换上.如果两个网格具有相同的级别,则效果很好.我首先想到在计算法线时我会错过一些面孔,但似乎它们都包含在计算中.

一些代码

每张脸的正常计算:

Vector3 u = vertices[item.Face1] - vertices[item.Face0];
Vector3 v = vertices[item.Face2] - vertices[item.Face0];

Vector3 fn = new Vector3((u.Y * v.Z) - (u.Z * v.Y), (u.Z * v.X) - (u.X * v.Z), (u.X * v.Y) - (u.Y * v.X));
fn.Normalize();
Run Code Online (Sandbox Code Playgroud)

在计算顶点周围的每个面的法线之后,我将所有面法线添加到顶点法线并对其进行标准化.结果显示在图片中,正如您在背景和网格本身中看到的那样,只要没有不同的细分级别,它就可以工作.

一些更多的代码

/// <summary>
/// This is a static indicies array which contains all indicies
/// for all possible meshes.
/// </summary>
private static readonly Int32[] // Subdivision
                             [] // All borders
                             [] …
Run Code Online (Sandbox Code Playgroud)

c# 3d mesh normals

12
推荐指数
1
解决办法
2057
查看次数

我可以在OpenGL ES中指定每个面法线并实现非平滑/平面着色吗?

我想在OpenGL ES 2.0中显示网格模型,它清楚地显示了实际的网格,所以我不希望在每个基元/三角形上有平滑的阴影.我能想到的唯一两个选择是

  1. 每个三角形都有自己的法线集,都垂直于三角形表面(但我想我不能用这个选项在三角形之间共享顶点)
  2. 使用黑色线条指示三角形/基本边缘,并使用共享顶点和每个顶点的一个法线以常规方式粘贴

它必须是这样的吗?为什么我不能简单地阅读原语并且不指定任何法线,并且以某种方式让OpenGL ES 2.0在每张脸上做出平坦的阴影?

类似的问题类似Stackoverflow问题,但没有解决方案的建议

normals opengl-es-2.0

9
推荐指数
1
解决办法
2691
查看次数

FbxSDK打破了法线

我正在尝试导出蒙皮网格.由于某些原因,如果我将一个皮肤簇添加到网格中,FbxSDK会破坏段边缘的法线.没有皮肤,一切看起来都很好.

例: 在此输入图像描述

码:

FbxLayerElementNormal *layerElementNormal = FbxLayerElementNormal::Create(mesh, "");
layerElementNormal->SetMappingMode(FbxLayerElement::eByControlPoint);
layerElementNormal->SetReferenceMode(FbxLayerElement::eDirect);

for (int vertIndex = 0; vertIndex < vertexCount; ++vertIndex)
{
    PackedNormal normal = vertices[vertIndex].normal;
    double x,y,z;
    x = (( (normal.data)        & 0xFF) / 127.5f - 1.0f);
    y = ((((normal.data) >> 8 ) & 0xFF) / 127.5f - 1.0f);
    z = ((((normal.data) >> 16) & 0xFF) / 127.5f - 1.0f);
    layerElementNormal->GetDirectArray().Add(FbxVector4(x,-y,z));
}

layer->SetNormals(layerElementNormal);
Run Code Online (Sandbox Code Playgroud)

我尝试了不同的映射mods(例如eByPolygonVertex)和参考mods,但到目前为止没有任何帮助.如果网格具有皮肤簇,则看起来像法线一样被完全忽略.我评论了上面的代码,皮肤模型看起来像左图上的一个.

我还尝试了不同的3D软件(Maya 2015,Maya 2013和3ds Max 2013)来检查导出的模型,但所有这些都给了我相同的结果.

PS此问题会影响任何蒙皮网格.

编辑 似乎这个问题是FBX管道中的一个错误:Autodesk论坛.为了绕过这个问题,我需要"传输属性".有人能帮忙吗?

c++ 3d normals fbx

9
推荐指数
1
解决办法
590
查看次数

计算平滑度为 100% 的平滑顶点法线的一般方法

我在网上看了很长时间,找不到这个问题的答案。为简单起见,让我们假设我需要完全平滑一组连接面的法线。我想找到一组向量之间的实际几何平分线,忽略重复的法线并保持三角形汤的准确性。基本上,它需要:

  • 使用三角形汤 - 无论是三个、4 个还是 4000 个三角形,法线仍然需要以几何正确的方式协同工作,而不会偏向于任意区域
  • 忽略重叠(平行)法线 - 如果我有一个立方体的边,它聚集在 3 个三角形中,或者一个三角形的两个边中的每一边都聚集在一个三角形中,最后一侧有 2 个(或更多)个三角形,或者一个有 100 万个三角形只有一侧的三角形,平分线不能改变

我似乎找到的最常见的法线平滑公式是,通过将法线向量相加并除以三来简单地平均它们;例子:

normalize((A + B + C) / 3);
Run Code Online (Sandbox Code Playgroud)

当然除以三是没有用的,这已经代表了人们提出的天真、自以为是的蛮力平均法的氛围;与此有关的问题还在于,即使是三角形汤和平行法线,它也会把时间弄得一团糟。

我似乎发现的另一个评论是保留初始“面”法线,因为它们来自生成它们的常见交叉乘法运算,因为这样它们(有点)相对于三角形的面积加权。在某些情况下,这可能是您想要做的事情,但是我需要纯平分线,因此面积不能影响公式,即使考虑到它,它仍然会被三角汤弄乱。

我看到了一个提到的方法,它说对相邻面之间的角度进行加权,但我似乎无法正确实施该公式 - 要么是那样,要么不是我想要的。然而,这对我来说很难说,因为我找不到一个简洁的解释,而且我的头脑因所有这些浪费的头脑风暴而变得麻木。

有人知道通用公式吗?如果有任何帮助,我正在使用 C++ 和 DirectX11。


编辑:这里有一些类似的问题,描述了一些方法;

还有这篇文章:http : //www.bytehazard.com/articles/vertnorm.html

不幸的是,我尝试的实现不起作用,我找不到关于哪个公式实际上是我需要的一个清晰、简洁的声明。经过反复试验,我终于发现按角度加权是正确的方法,只是我无法正确实现它;因为它现在似乎正在工作,所以我将在下面添加我的实现作为答案。

algorithm 3d vertices normals

9
推荐指数
1
解决办法
7853
查看次数

Tangent,binormal和其他与着色器相关的东西

许多映射技术(包括法线凹凸贴图,视差贴图等)都需要特殊的每顶点切线空间(切线,法线,副法线/比特).

这显然意味着,我的模型不仅要出口的顶点位置,纹理坐标每个顶点的法线近似,而且切空间的基向量(通常是一个tangent),因为另外一个可以直接在着色器中使用cross(tangent, normal).

请注意,position,normal,uv和tangents实际上是以下列方式相互依赖的(您必须知道关于顶点的所有其他内容以准备切线基础).

position -> normal ->  tangents
            uv     ->
Run Code Online (Sandbox Code Playgroud)

现在 - 在现代3D游戏/渲染引擎中如何处理这类事情?

它们实际上是为每个顶点提供法线,切线uv坐标还是可以在运行时以某种方式计算它们?它们应该是模型数据的一部分还是应该是仅运行时属性?

我也知道,当使用Direct3D10+几何着色器时,实际上可以在运行时准备法线和切线(显然,因为我们可以访问每个三角形中的顶点) - 是否值得或者这些东西是否应该总是预先计算

3d shader normals

8
推荐指数
1
解决办法
2990
查看次数