(GLUT)円を動かして波紋を作る

OpenGL
TVアニメ「恋は雨上がりのように」 本予告PV

アニメ『恋は雨上がりのように』(2018)

おじさんに恋するきっかけが謎なのですが、まあ理屈じゃないですね。雨の日は気分も変わるので、そういうこともあるのでしょう。

今回は、前回の円のプログラムを改造して、波紋の動きを作ってみます。

void maru_init()
{
    struct maru_struct* p;
    int i;
    for(i=1;i<MARU_NUM;i++){
        p = &maru[i];
        if(p->status != MARGE){
            p->rx = ((rand()%200)-100)/100.0;
            p->ry = ((rand()%200)-100)/100.0;
            p->rsize = (rand()%50)/2000.0;
            p->dir = rand()%360;
            p->color = rand()%9;
            p->status = ALIVE;
        }
    }
}

乱数で円の位置を決めていましたが、角度以外は固定に変更。

void maru_init()
{
    struct maru_struct* p;
    int i;
    for(i=1;i<MARU_NUM;i++){
        p = &maru[i];
        if(p->status != MARGE){
            p->rx = 0;
            p->ry = 0;
            p->rsize = 0.01;
            p->dir = rand()%360;
            p->color = BLUE;
            p->status = ALIVE;
        }
    }
}

そして、衝突処理をコメントアウト。

void callback_display()
{
    struct maru_struct* p;
    int i;
    glClearColor(COLOR(WHITE));
    glClear(GL_COLOR_BUFFER_BIT);

    maru_move();
    for(i=1;i<MARU_NUM;i++){
        p = &maru[i];
        if(p->status != MARGE){
            maru_disp(p->rx, p->ry, p->rsize,p->color);
//            maru_collision_check(i);
        }
    }

    glFlush();
}

以上の修正をして、実行するとこのようになります。

続いて、端にいったら波紋が消えるようにステータスを変更します。MARGEという名前はおかしいので、後で直します。

void maru_move()
{
    struct maru_struct* p;
    int i;

    for(i=1;i<MARU_NUM;i++){
        p = &maru[i];
        if(p->status != MARGE){
            p->rx += 0.05 * cos(p->dir*M_PI/180.0);
            if(p->rx < -1.0) p->status = MARGE;
            if(p->rx >  1.0) p->status = MARGE;
            p->ry += 0.05 * sin(p->dir*M_PI/180.0);
            if(p->ry < -1.0) p->status = MARGE;
            if(p->ry >  1.0) p->status = MARGE;
        }
    }
}

背景を白から黒に変更します。

