[processing]魔方陣とかSF円とか(Processing Advent Calendar 2011 – 20日目)

Posted under processing by uechoco on 火曜日 20 12月 2011 at 01 : 02 : 20

Processing Advent Calendar 2011の2回目の登場です。
20日目の担当ということで、最近Processingと疎遠でphpやらpythonやらと戯れている私は既にネタ切れですw

Processingは何かのプロダクトのプロトタイプを作ったり、自分が作りたいアニメーションを作ったりするのに向いていると言われています。
今回は私の趣味で、魔方陣とかSFちっくな円とか、そういうものを2種類公開いたします。

ミッドチルダ式魔方陣

Processing:
  1. /**
  2.  * ミッドチルダ式魔法陣 (元ネタ:魔法少女リリカルなのは)
  3.  *
  4.  * @title mugityax | 背景作成
  5.  * @link http://www.mugityax.com/weblog/2006/06/post_1.html
  6.  *
  7.  * @title ミッドチルダフォント置き場
  8.  * @link http://midfont.refy.net/
  9.  */
  10.  
  11. float rot1, rot2;
  12. PFont font1, font2;
  13.  
  14.   size(400, 400);
  15.   colorMode(HSB, 100);
  16.   frameRate(30);
  17.   smooth();
  18.   background(0);
  19.  
  20.   textAlign(CENTER, CENTER);
  21.  
  22.   font1 = loadFont("MID-CHILDA_Regular-30.vlw");
  23.   font2 = loadFont("MID-CHILDA_Regular-15.vlw");
  24.   //font1 = createFont("mid-childa_R.ttf", 30, true);
  25.   //font2 = createFont("mid-childa_R.ttf", 15, true);
  26.  
  27.   rot1 = rot2 = 0;
  28. }
  29.  
  30.   background(0);
  31.   {
  32.     noFill();
  33.     translate(width / 2, height / 2);
  34.     final float rl = 120 / sqrt(2); // 84.85281
  35.     final float ro = 149;
  36.    
  37.     // 固定円
  38.     {
  39.       drawLightEllipse(0, 0, 180*2, 180*2); // 外周円-二重外円
  40.       drawLightEllipse(0, 0, 175*2, 175*2); // 外周円-二重外円
  41.       drawLightEllipse(0, 0, 120*2, 120*2); // 外周円-内円
  42.       drawLightEllipse(0, 0, rl*2, rl*2); // 内周方形内-外円
  43.       drawLightEllipse(0, 0, 60*2, 60*2); // 内周方形内-内円
  44.     }
  45.    
  46.     // 外周小円・内周方形1
  47.     pushMatrix();
  48.     {
  49.       rotate(rot1);
  50.       // 外周小円
  51.       final float[] rm = {50, 45};
  52.       for (int i = 0; i <rm.length; i++) {
  53.         drawLightEllipse(0, -ro, rm[i], rm[i]);
  54.         drawLightEllipse(ro, 0, rm[i], rm[i]);
  55.         drawLightEllipse(0, ro, rm[i], rm[i]);
  56.         drawLightEllipse(-ro, 0, rm[i], rm[i]);
  57.       }
  58.       // 内周方形1
  59.       drawLightQuad(0,-120,120,0,0,120,-120,0);
  60.     }
  61.     popMatrix();
  62.    
  63.     // 内周方形2
  64.     pushMatrix();
  65.     {
  66.       rotate(rot2);
  67.       drawLightQuad(-rl,-rl,rl,-rl,rl,rl,-rl,rl);
  68.     }
  69.     popMatrix();
  70.    
  71.     final String[][] ot = {
  72.       {"Y","S","T","D","U","X","K","j","L","z","D","K","F","A","M","B","Y","o","h","Z","O","T","U","V","i"},
  73.       {"J","Z","p","V","A","Y","F","r","j","s","v","W","T","h","G","S","c","H","X","K","k","o","d","B","u"},
  74.       {"b","F","M","r","g","R","V","y","N","B","A","x","q","C","T","p","E","L","K","a","w","j","k","J","P"},
  75.       {"H","a","G","d","W","S","n","M","X","s","E","x","A","o","Z","C","b","f","k","U","V","i","Y","B","D"},
  76.       {"E","y","t","H","L","o","Q","W","T","h","a","d","C","B","b","w","v","D","s","Y","z","e","R","n","S"},
  77.       {"K","B","f","T","k","R","e","d","w","z","S","m","D","J","P","F","j","o","n","r","u","x","g","v","b"},
  78.       {"z","G","q","e","u","w","W","a","U","X","i","r","A","Y","D","t","N","V","k","P","Q","p","g","E","K"},
  79.       {"b","v","d","B","g","z","D","h","j","Q","n","U","G","Z","q","u","F","r","T","X","a","m","W","t","Y"},
  80.       {"Z","K","U","T","e","A","G","c","X","i","Q","o","R","F","k","t","p","D","J","d","r","q","n","V","E"},
  81.     };
  82.     final int[][] a_set = {
  83.       {14, 78, 4},
  84.       {102, 170, 4},
  85.       {192, 260, 4},
  86.       {282, 350, 4}
  87.     };
  88.  
  89.     // 外周文字
  90.     pushMatrix();
  91.     {
  92.       rotate(rot1);
  93.       fill(100);
  94.       textFont(font1);
  95.       for (int i = 0; i <4; i++) {
  96.         int c = 0;
  97.         for (int a = a_set[i][0]; a <a_set[i][1]; a+=a_set[i][2]) {
  98.           pushMatrix();
  99.           rotate(radians(a));
  100.           translate(ro, 0);
  101.           rotate(HALF_PI);
  102.           text(ot[i][c++], 0, 0);
  103.           popMatrix();
  104.         }
  105.       }
  106.     }
  107.     popMatrix();
  108.  
  109.     // 内周文字
  110.     pushMatrix();
  111.     {
  112.       rotate(rot2);
  113.       fill(100);
  114.       textFont(font2);
  115.       for (int i = 0; i <4; i++) {
  116.         int c = 0;
  117.         for (int a = a_set[i][0]; a <a_set[i][1]; a+=a_set[i][2]) {
  118.           pushMatrix();
  119.           rotate(radians(a));
  120.           translate(70, 0);
  121.           rotate(HALF_PI);
  122.           text(ot[i][c++], 0, 0);
  123.           popMatrix();
  124.         }
  125.       }
  126.     }
  127.     popMatrix();
  128.    
  129.   }
  130.   popMatrix();
  131.   update();
  132. }
  133.  
  134. void update() {
  135.   rot1 += 0.04;
  136.   rot2 -= 0.04;
  137. }
  138.  
  139. void drawLightEllipse(float a, float b, float c, float d) {
  140.   stroke(100, 100, 80, 40);
  141.   ellipse(a, b, c, d);
  142.   stroke(95, 100, 80, 60);
  143.   ellipse(a, b, c, d);
  144.   stroke(90, 100, 80, 80);
  145.   ellipse(a, b, c, d);
  146.   strokeWeight(1.5);
  147.   stroke(100);
  148.   ellipse(a, b, c, d);
  149. }
  150.  
  151. void drawLightQuad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
  152.   stroke(100, 100, 80, 40);
  153.   quad(x1, y1, x2, y2, x3, y3, x4, y4);
  154.   stroke(95, 100, 80, 60);
  155.   quad(x1, y1, x2, y2, x3, y3, x4, y4);
  156.   stroke(90, 100, 80, 80);
  157.   quad(x1, y1, x2, y2, x3, y3, x4, y4);
  158.   strokeWeight(1.5);
  159.   stroke(100);
  160.   quad(x1, y1, x2, y2, x3, y3, x4, y4);
  161. }
  162.  
  163.   save("mid_tilde_magic_circle.jpg");
  164. }

