zoukankan      html  css  js  c++  java
  • 三角网格中一些描述符

    一、问题描述:

    当几个面共享了一个顶点时,该如何设置这个顶点的法线呢?

    二、下面是参考 Max Wagner 的 文章 《Generating Vertex Normals》,记的笔记。

    1. 设顶点法线与设面法线有什么区别?

    面的法线是与面垂直的线(数学意义)。但在OpenGL中好像并非这样。严格意义上讲,点是没有法线的。点的法线是在使用Phone或Gouraud模型时计算光照使用。如果一个面上的所有法线都一样,他们的光照也就一样,就会产生 flatness 效果;而如果把每个顶点的法向设置不同,则更平滑。

    2. The Intuition behind Vertex Normals

    光线会被应用到每个顶点,并且根据面法线和光照方向的点积去调整光线颜色的强度。这个光照颜色与预先设定的顶点颜色(相加?)(这是Diffuse情况下,Specular, Ambient 情况下也是一样)。因此,如果是三角面,三个顶点就是有面法线和光照方向的同样的点积。三个顶点使用相同的法向导致三角面成为flat,这是不对的。But imagine we could actually sample the “true” surface at the vertices themselves; then we would surely get more variation amongst the vertex normals, in turn creating a (smooth) variation in the diffuse lighting terms. But how can we sample the “true” surface?

    很不幸,我们得不到"true" face。但是我们可以得到接近的,利用几个三角面共享了一个顶点。“平均”这个顶点所有邻接三解形的面法线(这个是可求的)(要搞清楚这个过程,我们可以利用一个三角形的三个顶点计算其法线,然后利用这个理论上的法线去设置三个顶点的法线,然后再由OpenGL的实现对三角面中每个顶点的法线进行插值,这个过程有点绕!)。

    3. The Algorithm

    (1) 针对每个顶点,先找到共享此顶点的所有三角形,然后计算这些三角形的面法线并相加,得到顶点的法线。(未考虑法线与各个面的夹角信息)。伪代码:

    [cpp] view plain copy
     
    1. struct Vertex { Position p, Normal n }  
    2. VertexList v  
    3. for each vertex i in VertexList v  
    4.  n ←Zero Vector  
    5.  for each triangle j that shares ith  
    6. vertex  
    7.   n ←n + Normalize(Normal(v, j))  
    8.  end for  
    9.  v[i].n ←Normalize(n)  
    10. end for  

    算法的时间复杂度为(O(n^2))

    (2) 这个算法有个问题是,有些地方就不是smooth,而是flat,比如四面体网格,若仍按上面的算法,结果就会很奇怪。

    一个解决方法是使用一个阈值判断一个面法线是否应该被加入到平均化过程。遍历顶点的过程中,存储一个面法向,这个面是这个顶点技术性包含于(technically belongs to)的面(as opposed to the triangles which share a copy of the vertex eleswhere in the triangle list)(什么叫技术性包含于?)。然后,当遍历共享此顶点的三角形时,先计算存储的面法线与当前三角形的面法线的点积,然后判断此点积是否大于某一阈值,如果小于此阈值,则不参与平均化过程。这个原理是什么呢?两个面法线的点积与其夹角的cos值相对应,如果这个cos值过小,说明法线的夹角较大(cos在0-180度单调递减)。(但论文中是这样说的:We are  effectively saying, if the angle between two surfaces is greater than throhold, don't average them。与计算的不统一啊)。

    伪代码:

    [cpp] view plain copy
     
    1. struct Vertex { Position p, Normal n }  
    2. VertexList v  
    3. epsilon e  
    4. for each vertex i in VertexList v  
    5.  n ←Zero Vector  
    6.  m ←Normalize(Normal(v, i%3))  
    7.  for each triangle j that shares ith  
    8. vertex  
    9.   q ←Normalize(Normal(v, j))  
    10.   if DotProduct(q, m) > e  
    11.    n ←n + q  
    12.   end if  
    13.  end for  
    14.  v[i].n ←Normalize(n)  
    15. end for  
  • 相关阅读:
    资源:mysql下载路径
    知识点:jar包与war包的差异
    Linux:jar服务部署
    Flyway:Spring Boot中使用Flyway来管理数据库版本
    Java:Java控制台输出保存进文件
    Maven:手动添加jar包进Maven本地库内
    Https:SSL双向认证机制(理论知识)
    Linux ubuntu 下寻找 texlive 缺失包 texlive 缺失包(转载)
    Android应用开发提高篇(4)-----Socket编程(多线程、双向通信)(转载)
    Android应用开发基础篇(12)-----Socket通信(转载)
  • 原文地址:https://www.cnblogs.com/haoyul/p/5791151.html
Copyright © 2011-2022 走看看