第029封“情书”:千与千寻 Naive Path Finding路径发现

第029封“情书”:千与千寻 Naive Path Finding路径发现_第1张图片

我没喝醉,只是道路太坎坷。太曲折。 — 每天翻译一篇教程,这就是我写给houdini的情书。 【首发于同名公众号:“致houdini的情书”】 <Entagma>Houdini 2016

第029封“情书”:千与千寻 Naive Path Finding路径发现_第2张图片

█ 我才不要过那种一帆风顺的人生呢!太乏味!

小马过河:

从前,有匹小马要过河。

    老水牛看到了,对他说:“别怕,水很浅,只到了我的膝盖。”

    小松鼠立刻跑了过来喊道:“不要相信他,水很深,我的朋友就是在这里淹死的!” 小马不知道该听谁的。

    马妈妈在旁边说道:“孩子!别理那两个神经病了,咱们走桥!”

下面是一个粒子的自我修养:

它要如何绕过前面的层层阻碍,到达它的梦想之地?

第029封“情书”:千与千寻 Naive Path Finding路径发现_第3张图片

这一节要实现的效果.....

▉今天是42岁第003天周日

这是写给houdini的

第029封“情书”

我是geo流程图

第029封“情书”:千与千寻 Naive Path Finding路径发现_第4张图片

我是solver流程图

本节需要注意的知识点:

1

实现从start绕过障碍物到达end的思路

1)首先在空间中填满点。

2)然后求得start和end之间全局方向适量。

3)再在寻找start的临近点。

4)求得start与临近点的局部方向矢量。

5)求得两个方向矢量的夹角.

6)取得最小的那个夹角.

7)取得最小夹角对应的点id。

8)当前点和最小夹角点各自移入相应的组里。

2

如何让start点在充满点的路径空间里始终保持id=0,

1)首先start连接active组,设置在这个组里。

2)然后路径空间的点连接active组,设置不在这个组里,但是有这个active组属性。

3)最后用merge合并。

第029封“情书”:千与千寻 Naive Path Finding路径发现_第5张图片

3

group与老版本区别

1)老版本Base Group:

  a)  * : “星号”表示选择所有点。

    b) !* :"叹号+星号"表示全部不选

2)老版本Base Group:

  a)  什么都不输入:表示选择所有点。

    b) * :    "星号"表示全部不选

4

本节使用函数的作用

1)point函数:通过找到end的位置,得到全局方向矢量

vectortgt = v@P - point(1,“P”,0); 

2)inpointgroup函数:通过判断@ptnum当前点在active组里来确定执行“寻找它的临近点”。

if(inpointgroup(0,"active",@ptnum)){

3)pgfind函数:在!active组里找@ptnum的临近点列表closepts。

intclosepts[] =pgfind(0,“!active”,v@P,searchrad,maxpts,searchrad);

4)foreach函数:遍历临近点列表closepts的所有点cpt,来找出那个最小角度的点nextpt。

foreach(int cpt; closepts){ 

5)dot函数:在数学中,数量积(dot product; scalar product,也称为点积)是接受在实数R上的两个向量并返回一个实数值标量的二元运算。

dot(normalize(tgt),normalize(cptgt))

6)acos函数:返回参数的反余弦。求得角度数值。

floatangle =acos(dot(normalize(tgt),normalize(cptgt)));

7)setpointgroup函数:设置点移入移出相应的组。

  setpointgroup(0,“active”,nextpt,1);

  setpointgroup(0,“active”,@ptnum,0);

  setpointgroup(0,“path”,@ptnum,1); 

接下来

理论部分

问题1:如何实现绕过障碍从start到end的路径

01)假使我们希望从A到B

02)但是路径上充满障碍

第029封“情书”:千与千寻 Naive Path Finding路径发现_第6张图片

03)如何找到绕经路线

第029封“情书”:千与千寻 Naive Path Finding路径发现_第7张图片

04)可以用点填满障碍的周围 :

第029封“情书”:千与千寻 Naive Path Finding路径发现_第8张图片

05)当然首先要画一条到B的矢量:

06)第二步找到距离A一定范围的点:

07)从中选择距离这条line最近的点:

第029封“情书”:千与千寻 Naive Path Finding路径发现_第9张图片

08)根据测量点到line的角度来判断:

08)C就是我们的下一个点

接下来

开始正式制作

使用软件houdini16.0.633

问题1:路径绕过障碍的空间如何填满点

1 创建隔离障碍物

1)sphere1

    a) frequency=32 

2)sphere2: 复制<1>

3)isooffset1

    a)  Fog volume

4)Scatter1

    a)  Count=50 ;//分布50点作为障碍物

    b)  关闭松弛;

5)pointwrangle1

    a)  创建pscale属性 ;  //建立点的随机大小

f@pscale = fit(rand(@ptnum + chi(“seed”)),0,1,0.05,0.3)

第029封“情书”:千与千寻 Naive Path Finding路径发现_第10张图片

大小随机

6)Relax1

    a)  Iter=200

    b)  √ relax in 3D //使球体错落分离

第029封“情书”:千与千寻 Naive Path Finding路径发现_第11张图片

分离

1)sphere 1 

    a)  uniform scale :0.85

7)copytopoint

8)vdbfrompoly1

    a)  Voxel:0.02

2 创建障碍物与外面大圆vdb布尔运算得到绕过障碍的路径VDB空间

9)sphere3

    a)  scale=1.8

    b)  frequency=32

第029封“情书”:千与千寻 Naive Path Finding路径发现_第12张图片

10)vdbfrompoly2 复制<8>

11)vdbcombine

    a)  Operation:SDF Difference

    b) 槽1接<10> ;槽2接<8>

12)volumeslice  切片

    a)  改变offset检查相交

第029封“情书”:千与千寻 Naive Path Finding路径发现_第13张图片

vdb

13) convervdb  转成fog

    1)  VDB

    2)  SDF to Fog

第029封“情书”:千与千寻 Naive Path Finding路径发现_第14张图片

转成fog粒子经过路径的空间

3 障碍物外面空间填满点

14) scatter2:

    1)  Iter=4

    2)  Count=10万  //增加点的密度

第029封“情书”:千与千寻 Naive Path Finding路径发现_第15张图片

//创建start和end两个点

4 增加起点start&终点end

15)add 1:    //命名 add_start

    1) Y=1.7

第029封“情书”:千与千寻 Naive Path Finding路径发现_第16张图片

start点

16)add 2:    //命名 add_end

    1) Y=-1

5 建立active组,确保start点id=0

分析)

    group1:搜索的出发点的周围点(用于测量角度)放入这个组。

    group2:这条路径上的点放到这个组。

//创建两个group

17)group1:

    a) name:active

    b) Entity:points

    c)  连接<15>

第029封“情书”:千与千寻 Naive Path Finding路径发现_第17张图片

start点在:active组里

18)group2:

a) 复制<17>

    b) 不含任何点: *  //不归入active

    c) 连接<14>

第029封“情书”:千与千寻 Naive Path Finding路径发现_第18张图片

填充的点有active属性,但不在active组里

19)merge1

    a) 合并两个group

第029封“情书”:千与千寻 Naive Path Finding路径发现_第19张图片

现在我们已经为后面的pointwrangle里点移入active组做好准备。

20)pointwrangle2

第1步:新建从start到end点的“全局方向 ” tgt

第029封“情书”:千与千寻 Naive Path Finding路径发现_第20张图片

end连接槽1,它的id=0

第029封“情书”:千与千寻 Naive Path Finding路径发现_第21张图片

vectortgt = v@P -point(1,“P”,0); 

第2步:判断如果当前点在active组里返回1;执行内部代码