まずは、魔方陣です。魔法少女リリカルなのはというアニメの中に出てくるミッドチルダ式魔方陣というものです。元ネタは全く知らないのですが、魔方陣的に描きやすかったので、参考にしました。専用のフォントも使用しています。プログラムは4つの構成要素になっていて、外周や内周の固定や回転する円、内周の正方形、外周円の文字、内周円の文字となっています。rotate()とmatrixを上手く使用して、座標軸を回転させることで描画する方式をとっています。仕組みさえわかってしまえば簡単にバリエーションが作成できます。

SF円

Processing:
  1. float cx, cy;
  2. int ringCount = 0;
  3. Ring[] rings = new Ring[1];
  4.  
  5.   size(400, 400);
  6.   background(0);
  7.   noFill();
  8.   smooth();
  9.   strokeCap(SQUARE);
  10.   ellipseMode(RADIUS);
  11.  
  12.   cx = width / 2;
  13.   cy = height / 2;
  14.  
  15.   float pRadius = 20, pWeight = 2;
  16.   while (pRadius <180) {
  17.     Ring r = addRing();
  18.     r.setWeight(random(2, 25));
  19.     r.setPosition(cx, cy);
  20.     r.setRadius(pRadius + (pWeight + r.weight) / 2 + 1);
  21.     r.setRadians(random(TWO_PI)+PI/3, random(TWO_PI)+PI/3);
  22.     r.setColor(#ffffff);
  23.     r.setRot(random(-0.05, 0.05));
  24.     pRadius = r.r;
  25.     pWeight = r.weight;
  26.   }
  27. }
  28.  
  29.   background(0);
  30.   for (int i = 0; i <ringCount; ++i) {
  31.     rings[i].draw();
  32.     rings[i].move();
  33.   }
  34. }
  35.  
  36. Ring addRing() {
  37.   if (rings.length == ringCount) {
  38.     rings = (Ring[]) expand(rings);
  39.   }
  40.   Ring r = new Ring();
  41.   rings[ringCount++] = r;
  42.   return r;
  43. }
  44.  
  45. class Ring {
  46.   float x, y, r;
  47.   float weight;
  48.   float startRad, endRad;
  49.   float rot;
  50.   color c;
  51.  
  52.   void draw() {
  53.     stroke(c);
  54.     strokeWeight(weight);
  55.     arc(x, y, r, r, startRad, endRad);
  56.   }
  57.  
  58.   void move() {
  59.     startRad += rot;
  60.     endRad += rot;
  61.     if (startRad> TWO_PI && endRad> TWO_PI) {
  62.       startRad -= TWO_PI;
  63.       endRad -= TWO_PI;
  64.     }
  65.   }
  66.  
  67.   void setPosition(float x, float y) {
  68.     this.x = x;
  69.     this.y = y;
  70.   }
  71.  
  72.   void setRadius(float r) {
  73.     this.r = r;
  74.   }
  75.  
  76.   void setRadians(float start, float end) {
  77.     this.startRad = start;
  78.     this.endRad = end;
  79.   }
  80.  
  81.   void setWeight(float weight) {
  82.     this.weight = weight;
  83.   }
  84.  
  85.   void setColor(color c) {
  86.     this.c = c;
  87.   }
  88.  
  89.   void setRot(float rot) {
  90.     this.rot = rot;
  91.   }
  92. }
  93.  
  94.   save("sf_arc_ring_magic_circle.jpg");
  95. }

