2012年2月28日火曜日

Androidでポリライン

シューティングゲームなんかでよく見るグネグネ曲がったホーミングレーザー

これを実際に作ろうとすると、中々に負荷がかかるです。
普通のテクスチャと違って頂点が固定化できないのでAndroidでは無理かなーと思ってたんだけどもとりあえずやってみた。

private static final int VMAX = 128;
 private static float v[] = new float[VMAX * 4];
 private static float t[] = new float[VMAX * 4];

 public static void renderPolyLine(Texture tex, Vector vlist, RenderParam param) {
  if (tex.isEnable == false) return;

  GL11 gl = Global.gl;

  int vCnt = vlist.size();
  if (vCnt <= 1) return;
  if (vCnt > VMAX) return;

  final float w = param.sx / 2;
  tex.bind();
  gl.glColor4f(param.r, param.g, param.b, param.a);
  param.setAlpha();

  float uv = 1.0f;
  Vec2 prevPos, pos, nextPos;
  float vx, vy, len;

  for (int i = 0; i < vCnt; i++) {
   prevPos = vlist.get(Math.max(0, i - 1));
   pos = vlist.get(i);
   nextPos = vlist.get(Math.min(vCnt - 1, i + 1));
   //一つ手前と、一つ先のベクトルから、向いている方向を得る
   vx = prevPos.x - nextPos.x;
   vy = prevPos.y - nextPos.y;
   len = (float) Math.sqrt(vx * vx + vy * vy);
   if(len == 0.0f)len = 1;
   vx *= w / len;
   vy *= w / len;

   //指定した横幅に広げる
   v[i * 4] = pos.x + vy;
   v[i * 4 + 1] = pos.y - vx;
   v[i * 4 + 2] = pos.x - vy;
   v[i * 4 + 3] = pos.y + vx;

   //テクスチャもセットする
   t[i * 4] = 0;
   t[i * 4 + 1] = uv;
   t[i * 4 + 2] = 1;
   t[i * 4 + 3] = uv;

   uv -= 1.0f / vCnt;
  }

  gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
  gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, Util.makeFloatBufferArchive(t));
  gl.glVertexPointer(2, GL11.GL_FLOAT, 0, Util.makeFloatBufferArchive(v));

  gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, vCnt*2);

  Vbo.repair();
 }
ソースはこんな感じ。 どこかで見かけたソースなんだけど、描画しようとしているある点の一つ前と1つ後から進行方向を求めて、直行ベクトル(と、その反対)に幅を広げてあげている頂点をセットする感じ。 3Dだと外積だけど、2Dなおでxとyを入れ替えるだけ。 で、UVをちょっとずつずらす(綺麗に0~1に収まるようにする)。 テストでホーミングレーザーをした図
予想通り激重いけど、馬鹿みたいにばらまかなければ使えるかな。 でも、ホーミングレーザーって馬鹿みたいにばら撒くから綺麗なのに。 だめじゃな。 ちなみに、レーザー画像を
にすればこんな感じでファンシー(?)になるのがステキング。