使用Processing和PixelFlow庫創建交互式流體太極動畫
- 引言
- 準備工作
- 效果展示
- 代碼結構
- 代碼解析
- 第一部分:導入庫和設置基本參數
- 第二部分:流體類定義
- `MyFluidDataConfig` 類詳解
- `MyFluidData` 類詳解
- `my_update` 方法詳解
- 流體類定義完整代碼
- 第三部分:太極類定義
- 太極類定義完整代碼
- 結語
引言
本教程將指導您如何使用Processing編程環境結合PixelFlow庫來創建一個交互式的流體太極動畫。PixelFlow是一個基于GPU的實時圖形庫,它提供了高效的流體模擬功能。我們將通過麥克風輸入的音頻振幅來驅動流體模擬,并在流體之上繪制一個動態的太極圖案。
本章項目代碼的獲取方式:去公主號【帥小柏】,回復【008】獲取喔
準備工作
-
安裝Processing:訪問Processing官網下載并安裝Processing IDE。
-
導入DwPixelFlow庫:在Processing中,通過菜單"Sketch" -> “Import Library…” -> “Add Library…”,搜索并安裝
DwPixelFlow
庫。 -
導入聲音庫:同樣地,搜索并安裝
Minim
庫,用于處理聲音輸入。
效果展示
什么?這個processing流體代碼竟然免費開源送給大家!!
代碼結構
我們的項目將包含以下幾個主要部分:
- 設置窗口和基本參數:定義窗口大小、背景色和線條顏色。
- 聲音輸入設置:使用Processing的
AudioIn
和Amplitude
類來獲取麥克風輸入的音頻振幅。 - 流體模擬設置:初始化PixelFlow庫,創建流體對象,并設置其參數。
- 太極圖案設置:創建太極對象,并為其分配繪制層。
- 主循環:在
draw
函數中更新流體模擬和太極圖案。
代碼解析
第一部分:導入庫和設置基本參數
import com.thomasdiewald.pixelflow.java.DwPixelFlow;
import com.thomasdiewald.pixelflow.java.fluid.DwFluid2D;import processing.core.*;
import processing.opengl.PGraphics2D;
import processing.sound.*;int viewport_w = 600; // 定義窗口寬
int viewport_h = 600; // 定義窗口高
color bg_color = #FFFFFF; // 背景色
color line_color = #000000; // 線條顏色DwFluid2D fluid; // 流體
PGraphics2D pg_fluid; // 流體層// 聲音麥克風輸入
AudioIn audioIn;
// 振幅-音量
Amplitude rms;Taichi taichi; // 太極
PGraphics2D pg_taichi; // 太極圖層
PGraphics2D pg_obstacles; // 障礙物
float taichi_radius = 100;void settings() {size(viewport_w, viewport_h, P2D);
}void setup() {background(bg_color);frameRate(60);// 設定聲音setupSound();// 設置流體參數setupFluid();// 設置太極圖setupTaichi();
}void setupSound() {audioIn = new AudioIn(this, 0);audioIn.play();rms = new Amplitude(this);rms.input(audioIn);
}void setupFluid() {// 初始化pixelflowDwPixelFlow context = new DwPixelFlow(this);context.print();context.printGL();// 流體模擬fluid = new DwFluid2D(context, width, height, 1);fluid.param.dissipation_velocity = 0.70f;fluid.param.dissipation_density = 0.60f;fluid.addCallback_FluiData(new MyFluidData(rms));// 流體層pg_fluid = (PGraphics2D)createGraphics(width, height, P2D);// 障礙物層pg_obstacles = (PGraphics2D)createGraphics(viewport_w, viewport_h, P2D);pg_obstacles.smooth(4);
}void setupTaichi() {pg_taichi = (PGraphics2D)createGraphics(viewport_w, viewport_h, P2D);pg_taichi.smooth(4);taichi = new Taichi(new PVector(width / 2, height / 2), 100, pg_taichi, rms);
}void draw() {// 流體更新drawFluid();// 太極圖drawTaichi();
}void drawFluid() {// 繪制障礙物drawObstacles();// 給流體增加障礙物fluid.addObstacles(pg_obstacles);// 流體更新fluid.update();fluid.renderFluidTextures(pg_fluid, 0);// 顯示流體層image(pg_fluid, 0, 0);// 顯示障礙物層image(pg_obstacles, 0, 0);
}void drawObstacles() {pg_obstacles.beginDraw();pg_obstacles.blendMode(REPLACE);pg_obstacles.clear();float x = width * 0.5;float y = height * 0.5;pg_obstacles.pushMatrix();pg_obstacles.translate(x, y);pg_obstacles.stroke(line_color);pg_obstacles.strokeWeight(2);pg_obstacles.noFill();pg_obstacles.circle(0, 0, 500);pg_obstacles.popMatrix();pg_obstacles.endDraw();
}void drawTaichi() {pg_taichi.beginDraw();pg_taichi.blendMode(REPLACE);pg_taichi.clear();pg_taichi.pushMatrix();taichi.display();pg_taichi.popMatrix();pg_taichi.endDraw();image(pg_taichi, 0, 0);
}
第二部分:流體類定義
-
MyFluidDataConfig
類:用于配置流體運動的參數,比如圓的位置、半徑、運動的角度和速度以及顏色等。 -
MyFluidData
類:實現了DwFluid2D.FluidData
接口,用于更新流體物理仿真的狀態,同時整合聲音輸入作為流體動態變化的一部分。 -
my_update
方法:是流體物理仿真更新的核心,它計算流體粒子的速度和位置,并且將這些數據傳遞給流體庫來模擬流動。
現在,讓我們進一步分析并解釋每個部分的作用以及如何操作。
MyFluidDataConfig
類詳解
這個類定義了流體仿真所需要的一些配置參數。例如:
x
,y
: 圓心位置。radius
: 半徑。isClockwise
: 定義旋轉方向。angleSpeed
: 角速度。rx
,ry
,prx
,pry
: 當前和之前的位置坐標。angle
: 當前角度。c
: 顏色。
MyFluidData
類詳解
此類使用 MyFluidDataConfig
中定義的配置來創建兩個配置對象 config1
和 config2
。它們負責控制流體仿真中兩個獨立的流動體的行為。此外,它接收一個Amplitude
對象(rms
),它可能用于分析音頻信號并將其影響應用于流體動畫。
my_update
方法詳解
這個方法是每一幀都會調用的,用于更新流體的狀態。步驟如下:
- 使用極坐標計算弧上點的位置。
- 隨機量產生抖動,使流動效果更自然。
- 計算速度,并根據是否順時針調整y軸速度。
- 將計算的位置和速度用來更新流體對象的狀態。
- 根據聲音級別調整流體密度的半徑大小。
- 添加顏色和密度到流體中。
流體類定義完整代碼
public class MyFluidDataConfig {float x; // 圓心位置xfloat y; // 圓心位置yfloat radius = 100; // 半徑boolean isClockwise; // 是否是順時針float angleSpeed = 0.04;float rx, ry, prx, pry; // 圓周運動,弧上的點位置,以及上一幀的點位置float angle = 0; // 角度color c; // 顏色
}public class MyFluidData implements DwFluid2D.FluidData {MyFluidDataConfig config1;MyFluidDataConfig config2;Amplitude rms;MyFluidData(Amplitude rms) {this.rms = rms;float x1 = width * 0.5;float y1 = height * 0.5;config1 = new MyFluidDataConfig();config1.x = x1;config1.y = y1;config1.radius = 130;config1.isClockwise = true;config1.angleSpeed = 0.05;config1.c = color(0.0, 0.0, 0.0);config1.angle = PI / 2;config2 = new MyFluidDataConfig();config2.x = x1;config2.y = y1;config2.radius = 130;config2.isClockwise = true;config2.angleSpeed = 0.04;config2.c = color(0.0, 0.0, 0.0);config2.angle = - PI / 2;}void my_update(DwFluid2D fluid, MyFluidDataConfig config) {float vscale = 14;float soundLevel = rms.analyze() * 1000;float delta = random(-3, 3);// 極坐標下計算弧上點的位置,用一個隨機量進行抖動config.rx = config.x + (config.radius + delta) * cos(config.angle); config.ry = config.y + (config.radius + delta) * sin(config.angle);// 計算速度float vx = (config.rx - config.prx) * vscale;float vy = (config.ry - config.pry) * vscale;// 順時針的話,需要乘以-1,因為y軸相反if (config.isClockwise) {vy = (config.ry - config.pry) * (-vscale);}float px = config.rx;float py = config.ry;// 順時針的話,需要乘以-1,因為y軸相反if (config.isClockwise) {py = height - config.ry;}// 給流體上的點添加速度fluid.addVelocity(px, py, 16, vx, vy);float radius1 = map(soundLevel, 10, 600, 15, 20);float radius2 = map(soundLevel, 10, 500, 8, 12);println(soundLevel, radius1, radius2);// 給流體上的點添加密度,顏色為c,半徑為radius1,稍微大點fluid.addDensity(px, py, radius1, red(config.c) / 255.0, green(config.c) / 255.0, blue(config.c) / 255.0, 1.0f);// 給流體上的點添加密度,顏色為白色,半徑為radius2,稍微小點fluid.addDensity(px, py, radius2, 1.0f, 1.0f, 1.0f, 1.0f);//fluid.addTemperature(px, py, 30, 10);// 現在終將成為過去config.prx = config.rx;config.pry = config.ry;// 增加弧度角,用于下一幀計算,才能旋轉float angleSpeed = constrain(radians(soundLevel * 0.03), 0.01, 0.08) * 3;println(soundLevel, angleSpeed);config.angle += angleSpeed;}@Overridepublic void update(DwFluid2D fluid) {my_update(fluid, config1);my_update(fluid, config2);}
}
第三部分:太極類定義
太極類定義完整代碼
class Taichi {PVector location;float radius;PGraphics2D pg;float angle = 0;Amplitude rms; Taichi(PVector location, float radius, PGraphics2D pg, Amplitude rms) {this.location = location;this.radius = radius;this.pg = pg;this.rms = rms;}void display() {float d = 2 * radius;float soundLevel = rms.analyze();angle += TWO_PI/360 * soundLevel * 20+6;pg.noStroke();pg.translate(location.x, location.y); // 平移坐標系,方便使用相對位置進行繪制pg.rotate(angle);pg.fill(0);pg.arc(0, 0, d, d, PI / 2, PI * 3 / 2);pg.fill(255);pg.arc(0, 0, d, d, -PI / 2, PI / 2);pg.fill(255);pg.circle(0, d / 4, radius);pg.fill(0);pg.circle(0, -d / 4, radius);pg.fill(0);pg.circle(0, d / 4, radius / 5);pg.fill(255);pg.circle(0, -d / 4, radius / 5);}
}
結語
通過本教程,您將學習到如何結合Processing的聲音輸入和PixelFlow的流體模擬功能,創建一個動態的太極動畫。您可以根據自己的創意進一步擴展這個項目,例如添加更多的交互元素或改變流體的行為。記得在編寫代碼時保持耐心,實踐是學習編程的最佳方式。