正式に何といったらよいのかわかりませんが、SF映画とかのコンソール画面とかの後ろ側で無駄にかっこ良く回ってるアレですw プログラムの仕組みとしては、円弧(arc)を何十にも重ねてそれぞれ別々の弧の長さや回転速度を持たせているだけです。プログラム上の工夫としては、円弧の部分をRingというクラスにまとめ、draw()ループから呼び出すメソッドはRing.draw()やRing.move()に限定することで、draw()ループを見やすくしています。このように、似たような動作をするオブジェクトをクラスとして定義して、パラメータの違いによって動作を変え、描画や移動の時はdraw()やmove()などのメソッドを作成して呼ばせるような手法は、プログラムをすっきりとさせるし、動作の塊がオブジェクトとしてまとまっているので、大変見やすくなっています。

最後に

と、今回は2つの作品の紹介で終わりでちょっと物足りなかったかと思います。

私はCGクリエイターと言うよりはCGに興味があるプログラマーなので、自分が作りたいものが作れれば良いという考えではなく、「この作品を作るにはどういうプログラムにすると上手く書けるか」という視点でProcessingのコードを書くことが多いです。前回の伝統模様の記事でも、いろんな書き方で伝統模様を書いていたのをご覧になっているかと思います。私の目標としては"CG自体の美"の次くらいに"プログラムコードの美"を追求していきたいと思っています。

