Houdini和Touchdesigner中实现场力与弹力的相互作用

最近一直在研究怎样怎样将程序化特效和动画从houdini中转移到touchdesigner中,前段时间拿着了leapmotion做开发,自己一个人自娱自乐也快玩疯了。

今天讲一讲从法国一个虚拟交互舞团某个场景中得到灵感,设计一个简单的通过斥力和弹力混合出来的平衡场效果。

首先看一看人家在舞台上达到的是个什么效果:

在应用之前,先讲一讲我通过这个视频看到的原理。

人物的运动提供了一个位置信息P,也许群体运动的那个画面中提取了运动的速度或者加速信息,这里先不做复杂的讨论。画面中的每个点pt与上述提供的信息位置P进行计算。主要产生两种力,第一个是根据点P与pt的位置距离和方向,预设一定阈值,在某个半径范围内行程排斥力,这个力可以是F = k * pow((maxDistance - distance)/maxDistance, n)。这样越接近点P的点受到的排斥力越大,同时通过调节n,可以让这个斥力更想磁场的排斥力。接下来是第二种力,我们可以称它为弹力,先记录下每一个点pt的原始不动的位置。一旦点收到排斥力的影响而离开了原始点,这时候将点拉回原始点的弹力就产生作用了,这个力的公式直接可以使用弹力公式F = k * distance。斥力设计成指数型,弹力依旧使用线性方程,这样的动画看起来也更有趣味性一些。

上面的分析基本上奠定了之后再houdini里面以及touchdesigner里面如何实现的方法了。

先讲一讲在houdini里面实现的方法。

在Houdini里面可以直接在sop solver里面通过帧数的迭代达到这样的效果,通过新建一个vex节点,分别读取目标点位置以及前一帧点的位置,速度值来计算出当前帧每个点的位置。

其中我抽取出了几个关键的参数来调整力的大小以及弹性的软硬程度:

Damp - 阻尼大小,能够影响减速的速度

Spring Index - 弹性指数,越大点抖起来越硬

Magnet Exponent - 用来调整斥力大小与距离的关系

Magnet Scale - 调整斥力大小

Max Distance - 立场半径

这里是Houdini的vex代码:

 1 #pragma label damp "Damp"
 2 #pragma label springIdx "Spring Index"
 3 #pragma label magExp "Magnet Exponent"
 4 #pragma label magnetScale "Magnet Scale"
 5 #pragma label maxDist "Max Distance"
 6
 7
 8
 9 sop
10 SpringMagnet(float damp = 0.9;
11             float springIdx = 0.5;
12             float magExp = 1;
13             float magnetScale = 0.5;
14             float maxDist = 1;
15                )
16 {
17 vector target = point(1, "P", 0);
18 vector rest   = point(geoself(), "rest", ptnum);
19
20 // get the spring force based on the rest position
21 vector displace = rest  - P;
22
23 vector springForce = displace * springIdx;
24
25 // get the magnet force from the target position
26 vector magDist = P - target;
27 float distance = length(magDist);
28
29 vector magnetForce = set(0,0,0);
30
31 if(length(distance) < maxDist){
32     distance = pow(fit(distance, 0 , maxDist, 1, 0), magExp);
33     magnetForce = normalize(magDist) * distance;
34 }
35
36 vector mainAcc = magnetForce * magnetScale + springForce;
37
38 v += mainAcc;
39 v = v * damp;
40 P += v;
41 }

接下来就是在TouchDesigner(简称TD)中的应用了,这才是重点 :P

TD里面对外部硬件接口的能力是非常强大的,自己的leapmotion前段时间借给同事去玩去了,所以这里首选Ipad上面的OSC作为操作输入口,提取了能够调节两个方向的slider值。

因为我的方法还是影响三维中的点,之后再把点渲染投射到平面上去。所以接下来就是常规的通过geo,light,camera和render搭建标准的三维场景。

完成之后将geo的连接给script sop。这里插一句,TD是全方位和python接轨,所以写脚本什么的直接用python的就好了。之前是Tscript,由于TD和Houdini是同根同源的开发平台,很多思想和理念都是一脉相承,Tscript像极了在Houdini里面写expression的感觉,但是没有像VEX这样完善的脚本语言支持,所以直接全部转接到了Python中。好处是一步到位,什么都用python这个胶水做好,目前不太方便的地方是tdu模块不是特别完善,很多vex中函数能够一步到位的问题,到了这里需要绕很多个弯。这个案例中我就遇到了Vector类中的normalize函数怎么也出不来正确的值,永远出来一个none对象,debug了很久最后查出原因了还是使用的老办法自己算一遍模才得到准确的norm。也许设计者的想法是我们在python中调用其他第三方模块来解决这些问题,但是作为一个Houdini玩家,被Houdini真的宠坏了,除了numpy,url,math这些常用的模块,其他真的不怎么熟悉了 TvT

