FireMonkey と C++Builder XE2 で、波の干渉を視覚化する

By: Chikako Yonezawa

Abstract: この記事では、C++Builder XE2 および FireMonkey を使用して、波の干渉を視覚化するために 3次元メッシュをどのように生成するかを解説します

    前提条件!

この記事は、以前の記事 “FireMonkey と C++ でカスタムメッシュを生成することにより、数学関数を視覚化する” を基にして構築しています。

    波の関数

この記事で使用する波の関数:

         f(x,y) = A*sin(1/L*r-v*t)

式内の項目:

  • (x,y) = 観測点
  • A = 振幅
  • L = 波の長さ
  • r = 波の中心と観測点間の距離
  • v = 波の伝播速度
  • t = 時間

この関数を C++Builder で表記すると次のようになります。

double f(double x, double y)
{
  return Amplitude*Sin(1/Length*Sqrt(Sqr(x-PosX)+Sqr(y-PosY))-Speed*t);
}

注意: この関数は、単に平衡状態を与えていることに注意してください。完全に始動のシナリオ、および、時間と距離で波が消えてしまう事実を無視しています。

以下のスクリーンショットは 1 つの波を表現しています。

Hide image
Click to see full-sized image

互いに干渉する 2 つの波の場合:

Hide image
Click to see full-sized image

そして、それが 4 つの波になった場合:

Hide image
Click to see full-sized image

    メッシュを生成する

メッシュを生成するために、以前の記事からコードを参照し、時間のパラメータを与えて少し変更します。

double f(double x, double y)
{
  int          i;
  double  Result = 0;

  for (i = 0; i < 4; i++) {
    if (Wave[i].Enabled)
      Result += Wave[i].Amplitude*Sin(1/Wave[i].Length*Sqrt(Sqr(x-Wave[i].PosX)+Sqr(y-Wave[i].PosY))-Wave[i].Speed*t);
  }

  return Result;
}

void __fastcall TForm3D2::GenerateWave(double t)
{
  int          MaxX = 30;
  int          MaxZ = 30;
  double  u, v;
  double  px[4], py[4], pz[4];
  double  d = 0.5;
  int          NP = 0;
  int          NI = 0;
  TBitmap *BMP;
  int          k;

  // We have to set these up front. The buffers are CLEARED every time Length is set!!!
  Mesh1->Data->VertexBuffer->Length = 2*MaxX*2*MaxZ/d/d*4;
  Mesh1->Data->IndexBuffer->Length = 2*MaxX*2*MaxZ/d/d*6;

  BMP = new TBitmap(1,360);
  for (k = 0; k < 360; k++)
    BMP->Pixels[0][k] = CorrectColor(HSLtoRGB(k/360.0,0.75,0.5));

  u = -MaxX;
  while (u < MaxX) {
    v = -MaxZ;
    while (v < MaxZ) {
      px[0] = u;
      pz[0] = v;
      py[0] = f(px[0],pz[0]);

      px[1] = u+d;
      pz[1] = v;
      py[1] = f(px[1],pz[1]);

      px[2] = u+d;
      pz[2] = v+d;
      py[2] = f(px[2],pz[2]);

      px[3] = u;
      pz[3] = v+d;
      py[3] = f(px[3],pz[3]);

      // Set the points
      Mesh1->Data->VertexBuffer->Vertices[NP+0] = Point3D(px[0],py[0],pz[0]);
      Mesh1->Data->VertexBuffer->Vertices[NP+1] = Point3D(px[1],py[1],pz[1]);
      Mesh1->Data->VertexBuffer->Vertices[NP+2] = Point3D(px[2],py[2],pz[2]);
      Mesh1->Data->VertexBuffer->Vertices[NP+3] = Point3D(px[3],py[3],pz[3]);

      // Map the colors
      Mesh1->Data->VertexBuffer->TexCoord0[NP+0] = PointF(0,(py[0]+35)/45);
      Mesh1->Data->VertexBuffer->TexCoord0[NP+1] = PointF(0,(py[1]+35)/45);
      Mesh1->Data->VertexBuffer->TexCoord0[NP+2] = PointF(0,(py[2]+35)/45);
      Mesh1->Data->VertexBuffer->TexCoord0[NP+3] = PointF(0,(py[3]+35)/45);

      // Map the triangles
      Mesh1->Data->IndexBuffer->Indices[NI+0] = NP+1;
      Mesh1->Data->IndexBuffer->Indices[NI+1] = NP+2;
      Mesh1->Data->IndexBuffer->Indices[NI+2] = NP+3;
      Mesh1->Data->IndexBuffer->Indices[NI+3] = NP+3;
      Mesh1->Data->IndexBuffer->Indices[NI+4] = NP+0;
      Mesh1->Data->IndexBuffer->Indices[NI+5] = NP+1;

      NP = NP+4;
      NI = NI+6;
      v = v+d;
    }
    u = u+d;
  }

  Mesh1->Data->CalcNormals();
  Mesh1->Material->Texture = BMP;
}

    メッシュのアニメーション化

上記のコードは、任意の時間 t で、4 つの波の間の相互作用の "スナップショット" を生成します。

波をアニメーション化するには、時間をインクリメントするためにタイマーを使用し、メッシュを繰り返し再生成するだけです。

void __fastcall TForm3D2::Timer1Timer(TObject *Sender)
{
  GenerateWave(t);
  t = t+0.1;
}

波は、このレコード型で表現されます。

struct TWave {
    bool Enabled;
    double     Amplitude;
    double     Length;
    double     PosX;
    double     PosY;
    double     Speed;
};

この記事に付属しているデモプロジェクトでは、始動する 4 つの波を宣言しました。

TWave       Wave[4] = {{False, 1, 1, -20, -20, 1},
               {False, 1, 1, +20, -20, 1},
               {False, 1, 1, +20, +20, 1},
               {False, 1, 1, -20, +20, 1}};

4 つの波のすべてが、その起点が座標系に分散しているのを除き、同じプロパティを持っていることに注意してください。具体的にそれらは (-20,-20), (+20,-20), (+20,+20), (-20,+20) に位置づけられています。

    デモアプリケーション

CodeCentral にこのデモアプリケーション のプロジェクト一式があります。

    お問い合わせ

embarcadero.com で aohlson へフィードバック等、メールでお気軽にご相談ください。

Server Response from: ETNASC03