めちゃめちゃなコードでもその場限りで描ければ良しとする考えもあるのですが、数カ月後とか、1年後とかにProcessingのコードを見て、何やっているかわからないと困る場合もありますよね。その点、プログラムコードの美しさも最初から追求していれば、後から読んでも読みやすいプログラムなので、理解がしやすいかと思います。

とまぁ、作品紹介ついでに本職プログラマーならではのプログラミングの視点をご紹介してみました。


[processing]伝統模様を描いてみよう(Processing Advent Calendar 2011 – 9日目)

Posted under processing by uechoco on 金曜日 9 12月 2011 at 00 : 01 : 56

Processingの記事を書くのは本当に久しぶりです。
Processing Advent Calendar 2011に参加しておりまして、9日目の担当ということで執筆いたします。

みなさんは、伝統模様と聞いてパッとイメージが浮かぶでしょうか?
たぶん着物やハンカチなどの絵柄に使われているのを見たことがあるかもしれません。

伝統模様は

  • 同じパターンが繰り返し使われている
  • 幾何学的な模様が多い

といった観点からとても不思議な模様で、またProcessingの練習で描いてみる題材としても適していると思っています。

百聞は一見にしかず、いくつか私の描いたものをコード付きでご紹介します。

青海波(せいがいは)

Processing:
  1. // 青海波(せいがいは)
  2.  
  3. int r = 80;
  4. int r2 = r * 2;
  5.  
  6.   size(400, 400);
  7.   background(255, 255, 255);
  8.   smooth();
  9.   noLoop();
  10. }
  11.  
  12.   noStroke();
  13.   background(255, 255, 255);
  14.  
  15.   boolean flag = true;
  16.   for (int y = 0; y <height + r2; y += r) {
  17.     int x_base = flag ? 0 : r / 2 ;
  18.     for (int x = x_base; x <width + r2; x += r) {
  19.       drawPattern(x, y);
  20.     }
  21.     flag = !flag;
  22.   }
  23. }
  24.  
  25. void drawPattern(float cx, float cy) {
  26.   ellipseMode(CENTER_RADIUS);
  27.   int script[][] = {
  28.     {80, 0, 0, 0},
  29.     {75, 255, 255, 255},
  30.     {65, 0, 0, 0},
  31.     {60, 255, 255, 255},
  32.     {50, 0, 0, 0},
  33.     {45, 255, 255, 255},
  34.     {35, 0, 0, 0},
  35.     {30, 255, 255, 255},
  36.     {20, 0, 0, 0},
  37.     {15, 255, 255, 255},
  38.     {5, 0, 0, 0}
  39.   };
  40.   for (int i = 0; i <script.length; i++) {
  41.     int len = script[i][0];
  42.     fill(script[i][1], script[i][2], script[i][3]);
  43.     ellipse(cx, cy, len, len);
  44.   }
  45. }

青海波は文字通り波をイメージした模様です。私のコードでは、2重のfor文でx, y座標をずらしながら、
パターン化した白黒の円を上から塗り重ねることで、青海波っぽく描いています。

星七宝繋ぎ(ほししっぽう)

