けいまさんですけど

死ぬ気でやってりゃ、そりゃ死ぬわ

はじめに

Cardboard開発メモ 1 - けいまさんですけど の続き。

いきなりミクさんを召喚するのは非常にレベルが高いことがわかった。理由としては、

  • NyMMDというライブラリ自体は問題ないのだけど、これのAndroidラッパーがGL ES 1.0を前提に設計されているので、GL ES 2.0で動くように書きなおす必要がある
  • GL ES 2.0を使わないという選択肢は、Cardboard.jarがGL ES 2.0に依存しているため、ない。
  • GLES20はプログラマブルシェーダを使うので、その知識が必要。座標とベクトルぶっこんでドーン!しても動かないらしい。

というわけで、まずは基本から攻めていくことにする。

三角形のレンダリング

NyMMD動かそうとしていた残骸があって微妙だけど、着目すべきはMyRenderer.javaのみ。
(MyRenderer.javaのコードは AndroidでNDKを使わないOpenGL ES 2.0 | ワンダープラネットエンジニア Blog から流用させていただいております。お陰で理解がそうとう深まりました。)

このコードでは頂点座標情報と色情報を同じ配列内に持たせていて、その結果としてVBO(Vertex Buffer Object)との結びつけで mStrideBytes を使っていたりします。
なので実際は色と頂点座標は分けたほうがいい気はした。

VertexShaderは合成ベクトルと頂点情報を演算させているだけ、FragmentShaderも色情報をそのまんま使っているだけ、というシンプルさ。
でも、これでちゃんとCardboard上には2つの像が描画されました。

考察

MyRenderer.java、そしてMainActivity.javaどこを見ても、像が2つ描かれるようなGLES20の処理はありません。
これは、MainActivityが継承しているCardboardActivtyがうまいことやっているから、という他ありません。
これはコードが公開されていないので、どういう処理をしているのかは公式ドキュメントの(セッション動画の)図を読むしかないのですが、

image

Render Sceneだけに注力すれば、あとはCardboardのAPIがよしなにやってくれるという感じです。

ちなみに

各種用語類は以下のサイトの記事を適当に読んで勉強しました。わかりやすい!

はじめに

そのうちQiitaにまとめたいけど、ちょっと纏めるまでの間にいろいろありそうなので、こちらにチェックポイントを書いていこうかな。

前提知識

やりたいこと

Live Coding de Nightの出し物を制作する。
CardboardのAPIを使ってミクさんを視姦したい。

検証

ログを見る

Nexus5(Android 4.4.4)で検証。

MainActivity.java を作成し、Logcatを追跡してみた。CardboardView.StereoRendererでimplementした部分を中心に。

```
08-18 15:40:49.809 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onSurfaceCreated()
08-18 15:40:49.809 19749-19767/net.pside.android.sample.cardboard W/CardboardView﹕ Surface size 1794x1005 does not match the expected screen size 1920x1080. Rendering is disabled.
08-18 15:59:02.845 21494-21521/net.pside.android.sample.cardboard D/MainActivity﹕ onSurfaceChanged(897,1005)
08-18 15:59:02.915 21494-21521/net.pside.android.sample.cardboard D/MainActivity﹕ onSurfaceChanged(960,1080)

08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onNewFrame()
08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onDrawEye()
08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onDrawEye()
08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onFinishFrame()

// ...

08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onNewFrame()
08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onDrawEye()
08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onDrawEye()
08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onFinishFrame()

// ...

08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onNewFrame()
08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onDrawEye()
08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onDrawEye()
08-18 15:40:49.919 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onFinishFrame()

08-18 15:41:06.229 19749-19749/net.pside.android.sample.cardboard W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
08-18 15:41:06.299 19749-19767/net.pside.android.sample.cardboard D/MainActivity﹕ onRenderShutdown()
```

気付き

  • onSurfaceChanged(int, int)は、Immersive Modeに移行した時に描画領域が大きくなるので呼ばれているみたい。
  • onNewFrame() -> onDrawEye() -> onDrawEye() -> onFinishFrame() の順にコールされる。onDrawEye()が2度呼ばれるのは、右目、左目、とレンダリングするため。どっちがどっちという情報はたぶん引数で渡されるオブジェクトにでも入ってるんだろう。
  • バックキーを押すとonRenderShutdown()がコールされた。別にバックキーに限定されず、RenderがShutdownされるときに呼ばれるんだろう(?)

