なんとなく書き始めたもの。

現場で若いエンジニアと話してると、
その子が「文系出身」なエンジニアだったりして、
ゲームを作る現場で必要となる数学の基礎が全然できてなかったりして、
場合によっちゃ数学アレルギー的な反応を見せたりして、
そんな自分でもUnity様が救済してくださると無邪気に過ぎる信仰を抱いていたりして、
そんな彼らを見ていると時々リサリサのように養豚場のブタを見ているような気分になることもあったりして、
時代的にそんな子が一人や二人じゃなさそうな気配も感じたりしたので、
なんとなくこんなのを書き始めてみた。

3D前夜1:予備知識の2D編 - Google スライド
3D前夜2: もうちょっと2D - Google スライド
3D前夜3: 行列 - Google スライド

まあ、実際使える資料にするまでに、いろいろ推敲したり進行練り直したりする必要があるわな。
あと当初3Dプログラマを突貫で育成する資料を書けないかなって思ってたんだけども、さすがに三角関数わかんない段階で何を教えても確実に無駄に終わるので、基礎として「彼らがなんとなく理解できてるつもりになってる2Dをがっつりやる」ところからかな、って感じでこんなのになった。
なんせ「どうしたらいいですかねー」に対し「こうしたらできるよ」って答えようにも、相手がその原理を理解できる素地がないとできないことってのは山のようにあるわけで。

購入書籍についてなんとなく。

久しぶりに書く記事は、お昼の帰りに購入した書籍とその感想です。

プログラミング言語C++ 第4版

プログラミング言語C++ 第4版

プログラミング言語C++ 第4版

C++11 に対応した形でC++を網羅した書籍を持っておきたいと思っていたので購入。
C++98 との差異についてもコンパクトにまとめられていて大変便利。

動かして学ぶ3Dゲーム開発の数学・物理

若い人が3Dやりたいと言い出したりとか、あるいは3Dをやらざるを得なくなったときの教育用として使えるかどうか見ておきたかったので購入…したはいいんだけど。

読んでみたら「3Dゲーム開発の〜」と銘打っているわりにはクォータニオンについて言及しておらず「本書の範囲を超えるため、ここでは言及しないものとします」の一点張りで、あんまり勧められる書籍ではなかった、というのが俺の感想*1

ゲーム開発に使うならクォータニオン無しじゃやってられんでしょ? 仮にUnity使ったって回転はクォータニオンで表してるんだから。3Dゲーム開発初学者が一番概念を理解するのに苦労するポイントの一つなので、書名に「3Dゲーム開発の数学・物理」を謳うなら全然「本書の範囲を超え」てないです。

これだったら2002年出版の

ゲームプログラミングのための3Dグラフィックス数学

ゲームプログラミングのための3Dグラフィックス数学

…を勧めちゃいますね。既に13年前の書籍なので今手に入るかわからないけども。
いずれにせよ、直交座標、ベクトル、行列、内積外積クォータニオンの全てについてしっかり解説してない書籍は、これから3Dゲーム開発を学ぼうって人にあんまりお勧めできないなあと思いましたですよ、ええ。

*1:索引で「クォータニオン」を引くと三カ所ページが示されていますが、その全てがこんな調子でした。

Androidの扱いにくいポイント

これまでAndroidではNDK+GLES2を使ってC++でゲームを作るなどはやったことがあったが、たまたま仕事でJavaを用いて標準UIのAndroidアプリを書く機会に恵まれた。その時に引っかかったななめ上の仕様に関する恨みつらみを並べ立ててみる。


この統一感に欠け、使うたびにバッドノウハウばかり次々溜まっていくAPI実装は一体何なのか。本当にgoogleはこれでいいと思ったのか。

Contextの引きずり回し

APIが事あるごとにContextを要求してくる。場合によってはActivityでなくてはならない。

このためプログラムを部品化するにあたって Context を引きずり回すような実装になってしまい依存性が拭い去れない。Activity を多機能にすると肥大化しやすい。

ActivityのonCreate()あたりでsingletonに握らせて、以後必要になったらそこから引っ張ってくる、みたいな方法も考えたけど、そういうシステムリソースの管理をユーザプログラムにさせるのっておかしくないだろうか。そういうのは裏でひっそり確実にやっておいてほしいのだけど。

ImageButton が Button クラスではなく ImageView の派生

どうやらAndroidの開発者は、ラベルに画像が使えるボタンは「ボタンであること」よりも「画像を表示できるものであること」のほうが大切だと考えているらしい。

ImageButton  |  Android Developers

findViewById()などでViewをButtonインスタンスに取得し OnClickListener を仕掛けるようなコードがあったとする。こんなの。

		Button button = (Button)findViewById(R.id.button_foobar);
		button.setOnClickListener(new View.OnClickListener() }
			@Override
			public void onClick(View v) }
				:
				:
			}
		}

このID = button_foobar のボタンをレイアウトXML上でImageButtonに置き換えたりするだけで落ちるようになる。せめて Button クラスの派生であるならば Button インスタンスとして受けることができるのだけども。