Processing:
  1. // 星七宝繋ぎ(ほししっぽう)
  2.  
  3. int r = 80;
  4. int r2 = r * 2;
  5.  
  6. float ct[] = new float[360];
  7. float st[] = new float[360];
  8.  
  9.   size(400, 400);
  10.   background(0, 0, 0);
  11.   smooth();
  12.   noLoop();
  13.  
  14.   ellipseMode(CENTER_RADIUS);
  15.  
  16.   for (int d = 0; d <360; d++) {
  17.     ct[d] = cos(radians(d));
  18.     st[d] = sin(radians(d));
  19.   }
  20. }
  21.  
  22.   background(0, 0, 0);
  23.  
  24.   stroke(255, 255, 255);
  25.  
  26.   noFill();
  27.   boolean flag = true;
  28.   for (int y = -20; y <height + r2; y += r) {
  29.     int x_base = -20 + (flag ? 0 : r);
  30.     for (int x = x_base; x <width + r2; x += r2) {
  31.       drawPattern(x, y);
  32.     }
  33.     flag = !flag;
  34.   }
  35.  
  36.   fill(0, 0, 0);
  37.   flag = true;
  38.   for (int y = -20; y <height + r2; y += r) {
  39.     int x_base = -20 + (flag ? 0 : r);
  40.     for (int x = x_base; x <width + r2; x += r2) {
  41.       drawPattern2(x, y);
  42.     }
  43.     flag = !flag;
  44.   }
  45. }
  46.  
  47. void drawPattern(float cx, float cy) {
  48.  
  49.   float p[][] = {
  50. //    {cx + r, cy - r, 0, 90, 180, 270},
  51. //    {cx - r, cy - r, 90, 180, 270, 360},
  52.     {cx - r, cy + r, 180, 270, 0, 90},
  53.     {cx + r, cy + r, 270, 360, 90, 180}
  54.   };
  55.  
  56.   for (int i = 0; i <p.length; i++) {
  57.     float tx = p[i][0];
  58.     float ty = p[i][1];
  59.     int crad_begin = (int)p[i][2];
  60.     int crad_end = (int)p[i][3];
  61.     int trad_begin = (int)p[i][4];
  62.     int trad_end = (int)p[i][5];
  63.  
  64.     beginShape(LINES);
  65.     for (int d = crad_begin; d <crad_end; d++) {
  66.       vertex(cx + ct[d] * r, cy - st[d] * r);
  67.     }
  68.     for (int d = trad_begin; d <trad_end; d++) {
  69.       vertex(tx + ct[d] * r, ty - st[d] * r);
  70.     }
  71.     endShape(CLOSE);
  72.   }
  73. }
  74.  
  75. void drawPattern2(float cx, float cy) {
  76.   ellipse(cx + r, cy, 10, 10);
  77.   ellipse(cx, cy + r, 10, 10);
  78. }

七宝模様は、円を重ね合わせることで、円の弧が星のように見える模様です。
私のコードはちょっと複雑ですね。たしか円を並べただけだと七宝模様に近づかなかったので、
円弧をvertex()で描いていったのだと記憶しています。

花亀甲(はなきっこう)

