■基本編
$ cat sketch_211223a.pde
int degree = 0;
int r = 100;
void setup(){
size(300,300);
frameRate(24);
smooth();
}
void draw(){
background(0);
degree += 2;
float x = width/2 + r * cos(degree*PI/180.0);
float y = height/2 + r * sin(degree*PI/180.0);
translate(x,y);
rotate(-degree * PI/15.0);
// These below are relative coorinates from the translated origin
// In this case, (0,0) is the center for rotation
rect(-10,-10,20,20);
/*** Save into PNG ***/
saveFrame("frames/######.png");
}
上記を実行すると以下のPNGが連番フレームで作成される。
$ ls *.png | (head; echo; tail)
000001.png
000002.png
000003.png
000004.png
000005.png
000006.png
000007.png
000008.png
000009.png
000010.png
000316.png
000317.png
000318.png
000319.png
000320.png
000321.png
000322.png
000323.png
000324.png
000325.png
この連番PNGファイルをffmpegで動画作成する。
$ ffmpeg -r 30 -i %06d.png -vcodec libx264 -pix_fmt yuv420p -r 60 out.mp4
■応用編その1
これはProcessingのご本家サイトからサンプルソースをベースに遊んでみたもの:
$ cat Tree.pde
float theta;
float a;
int direction;
int bCount = 120;
void setup() {
size(640, 480);
smooth();
a = 0;
direction = 1;
}
void draw() {
background(0);
frameRate(24);
stroke(255);
theta = radians(a);
translate(width/2,height);
line(0,0,0,-240);
translate(0,-240);
branch(bCount);
a += direction;
if( a < 0 || a > 1280 ) {
direction = -1 * direction;
}
/*** Save into PNG ***/
saveFrame("frames/######.png");
}
void branch(float h) {
// Each branch will be 2/3rds the size of the previous one
h *= 2.0/3;
// All recursive functions must have an exit condition!!!!
// Here, ours is when the length of the branch is 2 pixels or less
if (h > 2) {
pushMatrix(); // Save the current state of transformation (i.e. where are we now)
rotate(theta); // Rotate by theta
line(0, 0, 0, -h); // Draw the branch
translate(0, -h); // Move to the end of the branch
branch(h); // Ok, now call myself to draw two new branches!!
popMatrix(); // Whenever we get back here, we "pop" in order to restore the previous matrix state
// Repeat the same thing, only branch off to the "left" this time!
pushMatrix();
rotate(-theta);
line(0, 0, 0, -h);
translate(0, -h);
branch(h);
popMatrix();
}
}
これまた、動画は添付できないのでイメージのみwww
■応用編その2
これは鎖をイメージしたこれ私の勝手オリジナルw
ElementManager em;
void setup(){
em = new ElementManager();
size(640,640);
stroke(255);
smooth();
background(0);
}
void draw(){
background(0);
translate(width/2, height/2);
scale(1,-1);
em.move();
em.renderAll();
/*** Save into PNG ***/
saveFrame("frames/######.png");
}
class Element{
float x;
float y;
Element follower = null;
public Element( float x, float y ){
this.x = x;
this.y = y;
}
}
class ElementManager{
final int NUM_OF_ELEMENTS = 128;
ArrayList al;
float len = 25;
int angle = 0;
ElementManager(){
al = new ArrayList();
for(int i=0;i<NUM_OF_ELEMENTS;i++){
al.add(new Element(-len*i,0));
}
// println(al.size());
}
public int getSize(){
return al.size();
}
public void move(){
angle += 1;
// The 1st one moves freewheelingly
Element e1st = (Element)al.get(0);
e1st.x += -10*cos(angle*PI/90.0);
e1st.y += 5*cos(angle*PI/180.0);
// println( e1st.y );
for(int i=1;i<al.size();i++){
Element e1 = (Element)al.get(i-1);
Element e2 = (Element)al.get(i);
// get unit vertor
float vx = e1.x - e2.x;
float vy = e1.y - e2.y;
float distance = sqrt(vx*vx + vy*vy);
vx /= distance;
vy /= distance;
// set new location
e2.x = e1.x - vx * len;
e2.y = e1.y - vy * len;
}
}
public void renderAll(){
for(int i=0;i<al.size()-1;i++ ){
Element e1 = (Element)al.get(i);
Element e2 = (Element)al.get(i+1);
rectMode(CENTER);
rect(e1.x, e1.y, 3, 3);
rect(e2.x, e2.y, 3, 3);
line(e1.x, e1.y, e2.x, e2.y);
}
}
}
■応用編その3
// $ astyle --delete-empty-lines --mode=java --indent=spaces=2 Chain.pde
// $ cat Chain.pde
ElementManager em;
void setup() {
em = new ElementManager();
size ( 1500, 640 );
stroke ( 255 );
smooth();
background ( 0 );
}
void draw() {
background ( 0 );
translate ( width/2, height/2 );
scale ( 1,-1 );
em.move();
em.renderAll();
/*** Save into PNG ***/
// saveFrame ( "frames/######.png" );
}
class Element {
float x;
float y;
// Element follower = null;
public Element ( float x, float y ) {
this.x = x;
this.y = y;
}
}
class ElementManager {
final int NUM_OF_ELEMENTS = 256;
ArrayList al;
float len = 25;
int angle = 0;
ElementManager() {
al = new ArrayList();
for ( int i=0; i<NUM_OF_ELEMENTS; i++ ) {
al.add ( new Element ( -len*i,0 ) );
}
// println(al.size());
}
public int getSize() {
return al.size();
}
public void move() {
angle += 1;
// The 1st one moves freewheelingly
Element e1st = ( Element ) al.get ( 0 );
e1st.x += 3*sin ( angle*PI/320.0 );
e1st.y += 5*cos ( angle*PI/180.0 );
// println( e1st.y );
for ( int i=1; i<al.size(); i++ ) {
Element e1 = ( Element ) al.get ( i-1 );
Element e2 = ( Element ) al.get ( i );
// get unit vertor
float vx = e1.x - e2.x;
float vy = e1.y - e2.y;
float distance = sqrt ( vx*vx + vy*vy );
vx /= distance;
vy /= distance;
// set new location
e2.x = e1.x - vx * len;
e2.y = e1.y - vy * len;
}
}
public void renderAll() {
for ( int i=0; i<al.size()-1; i++ ) {
Element e1 = ( Element ) al.get ( i );
Element e2 = ( Element ) al.get ( i+1 );
rectMode ( CENTER );
rect ( e1.x, e1.y, 3, 3 );
rect ( e2.x, e2.y, 3, 3 );
line ( e1.x, e1.y, e2.x, e2.y );
}
}
}