精华内容
下载资源
问答
  • 固体表面法线方向黑度测定实验.pdf
  • 针对三维点云在泊松曲面重构过程中由于法线方向不一致而导致重构结果出现偏差的问题,提出一种基于改进法线方向的泊松曲面重构算法。利用包围盒将原始点云分割为若干个立方体体素,并将每个有效体素标记为“位置已知”...
  • 固体表面法线方向黑度测定实验.docx
  • 柱面是一种双曲率面,它是一种特殊的非旋转对称非球面,其子午方向上的母线是直线,弧矢方向上的母线为圆弧。
  • 法线的严谨定义我不关心,你只要知道,模型是由点线面组成的,法线是每个面“正上”的方向。我们,开始吧。首先,还是上节那个shader(你也可以重写一遍,加深记忆),在里面改就好。在Properties里面,加一行:_...

    上节的流程走下来,你一定对shader有了个大体的了解。咱们现在让这个了解更进一步。如题,我们聊法线。对法线的严谨定义我不关心,你只要知道,模型是由点线面组成的,法线是每个面“正上”的方向。

    我们,开始吧。

    首先,还是上节那个shader(你也可以重写一遍,加深记忆),在里面改就好。在Properties里面,加一行:

    _Height(“高度”,Float)=1添加高度变量

    经过上节的学习,我想我需要解释的只有括号里表示变量类型的那一项,Float吧?这也很简单,它表示的是一个数(别管什么浮点数,你就理解成数就行)(当然稍稍严谨一些的话,是实数)。你肯定能看懂“高度”二字,对,这个值用来给我们的球增高。写完之后保存,到unity界面的材质面板看看效果,嗯,是这样的:材质面板效果

    我只说两点:你可以在后面那个框里直接输入数据,也可以把光标移到“高度”两字上,待鼠标两侧有小三角时,按住拖动也可以更改数值。

    好了,咱们接下来把这个值用到代码里吧。在上次写fixed4 _Color;的下面接着写:

    float _Height;写就完事了

    如果你在上文用的不是_Height这个名称记得要对应更改。

    1.获取法线

    然后是今天的重中之重,法线向量!在a2v结构体(不记得的自觉去第一节翻看)里写:

    fixed3 normal:NORMAL;从模型中获取法线

    这里,fixed3是法线向量的类型,有三个参数的向量,凡是表示方向的向量都是只有三个参数;后面的冒号和大写的NORMAL表示从模型里取法线,这些是不能自己发挥的;只有变量名,也就是小写normal,你随意写了,记住别忘了就好。

    这就表示咱们从模型中拿到了法线,这个法线是在模型坐标系下的。经过第一节的介绍想必你也知道了,一般从模型直接拿出的东西是不能用的,得加工下。但这次,咱们用完了再加工。在顶点函数里变换顶点坐标的语句之上(在我这是o.pos=UnityObjectToClipPos(v.vertex);),写:

    v.vertex.xyz += _Height * v.normal;法线方向的高度增加

    我这写在了v2f变量声明之前,你也可以写在声明它之后,都可以的。

    这行语句,第一项,v.vertex.xyz,v.vertex我想你知道是啥意思,顶点位置信息嘛,一个四个参数的向量(以后我会说四维向量,一个意思),而.xyz的意思是前三个数;这是有意思的地方了,在shader里,假如vector是个四维向量,那么vector.x是第一个数;同理y,z是第二三个数,第四个数用w表示。这些是可以混用的:vector.xz表示一个二维向量,其第一个数是vector.x,第二个数是vector.z;这种写法挺带感的,写多了就会很顺手:vector.zwxy、vector.zxxx……

    第二项是个运算符+=,你一定不陌生;你要是陌生的话,啊,我也不知道该咋办了。

    _Height是我们上面定义的变量,别忘了;v.normal是法线向量。

    然后这行语句的意思是,每个顶点的xyz坐标都在法线方向上加_Height的高度。

    什么都不用改,切到unity界面,你会看到一个比之前大的球。大的小球

    试试改变“高度”值,看看球的变化。

    /*

    如果v.vertex.xyz只加了_Height会怎样?

    v.vertex.xyz +=fixed3(_Height, _Height, _Height);

    也有个更简洁的写法:v.vertex.xyz += _Height;

    试一下你就会发现,小球形状大小没有变化,只是往上移动了点。对,如果只加个_Height的话,相当于模型的每个点的每个xyz坐标值都加了_Height,模型各点的绝对位置改变了,而相对位置没变。位置移动而形状大小未变

    从这里也能领会到为什么说法线是每个面“正上”的方向。

    */

    不知道你有没有好奇过,在unity的Scene面板右上角的坐标指示,为啥x轴是红的,y轴是绿的,z轴是蓝的?坐标轴的颜色

    现在你知道了吧,因为位置坐标和颜色用的都是同一种数据类型fixed4,xyz正好对应rgb。现在,让我们直观地来感受一下。

    2.传递法线信息

    我们决定输出颜色。既然要输出颜色,就要用到片元函数,也就意味着我们要把顶点函数得到的数据传给片元函数,所以必须在v2f结构体里给它留个位置:

    fixed3 worldNormal:TEXCOORD0;留个位置

    我猜你有两处要问的,一个worldNormal,一个TEXCOORD0。

    worldNormal是我们要把它从模型本身的坐标系转换到世界坐标系(我也不知道它为啥叫世界坐标系,反正在这个坐标系下计算比较方便),worldNormal就是世界坐标系里的法线。

    TEXCOORD0是第0号(就是第一个,程序都这么数数,从零开始)的寄存器。你不需要知道什么叫纹理坐标,什么叫寄存器,你只需要知道它就是个筐,什么都能往里装,每装一个末尾序数加一就行。这个筐就把worldNormal这个变量装着运到片元函数里。顺便说一句,在v2f里的TEXCOORD是运输数据的工具,而在a2v里TEXCOORD则是读取纹理(就是图片)的工具,现在有个概念就好,以后细说。

    /*

    你可能会问为什么pos变量没有用TEXCOORD计数运输,那是因为人家直接返回了,不需要往片元函数里传递

    */

    怎么转换呢?还记得第一节里的UnityObjectToClipPos()函数吗(要是不记得了就再去看一遍)?那是从模型坐标转到裁剪坐标的,咱们今天用的跟他这个类似:

    o.worldNormal=UnityObjectToWorldNormal(v.normal);坐标转换

    没什么好说的,一目了然,记住就好。也不难记嘛,模型到世界的法线。顺便说一句,这个转换后的法线向量是标准化的,长度为1。

    然后就只需要把片元函数的return语句改为:

    return fixed4(i.worldNormal, 1);返回法线

    然后,到unity界面看看效果吧!越红表示法线向量越指向x轴,再对照下Scene面板右上角坐标轴,借此加深对法线和颜色的理解。形象直观的颜色

    发挥你的想象力,对法线做更多的改动吧,很好玩的。

    展开全文
  • Python在3D数据中根据点以及法线方向提取切片 在处理3D图像数据(CT图像,MRI图像)中,有时需要对其进行提取切片的操作,一般都是按照X,Y,Z三个轴来提取切片,然而在一些情况下需要根据某点的法线方向提取过这点的...

    Python在3D数据中根据点以及法线方向提取切片

    在处理3D图像数据(CT图像,MRI图像)中,有时需要对其进行提取切片的操作,一般都是按照X,Y,Z三个轴来提取切片,然而在一些情况下需要根据某点的法线方向提取过这点的切片,在这里根据的 matlab代码 改写成python的版本。
    在这里插入图片描述

    原理

    在matlab的代码上主要是分为几步来获得斜切平面的
    (1)初始化切平面,在这里切平面可以当成一把刀,初始化的切平面是平行于XY平面的。
    (2)通过绕一点以及一个方向旋转改切平面,这样的话就知道往哪切了,只要将初始切平面的法线方向变换至切平面法线的方向,同时对初始平面上的点进行同样的变换,便可得到最后的切平面。
    (3)因为旋转之后的点会产生小数,所以还需要取整操作。

    代码

    import numpy as np
    import math
    import scipy.linalg as linalg
    import nibabel as nib
    import matplotlib.pyplot as plt
    
    def sphere(shape, radius, position):
        semisizes = (radius,) * 3
        grid = [slice(-x0, dim - x0) for x0, dim in zip(position, shape)]
        position = np.ogrid[grid]
        arr = np.zeros(shape, dtype=float)
        for x_i, semisize in zip(position, semisizes):
         arr += (np.abs(x_i/semisize) ** 2)
        return arr <= 1.0
    
    
    def loc_convert(loc, axis, radian):
        '''
    	实现点按某个轴旋转一定度数后得到新点坐标
        :param loc:原始坐标
        :param axis: 绕旋转的轴(点)
        :param radian: 角度
        :return: 新坐标
        '''
        radian = np.deg2rad(radian)
        rot_matrix = linalg.expm(np.cross(np.eye(3), axis / linalg.norm(axis) * radian))
        new_loc = np.dot(rot_matrix, loc)
        return new_loc
    
    def extract_slice(img, c, v, radius):
        '''
        :param V:3d 图像
        :param center-c: 中心(x,y,z)
        :param normal-v: 法向量(v1,v2,v3)
        :param radius: 半径,即边长的一半
        :return:
        slicer:得到的2d切片
        loc: 得到切片对应的原3d坐标
        '''
        # 设置初始面
        epsilon = 1e-12
        x = np.arange(-radius, radius, 1)
        y = np.arange(-radius, radius, 1)
        X, Y = np.meshgrid(x, y)
        Z = np.zeros_like(X)
        loc = np.array([X.flatten(), Y.flatten(), Z.flatten()])
    
        # 设置初始平面,垂直于Z轴,将向量变为单位向量
        hspInitialVector = np.array([0, 0, 1])
        h_norm = np.linalg.norm(hspInitialVector)
        h_v = hspInitialVector / h_norm
        h_v[h_v == 0] = epsilon
        v = v / np.linalg.norm(v)
        v[v == 0] = epsilon
    
        # 计算初始法线与最后法线的角度
        hspVecXvec = np.cross(h_v, v) / np.linalg.norm(np.cross(h_v, v))
        acosineVal = np.arccos(np.dot(h_v, v))
        hspVecXvec[np.isnan(hspVecXvec)] = epsilon
        acosineVal = epsilon if np.isnan(acosineVal) else acosineVal
    
        # 得到旋转后的坐标
        loc = loc_convert(loc, hspVecXvec, 180 * acosineVal / math.pi)
        sub_loc = loc + np.reshape(c, (3, 1))
        loc = np.round(sub_loc)
        loc = np.reshape(loc, (3, X.shape[0], X.shape[1]))
    
        # 生成初始切片,以及对应的索引值
        sliceInd = np.zeros_like(X, dtype=np.float)
        sliceInd[sliceInd == 0] = np.nan
        slicer = np.copy(sliceInd)
    
        # 将3D图像对应的像素值以及对应的坐标赋值给对应的切片
        for i in range(X.shape[0]):
            for j in range(X.shape[1]):
                if loc[0, i, j] >= 0 and loc[0, i, j] < img.shape[0] and loc[1, i, j] >= 0 and loc[1, i, j] < img.shape[1] and loc[2, i, j] >= 0 and loc[2, i, j] < img.shape[2]:
                    slicer[i, j] = img[
                        loc[0, i, j].astype(np.int), loc[1, i, j].astype(np.int), loc[2, i, j].astype(np.int)]
        slicer[np.isnan(slicer)]=0
        return slicer, sub_loc,loc
    
    if __name__ == '__main__':
    
        arr = sphere((256, 256, 256), 100, (127, 127, 127))
        print(arr.shape)
        c = [150,150,150]
        n = [1, 2, 3]
        slicer, sub_loc, loc = extract_slice(arr, c, n, 100)
        print(slicer)
        plt.imshow(slicer)
        plt.show()
    
    展开全文
  • 从相反的法线方向观察,顺时针还是逆时针是相反的。 多边形的时针方向与法线方向的关系呈右手法则关系。 GoogleEarth中的面具有时针方向,法线方向为正向,反之为负向 GoogleEarth的垂面在法线方向为亮色,反向为...

    从相反的法线方向观察,顺时针还是逆时针是相反的。

    多边形的时针方向与法线方向的关系呈右手法则关系。

    GoogleEarth中的面具有时针方向,法线方向为正向,反之为负向

    GoogleEarth的垂面在法线方向为亮色,反向为暗色

    GoogleEarth的水平面或斜面无论法线指向天空还是地面,背离地面的一侧总是亮色。

    要保证多边形的各侧向垂面的法线总是朝外(保持外侧面为亮面),若该多边形为顺时针,则各垂面边框按从高点起始,先画水平线到下点,再画垂线到低点,最后回到高点的方法。反之,若该多边形为逆时针,则各垂面边框应从高点开始,先画垂线到低点,再画水平线到下点,最后回到高点的方法。

    换句话说,假设各垂面都从高点开始画,如果多边形是顺时针的,则先画水平线;如果多边形是逆时针的,则先画垂直线。归纳为 “顺高水,逆高垂”。

     

    凸多边形只有具有一个时针方向,但凹多边形的凸边和凹边时针方向不相同。一个多边形无论凹凸,判断每相邻两边的时针方向更有意义。由3点构成的两边,计算这3点的卷积(CorssProduct),卷积为正是逆时针,卷积为负是顺时针。

    卷积=(ΔXi,ΔYi)×(ΔXi+1,ΔYi+1),即 cp=(xi-xi-1)×(yi+1-yi)-(yi-yi-1)×(xi+1-xi), 若cp>0,该点为逆时针点。反之为顺时针点。

    同时,如果一个多边形是凸多边形,那么,它每个顶点的卷积都为正或都为负。凹多边形的所有顶点的卷积有的为正有的为负。

    此外,如果多边形存在重合的两点,或连续3点在一条直线上,那么,卷积=0,没有时针方向,也不区分凹凸。

     

    代码示例1:判断一个多边形是顺时针还是逆时针

    /*

       Return the clockwise status of a curve, clockwise or counterclockwise

       n vertices making up curve p

       return 0 for incomputables eg: colinear points

              CLOCKWISE == 1

              COUNTERCLOCKWISE == -1

       It is assumed that

       - the polygon is closed

       - the last point is not repeated.

       - the polygon is simple (does not intersect itself or have holes)

    */

    int ClockWise(XY *p,int n)

    {

       int i,j,k;

       int count = 0;

       double z;

     

       if (n < 3)

          return(0);

     

       for (i=0;i<n;i++) {

          j = (i + 1) % n;

          k = (i + 2) % n;

          z  = (p[j].x - p[i].x) * (p[k].y - p[j].y);

          z -= (p[j].y - p[i].y) * (p[k].x - p[j].x);

          if (z < 0)

             count--;

          else if (z > 0)

             count++;

       }

       if (count > 0)

          return(COUNTERCLOCKWISE);

       else if (count < 0)

          return(CLOCKWISE);

       else

          return(0);

    }

     

    代码示例2:判断一个多边形是凸多边形还是凹多边形

       Return whether a polygon in 2D is concave or convex

       return 0 for incomputables eg: colinear points

              CONVEX == 1

              CONCAVE == -1

       It is assumed that the polygon is simple

       (does not intersect itself or have holes)

    */

    int Convex(XY *p,int n)

    {

       int i,j,k;

       int flag = 0;

       double z;

     

       if (n < 3)

          return(0);

     

       for (i=0;i<n;i++) {

          j = (i + 1) % n;

          k = (i + 2) % n;

          z  = (p[j].x - p[i].x) * (p[k].y - p[j].y);

          z -= (p[j].y - p[i].y) * (p[k].x - p[j].x);

          if (z < 0)

             flag |= 1;

          else if (z > 0)

             flag |= 2;

          if (flag == 3)

             return(CONCAVE);

       }

       if (flag != 0)

          return(CONVEX);

       else

          return(0);

    }

     

    转载于:https://www.cnblogs.com/mol1995/p/10890367.html

    展开全文
  • 很简单的一个小东西.纪录一下, 先上效果图:

    很简单的一个小东西.纪录一下,

    先上效果图:

    然后是代码,

    就是用到了RaycastHit.normal

        public GameObject line;
        RaycastHit hit;
        private void Update()
        {
            if (!Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
                return;
            line.transform.position = hit.point;
            var rot = hit.transform.rotation;
            line.transform.forward = hit.normal * 180;
        }

    把跟随移动的小玩意拖上来就行了,

    展开全文
  • houdini中使用vex旋转对象法线方向方法 vex如下: //创建法线,当对象物体有面的时候N的默认数值是{0,1,0}; //对象物体为点的时候需要定义N的数值 @N={0,1,0}; //创建矩阵m,并旋转矩阵中的{0,1,0}的矢量至...
  • 如何沿法线方向挤出面

    千次阅读 2019-08-30 13:22:27
    实际上我们想要的是每一个面都沿着各自的法线方向挤出。 这时候需要Alt + E键调出挤出命令的菜单 选择沿法向挤出面,这样就得到了我们想要的结果 小结 我们为角色增服装和盔甲等结构的时候,会...
  • RGB 颜色值用于存储矢量的 X、Y、Z 方向,其中的 Z 为“向上”(与 Unity 通常使用 Y 作为“向上”的惯例相反)。此外,纹理中的值视为经过减半处理,即添加了 0.5 的系数。这样就能存储所有方向的矢量。因此,为了...
  • InSb面阵探测器法线方向力学参数选取研究
  • % X and Y components of the normals vectors are between -1 and 1.% The step number specifies the size of the output image.range = -1:0.01:1;% Repeat the range to build a matrixX = repmat(range, [size...
  • 用于显示模型法线方向的shader 原理很简单,就是获取顶点坐标信息作为起点,沿着法线方向在指定长度的位置画一条线段。我的代码里都有详细注释。 翠花,上效果图~ Shader "Unlit/normal" { //变量接口 ...
  • 通过HTCVive手柄发射射线控制物体的吸附效果,类似于帖在...通过手柄射线获得碰撞点的位置和法线方向using UnityEngine; using System.Collections; public class SteamVRControllerBase : MonoBehaviour { publ...
  • 在早期制作端游时候做树,遇到过树叶正反面的问题,...后来制作手游的时候发现可以通过修改模型的法线达到理想效果 <Rime> 以下是几种工具 可以使用UserNormalTranslator工具: Softimag...
  • 多变形建模过程中,反复的挤压、调整,容易造成多边形顶点法线方向混乱,有的指向所建模型的外部、有的指向模型内部,从而导致模型看起来一部分黑、一部分白,如下图所示。这个时候通过执行面的反转(Reverse)是不...
  • maya中查看法线方向并更改

    万次阅读 2013-12-08 23:10:54
    如何在maya中查看法线方向并更改 在maya中查看法线是否正确,可以依次打开display---polygons---face normals就可以显示物体的法线方向了。如果顺着z轴正反向就是正确的,如果反方向就是反的, 选择要反转法线...
  • Unity Shader 学习笔记 (七) 根据切线和法线方向设置模型颜色shader 法线方向颜色Shader Shader代码 Shader "Custom/faxianColor" { SubShader { Pass { Fog { Mode Off} CGPROGRAM //顶点着色函数入口 ...
  • 右手定则判断法线方向

    千次阅读 2013-03-21 00:15:00
    如果角A是锐角,向量AB * AC 求出的是三角形ABC的法向量;...PI才能使用右手定则说是从AB到AC,否则应使用从AC到AB,才不会导致法线反向。 转载于:https://www.cnblogs.com/qingsunny/archive/2013/03/21/29...
  • 【源码,可编辑】自己写的3dmax统一法线脚本,非常规好用,操作简单,max各个版本都兼容,拖入max场景,选中物体,直接运行脚本即可统一场景中所有物体的法线
  • 在我们获得点云数据后,为了能够进行表面重建或者是进行物体的位姿确定,我们都需要确定物体表面的发现方向。 PCL中有现成的计算物体法线的类NormalEstimation,这个类做了以下3件事 1.得到p的最近邻 2.计算p的...
  • 利用Halcon均匀分割曲线,并标记法线方向。 原始图片: 处理效果如下所示: 代码: read_image (Image, 'C:/Users/Sawyer/Desktop/13_36559_e7fc764b4adb61d.png') edges_sub_pix (Image, Edges, 'canny', 1, 30, ...
  • 3DS MAX 显示法线方向

    万次阅读 2009-11-16 22:44:00
    3DS MAX显示法线,添加“编辑法线”修改器 游戏模型根本就没有法线,不带法线
  • 前言法线可以用来计算光照,废话少说进...13.1 点乘的结果显示两个向量有多相像因此当光线照到一个模型上面时,我们便可以问:”光线方向与法线方向的点乘结果是什么?“如果L的向量与N一样(N Dot L=1),那么表示模...
  • 3DMAX编辑法线插件
  • \frac{\partial F}{\partial x_n}) ΔF=(∂x1​∂F​,∂x2​∂F​,…,∂xn​∂F​) 某点法线的几何意义是垂直于改点切线或切面的向量,对于隐函数 F(x1,x2,…,xn)=0F(x_1, x_2, \dots, x_n)=0F(x1​,x2​,…,xn​)=...
  • 方向导数、梯度、法线间的关系

    千次阅读 2018-06-25 22:06:00
    函数在点P处,沿着方向V的变化率大小,得到结果是一个数值。 对于一个二元函数,其方向导数为(word里面写好公式复制不上来,气人只能截图) 证明如下:由 两边同时除以得到下式子: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,641
精华内容 8,656
关键字:

法线方向