HoudiniVex笔记_P16_GeometruFunction几何体函数

2023-10-14 18:59

本文主要是介绍HoudiniVex笔记_P16_GeometruFunction几何体函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原视频:https://www.youtube.com/playlist?list=PLzRzqTjuGIDhiXsP0hN3qBxAZ6lkVfGDI
Bili:Houdini最强VEX算法教程 - VEX for Algorithmic Design_哔哩哔哩_bilibili

Houdini版本:19.5

先复习下几何体属性Vertex、Point、Primitive、Detail之间的关系,如下图,

1、添加点

eg.创建类型为Detail的AttributeWrangle节点,写入如下代码,

int pt = addpoint(0, set(0, 0, 0));     //原点添加一个点
setpointattrib(0, 'num', pt, pt+1);     //对点添加属性,属性命名为 num,值为1

结果为:在场景的原点处创建了一个点,其在表格中为:

2、创建螺旋点

eg.创建类型为Detail的AttributeWrangle节点,写入如下代码,

float ang = chf('ang') * $PI;   //角度值float steplen = chf('len');for(int i=0; i<chi('num'); i++){float x = cos(i * ang);     //x坐标float z = sin(i * ang);     //z坐标float y = i * 0.1;          //每次循环高度递增vector pos = set(x, y, z) * steplen;    //相当于缩放int pt = addpoint(0, pos);  //创建点
}

结果:在 Ang=0.1,num=0.2,num=100 条件下,(为排版美观,图已旋转)

3、绘制多边形

eg.创建一个三角形,把360°均分,每120°创建一个点,然后连接起来。
操作:创建类型为Detail的AttributeWrangle节点,写入如下代码,

float ang = chf('ang') * $PI * 2.0;    //初始点的角度值int pt1 = addpoint(0, set(cos(ang), 0.0, sin(ang)));
int pt2 = addpoint(0, set(cos(ang + radians(120.0)), 0.0, sin(ang + radians(120.0))));
int pt3 = addpoint(0, set(cos(ang + radians(240.0)), 0.0, sin(ang + radians(240.0))));int poly = addprim(0, 'poly', pt1, pt2, pt3);

结果:滑动ang值,三角形旋转,

4、创建锥形

先创建锥形底面,底面的点与顶点依次连接

 eg.创建类型为Detail的AttributeWrangle节点,写入如下代码,

float rad = chf('rad');         //圆锥底面半径
float height = chf('height');   //圆锥高度
int num = chi('num');           //圆锥底面点数int pts[] = array();
for(int i=0; i<num; i++){float ang = $PI * 2.0 / num * i;    //360°按点数均分int pt = addpoint(0, set(cos(ang), 0.0, sin(ang)) * rad);append(pts, pt);        //生成的点存到数组中
}
i[]@pts = pts;int cpt = addpoint(0, set(0, height, 0));   //圆锥高度//底面相邻的两个点与顶点相连
for(int i=0; i<len(pts); i++){int pt1 = pts[i];int pt2 = pts[(i+1) % len(pts)];    //取余数更保险int tri = addprim(0, 'poly', cpt, pt1, pt2);
}

结果:

5、创建线

  eg.创建类型为Detail的AttributeWrangle节点,写入如下代码,

int pt1 = addpoint(0, set(-1.0, chf('h1'), 0.0));
int pt2 = addpoint(0, set(1.0, chf('h2'), 0.0));int polyline = addprim(0, 'polyline', pt1, pt2);

结果:略

6、螺旋形折线

与【2、Create Sprial Points创建螺旋点】类似,可使用 addvertex() 函数 或 addprim() 函数

 eg.创建类型为Detail的AttributeWrangle节点,写入如下代码,

float ang = chf('ang') * $PI;   //角度值float steplen = chf('len');//方法一
//int sprialcrv = addprim(0, 'polyline');     //声明一个空折线对象//方法二
int pts[] = array();for(int i=0; i<chi('num'); i++){float x = cos(i * ang);     //x坐标float z = sin(i * ang);     //z坐标float y = i * 0.1;          //每次循环高度递增vector pos = set(x, y, z) * steplen;    //相当于缩放int pt = addpoint(0, pos);  //创建点//方法二append(pts, pt);//方法一//addvertex(0, sprialcrv, pt);        //添加顶点
} //方法二
int sprialcrv = addprim(0, 'polyline', pts);

