プログラミングアート
3DCG
Processingによる3DCGグラフィック作品
CGプログラミング作品「星の最期」
概要
 この作品は全てがprocessing言語で描かれた3Dグラフィック作品です。超新星爆発の色彩やフォルムを元に線の重なりによる美しさをテーマに製作しました。炎や爆発特有の繊細に揺らぐ曲線の集合体のようなフォルム、それらが重なり合うことで引き立つそれぞれの色彩に魅力を感じ、これをプログラミングで表現しました。2本ずつ枝分かれしていく単純な再帰構造を元に、3本目を追加し元の2本と微妙に重ね合わせることで複雑な線にしています。
 また、実行するごとに違ったテイストの爆発が起きるため、様々な色、形、雰囲気を楽しむことができます。
実行結果例
Processingコード
int a = 12;      //線の透明度
int dd = 400;    //最初の角度(初期値用)415
int d = dd;      //最初の角度(動かす用)
int p = 5;       //何度ずつ増やすか

int sen_step;        
float sen_angle;
float sen_length;
float sen_start;
float sen_scale;

float x, y, z;
float hoshi;

PVector location;

int sss;
int step=sss;

float[] r = new float[4];
float[] g = new float[4];
float[] b = new float[4];
float ran;

void setup() {
  size(1300, 800, P3D);
  rectMode(CENTER);
  colorMode(RGB, 255, 255, 255, 100);
  background(0);   
  frameRate(1); 
  sen_step = 10;        //再帰回数 10以上で動作重
  sen_angle = radians(d);    //分かれる角度 315
  sen_length = 190;      //最初の線の長さ
  sen_start = 0;        //スタート地点(中心)

  newSen();   
  iro();
  effect();
}

void draw() {

  sen_angle=radians(d);      
  d += p;                      //pの値ごとに再帰時の角度を変える
  println(d);

  if (d>dd+p*3) {    
    save("bon" + 0 + ".png");         //画像を保存
    noLoop();                        //角度が規定値に達したら停止(4回描画したら)
  }

  translate(width/2, height/2, 0);        //原点を画面の中心へ

  rotateX(radians(random(240, 400)));      //フレームごとに回転させてズレを作る
  rotateZ(radians(random(320))); 

  if (d450) {
      b[i] = random(0, 100);
    } else {
      b[i] = random(255);
    }
  }
}

.mo{
void huyasu() {

  pushMatrix();

  blendMode(ADD);                 //色反映
  strokeWeight(1);
  noFill(); 

  if (step>sen_step-1) {          //再帰2回目まで描画しない
    noStroke();
  } else {   

    if (d>=dd+p*4) {
      stroke( r[0], g[0], b[0], a );
    } else if (d>=dd+p*3) {
      stroke( r[1], g[1], b[1], a );
    } else if (d>=dd+p*2) {
      stroke( r[2], g[2], b[2], a );
    } else if (d>=dd+p) {
      stroke( r[3], g[3], b[3], a );
    }
  } 


  translate(0, -sen_length, 0); //中心を軸にランダムで回転し、増やす


  for (int i=0; i<6; i++) { 
    translate(0, sen_length, 0);       
    rotateX(radians(random(360)));
    newSen();
  }


  for (int i=1; i<=4; i++) { 
    translate(0, sen_length, 0);
    rotateZ(radians(random(360)));
    newSen();
  }
  popMatrix();
}


void newSen() {
  sen(sen_start, sen_length, sen_step);
}

void sen(float start, float nagasa, int step) {

  float angle;        //再帰時の角度の設定用
  sss=step;

  line(0, 0, 0, -nagasa);

  translate(0, -nagasa);        //ずれを戻して中心に修正
  nagasa *= sen_scale;          //次の再帰の長さを計算


  if (step > 0) {

    angle = sen_angle;

    //3方向に分かれる線を描画。
    pushMatrix();    
    rotateX(angle);  
    rotateZ(angle);
    sen(start, nagasa, step-1);
    popMatrix(); 

    pushMatrix();
    rotateX(-angle);   
    rotateZ(-angle);
    sen(start, nagasa, step-1);
    popMatrix();

    pushMatrix();            
    rotateX(0);            //3本目は角度をずらす
    rotateZ(angle/2);
    sen(start, nagasa, step-1);
    popMatrix();
  }
}
	
void effect() {  

  blendMode(ADD);

  for (int i=0; i<200; i++) {          //星をちりばめる
    pushMatrix();

    x=random(-1000, width+1000);
    y=random(height+1000);
    z=random(-1200, -1000);

    hoshi=random(3);
    translate(0, -300, 0);

    stroke(random(180, 255), random(180, 255), random(180, 255), 50); //星本体
    strokeWeight(hoshi);
    point(x, y, z);

    stroke(random(180, 255), random(180, 255), random(180, 255), 10); //発光、ぼかし
    strokeWeight(hoshi*2);
    point(x, y, z);
    strokeWeight(hoshi*3);
    point(x, y, z);
    strokeWeight(hoshi*4);
    point(x, y, z);

    popMatrix();
  }


  location = new PVector(0, 0);                //背景モヤ   

  pushMatrix();
  translate(width/2, height/2, 0);
  scale(random(4, 8));


  for (float i=0; i<400; i+=0.1) {
    location.x = cos(radians(i)) * width/2.5;
    location.y = sin(radians(i*3)) * height/2.5;
    location.z = sin(radians(i*10)) * height/1.5;
    strokeWeight(50);
    stroke(r[3], g[3], b[3], 2);
    point(location.x, location.y, location.z);

    location.x = cos(radians(i)) * width/2.5;
    location.y = sin(radians(i*3)) * height/2.5;
    location.z = sin(radians(i*10)) * height/1.5;
    strokeWeight(160);
    stroke(r[1]-80, g[1]-80, b[1]-80, 1);
    point(location.x, location.y, location.z);
  }

  popMatrix();


  pushMatrix();                                //点々演出
  translate(width/2, height/1.4, 0);

  for (float ii=0; ii<600; ii+=1) {

    rotateY(radians(ii*random(1, 50)));   
    rotateX(radians(ii));

    for (float i=0; i<40; i+=1) {
      location.x = cos(radians(i*0.7)) * width/2.6;
      location.y = sin(radians(i*0.2)) * height/2.6;
      location.z = sin(radians(i*0.3)) * height/2.6;
      strokeWeight(1);

      stroke(r[2], g[2], b[2], 30);
      point(location.x, location.y, location.z);
      strokeWeight(1);
      stroke(r[1], g[1], b[1], 15);
      point(location.x+50, location.y+50, location.z+5);
    }
  }

  popMatrix();
}