在Houdini里固定半径范围内改变权重中心点的方法

大家都知道如果使用点云或者使用类似attribTransform这样的节点来采样或者传值的时候,都是以点为圆心一定半径均匀的采样,近几天为了做一些比较特殊的牵引效果所以好好琢磨了一下非均匀的线性采样方法,这个词有点太绕,我先上两张对比图看一看:

权重改变前                       权重改变后

要求是在上面第一张图限定的半径范围内,改变权值为1的中心点位置该点到圆的边缘还是从1到0的线性渐变过度(如果用指数运算就不是线性了,但还是连续过渡的渐变)。

这里的方法其实也不算特别复杂,下面是我对方法求导的思维过程:

这里M是原来的中心点;M‘是移动后想要变换过去的中心点;P目标面上的任意一个点,当然该点是以M为中心R为半径的球内部的一个点;P‘是从M‘P延长线与刚才提到的M为中心的球的焦点。因为这四个点必然在同一个平面上,所以我们直接可以转化为平面三角算数题。

重新变换之后,权重中心点在M‘上,所以P点的实际权重值应该是PM‘ / P‘M‘,点M,M‘,P都是空间内已知的三个点了,所以难点就是求出M‘P‘的长度了。

三角数学中学知识啊中学知识啊,全还给老师了,忘记公式也是在所难免的,好在我们还有wiki:http://en.wikipedia.org/wiki/Triangle

这个页面中有提到一个非常重要的公式是我用到了的,当然也许你根本不用查这个页面就知道了:

在我画的草图里面θ角是用向量可以算出来的,这样的话φ角也用是能用M‘M算出来的,所以M‘P‘对应的α角也能求出来,同理M‘P‘对应的也出来了。

在Houdini实现方法:

pw_maxRadius:

int handle = pcopen(1, "P", P, 99, 1);
float maxDis = ch("maxDis");
float pow = ch("pow");

while(pciterate(handle)){
    float distance;
    pcimport(handle, "point.distance", distance);

    distance = fit(distance, 0, maxDis, 1, 0);
    distance = pow(distance, pow);
    //[email protected] = distance;
    @Cd = set(distance, 0, 0);
}

pw_deform_weight:

float pi = 3.14159265354;
float maxRadius = ch("maxRadius");
float gradient = ch("gradient");

int handle = pcopen(1, "P", P, 99, 1);
int pointNum;
while(pciterate(handle)){
        pcimport(handle, "point.number", pointNum);
}

vector origPos = point(1, "P", pointNum);
vector deformedPos = point(2, "P", pointNum);

vector m = origPos - deformedPos;
vector s = @P - deformedPos;

float sinTheta = length(cross(normalize(m), normalize(s)));
float factor = maxRadius / sinTheta;
float sinBeta = length(m) / factor;
float alpha;
//check the theta angle is less or more than 90 degrees
if(dot(m, s) > 0){
        alpha = pi - asin(sinTheta) - asin(sinBeta);
}
if(dot(m, s) < 0){
        alpha = asin(sinTheta) - asin(sinBeta);
}
if(dot(m, s) == 0){
        alpha = acos(length(m) / maxRadius);
}

f@alpha = alpha;
float edge = factor * sin(alpha);

float distance = length(s) / edge; 

if(distance<=1){
        distance = pow((1- distance), gradient);
        v@Cd = set(distance, 0, 0);
        f@distance = distance;
}
else{
        v@Cd = set(0, 0, 0);
        f@distance = 0;
}

pw_deform:

float dragScale = ch("dragScale");
float pushScale = ch("pushScale");

int handle = pcopen(geoself(), "P", P, 99, 20);
int count = 0;
vector smoothColor = set(0, 0, 0);

vector origPos = point(1,"P",0);
vector deformedPos = point(2,"P",0);
vector deform = deformedPos - origPos;

while(pciterate(handle)){
        int pointNum;
        pcimport(handle, "point.number", pointNum);
        if(pointNum != @ptnum){
                vector tmpColor;
                pcimport(handle, "Cd", tmpColor);
                smoothColor += tmpColor;
                count ++;
        }
}

smoothColor /= float(count);
@Cd = smoothColor;
f@distance = smoothColor.r; 

@P += (normalize(@N) * pushScale + deform * dragScale) * smoothColor.r;

这个方法的要求是M‘M的距离不能超过半径R的值(超出了会出错),而且球外所有点的权重值都会大于1。

时间: 2024-11-10 18:18:50