结果:在 Ang=0.1,num=0.2,num=100 条件下,(为排版美观,图已旋转)

7、 删除点和面

eg.①创建一个Grid节点,细分设置20*20,
②创建类型为Points的AttributeWrangle节点,与Grid连接,

float rad = chf('d');
if(length(@P) < rad){removepoint(0, @ptnum);    //图一
}

③创建类型为Primitives的AttributeWrangle节点,与Grid连接,

float rad = chf('d');
if(length(@P) < rad){removeprim(0, @primnum, 1);     //图二removeprim(0, @primnum, 0);     //图三
}

结果为:当半径 d=0.5 时,

8、从面获取点

eg.给Box每个面开孔,如下图所示,

理论:
①获取每个面的四个顶点,
②面的中心点与面的每个顶点为方向,自定长度,可得出新顶点(挖孔面的点)的位置,
③面的顶点与新顶点,两两相连。
操作:
创建类型为Polygon的Box,添加并连接在类型为Primitives的AttributeWrangle节点,写入代码,

int pts[] = primpoints(0, @primnum);    //获取每个面的顶点i[]@pts = pts;                        //可写可不写
int npts[] = array();
for(int i=0; i<len(pts); i++){         //循环次数为每个面的顶点数int pt = pts[i];vector pos = point(0, 'P', pt);         //面中心点位置vector dir = (pos -@P) * chf('size');   //中心点与面顶点为方向 * 自定义长度vector newpos = @P +dir;                //新顶点位置int newpt = addpoint(0, newpos);        //创建点append(npts, newpt);                    //对新的4个顶点放入数组pts中
}for(int i=0; i<len(pts); i++){              int pt1 = pts[i];                       //面的顶点int pt2 = pts[(i+1) % len(pts)];int pt3 = npts[(i+1) % len(pts)];       //新的顶点int pt4 = npts[i];int poly = addprim(0, 'poly', pt1, pt2, pt3, pt4);  //面顶点与新顶点两两相连
}removeprim(0, @primnum, 1);     //删除面,不保留点
//结果略

9、Primitives From Points从点获取面

pointprims() 函数,返回一个数组,返回包含该点的面。

eg.获取包含该点@ptnum的面,这些面的中心点与该点@ptnum依次连接,如下,

 操作:

创建类型为Polygon的Box,添加并连接在类型为Points的AttributeWrangle节点,写入代码,

int prims[] = pointprims(0, @ptnum);    //包含该点的面/图元i[]@prims = prims;int pts[] = array();
for(int i=0; i<len(prims); i++){        //包含该点的面有3个,所以循环3次int prim = prims[i];vector pos = prim(0, 'P', prim);    //在这3个面的中心位置创建点,有3个点int pt = addpoint(0, pos);append(pts, pt);removeprim(0, prim, 1);     //删除box的6个面,不保留点//在这里先删除,也不会影响其它点的运行
}for(int i=0; i<len(pts); i++){      //每2个面的中间点与点@ptnum相连int pt1 = pts[i];int pt2 = pts[(i+1) % len(pts)];int pt3 = @ptnum;int poly = addprim(0, 'poly', pt1, pt2, pt3);
}

10、Vertex顶点排序

强烈推荐【以下内容大多摘自:知乎@刘鹏云——houdini 中的几何体函数2】

上一节案例创建了一个奇奇怪怪的菱形,它的法线并不全都是朝外,所以本节把它改正。

理论:
①利用点积判断面的朝向/法线,图片来自@知乎刘鹏云,

②反转顶点的顺序来实现面法线反转。
场景中打开顶点、面、面法线(添加类型为Primitives的Normal节点)、表格Vertices,观察可知,面法线与顶点的顺序有关:左手定则——>握拳方向和顶点排序方向保持一致,拇指方向即是面法线方向。

 操作:
①继续使用【9、Primitives From Points从点获取面】的案例,
②添加 fuse节点(融并相同点)、类型为Primitives的法线normal节点,
③添加类型为Primitives的AttributeWrangle节点,
④对上述节点依次相连,并在最后的节点写入以下代码,