Processing:
  1. // 花亀甲(はなきっこう)
  2.  
  3. float ROOT_3 = (float)Math.sqrt(3);
  4. float ROOT_3_DIV_2 = ROOT_3 / 2.0;
  5.  
  6. float ROOT_2 = (float)Math.sqrt(2);
  7. float ONE_DIV_ROOT_2 = 1 / ROOT_2;
  8.  
  9. int ix = -20;
  10. int iy = -20;
  11. int r = 50;
  12. int r2 = r * 2;
  13. int in_r = r - 8;
  14.  
  15. float ct[] = new float[360];
  16. float st[] = new float[360];
  17.  
  18.   size(400, 400);
  19.   background(255, 255, 255);
  20.   smooth();
  21.   noLoop();
  22.  
  23.   for (int d = 0; d <360; d++) {
  24.     ct[d] = cos(radians(d));
  25.     st[d] = sin(radians(d));
  26.   }
  27. }
  28.  
  29.   background(255, 255, 255);
  30.  
  31.   boolean flag = true;
  32.   for (float y = iy; y <height + r2; y += r * 3 / 2) {
  33.     float x_base = ix + (flag ? 0 : r * ROOT_3_DIV_2);
  34.     for (float x = x_base; x <width + r2; x += r * ROOT_3) {
  35.       drawPattern(x, y);
  36.     }
  37.     flag = !flag;
  38.   }
  39. }
  40.  
  41. void drawPattern(float cx, float cy) {
  42.  
  43.   float out_len = r;
  44.   float in_len = r - 5;
  45.  
  46.   int deg_list[] = {30, 330, 270, 210};
  47.   int deg_list2[] = {30, 330, 270, 210, 150, 90, 30};
  48.  
  49.   // 外側の亀甲
  50.   stroke(0, 0, 0);
  51.   noFill();
  52.   drawTortoiseshell(cx, cy, r, deg_list);
  53.  
  54.   // 内側の亀甲
  55.   drawTortoiseshell(cx, cy, in_r, deg_list2);
  56.  
  57.   // 中央文様
  58.   drawFlower(cx, cy, 7, 30, 20);
  59. }
  60.  
  61. void drawTortoiseshell(float cx, float cy, float r, int[] deg_list) {
  62.   float ox = ct[deg_list[0]] * r;
  63.   float oy = -st[deg_list[0]] * r;
  64.   for (int i = 1; i <deg_list.length; i++) {
  65.     float nx = ct[deg_list[i]] * r;
  66.     float ny = -st[deg_list[i]] * r;
  67.     line(cx + ox, cy + oy, cx + nx, cy + ny);
  68.     ox = nx;
  69.     oy = ny;
  70.   }
  71. }
  72. void drawFlower(float cx, float cy, int thin, int len, int len2) {
  73.   noStroke();
  74.   fill(0, 0, 0);
  75.  
  76.   // 上の葉(90〜270)
  77.   // 下の葉(-90〜90)
  78.   for (int i = 0; i <360; i++) {
  79.     float x = - st[safe_degrees(i * 2)] * len / thin;
  80.     float y = ct[safe_degrees(i)] * len;
  81.     vertex(cx + x, cy + y);
  82.   }
  83.   endShape(CLOSE);
  84.  
  85.   // 右の葉(-90〜90)
  86.   // 左の葉(90〜270)
  87.   for (int i = 0; i <360; i++) {
  88.     float x = ct[safe_degrees(i)] * len;
  89.     float y = - st[safe_degrees(i * 2)] * len / thin;
  90.     vertex(cx + x, cy + y);
  91.   }
  92.   endShape(CLOSE);
  93.  
  94.   // 左下の葉(90〜270)
  95.   // 右上の葉(-90〜90)
  96.   for (int i = 0; i <360; i++) {
  97.     float x = - st[safe_degrees(i * 2)] * len2 / thin;
  98.     float y = ct[safe_degrees(i)] * len2;
  99.     float dx = -1 * ONE_DIV_ROOT_2 * (x - y);
  100.     float dy = -1 * ONE_DIV_ROOT_2 * (x + y);
  101.     vertex(cx + dx, cy + dy);
  102.   }
  103.   endShape(CLOSE);
  104.  
  105.   // 右下の葉(90〜270)
  106.   // 左上の葉(-90〜90)
  107.   for (int i = 0; i <360; i++) {
  108.     float x = ct[safe_degrees(i)] * len2;
  109.     float y = - st[safe_degrees(i * 2)] * len2 / thin;
  110.     float dx = -1 * ONE_DIV_ROOT_2 * (x - y);
  111.     float dy = -1 * ONE_DIV_ROOT_2 * (x + y);
  112.     vertex(cx + dx, cy + dy);
  113.   }
  114.   endShape(CLOSE);
  115. }
  116.  
  117. int safe_degrees(int deg) {
  118.   while (deg>= 360) deg-=360;
  119.   while (deg <0) deg += 360;
  120.   return deg;
  121. }

亀甲模様に花柄がついた、花亀甲という模様です。コードもだいぶ複雑になって来ました。プログラムは太い亀甲を描くルーチン、細い内側の亀甲を描くルーチン、そして花柄模様を描くルーチンの3種類に分かれています。そしてそれらを1つのぱたーんとしてまとめあげて、亀甲の中心点を移動させることでパターン化しています。花柄を描くときやcos()やsin()に係数を掛けて、円を歪ませることで花びらの1枚1枚を描いています。