在Houdini里固定半径范围内改变权重中心点的方法的相关文章

外网訪问内网应用实现之无公网IP、多port、固定port、UDP等应用的实现方法

有公网IP时,能够通过路由映射来实现外网訪问内网.然,当没有公网IP时,怎样实现外网訪问内网应用? 硬件路由方法因为无公网不可行,能够使用软件port映射的方法.如开放的NAT123全port映射. 全port映射的原理是利用在内网软件将域名绑定server,外网通过域名的訪问实现.此方式不须要改变訪问port,但须要在訪问时,同一时候启用点到点的訪问端. 实现过程: 1,内网使用开放的NAT123port映射. 2,加入映射.选择全port映射. 3,外网地址能够使用自己的域名,也能够直接使用

导航固定时页面内锚点跳转问题

写在前面: 记录对一个小问题的不算解决的方法,大家如果有更好的方法,欢迎交流,谢谢 Demo百度云链接:http://pan.baidu.com/s/1qW9NLlM 问题说明:上面导航栏固定,页面内实现锚点平滑跳转,跳转时如何使页面处于导航栏之下? 解决方式:通过一个div,给div导航的高度,每次跳至div处 问题图片: 希望蓝色位于导航下方: 解决后的问题图片: 补加一个div,定位到红色处 页面平滑跳转代码javascript <script> $('.learnmore').clic

UIButton点击后改变背景的等方法 按钮

请问下UIButton点击后改变背景的方法 http://www.cocoachina.com/bbs/read.php?tid-48666-keyword-UIButton.html ? 1 2 3 4 5 6 7 8 9 10 11 12 13 //初始设置: UIImage *bgImg1 = [UIImage imageNamed:@"Selected.png"]; UIImage *bgImg2 = [UIImage imageNamed:@"Unselected.

SQL SERVER2008不在同一局域网内实现订阅发布的方法

我们知道,在新建订阅的时候,必须要使用实际服务器的真实名称才可以,IP地址,别名都不可以,在同一个局域网内是没有问题的.但是两台服务器不在同一个局域网内就不行了 要想实现订阅和发布,本人用到的最简单的方法: 一:查看实际服务器的名称: 二:在发布的服务器的hosts文件里添加上要推送的订阅服务器的IP地址和名称,记得,这个名称需要和发布服务器的名称保持一致 这样,就可以对他们建立连接了: SQL SERVER2008不在同一局域网内实现订阅发布的方法,布布扣,bubuko.com

Struts2一个Action内包含多个请求处理方法的处理,method的使用方法,struts2中

struts2的关于method="{1}"意思详解 <action   name= "Login_* "   method= "{1} "   class= "mailreader2.Login ">中Login_*带*是什么意思?method= "{1} "带{}这个是什么意思?====================================================name=

ABAP 动态生成内表的几种方法

最近要写个程序,既有更新的,也有删除的,需要涉及到很多系统表,如果一个表一个表进行更新或者删除太慢了,于是就想通过创建动态内表来实现这些功能,在网上找了一些资料,经过多次尝试,终于测试成功了.网上讲述的创建动态内表的方法大致有两种.我做了一下测试,源代码附后.在这里提醒大家一点,在做动态更新程序的时候,要注意两点:      1.使用modify (p_tabname) from <dyn_wa>. 的时候,一定要确定要更新的字段是不是系统表的关键字段,如果是关键字段的话,需要先删除这条记录,

python装饰器内获取函数有用信息方法

装饰器内获取函数有用信息方法 .__doc__用于得到函数注释信息 .__name_用于得到函数名 在函数引用装饰器的时候,函数名会变为装饰器内部执行该函数的名字,所有在直接执行函数名加.__doc__或__name_的时候得到的是,装饰器内部函数的注释信息和名字.因为函数名被替换了. 所以想得到实际的内容,需要引用一个模块,from functools import wraps,并在装饰器函数内部再加一个@wraps的形式改变,得到实际想得到的信息. 作用是在函数加上装饰器后让能够得到真正原来

应用内设置语言不重启方法

1.设置本应用方法网上有很多,大概如下 Resources resources = getResources(); Configuration config = resources.getConfiguration(); DisplayMetrics dm = resources.getDisplayMetrics(); config.locale = locale; //目标语言 resources.updateConfiguration(config, dm); resources.flus

C#实现在Form里面内嵌dos窗体的方法

C#实现在Form里面内嵌dos窗体的方法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 using System; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Diagnostics; namespace cmdForm {  public partial class F