代码这部分基本是和VEX里面的一个思路了,重新用python写一遍。其实从这两个功能一致但是环境不一样的代码可以看出houdini和TD的不同了。

 1 # me is this DAT.
 2 #
 3 # scriptOP is the OP which is cooking.
 4
 5 def cook(scriptOP):
 6     import math
 7
 8     #use button to refresh the screen
 9     button = op(scriptOP.par.string2.eval())
10     if button[0].eval() != 0:
11         scriptOP.clear()
12
13     #get the controller data
14     controlOp = op(scriptOP.par.string1.eval())
15     damp        = float(controlOp[‘Damp‘, 1])
16     springIdx  = float(controlOp[‘Spring Index‘, 1])
17     magExp     = float(controlOp[‘Magnet Exponent‘,1])
18     magScale   = float(controlOp[‘Magnet Scale‘, 1])
19     maxDist    = float(controlOp[‘Max Distance‘, 1])
20
21     #get the target position
22     target = op(scriptOP.par.string0.eval())
23     targetPos = tdu.Vector(target.points[0].x, target.points[0].y, target.points[0].z)
24
25     #get the me.points
26     myPoints = scriptOP.points
27     if not myPoints:
28         scriptOP.copy(scriptOP.inputs[0])
29         myPoints = scriptOP.points
30
31     for i in range(len(myPoints)):
32         #get the current point position and rest position
33         ptPosition   = tdu.Vector(myPoints[i].x, myPoints[i].y, myPoints[i].z)
34         restPosition = myPoints[i].rest
35
36         #define the spring force
37         displace = restPosition - ptPosition
38         springForce = displace * springIdx
39         #print(springForce)
40
41         #define the magnet force
42         magDirection = -(targetPos - ptPosition)
43         magDistance = magDirection.length()
44         magForce = tdu.Vector()
45         if magDistance < maxDist:
46             scaleDist = 1 - magDistance / maxDist
47             mode = math.sqrt(magDirection[0]*magDirection[0] + magDirection[1]*magDirection[1] + magDirection[2]*magDirection[2])
48             magDirection /= mode
49             magForce = magDirection * scaleDist * magScale
50
51
52         #combine all forces together
53         acc = magForce + springForce
54
55         #add to vel and update the point position
56         myPoints[i].v[0] += acc[0]
57         myPoints[i].v[1] += acc[1]
58         myPoints[i].v[2] += acc[2]
59
60         myPoints[i].v[0] = myPoints[i].v[0] * damp
61         myPoints[i].v[1] = myPoints[i].v[1] * damp
62         myPoints[i].v[2] = myPoints[i].v[2] * damp
63
64         myPoints[i].x += myPoints[i].v[0]
65         myPoints[i].y += myPoints[i].v[1]
66         myPoints[i].z += myPoints[i].v[2]
67
68     return

因为TD是开发实时交互应用的平台,所以时效性是非常重要的一个关键。做好的一整套打包成程序在1280*720分辨率下跑起来的是后基本上速度是在30帧稍稍多一点,平均每帧计算时间是31.36ms,但是script sop中的脚本因为是每一帧都要计算一遍的,而消耗时间每帧将近21ms左右,尽然是总时长的2/3。这里我使用的点数是30 * 48 = 1440个。可想而知,脚本的优化很大成程度上会影响程序动画的效果。这个在以后的日子里面得好好研究。

还有一个值得注意的地方是,这个案例中我把点的运动速度转到chop中去,目的是想让它在运动的时候可以通过速度的变化来改变自身的颜色值。把速度变化值变为波形之后,在这个基础上进行变换效率是非常高的,可能是这一块的内置计算方法做过非常大的优化,以后试试看能不能直接在波形上做计算,在把chop的channel传给点的坐标上。

这一篇先到这里了。

时间: 2024-11-06 11:05:37

Houdini和Touchdesigner中实现场力与弹力的相互作用的相关文章

TouchDesigner中通过GLSL 把视频变成六角形、三角形和圆形的像素化效果

做的几个类似的滤镜实验,主要是想把普通的视频做成能有一些比较风格化的效果,参考了shadertoys里面的一些案例,然后在touchdesigner中分别实现了六角形.三角形和圆形的马赛克效果,如果再做一些颜色调整其实能达到比较有意思的互动效果.下面是效果图: original hexagon circle triangle 当然所有效果也都是实时的. 下面是代码: HEXAGON,这个效果在搜寻最近六边形上有一个大神已经把算法做好了,直接照着他的用就好了: http://www.gamedev

Unity3D 中3D刚体组件的力

一般一个物体除了手动添加刚体受到重力作用外,还可以给该刚体添加一个其他的力. 这里就要涉及到一个恒定力(Constant Force)组件 首先要去掉物体的重力(因为重力是刚体组件中默认的一个向下的力)影响.然后在力组件中添加一些力去控制该物体.