HorizontalScrollView が ScrollView ではない

Androidにおいて、垂直スクロールと水平スクロールは「全く異なる機能」である。

setOrientation() で VERTICAL と HORIZONTAL を切り替えられる LinearLayout と異なり、ScrollView および HorizontalScrollView なる二つの別クラスとして実装されていて、しかもどちらかがもう一方の派生、というわけでもない。

ScrollView  |  Android Developers
HorizontalScrollView  |  Android Developers

(参考)LinearLayout  |  Android Developers

両方とも FrameLayout の派生であり、この FrameLayout はスクロールに関する機能を持たないため、「縦横兼用のスクロール機能を持った何か」を実装しようとすると、ポリモーフィズムを利用して実装を統一する、ということができず、両者それぞれのコードを書き分けることになりめんどくさい。

FrameLayout  |  Android Developers

せめてFrameLayoutとの間にAbstractScrollView(仮)的なものを挟んでいてくれたらそれを使ってコードを共通化できたりするわけだが。つまり現在

  • FrameLayout
    • ScrollView
    • HorizontalScrollView

となっているクラス階層を

  • FrameLayout
    • AbstractScrollView(仮)
      • ScrollView
      • HorizontalScrollView

みたいにできんものかなぁと。

ScrollView がことごとく TouchEvent に蓋をしている。

onInterceptTouchEvent() も含め、自身のスクロールに必要ない TouchEvent をことごとく阻害する。ScrollViewに限らず、Androidの TouchEvent まわりは、最初の ACTION_DOWN を取ったView以外全てが蚊帳の外になる仕様が腐ってると思うのだけども、とりわけ ScrollView はその腐り方が半端ではない感じ。

とりあえずTouchEventまわりはなんとかできんものだろうか。

ScrollView内部サイズの扱いが面倒

デフォルトでfillViewportがfalseになっていると、内部スクロール領域を縮められるだけ縮めようとするので、スクロール方向のレイアウトサイズ指定をMATCH_PARENTにしてあると縮んでしまう。これ、true をデフォルトにしておいたほうが絶対便利だと思うのだが(そもそもfillViewportに関する情報も意識してないと行き着かない感じ)。あと、ScrollView 自体は ViewTreeObserver で OnGlobalLayoutListener を仕掛けても正しいサイズが取れないっぽい。

  • fillViewport を true にする
  • FrameLayout などを addView() して、そこに対し ViewTreeObserver で OnGlobalLayoutListener を仕掛ける

みたいにしないと確定されたサイズが取れないし、確定してから中身を作らないと色々面倒なことになる。前二つの項目も含め、ScrollView 周りはとかく仕様が想像のななめ上をいっており、ひたすら地雷原である印象。

ScrollView  |  Android Developers(setFillViewport)

fillViewport の true がデフォルトで、ScrollView 本体から ViewTreeObserver で正しくサイズが取れて、HorizontalScrollViewとスクロール機能のインタフェースを基底レベルで共有してくれていれば概ね想像どおりの挙動なのだけども。

アプリ全体で用いるデフォルトフォントの変更ができない

誤解を招かないように言っておくと、
「アプリ全体で標準のTextViewが用いるフォントファミリーを、システムが提供している中から選択すること」
はできる。
「特定箇所のテキスト表示にTextViewをextendsした独自クラスを用いてフォントを変更する」
こともできる。
「OS環境全体で使用するフォントをなんらかの.ttfに置き換える」
こともできるようだ。

ただ、少なくとも

  • 特定のアプリ上で
  • 標準のTextViewが用いるフォントを
  • 開発者が用意した.ttfで
  • 置き換えること

を実現する方法は見つけられなかった。これができないと「先にレイアウトを標準のTextViewで組み上げ、後から全体のデフォルトフォントを変更する」という作り方ができなくてめんどくさいんだけども。

「その方法を提供しない理由」とかは別に聞きたくないし興味もないんだが、ほんとにこれできないの?

明日は春分の日

2015年は3/21が春分の日となる。


春分」とはこの地球がその軌道上の春分点を通過するということであり、春分点とは地軸のベクトルと地球から見た太陽のある方向のベクトルが成す角が直角となる点のことだ。3D的に言うなら、これらを単位ベクトル化して内積をとれば春分点において{\cos\frac{\pi}{2}=0}となるはず、という位置を地球が通過する日だ。


毎年だいたいこの時期、 3/20〜3/21に春分の日がおとずれるのは、現在使われている暦であるグレゴリオ暦が概ね正確であるということで、これを定めた16世紀のローマ教皇グレゴリウス13世のもと制定に関わった先人たちのおかげだが、そもそも改暦に踏みきった理由が、この春分の日を3/21と定めていたユリウス暦上で天文学上の春分とずれまくり、復活祭(イースター)の日付を決めるのに困るという宗教上の理由だった。


