工程链接
链接:https://pan.baidu.com/s/1RUdVyNYY2VIK1SkvN3eLyQ
提取码:zfof
之前看的houdini教程,都是使用pcopen来打开一个点云,然后用完还要关闭这个点云文件,节省资源。可是到了最近的教程,都是直接使用pcfind来查找点云。我以为pcfind是pcopen的一个简化版,但是实际上两者在处理数据的时候并不一样。
但是pcfind和nearpoints结果是一样的。另外这里虽然一直提的pcopen,但是在具体处理点云数据的时候是使用pcfilter函数,因为它依靠pcopen为前提,所以标题写为pcopen了。
可以下载上面那个工程看下,简单来说就是使用模型的点法线和位置做叉乘,得到的新的矢量作为volume的速度场。重点不是在于实现方式,而是pcopen和pcfind所产生结果的差异和原因。
在都是1个单位范围内查找10个点的前提下,两个的结果是这样的:

因为资产模型是一把剑,能看到当都获取10个点信息的时候,pcopen是可以维持住一把剑的基本形态,而pcfind则是完全的自我扰乱。
这个跟我写pcfind的函数方式有关系:
1 2 3 4 5 6 7 8 9 10 11 12 |
float radius = chf("radius"); int maxpoints = chi("maxpoints"); int cpt[] = pcfind(1, "P", @P, radius, maxpoints); vector pos; vector normal; foreach(int pt;cpt) { pos = point(1, "P", pt); normal = point(1, "N", pt); pos = normalize(pos - @P); } v@vel = cross(pos, normal); |
虽然使用foreach来处理这10个点的数据,但是后面的点会覆盖掉前面的点的数据,所以最后使用到的数据只是第10个点的数据,跟前面9个点毫无关系。
但是pcopen中是不需要自己处理怎么选择10个点的数据的,它有一个专门的pcfilter来过滤这10个点的数据:
1 2 3 4 5 6 7 |
float radius = chf("radius"); int maxpoints = chi("maxpoints"); int cpt = pcopen(1, "P", @P, radius, maxpoints); vector pos = pcfilter(cpt, "P");; vector normal = pcfilter(cpt, "N"); pos = normalize(pos - @P); v@vel = cross(pos, normal); |
所以这里的代码并没有用到循环。而pcfilter处理多个点的数据时,是有一套自己的计算方式,可以查看一下帮助文档,简单说就是越靠近中心的点数据权重越大,而不是把10个点的数据相加再除以10。
因此pcopen考虑到了10个点的数据,并做了数据“顺滑”处理。
当然我们可以自己在pcfind中手动定义一个平均数值的操作,这样的结果基本和pcfilter差不多了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
float radius = chf("radius"); int maxpoints = chi("maxpoints"); int cpt[] = pcfind(1, "P", @P, radius, maxpoints); vector pos; vector normal; vector pos1; vector normal1; foreach(int pt;cpt) { pos = point(1, "P", pt); normal = point(1, "N", pt); normal1 += normal; pos1 += normalize(pos - @P); } v@vel = cross(pos1/maxpoints, normal1/maxpoints); |
这样平均处理后,两者的结果很接近,但是能看出来,还是pcopen的结果更顺滑。

当然,如果自己真的按着pcfilter那种过滤公式来计算数据的话,理论上结果应该是相同的。
(完)
感谢大佬分享!
pcpcfilter确实是对找到的点的数据进行了filter平滑处理,按照一定的比重(效果很nice)
但是楼主的pcopen与pcfind的写法不一样才导致了这种差别
pcfind是取得是找到的第9个点的数据,pcopen取第9个点的数据是这样写的。
float radius = chf(“radius”);
int maxpoints = chi(“maxpoints”);
int cpt = pcopen(0, “P”, @P, radius, maxpoints);
vector pos;
vector normal;
int count = pcnumfound(cpt);
for(int i = 0; i < count; i++){
int ptnum = 0;
pciterate(cpt);
pcimport(cpt, "point.number", ptnum);
pos = point(0, "P", ptnum);
normal = point(0, "N", ptnum);
pos = normalize(pos – @P);
}
pcclose(cpt);
v@vel = normalize(cross(pos, normal));
经过我的实验,这样写pcfind与pcopen的结果是一样的。
具体区别我也不知道,期待楼主再开贴细说
再次感谢大佬分享!