はじめに

マチ★アソビお疲れ様でした。

マチアプリの分析

マチ★アソビ vol.12 時点でのマチ★アプリのAnalyticsデータを基にした分析を行います。

セッション(アクセス数)とユニークユーザー数

マチ★アソビ vol.12のために作成した、マチ★アソビのイベント確認サイト(Webアプリ)「マチ★アプリ」は、2014年4月21日ごろに公開し、
本日5月6日までの間に 1183セッション、 714ユーザーの方々にアクセスして頂きました。

特に4月29日に行ったハッシュタグ付きの宣伝ツイートが比較的よくRTして頂けたこともあり、その1日だけで434セッションを記録しました。

地域

日本からのアクセスが殆どを占めています。アメリカやイギリス、韓国からのアクセスもありましたが、誤差と言える程度です。

さて、都道府県別ではどうでしょうか?以下の4つの地域からは100アクセス以上を計測しました。

  • 東京
  • 大阪
  • 徳島
  • 福岡

首都圏や、開催都市の徳島からのアクセスが多いのは想像通りですが、福岡からのアクセスが多かったのが意外でした。「マチ★アソビカフェ」の影響もあるのでしょうか。よくわかりません!

閲覧環境とモバイルデバイス

マチ★アプリでの「モバイル:タブレット:PC」の比としては、およそ「15 : 1 : 7」の比率でした。
マチ★アプリはスマートフォンでの閲覧に特化したWebサイトでしたが、PCの倍以上の閲覧数になるとは思っていなかったので驚きです。

また、気になる閲覧端末トップ10は・・・

  • Apple iPhone
  • LG Nexus 5
  • (not set)
  • Sony SO-02F Xperia Z1 f SO-02F for DoCoMo
  • Fujitsu F-06E ARROWS NX F-06E for DoCoMo
  • Apple iPad
  • DoCoMo SO-04D Xperia GX
  • Google Nexus 7
  • Apple iPod
  • DoCoMo SO-04E Xperia A

Xperia AとNexus 5は僕が保有している端末です(そのためアクセス数は多いけどユニークユーザー数は少ない)。

iPhoneからのアクセスが、モバイルからのアクセスのほとんどを占めていました。これは予想通りです。
というのも、地方都市はiPhone最強伝説が根強く生きています。マチアプリをネイティブアプリではなくWebアプリにしたのは、
iOS対応を行う上でWebを使うことが自分にとって最も楽にできるやりかただったからです。

ちなみに、iOSとAndroidの比率は6:4でした。

ふぁぼ機能

「ふぁぼる」ボタンは216回押されていたようです。全体的には78イベントでふぁぼが押されました。

実は、ふぁぼるボタンを押された回数を計測していました。(どのイベントをふぁぼったか、も取得しています。)

ただし、個人を特定できるといろいろ厄介なため、「ふぁぼるボタンを押したら計測する」というロジックにしてあります。
つまり、ふぁぼるボタンを連打すると、それぞれカウントがプラスされていきます。
あと、イベントタイトルをキーとして集計していたため、途中で名前を変更したイベントは別物として集計されています。
(ただ今回はそれに引っかかるようなイベントはなかった。。。はず。)

そういういい加減な感じではありますが、イベントのふぁぼられ数トップ10は以下のとおり。

  • 今井麻美のSSG vs 原由実の○○ラジオ 公開合同イベント
  • 鈴木このみ LIVE in マチ★アソビ
  • TVアニメ「アイドルマスター シンデレラガールズ」トークイベント
  • アーク×マチ★アソビ スペシャルトークショー
  • ガールズ&パンツァー 「これが本当のアンツィオ戦です!」 スペシャルトークショー
  • 【徳島駅】マチ★アソビ vol.12 記念入場券販売
  • Tridentミニライブ&トーク
  • 藍井エイル&ELISAライブ
  • 「神クロ」関連トークショー
  • 【前夜祭情報】Wake Up, Girls!スペシャルステージ(仮)

納得の結果ですね。

技術的な総括