if(inpointgroup(0,"active",@ptnum)){

第3步:求当前点四周的“临近点”closepts,而且要在“!active”(非active)组里寻找;

intclosepts[] =pgfind(0,“!active”,v@P,searchrad,maxpts,searchrad);

第4步:foreach循环遍历点列表里每个临近点cpt

foreach(int cpt; closepts){

第5步:求当前点(start)与临近点的“局部方向”cptgt

vectorcptgt = v@P -point(0,“P”,cpt); 

第029封“情书”:千与千寻 Naive Path Finding路径发现_第22张图片

第6步:用“三角函数” 求夹角angle(两个方向"tgt"和"cptgt"的)

floatangle =acos(dot(normalize(tgt),normalize(cptgt)));

第7步:找到最小的angle

floatoangle = 1000;

if(angle

          oangle = angle;

第8步:更小的angle对应的id

//-----初始化变量

int nextpt = -1;

nextpt = cpt; 

第9步:把所有点各自归入相应的组

  setpointgroup(0,“active”,nextpt,1); nextpt就是下一个点添加进active,

  setpointgroup(0,“active”,@ptnum,0);    //@ptnum(当前点id)移出active组

21)solver1

a) pointwrangle2拷入,

    b) 连接

第029封“情书”:千与千寻 Naive Path Finding路径发现_第23张图片

22)delete1

a) Group:active;

  b) Operation: Delete on-select

  c) Entity:points

第029封“情书”:千与千寻 Naive Path Finding路径发现_第24张图片

现在只显示一个点,因为vex每次只产生一个点,

/第10步:

1)在外面建一个path组

23)group3

a) Group:path;

    b) Base Group: *

  2)把当前点归入path组

setpointgroup(0,“path”,@ptnum,1);    //@ptnum移入path组里

22)delete1

a) Group:path  ;//改成保留path组的点

第029封“情书”:千与千寻 Naive Path Finding路径发现_第25张图片

剩下的可以:可以把start换成多个点

=vex代码!==

//---------------- <区域1>找到start周围指定半径范围内的点------------------

//----- “搜索半径”,“最大点数”两个变量----

float searchrad = 1.0; 

int maxpts = 32;

//-----旧的角度变量old angle  设一个很高的值----

float oangle = 1000;

//-----初始化变量

int nextpt = -1;

    //-------第1步:新建从start到end点的“全局方向 ” tgt---------

vector tgt = v@P - point(1,“P”,0);        //当前点位置-“槽1”的点的位置,ptnum=0

    //-------第2步:判断如果当前点(start)在active组里返回1;执行内部代码--------------

if(inpointgroup(0,"active",@ptnum)){

  //--------第3步:求当前点(start)四周的“临近点”closepts (!active组里)--------

int closepts[] = pgfind(0,“!active”,v@P,searchrad,maxpts,searchrad); //在 “!active”组,搜索半径=searchrad,增加两个新增变量maxpts,searchrad,第二个searchrad是搜索精度divsize,大多数情况divsize跟radius相同,

  //------------------ <区域2>测量角度,找出最小角度的点-------------------

  //--------第4步: foreach循环遍历点列表里每个临近点cpt-------------

  foreach(int cpt; closepts){                //新变量countpoint=cpt

  //--------第5步:求当前点(start)与临近点的“局部方向”cptgt ----------

  vector cptgt = v@P - point(0,“P”,cpt);  //从当前点start到cpt(count point target)点

  //--------第6步:用“三角函数” 求夹角angle(两个方向"tgt"和"cptgt"的)---------

float angle = acos(dot(normalize(tgt),normalize(cptgt))); // dot返回点积:两个向量并返回一个实数值标量

  //--------第7步:找到最小的angle----------

      //使用if语句,检查curent angle---分析:如果angle<前一个angle,它就被写进oangle--

  if(angle

          oangle = angle;

  //-------第8步:更小的angle对应的id--------; ,

          nextpt = cpt;       

      }

  }

  //. -------第9步:把nextpt和当前点各自归入相应的组---------

  setpointgroup(0,“active”,nextpt,1); nextpt就是下一个点添加进active,

  setpointgroup(0,“active”,@ptnum,0);    //@ptnum(当前点id)移出active组

//. -------第10步:把当前点归入path组,在外面建一个path组--------

  setpointgroup(0,“path”,@ptnum,1);      //@ptnum移入path组里

}

今天就到这儿了,收功

教程翻译自entagma的网络教程

下一节:20170102 Special Guest - Ben Watts- Shortest Path Growth最短路径增长


第029封“情书”:千与千寻 Naive Path Finding路径发现_第26张图片

本文图片全部原创,版权归原作者所有。

你可能感兴趣的:(第029封“情书”:千与千寻 Naive Path Finding路径发现)