先ほどの星七宝のコードでも出てきたのですが、私のコードでは、cos()とsin()を0〜359度分、予め計算した状態で配列に確保しています。
これはコードの内部で使用する角度をを0〜359の整数に限定することで、描画中にcos()関数、sin()関数の結果がそれぞれ360通りに限定されるので、予め計算しておくことが出来るようになっています。小さな静止画を描くときはそこまで効力を発揮しないのですが、動く物体を描くときや、大量にcos()、sin()関数を使うときは非常に高速に計算ができます(関数を呼び出して計算させるより、予め計算結果を溜めておいたものを使用したほうが速のです)。

武田菱(たけだびし)

武田氏の家紋である「四つ割菱」の入った模様です。

Processing:
  1. // 武田菱(たけだびし)
  2.  
  3. float ROOT_3 = (float)Math.sqrt(3);
  4. float ROOT_3_DIV_2 = ROOT_3 / 2.0;
  5.  
  6. int ix = -60;
  7. int iy = -60;
  8. int block_w = 100;
  9. int block_h = 60;
  10. float ey = 10;
  11. float ex = ey * ROOT_3;
  12.  
  13. float ct[] = new float[360];
  14. float st[] = new float[360];
  15.  
  16.   size(400, 400);
  17.   background(0, 0, 0);
  18.   smooth();
  19.   noLoop();
  20.  
  21.   for (int d = 0; d <360; d++) {
  22.     ct[d] = cos(radians(d));
  23.     st[d] = sin(radians(d));
  24.   }
  25. }
  26.  
  27.   background(0, 0, 0);
  28.  
  29.   strokeJoin(MITER);
  30.  
  31.   boolean flag = true;
  32.   for (float y = iy; y <height + block_h; y += (block_h + ey) / 2) {
  33.     float x_base = ix + (flag ? (block_w + ex) / 2 : 0);
  34.     for (float x = x_base; x <width + block_w; x += block_w + ex) {
  35.       drawPattern(x, y, block_w, block_h);
  36.     }
  37.     flag = !flag;
  38.   }
  39. }
  40.  
  41. void drawPattern(float x, float y, float block_w, float block_h) {
  42.  
  43.   float subblock_w = block_w / 2;
  44.   float subblock_h = block_h / 2;
  45.   float cx = x + subblock_w;
  46.   float cy = y + subblock_h;
  47.   int m = 8;
  48.  
  49.   stroke(255, 255, 255);
  50.   noFill();
  51.   for (int i = m; i>= 4; i-=2) {
  52.     float w = lerp(0, subblock_w, i / (float)m);
  53.     float h = lerp(0, subblock_h, i / (float)m);
  54.     quad(
  55.       cx, cy - h,
  56.       cx - w, cy,
  57.       cx, cy + h,
  58.       cx + w, cy
  59.     );
  60.   }
  61.   float w = lerp(0, subblock_w, 4 / (float)m);
  62.   float h = lerp(0, subblock_h, 4 / (float)m);
  63.   line(cx - w / 2, cy - h / 2, cx + w / 2, cy + h / 2);
  64.   line(cx + w / 2, cy - h / 2, cx - w / 2, cy + h / 2);
  65. }
  66.  
  67. int safe_degrees(int deg) {
  68.   while (deg>= 360) deg-=360;
  69.   while (deg <0) deg += 360;
  70.   return deg;
  71. }

こちらのコードはそこまで複雑ではありません。四角形を描くquad()関数を多用して、上手く菱形を描いています。

おわりに

簡単ではありますが、伝統模様をお見せしました。
これ以外にも伝統模様はたくさんありますので、調べてみて、「この模様はどうやってProcessingで描いたら上手く書けるかな?」なんて考えてみてはいかがでしょうか。伝統模様に限らず、身近なデザインでも「Processingでどうやって書いたらいいかな?」って考えてみると、Processingの腕が上達するかもしれません。

それでは、次回は@reona396さんです。よろしくお願いします!


[p5]Processing情報発信サイト「proce55ing.walker(α)」リリースしました

Posted under processing by uechoco on 日曜日 5 4月 2009 at 14 : 18 : 26

proce55inginfo-captureed-image以前にも告知していましたが、Processingの情報発信サイト「proce55ing.walkerを本日公開いたしました。