vector dir = normalize(@P);     //原点到面中心点的向量值
float dotval = dot(dir, @N);    //点积<0,法线朝内
if(dotval<0){int vts[] = primvertices(0, @primnum);      //该面的所有顶点int pts[] = array();for(int i=0; i<len(vts); i++){              //顶点所在的点pointint vt = vts[i];int pt = vertexpoint(0, vt);append(pts, pt);}pts = reverse(pts);         //顶点组反排序,也可以在下面的循环条件内改为 i--for(int i=0; i<len(pts); i++){int pt = pts[i];int vt = vts[i];//setprimvertex(0, -1, vt, pt);setprimvertex(0, @primnum, i, pt);      //对顶点进行重排序,此函数记得去看@刘鹏云的文章}
}

 结果:略

关于 setprimvertex() 函数解析:图片来自知乎@刘鹏云

顶点的序号在geometry spreadsheet 的显示排列

 而primvertices 返回的顶点号排序是线性的,每个顶点号都具有一个确切的数字.

11、最近点

eg.按下图创建节点,

一些必要或非必要设置:
box2类型设为Polygon;
isooffset1采样设为50或随意:
add节点添加一个点,color节点可要可不要;
nearpoint类型为Points,写入代码,

int npt = nearpoint(1, @P);vector npos = point(1, 'P', npt);
int newpt = addpoint(0, npos);int line = addprim(0, 'polyline', @ptnum, newpt);

 结果为:图片来自知乎@刘鹏云,

12、最近点们

eg.直接使用【11、Line with Nearpoints最近点】的案例,代码修改为:

int npts[] = nearpoints(1, @P, chf('dist'));i[]@npts = npts;for(int i=0; i<len(npts); i++){int npt = npts[i];vector npos = point(1, 'P', npt);int newpt = addpoint(0, npos);int line = addprim(0, 'polyline', newpt, @ptnum);
}

 结果:更改距离及点位置,图片来自知乎@刘鹏云,

13、最近点与相连

eg.继续使用【11、Line with Nearpoints最近点】的案例,删除部分节点

代码节点修改为:

int npts[] = nearpoints(0, @P, chf('dis'));     //最近点     搜索当前点的最近点,搜索范围:disfor(int i=0; i<len(npts); i++){int npt = npts[i];if(@ptnum < npt){   //避免重复相连int line = addprim(0, 'polyline', npt, @ptnum);}
}

 结果为:滑动dis值,图片来自知乎@刘鹏云,

14、几何体最近点

minpos() 函数:给一个位置,在几何体上找出对应最近的点。

本次案例大概是要做这么一个东西:

 操作:
如上右图,创建类型为Point的AttributeWrangle节点代替ray1节点,并写入如下下代码,
小球类型polygon,细分、大小看着设,

vector mpos = minpos(1, @P);@P = mpos;//结果:如上右图

15、柱体与螺旋线最近点

eg.一大一小的圆柱,中间放一根螺旋线,寻找螺旋线对应的最近点,

操作:
①按下图添加节点:

②一些设置:
a)sprial节点的代码使用【6、Create Sprial Polyline螺旋形折线】案例的代码,
b)tube1、tube2都是Polygon类型,它们的高度、大小与sprial节点的通道进行绑定(也可以自由设定),

c)scatter2节点粒子数随意,
d)在类型为Points的minpos_branches节点中写入如下代码,

vector mpos = minpos(1, @P);
int mpt = addpoint(0, mpos);
int line = addprim(0, 'polyline', @ptnum, mpt);

结果:大概如开头的右图 ,感兴趣可以改变螺旋线通道值,查看不同的变化。

16、相交函数

intersect() 函数:返回第一个相交点位置、UV值,若值为-1,则没有相交点

eg.先上结果,寻找直线与小球的相交点,下图使用红色小球代替相交点,(如果直线在小球内部,表示没有相交点),

操作:
①按下图添加节点,

②一些设置,
a)两个小球Sphere类型可设置为Polygon,其中Sphere3可将其缩放,
b)copytopoints1节点的Target Points设置为interpt
c)在类型为Primitives的intersect节点写入如下代码,

vector pos1 = point(0, 'P', 0);
vector pos2 = point(0, 'P', 1);
vector dir = pos2 - pos1;       //直线的长度及方向vector p, uv;
int interprim = intersect(1, pos1, dir, p, uv); //直线与小球的相交点,interprim是相交点所在的面
i@interprim = interprim;if(interprim >= 0){             //如果无相交点,则interprim值为-1int npt = addpoint(0, p);setpointattrib(0, 'Cd', npt, set(1, 0, 0));setpointgroup(0, 'interpt', npt, 1);            //对该点设置属性,方便后面小球复制到这里来
}

