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

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

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

小马过河:

从前,有匹小马要过河。

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

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

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

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

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

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

▉今天是42岁第003天周日

这是写给houdini的

第029封“情书”

我是geo流程图

我是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合并。

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)但是路径上充满障碍

03)如何找到绕经路线

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

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

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

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

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)

大小随机

6)Relax1

    a)  Iter=200

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

分离

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

10)vdbfrompoly2 复制<8>

11)vdbcombine

    a)  Operation:SDF Difference

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

12)volumeslice  切片

    a)  改变offset检查相交

vdb

13) convervdb  转成fog

    1)  VDB

    2)  SDF to Fog

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

3 障碍物外面空间填满点

14) scatter2:

    1)  Iter=4

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

//创建start和end两个点

4 增加起点start&终点end

15)add 1:    //命名 add_start

    1) Y=1.7

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>

start点在:active组里

18)group2:

a) 复制<17>

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

    c) 连接<14>

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

19)merge1

    a) 合并两个group

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

20)pointwrangle2

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

end连接槽1,它的id=0

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); 

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

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

第7步:找到最小的angle

floatoangle = 1000;

if(angle<oangle){

          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) 连接

22)delete1

a) Group:active;

  b) Operation: Delete on-select

  c) Entity:points

现在只显示一个点,因为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组的点

剩下的可以:可以把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){

          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最短路径增长


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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容

  • 接口第一章: 接口业务方向 接口规范:http://open.weibo.com/wiki/2/comments...
    Curry_30阅读 1,672评论 0 0
  • 50、Pow(x, n) Implement pow(x, n), which calculates x rais...
    BigBigFlower阅读 367评论 0 0
  • 姓名:肖福青~公司:阜阳市豹子头服饰科技有限公司 【日精进打卡第250天】 448期乐观三组学员 472期利他二组...
    福青_3a67阅读 431评论 0 2
  • 最近听了我们花姐的五步逆袭课程,很多学员分享了他们所学,感悟等等,今天我们就来分享一下P0020许露优秀社长的成长...
    她习社阅读 232评论 0 0
  • Nginx之安装配置 标签(空格分隔):高并发网站 Nginx编译安装 安装方法:安装前需要安装:gcc pcre...
    淼熙蕻阅读 286评论 0 0