void callback_display()
{
    struct maru_struct* p;
    int i;
    glClearColor(COLOR(BLACK));
    glClear(GL_COLOR_BUFFER_BIT);

実行結果です。

次に、段階的に波紋を出すため、遅延処理を組み込みます。

void maru_init()
{
    struct maru_struct* p;
    int i;
    for(i=1;i<MARU_NUM;i++){
        p = &maru[i];
        p->rx = 0;
        p->ry = 0;
        p->rsize = 0.01;
        p->dir = rand()%360;
        p->color = BLUE;
        p->status = INIT;
        if(i <= 100){ p->count = 0;}
        else if(i <= 200){ p->count = 20;}
        else if(i <= 300){ p->count = 30;}
        else if(i <= 400){ p->count = 40;}
        else if(i <= 500){ p->count = 50;}
        else if(i <= 600){ p->count = 60;}
        else if(i <= 700){ p->count = 70;}
        else if(i <= 800){ p->count = 80;}
        else if(i <= 900){ p->count = 90;}

    }
}

実行結果。


雨の落ちる場所はランダムなので、波紋毎に位置を変えました。
全ソースです。

takk@deb9:~$ cat -n hamon.c
     1  #include <GL/glut.h>
     2  #include <math.h>
     3
     4  #define DEG2RAD(deg) deg * 2.0 * M_PI / 360.0
     5
     6  GLdouble colors[][4]={
     7  {0.0, 0.0, 0.0, 0.0},   //0 BLACK
     8  {0.6, 0.3, 0.2, 0.0},   //1 BROWN
     9  {1.0, 0.0, 0.0, 0.0},   //2 RED
    10  {1.0, 0.7, 0.3, 0.0},   //3 ORANGE
    11  {1.0, 0.0, 1.0, 0.0},   //4 YELLOW
    12  {0.0, 1.0, 0.0, 0.0},   //5 GREEN
    13  {0.0, 0.0, 1.0, 0.0},   //6 BLUE
    14  {1.0, 0.0, 1.0, 0.0},   //7 PURPLE
    15  {0.5, 0.5, 0.5, 0.0},   //8 GLAY
    16  {1.0, 1.0, 1.0, 0.0},   //9 WHITE
    17  };
    18
    19  #define BLACK 0
    20  #define BLUE 6
    21
    22  struct maru_struct
    23  {
    24      GLdouble rx;
    25      GLdouble ry;
    26      GLdouble rsize;
    27      int count;
    28      int color;
    29      int dir;
    30      int status;
    31  };
    32
    33  #define MARU_NUM 900
    34  #define INIT 0
    35  #define ALIVE 1
    36  #define LOST 2
    37
    38  struct maru_struct maru[MARU_NUM];
    39
    40  #define COLOR(n) colors[n][0],colors[n][1],colors[n][2],colors[n][3]
    41
    42  void maru_disp(GLdouble x, GLdouble y, GLdouble r, int color)
    43  {
    44      GLdouble xx, yy;
    45      int i,n=20;
    46      double deg,offs = 90.0;
    47
    48      glBegin(GL_POLYGON);
    49      glColor4f(COLOR(color));
    50
    51      for(i=0; i<n; i++){
    52          deg = (360.0/n) * i + offs;
    53          xx = x + r * cos(DEG2RAD(deg));
    54          yy = y + r * sin(DEG2RAD(deg));
    55          glVertex2d(xx, yy);
    56      }
    57
    58      glEnd();
    59  }
    60
    61  void callback_timer(int value)
    62  {
    63      glutPostRedisplay();
    64      glutTimerFunc(30,callback_timer,0);
    65  }
    66
    67  void maru_init()
    68  {
    69      struct maru_struct* p;
    70      int i;
    71      GLdouble arr_rx[8];
    72      GLdouble arr_ry[8];
    73      for(i=0;i<8;i++){
    74          arr_rx[i] = ((rand()%200)-100)/100.0;
    75          arr_ry[i] = ((rand()%200)-100)/100.0;
    76      }
    77      for(i=1;i<MARU_NUM;i++){
    78          p = &maru[i];
    79          p->rx = 0;
    80          p->ry = 0;
    81          p->rsize = 0.01;
    82          p->dir = rand()%360;
    83          p->color = BLUE;
    84          p->status = INIT;
    85          if(i <= 100){ p->count = 0;}
    86          else if(i <= 200){ p->count = 20; p->rx=arr_rx[0]; p->ry=arr_ry[0];}
    87          else if(i <= 300){ p->count = 30; p->rx=arr_rx[1]; p->ry=arr_ry[1];}
    88          else if(i <= 400){ p->count = 40; p->rx=arr_rx[2]; p->ry=arr_ry[2];}
    89          else if(i <= 500){ p->count = 50; p->rx=arr_rx[3]; p->ry=arr_ry[3];}
    90          else if(i <= 600){ p->count = 60; p->rx=arr_rx[4]; p->ry=arr_ry[4];}
    91          else if(i <= 700){ p->count = 70; p->rx=arr_rx[5]; p->ry=arr_ry[5];}
    92          else if(i <= 800){ p->count = 80; p->rx=arr_rx[6]; p->ry=arr_ry[6];}
    93          else if(i <= 900){ p->count = 90; p->rx=arr_rx[7]; p->ry=arr_ry[7];}
    94      }
    95  }
    96
    97  void maru_collision_check(int my_index)
    98  {
    99      struct maru_struct *my;
   100      struct maru_struct *p;
   101      int i;
   102      my = &maru[my_index];
   103      for(i=1;i<MARU_NUM;i++){
   104          if(i!=my_index){
   105              p = &maru[i];
   106              if(p->status != LOST)
   107                  if((my->rsize + p->rsize) >=
   108                  sqrt(pow(my->rx - p->rx,2)+pow(my->ry - p->ry,2))){
   109                      if(my->rsize > p->rsize){
   110                          my->rsize += p->rsize/2;
   111                          p->status = LOST;
   112                      }else{
   113                          p->rsize += my->rsize/2;
   114                          my->status = LOST;
   115                      }
   116                  }
   117          }
   118      }
   119  }
   120
   121  void maru_move()
   122  {
   123      struct maru_struct* p;
   124      int i;
   125
   126      for(i=1;i<MARU_NUM;i++){
   127          p = &maru[i];
   128          if(p->status == INIT){
   129                  if(p->count <= 0){
   130                          p->status = ALIVE;
   131                  }else{
   132                          p->count--;
   133                  }
   134          }
   135          if(p->status == ALIVE){
   136              p->rx += 0.05 * cos(p->dir*M_PI/180.0);
   137              if(p->rx < -1.0) p->status = LOST;
   138              if(p->rx >  1.0) p->status = LOST;
   139              p->ry += 0.05 * sin(p->dir*M_PI/180.0);
   140              if(p->ry < -1.0) p->status = LOST;
   141              if(p->ry >  1.0) p->status = LOST;
   142          }
   143      }
   144  }
   145
   146  void callback_display()
   147  {
   148      struct maru_struct* p;
   149      int i;
   150      glClearColor(COLOR(BLACK));
   151      glClear(GL_COLOR_BUFFER_BIT);
   152
   153      maru_move();
   154      for(i=1;i<MARU_NUM;i++){
   155          p = &maru[i];
   156          if(p->status == ALIVE){
   157              maru_disp(p->rx, p->ry, p->rsize,p->color);
   158          }
   159      }
   160
   161      glFlush();
   162  }
   163
   164  int main(int argc, char *argv[])
   165  {
   166      maru_init();
   167
   168      glutInit(&argc, argv);
   169      glutInitDisplayMode(GLUT_RGBA);
   170      glutCreateWindow("hamon4");
   171
   172      glutTimerFunc(5000,callback_timer,0);
   173      glutDisplayFunc(callback_display);
   174
   175      glutMainLoop();
   176
   177      return 0;
   178  }
   179
takk@deb9:~$

こうなります。

コメント

タイトルとURLをコピーしました