ProcessingJoy ——愛如煙塵【JAVA】

這是我參與8月更文挑戰的第8天,活動詳情查看: 8月更文挑戰java

效果圖

該效果其實核心思想是將多「層」的心形煙進行組合,首先咱們來定義其中一 「層」 的心形煙的實現代碼。markdown

Heart.pde

class Heart{
  float seed = random(10,1000);
  float offset = random(TWO_PI);
  
  float ff = random(0.5,2.5);
  float sw = random(0.8,1.8);
  
  float part = 0.1+0.5*pow(random(1),2.0);
  float rf = random(0.5,1.15);
  
  float d = random(10,120);
  int m = 500; ///< 500 個點
  OpenSimplexNoise noise = new OpenSimplexNoise(); ///< 噪聲,用於擾動心形
  
  float R = 150;
  float xh(float p){
    return R/15.0*16*pow(sin(p),3);
  }
  float yh(float p){
    return  R/15.0*(-13*cos(p) +5*cos(2*p) + 2*cos(3*p) + cos(4*p));
  }

  void show(float q){
    for(int i=0;i<m;i++){
      
      float p = 1.0*i/m;
      float theta = offset + part*TWO_PI*i/m;
      
      float rad = 1.3f;
      int per = 2;
      
      float xx = rf*xh(theta) + pow(p,3.0f)*d*(float)noise.eval(seed + rad*cos(TWO_PI*(per*p-q)),rad*sin(TWO_PI*(per*p-q)));
      float yy = rf*yh(theta) + pow(p,3.0f)*d*(float)noise.eval(2*seed + rad*cos(TWO_PI*(per*p-q)),rad*sin(TWO_PI*(per*p-q)));
      
      strokeWeight(sw);
      stroke(255,ff*18*sin(PI*p));
      
      point(xx,yy);
    }
  }
}
複製代碼

 其中關鍵的代碼(以下所示)表明的公式能夠繪製出心形(將 360° 分紅了 m 份,而後每一個位置放置一個點,只要劃分的足夠細,就能夠看起來像是一個完整的 ♥)app

float R = 150;
  float xh(float p){
    return R/15.0*16*pow(sin(p),3);
  }
  float yh(float p){
    return  R/15.0*(-13*cos(p) +5*cos(2*p) + 2*cos(3*p) + cos(4*p));
  }
複製代碼

 簡化後對應函數示意圖以下所示dom

而後經過疊加 Simplex 噪聲的隨機擾動,咱們就能夠模擬出煙塵的效果。函數

HeartSmoke.pde(主入口)

 自此基礎上,接着咱們構造多層(本例爲 250 層)的心形煙塵,並將它們疊加起來一層一層繪製工具

float t, c;

int samplesPerFrame = 5;
int numFrames = 100;        
float shutterAngle = .6;

int n = 250; ///< 250 層 ♥

Heart[] array = new Heart[n];

void setup(){
  size(600,600,P3D);

  for(int i=0;i<n;i++){
    array[i] = new Heart();
  }
}

void show(){
  background(0);
  push();
  translate(width/2,height/2);
  
  for(int i=0;i<n;i++){
    array[i].show(t);
  }
  
  pop();
}

void draw() {

    t = mouseX*1.0/width;
    c = mouseY*1.0/height;
    if (mousePressed)
      println(c);
      
    frameCount = 0;
    show();

    /// @note 保存序列 gif,後期可用 gifsicle 合成真正的 gif
    // saveFrame("fr###.gif");
}

void keyPressed(){
  if(key == 'r' || key == 'R'){
    recording = !recording;
    println("recording:" + recording);
  }
}
複製代碼

最後附上 OpenSimplexNoise.pde(因爲代碼過長,爲了避免影響閱讀,因此上傳到百度網盤),關於噪聲的詳解能夠看我以前寫的一篇ShaderJoy —— 噪聲之美,你們一塊兒 「噪」 起來 【GLSL】oop

連接:pan.baidu.com/s/1uKqedakx… 提取碼:u8ru post

如何合成 GIF 

gifsicle 下載連接:www.lcdf.org/gifsicle/ ui

下載安裝完成以後,打開命令行工具,執行如下命令(默認各幀的命名模式爲 fr*.gif) ,最終生成 anim.gif,各幀的延遲爲 10 / 100 surl

gifsicle --delay=10 --loop fr*.gif > anim.gif
複製代碼

gifsicle 支持的更加複雜的命令行請參見其官方手冊

相關文章
相關標籤/搜索