- 寫在前面的廢話 -
前段時間,當我打開之前講過的使用Spring CHOP實現彈力線條的源文件,認真地看了下裡面密密麻麻的節點、一行行的代碼,當時我的內心:這誰做的啊,這麼麻煩,這麼多沒用的節點和代碼,我不寫一行代碼重做它好了。
翻了一下《代碼本色》中Processing的實現原理和代碼,原理和之前使用Spring CHOP的做法一樣,但發現使用TD的一些TOP節點實現起來更加方便。下面就一起打開TD,不用一行代碼實現彈力的效果吧。
就是這玩意
主要都是使用TOP節點計算
- 視頻教程 -
第一次錄製視頻教程
- 製作思路 -
我們還是以之前TD雜談02 - Spring CHOP中的彈力線條效果為例,這次主要是使用TD中的一些TOP節點去計算彈力,製作思路也是和之前講解的思路一致,最終互動效果類似下方視頻。
最終效果
主要步驟:一、製作25*3的點(列數自己確定)二、滑鼠與線條的觸發事件三、計算彈力(主要)四、音樂添加與觸發
· 製作一排點並渲染成線條
像之前講過的一樣,我們需要製作一排線(這裡是25 * 3),每根線有3個頂點,只使用中間頂點來計算彈力即可。
使用漸變方式為Horizontal和Vertical的兩個Ramp TOP,接入Reorder,分別輸出R和G通道,B通道設置為zero,我們將會得到25 * 3沿x、y的點。然後把點轉成線條渲染出來。
這裡需要注意的是,所有TOP的Pixel Format要設置成32bit,不然無法儲存更多的數據。
轉成線條、調整位置
· 滑鼠與線條的觸發事件
完成了基本的線條之後,我們先來實現滑鼠與每根線的觸發事件,在TD裡面實現這個可以通過寫代碼或者使用Render Pick,使用TOP計算本質上也是和寫代碼一樣,都是通過兩點間的距離公式來判斷滑鼠當前位置觸發了哪根線條。
兩點間的距離公式
因為只需要用到x位置,把滑鼠的x坐標轉成TOP,使用Crop將中間的點提取出來並設置成32 bit float(Mono),接下來就是使用公式了。使用Subtract對兩個數據相減,再使用Math進行平方和開方,移動滑鼠接近每根線條,對應像素位置圖像顯示越黑(值越小),最後使用Threshold設置觸發距離,並把觸發信號轉成0和1。
主要調的參數
做到這裡,觸發信號基本已經完成,因為現在信號是0和1的狀態,我們需要使線條根據滑鼠移動的快慢決定彈力的大小和滑鼠移動的方向決定線條初始彈動的方向,這一步驟我們把彈力實現出來後再製作,這樣就方便觀看。接下來就到了最關鍵的步驟,計算彈力。
· 計算彈力
在開始製作前,先看一下Processing中的一個關於彈力的案例,我們根據裡面核心的代碼用TD的節點去實現。
https://processing.org/examples/springs.html
Processing中關於彈力的案例
force = -k * (tempypos - rest_posy); // f=-ky accel = force / mass; // Set the acceleration, f=ma == a=f/m vely = damp * (vely + accel); // Set the velocity tempypos = tempypos + vely; // Updated position
這個案例計算彈力用到的公式主要是上面這幾行代碼,tempypos是初始位置,對應到TD中的就是最開始時製作的線條中間點的x,rest_posy是滑鼠的Y值,對應的是線條中間點的x加上滑鼠移動產生差值的數據。k是彈力常數,mass是質量,damp是阻尼係數。接下來我們通過使用TOP節點一步步實現每一行代碼。
f=-ky a=f/m
先把代碼裡的公式用節點連出來,把初始位置和上一步做完的觸發信號(force)相減,然後再乘以彈力常數,除以質量,第一行和第二行代碼在一個math裡面計算了。
初始狀態下,力和加速度是為零的,根據彈力運動的狀態來看,我們能想到最終TOP裡面的數據是初始位置加上一個來回閃動並在一定時間內歸零的數據,而要讓數據動起來,我們需要在初始位置後面添加一個Feedback。
vely = damp * (vely + accel)
這一步我們需要計算速度,初始狀態下,速度也是為0,所以需要在這裡使用constant創建一個為0的速度,在代碼中,先拋開阻尼係數不管,vely = vely + accel,想要在數據動的時候每幀都加上原來的速度,我們需要再添加一個feedback,把最終相加的速度(add)給到feedback中。
到這一步,把數據和初始位置相加,移動滑鼠,我們會發現TOP裡面的顏色一直跳動不會停下來,這是因為阻尼係數還沒有添加上去。
添加阻尼係數這一步需要注意,阻尼係數是在加速度相加之後再運算的,所以乘以阻尼係數需要在feedback後面進行運算,而不是在add節點後面。(最開始我就在這翻車了)
tempypos = tempypos + vely
最後把第一個feedback(這個feedback的target需要接入後面這個add)和速度相加(add),移動滑鼠,線條的彈力就完成了。
數據需要閃動並逐漸消失
· 滑鼠控制力的大小和方向
現在線條的彈力和方向都是一致的,我們把前面剩下的滑鼠速度控制力的大小,左右控制方向添加上。
這一步其實和使用Feedback CHOP獲取滑鼠前後幀數據是一樣的,但在TOP裡面使用的不是Feedback,而是使用Cache存儲前一幀的數據再相減。需要注意的是Cache中的always cook要打開。
因為前面的觸發數據是0和1的數據,我們把滑鼠前後幀的數據拉伸為同等的解析度,和觸發數據相乘就能實現根據滑鼠移動速度作為力的大小。
到這裡我們已經達到不寫一行代碼實現了之前使用Spring CHOP做的效果的目標了。
· 音樂添加和觸發
前面的觸發信號都做好了,音樂觸發這裡就很簡單了。把音樂文件夾的Table拉到Audio Play參數中的Dat List中,使用觸發信號調用Audio Play的play方法。等等,不是說不寫一行代碼嗎... ...好吧,打臉了,要寫一行,因為這方法是最方便了。
play(index, start=True, loop=False, delaySeconds=0.0, pan=None, rolloff=None, volume=None, fadeSeconds=0.0)還是寫了一行代碼
說起音樂播放這事,想起自己當時真的是愚蠢。之前使用Spring CHOP做的那版,我是這樣做的:有多少個音樂文件就用代碼創建多少個 Audio File In,然後把輸出都組合起來給到Audio Device Out。
用了超級多節點
整個案例製作就完成了,對比兩種方法,使用TOP計算更加方便,不需要做太多的數據轉化,也不需要寫太多代碼,在運行上效率也更快。
之前使用Spring CHOP做的那一版有很多節點可以簡化掉的,畢竟是剛學TD不久的時候製作的,有時間再優化一下。
使用CHOP做的,裡面還有很多節點
使用TOP做的,更加方便
- 結語 -
這次分享就到此結束了,公眾號後臺回復」SpringTOP「可獲取TD文件下載地址。
以後我們會繼續與大家分享一些關於使用TOP做一些公式、算法運算的技巧,敬請關注。
Touchdesigner · Notch · Arduino · Blender