よかったところ

  • Google Cloud Storageが思ったよりタフでよかった。(キャッシュ効き過ぎな感じはありましたが。。)
  • Google Calendar APIや、GData APIが思ったよりタフで(ry
  • OnsenUIをつかってアプリを作ったことを公表し宣伝ツイートしたら多くの人に作品を一目見てもらった
    • ただしOnsenUIが最適かどうか分かりません。次はIonic Framework使ってみて、比較検証したい。
  • 友人知人から非常に良い反応・大きなフィードバックを頂けた
  • チュートリアルをまじめに用意したので、それなりには使ってもらいやすいものを提供できた
  • ぐらぷす神 is GOD
    • ぐらぷすさんに泣きついたら element.bind() 使うやり方を教えてもらって解決できた部分があった

悪かったところ

  • FullCalendarに表示する項目数が増えると操作性が悪くなる(スクロールが引っかかるなど)
  • Windowsで作業するとGCSにファイルをアップするときにたいへんつらいのでWindows捨てたい
  • カレンダーON/OFFが重かった。もっとアルゴリズムを洗練させる必要がある。
  • お気に入り機能が微妙にわかりづらかったのと、初回宣伝時に間に合わなかったのが悔やまれる。

まとめ

マチ★アソビ vol.13がアナウンスされました。それまでの間に改善点はできる限り改善したいと思います。

ひとはずはお疲れ様でした!

はじめに

もういくつ寝るとマチ★アソビ。

マチ★アソビ

当ブログでもしばしば話題にしている、徳島で行われる年2回のガチイベント。

僕が徳島を好きな理由として、このイベントがあることは理由の1つとして挙げられると思います。
(他にもちょっと常軌を逸した県民性とかも好きですがまぁそれはそれとして)

こうどなじょうほうせん

マチ★アソビは、とにかく情報戦が激しいのです。
イベントが近づいてくる今現在のところ、まだイベントの情報開示は半分も終わってないと思います。
そういう情報をすぐさまキャッチするために、Twitterなどのツールを使って情報を集めなければなりません。

情報を集めて整理すること

集めた情報は整理しなければなりません。
具体的には・・・

  • どこで何が行われるのかを把握する
  • それを一覧管理する
  • そのなかで行きたいものをピックアップする
  • 当日には節度を守り体調管理を充分に行いイベントを楽しむ

ぶっちゃけ上記2点はマチ★アソビのフライヤーが公開されればOKなのですが、そのフライヤーの情報は、場所ごとのイベントが列挙されているだけ(これだけでも価値ある情報です!)となります。
まぁ慢性的なリソース不足だったりで難しいのは知っていたので仕方ない感じです。

ともあれ、僕がずっと欲しかったのは、「このイベントの裏番組なんだっけ」を一望できることでした。
そんなわけでマチ★アソビvol11くらいから色々思案していたものがやっと形になったので公開します。

マチ★アプリ

「ないものは作れ!」の精神で制作しました。構想2年、制作2週間。

現在は評価段階のベータ版として公開しています。
そのため、表示されている情報は「マチ★アソビ vol.11」の内容です。
マチ★アソビの前夜祭が24日ごろに行われるので、そのあたりからvol.12モードに切り替えようと思います。

マチ★アプリでできること

  • イベントの日別表示
    • 左にスワイプ(画面左上の[三]をタップ)して表示される表示ON/OFFパネルを切り替えることで、会場ごとのイベントの表示/非表示を切り替えることができます
    • 例えばボードウォークは興味ないね!って人はチェック切れば消えるので可視性UP
  • 公式Twitter、ハッシュタグの確認
    • 画面右上の鳥アイコンをタップすると表示されます
    • 画面下部のタブを切り替えて表示を切り替えます
    • ハッシュタグページでは、画面下部の入力ボックスみたいなのをタップするとツイートできるっぽいです

実装したいなーって思ってるもの

以下はまだ実装してないのですが、なんとか頑張って実装したいですね。。

  • イベントをふぁぼる
    • 行きたいイベントをタップしてお気に入りに追加
    • お気に入りに追加したイベントだけを表示する機能
    • ふぁぼを集計して人気のあるイベントとか事前に確認できたら楽しそうだけど、一気にめんどくさくなる雰囲気 is ある

技術的統括

苦労した点

画面を左から右にスワイプすると、カレンダーの表示ON/OFFスイッチが出てきます。このスイッチの切替でカレンダー部分のデータが切り替わるロジックがけっこうきつかったです。
使用しているカレンダーライブラリがデータをチェックしているのですが、そのチェックをすり抜けるようなデータ操作をすると想定外の動きをします。
なので、データ操作する部分は気をつけて(そして時にまわりくどいような)データ操作を行うようにしました。
これに気がつくのに結構かかった。。。

OnsenUIについて

いわゆるモバイルUIフレームワークとしてOnsenUIを採用しました。

最近はIonic Frameworkが結構人気っぽいのですが、あえてOnsenUIを選んだのは、まぁAndroid Bazzar and Conferenceで色々とお話を聞いたからという。

使い勝手に関して、割と素直ではあるのですが、CSSとして提供されているけどComponentがないケース(ButtonBarとか)があって、そこはやや苦労しました。
あと基本的にDirectiveのコードは読まないと何やってるか理解できなかったり、うまくUIを構築できなかったりしますね。。
あんま良い考え方ではないですしOnsenUIに限った話ではないですが、せっかく楽するためにフレームワーク選んでいるのに、なんかあった時に実装まで掘るの、ちょっと手間だなぁとは思います。

色々言ってますが、HTMLで実装できるくせに(とあえて書く!)サクサク動くのは時代の進歩すげーなぁと思いました。

(ちなみにカレンダー部分は重い、これは仕方ないね)

github

PullRequestやご意見などあればどうぞー。

まとめ

マチ★アソビ楽しみですね

はじめに

今日の東京はクソサムイ。。。皆様もお体壊されないように。。。

Docker

Docker meetup #2 というイベントに行ってきた。

僕はここ半年くらいはどっぷりフロントエンドばかりやっており、サーバーサイドはてんで分からず、いつの間にかサーバーサイドは「食わず嫌い」改め「触らず怖い」になっていた。
(LAMP環境みたいなのは構築できますが、複数台構成とかは経験がない。。)
でもDockerに関する発表を見ている限り、全然怖くないじゃん、という感想になった。

そもそもDockerは現行の仕組み上、シェルスクリプトのような感じで書くことが出来る。1行1コマンドのような感じ。
このあたりの気軽さは、その仕組み上がっちりした感じになるChefと比較すると明らかに敷居が低い。

そんなわけで、かねてよりちゃんと実装し直さないといけないなと思っていた、とあるTwitterボットをDocker上に載せることにした。

Google Compute Engine

Docker meetup #2の会場はGoogleの東京オフィスだった。そこで500ドル分のクーポンを貰った。
これを使わない手はないし、Googleの人もGCEでDocker使いましょう!みたいなこと言ってたので使ってみた。

GCE自体は、GoogleのUIで操作できるAWSという印象。実際提供しているもの自体はそこまで違うわけでもないし、そりゃそうなんだけど。
gcutilというツールがあり、基本的にはこれを使ってSSH接続したりする。直接SSHコマンドもOKなんだけど、gcutilは鍵のやり取りなんかもうまくやってくれているので楽。

あと財務管理が楽だという話もあるようで。詳しくは以下スライドをチェック。

Ruby

もともと運用していたTwitterボットは、Webサービスを使って静的にツイートさせていた。
ただ、元となるデータがGoogleスプレッドシート上で管理してあったので、これを直接参照できるようにしたかった。
とりあえず、まずはツイートする「仕組み」を作成することに。

Rubyのtwitterモジュールで、ファイルを実行するたびに(ruby twbot.rb)ツイートするようにした。
twbot.rbでは、だいたい以下の様なことをやっている。

  • 「データソース(Googleスプレッドシート)からデータを取得」
  • 「記録しておいたindexをインクリメントし、それを取得データの配列のindexとして取得」
  • 「取得データのツイート」
  • 「前回ツイートした配列のindexを記録」

なんでRubyかというと、知っている限り一番ラクに目的を果たせるのがRubyのtwitterモジュールだったから、という。

Google Apps Script

上記サイトを参考にしつつ、スプレッドシートのデータをJSONとして得るクチを作成した。このスクリプトの場合は全件をJSONで返すし、ボットスクリプトで「どれをツイートしたか」を保持する仕組みが必要になる(というか僕が作ったものはそうなっている)。

けれど、実際やるんだったらGAS側でカウンターを保持するようにするのが色々楽かもしれない。getSequence()とかそういうノリで、実行するたびに1件ずつ取得していく感じ。

結果

たまに壊れてる時ありますが、原因調査中だったりします。

ともあれ、無事にボットを動かすことが出来た。

まとめ

Docker面白い。うまくやったら結構いいかんじなのでは。

追記

ふと思ったが、これJenkinsでやればいいやんけ案件だった