グレゴリオ暦における「閏年」の決め方を知っていればわかるが、現在の閏年は400年の間に97回訪れる。対してユリウス暦では4年に一度なので400年に100回の閏年となる。これだけでも、両者には400年に3日の差が生じる精度差があることがわかる。紀元前45年から使われはじめたカエサルが定めた暦であれば、16世紀までの間には10日以上ずれるわけで、そりゃクリスチャンの皆さんも困ってただろう。


精度でいえば、グレゴリオ暦は約3221年に1日程度のずれであり、運用が開始された1582年10月からまだ433年目なので、まあ当面は大丈夫だし、昨今は閏秒を挟むなど更に細かな調整が入っており実際にずれるのはまだ遠い先の話。

リプレース作業: Roland UA-25 から Roland QUAD-CAPTURE UA-55

YosemiteでサポートされなくなったUA-25に代わり、QUAD-CAPTURE UA-55 へのリプレース作業を行ったわけなのだが、両者の入出力系統仕様の違いにより、リプレース時にオーディオI/F以外の部分にも変更が必要になる。単にプラグの仕様が変わるだけの場合から、間にコンバータを挟む必要が生じるケースまである。

UA-25 から UA-55 への変更で大きく変わるのは2点。

背面のライン出力はピンプラグから標準プラグになる

UA-25では背面のラインOUTPUTが標準プラグとピンプラグの両方が用意されていたが、UA-55はこれが標準プラグのみになった。ピンプラグを中心に運用していたので、この部分は変換プラグを用いて対応。

 デジタル入出力が角型光コネクタではなくCOAXIALコネクタになった

うちの環境ではPS3およびPS4の音声をHDMIに出力したものをHDMIセレクタに通したのち、音声のみを分離して角型光コネクタでUA-25に入力していたのだが、UA-55ではデジタル入出力がCOAXIAL端子になったため、この部分に対応せざるを得なくなった。アナログ系のケーブルと異なり変換プラグでは対応できないため、audio-technica製AD-HDSL1を用いて角型光デジタル入力をCOAXIAL出力に変換した上で接続。

AT-HDSL1 | スピーカー/ミキサー/AVアクセサリー | 一般製品 | オーディオテクニカ


とりあえずはこれでオーディオI/Fのリプレースはひと段落。

Roland QUAD-CAPTURE UA-55

「主役メカ交代」というイベントはそれこそ俺が知る限りでも「ジャンボーグA」の時代からあるわけだ。それらはアニメや特撮の中だけの話ではない。使用している機材が置き換わるとき、あなたは主役メカ交代イベントの当事者となる。


そんなわけで、先日 MacOS 10.10 Yosemite ではサポートされないことが発覚したオーディオI/F EDIROL UA-25(Roland) に代わる、あらたな機材を調達してきた。Roland UA-55 QUAD-CAPTURE。主役メカ交代イベントにふさわしく、同じ系譜に連なるオーディオI/Fである。

Roland - JP

…しかしまあ、Roland 製品の添付 DAWSONAR LE から Abelton Live Lite に変わるなど、Roland 製品を取り巻く環境もDTM環境を整えはじめた7年前と大きく異なってきている。よく見たら使っているMIDIキーボード PCR-500 あたりもUSB-MIDIドライバがYosemiteでサポートを打ち切られていたりするけども、そちらはMIDIケーブルで繋いでいるため、MIDIコネクタが何らかの形でサポートされる限りはあまり影響はない。このあたり、近年になって用いられるようになったUSBによる接続よりも30年以上前の1983年から存在する31.25kbpsシリアル通信のMIDIコネクタ規格のほうが頼りになる、というのもソフト屋として色々と考えさせられる点がある。


あとはDAWだな…

EDIROL UA-25, Yosemite でサポートされず。

さて、長らく Mountain Lion のまま運用してきたうちのMBPを、iOSの開発環境であるxcode6の都合でYosemiteにしてみたわけだが…


これまでDTM機材および音声系統のコアとして用いてきた EDIROL UA-25*1 が動作しない。Roland のページを確認したところ…

Roland - JP
「申し訳ございませんが、OS X Yosemite には対応いたしません。」

の扱いに。


…まあついにこの日が来たか、という感じではある。なんせ購入したのがまだWindows XPが現役だった頃かつEDIROLのブランドが生きていた頃だから、当然2010年以前(具体的には2008年)。既に7年前の機体だし、後継機種も次々出ているので、いつサポートを打ち切られてもおかしくはなかったわけで。しかし面白いことに Windows 8.1 では継続してサポートされている。


2年ほど前に、DTM環境を Windows 上の SONAR から Mac上の Logic Pro に移行したわけだけども、Yosemite でUA-25が使えないとなるといかなる道を採るべきか。

  1. 新しいオーディオI/Fを購入する
  2. OSをMarvericksにダウングレードする(一応サポートされている)
  3. Windows 環境に回帰する

さあどれだw

*1:"EDIROL"は2010年9月まで使用されていたRolandのブランド。