管理人が私を含めて3人おり、まずはブログ形式でprocessing関連の入門記事、バージョンアップ情報、関数の使い方、ライブラリの使いあた、マニアックな使い方などを発信していく予定です。

また、フォーラム(質問掲示板)を設置してありますので、随時processingに関する質問、およびサイトに関する質問・要望を受け付けています

ゆくゆくは日本で一番のprocessingポータル・コミュニティサイトにしていこうという意気込みです。processingに興味のある方は是非ご覧になってください。また「こんなコンテンツがあるといいよね」「こんな記事書いてほしい」などのご要望がありましたら、お気軽にフォーラムに書き込んでいただけると助かります。


[processing]新サイトを準備中です

Posted under processing by uechoco on 日曜日 15 3月 2009 at 19 : 43 : 24

Processingだけを扱った新サイトを準備中です。私だけでなく、共同で立ち上げを予定しています。そのうちこのブログに投稿したProcessing関連の記事の多くを寄稿する予定です。近日中に開設する予定です。

っていう告知だけ。


[Processing]PVectorサンプル(1.0リリース記念)

Posted under processing by uechoco on 水曜日 3 12月 2008 at 22 : 45 : 12

Processing 1.0リリース記念として、いくつか新しい機能のサンプルコードを書いてみました。

まずはPVectorクラス。リファレンスには英語で主な使い方は書いてあるものの、実際のソースコードはありませんでした。

リファレンスに従い、position(位置)、velocitiy(速度)、acceleration(加速度)をPVectorクラスで表した実用的なサンプルを書いてみたので、PVectorクラスの1つの使い方として参考にしてみてください。

Processing:
  1. PFont font;
  2. PVector position, velocity, acceleration;
  3. final int WIDTH = 250, HEIGHT = 250;
  4. final int STATUS_HEIGHT = 50;
  5.  
  6.   // 画面の初期化
  7.   size(WIDTH, HEIGHT + STATUS_HEIGHT);
  8.  
  9.   noStroke();
  10.   colorMode(RGB, 256);
  11.   background(255, 255, 255);
  12.  
  13.   // フォントの初期化
  14.   font = loadFont("ArialNarrow-14.vlw");
  15.   textFont(font);
  16.  
  17.   // 自機の初期化
  18.   position = new PVector(WIDTH / 2, HEIGHT / 2, 0);
  19.   velocity = new PVector(3, 4, 0);
  20.   acceleration = new PVector(0.01, 0.01, 0);
  21. }
  22.  
  23.   // 背景消去
  24.   fill(255, 255, 255, 30);
  25.   rect(0, 0, WIDTH, HEIGHT);
  26.   fill(255, 255, 255);
  27.   rect(0, HEIGHT, WIDTH, STATUS_HEIGHT);
  28.  
  29.   // 自機描画
  30.   fill(255, 0, 0);
  31.   ellipse(position.x, position.y, 10, 10);
  32.  
  33.   // 速度表示
  34.   fill(0, 0, 0);
  35.   text("Position: " + position, 0, height - STATUS_HEIGHT + 14);
  36.   text("Velocity: " + velocity.mag(), 0, height - STATUS_HEIGHT + 14 * 2);
  37.   text("Acceleration: " + acceleration.mag(), 0, height - STATUS_HEIGHT + 14 * 3);
  38.  
  39.   // 場所の更新
  40.   position.add(velocity);
  41.   if (position.x <= 0 || position.x>= WIDTH) {
  42.     velocity.x *= -1;
  43.     acceleration.x *= -1;
  44.     position.x += velocity.x;
  45.   }
  46.   if (position.y <= 0 || position.y>= HEIGHT) {
  47.     velocity.y *= -1;
  48.     acceleration.y *= -1;
  49.     position.y += velocity.y;
  50.   }
  51.   velocity.add(acceleration);
  52. }

実行画面(クリックで拡大)

サンプルコードのダウンロード:PVectorSample.zip


次ページへ »

Copyright © 2012 うえちょこ@ぼろぐ. WP Theme created by Web Top.