17、相交与投影

利用相交函数,本次做一个立方体在地面上的投影。

eg.先上结果:图片来自知乎@刘鹏云,注意,调整直线方向时,必须使其余地面有相交点,否则…

理论:以矩形的顶点为起始点 + 直线为方向(归一化)及自定义长度,然后与地面相交,
操作:
①按下图添加节点:
②一些设置:
a)grid2节点大小随意,类型为Polygon,
b)group1节点命名为floor,
c)box3节点中心点Y值设为1,类型为Polygon,
d)color2节点颜色随意,
e)类型为Points的shadow节点写入如下代码,

vector lpos1 = point(2, 'P', 0);
vector lpos2 = point(2, 'P', 1);
vector ldir = normalize(lpos1 - lpos2) * 1000;      //直线方向+自定义长度vector p, uv;
int interprim = intersect(1, 'floor', @P, ldir, p, uv); //矩形顶点——>直线方向+自定义长度,其其余地面的相交点
i@interprim = interprim;@P = p + set(0, 0.001, 0);      //矩形的点映射到相交点,不加0.001,影子会与地板重叠
@Cd = set(0, 0, 0);             //黑色"影子"

18、多边形相邻点

先上结果,

操作及设置:
按上右图添加节点,并进行设置,
a)sphere4节点类型为polygon,
b)divide1节点勾选 Compute Dual,即把多边形变成偶数点/边,
c)在类型为Points的neighbours节点写入如下代码,

int neighs[] = neighbours(0, @ptnum);       //与该顶点相连的点int poly = addprim(0, 'poly');
for(int i=0; i<len(neighs); i++){int neigh = neighs[i];vector npos = point(0, 'P', neigh);vector dir = npos - @P;                    //顶点与相邻点之间为方向vector newpos = @P + dir * chf('rad');    int newpt = addpoint(0, newpos);        //顶点与相邻点的之间位置创建一个新点addvertex(0, poly, newpt);              //三点成面,即三角形
}removepoint(0, @ptnum);     //删除小球的点

结果:图片来自知乎@刘鹏云,

19、随机取点的相邻点及相连接

 在模型上随机选点,该点的相邻点连成线。

先上结果:线框显示模式下,随机seed值为随机,

理论:
随机在模型上取点,该点的相邻点构成线,
连线之前,判断【该点的相邻点】是否已经使用过,
未使用过,则继续使用【该点的相邻点】的【相邻点】,以此循环。
操作:
①按上图添加节点,
②一些设置:
a)remesh节点的Target Size设为0.1或随意。它的作用是使用(近似等边)三角形重新创建输入曲面的形状,
b)在类型为Detail的attributeWrangle节点写入如下代码,

int conns[] = array();      //该数组用作保存已使用过(已连接)的点for(int t=0; t<1000; t++){int pt = npoints(1) * rand(chf('seed') + 5.25 * t);     //获取随机点pt,rand()函数随机返回0~1if(find(conns, pt) < 0){                        //若该随机点没有使用过,则执行循环int polyline = addprim(0, 'polyline');      //创建一个空折线,后续添加点,连成线//循环创建多个点连成多段线for(int i=0; i<1000; i++){append(conns, pt);                      //把该点加入数组conns,即标记为已使用vector pos = point(1, 'P', pt);         //随机点pt的位置int newpt = addpoint(0, pos);           //在随机点的位置创建新的点vector col = rand(2.651 * t + chf('seed')); //创建一个随机值,下面用作创建随机颜色setpointattrib(0, 'Cd', newpt, col);    //随机颜色addvertex(0, polyline, newpt);          //在随机点创建的点,添加到折线中去int npts[] = neighbours(1, pt);         //随机点的相邻点int check = 0; //检查相邻点们有没有使用过,未使用过,则该点用作下一个点for(int n=0; n<len(npts); n++){         int npt = npts[n];if(find(conns, npt) < 0){           //相邻点未使用过,执行if内代码pt = npt;                       //未使用过的点,作为下一个"随机点"check = 1;break;}}if(check == 0){break;}}}
}

这篇关于HoudiniVex笔记_P16_GeometruFunction几何体函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/212482

相关文章

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注