中互联携手合作伙伴召开首届O2O营销峰会暨产品发布会

5月15日,中互联首届O2O营销峰会暨产品发布会在京举行.来自品牌机构.电商.游戏和中小企业广告主等领域的合作伙伴与中互联共同见证了新产品和多项创新服务的发布,并探讨了O2O营销行业的未来发展趋势,以及如何共同协作构建O2O营销生态圈. 据了解,此次会议是由专业的O2O综合解决方案中互联倾力打造,公司2014年8月获得数千万融资并启用国际顶级域名ZHL.COM,正式全面进军O2O,为成为国内领先的O2O智慧化移动数据解决方案提供商而全面发力. 本次发布会以"舞在风口,谁主沉浮--互联网+时代下,

【Unity】11.6 恒定力 (Constant Force)

分类:Unity.C#.VS2015 创建日期:2016-05-02 一.简介 恒定力 (Constant Force) 是用于向刚体 (Rigidbody) 添加恒定力的快速实用工具,适用于类似火箭等发射出来的对象,这些对象在起初并没有很大的速度但却是在不断加速. 如果您不希望单次发射对象(如火箭)以较大速率启动而是希望缓慢地进行加速,则这十分适用于这类对象. 下图是由恒定力 (Constant Force) 向前推动的火箭: 二.相关属性 1.Force (力) 在世界坐标空间中应用的力的向

职场二年级转型C++的困惑

[来信] 老师.你好.看了你的博客和採訪.不由主自地给你发私信,感觉你能解答我的问题. 学生90后,2012年毕业于某不知名院校.两年工作经验(第一年C#,第二年java,直到如今),一直想转型C++开发,近来思考了非常多.非常烦燥. 转型原因是厌倦了ERP开发.增删查改.经常使用框架之类的东西,希望能向研发或低层一点的方向发展.希望多一点接触算法和设计模式的知识. 问题一:C++的开发主要有哪些领域?游戏开发?win32.MFC?server开发?(在网上略微看了一些招聘,好像大多都是游戏开发

【转载】非线性分析中的ansys跟踪显示

原文地址:http://muchong.com/html/201209/4936556.html 在ansys output windows 有 force convergenge valu 值 和 criterion 值,当前者小于后者时,就完成一次收敛.非线性计算是一个迭代计算的过程,曲线表示两次迭代之间的误差,图中分别表示力和位移在迭代过程中的每次迭代之间的误差 两条线的意思分别是:F L2: 不平衡力的2范数F CRIT: 不平衡力的收敛容差,如果前者大于后者,说明没有收敛,要继续计算.

从强提醒说起——社交场景下的万有“隐力”

2018年的最后一天,微信推出了上线以来的第7个大版本:微信v7.0.在微信v7.0里,微信推出了三个大功能:即刻视频,好看和强提醒.分别代表了社交场景下的3个热点:流媒体.Timeline.即时通讯.作为一个即时通讯行业的从业者,看到“强提醒”这样的功能在微信上亮相,想和大家聊聊这背后的碰撞和演变. 打开新版微信,在你关心的联系人会话页面点击右上角,除了过去的置顶聊天和消息免打扰,新增了一个强提醒开关.打开开关,微信会将对方3小时内发送的第一条消息全屏提醒,并伴随着震动.无论你是打开了微信ap

软件工程师如何提升自己的思考力(转)

原文:https://mp.weixin.qq.com/s/wQXg2fYD167DNJ2jzmL1ug 阿里妹导读:很多程序员在工作一段时间后会遇到迷茫期,虽有技术傍身,也难免会产生焦虑,反复思考怎样才能快速成长.关于如何提高自己的思考力,运用思考的力量推动能力提升,以此实现技术成长,阿里巴巴盒马产品技术部的岩动总结了一套思考方法,分享给每个正在成长的程序员.(本篇文章较长,阅读时间约30分钟,建议收藏后,找一个合适的时间慢慢品读哦) 引言 我们来看一下几类在程序员成长.发展的常见问题,如果你

【CSS】Houdini, CSS的成人礼

前情提要 CSS:老板,你看ES9,ES10都出来了,您看我的事情什么时候... W3C: 这不是正在走着流程嘛!小C你不要心急! W3C:(语重心长)你看啊,我们先(1)提个开发提案章程, 然后再批准成立工作组(2)紧接着工作组建立标准和指南,然后再修改修改.(3)再然后啊,给顾问委员会技术报告审核一下(4)最后浏览器厂商再实现一下 这不就完事了吗?大概不到10年咱们就全部搞定了吧 CSS: ...... (难过) W3C:(顿了顿):但是这些年啊,你的刻苦努力我们都是看在眼里的! CSS:所