帰ってきた人生戦闘詳報

madtape.com

2015-06-29

[][][] 学ぶことへの突破口 02:11

実のところ自分は中学高校と数学は得意ではなく、お世辞にも良い成績ではなかった。

おまけに大学にも行っていないので、学校での数学教育は高校卒業と同時に終わってしまっていた。

中学高校で何を習ったかの項目は覚えてはいるが、それらの詳細がどんなものであったのかを理解したのは学校を出て月日が経過し、自力でそのあたりを学び直してからである。それ以降、数学以上にあらゆることの役に立つ道具とは出会えていない。つまり現時点に至るまで、数学は公私ともに役に立ち続けているということ。


正直この「学び直し」は二度手間であったと感じているので、

現役の中高生には「学校で学べるうちにそれらを理解しておいた方が良い」と言うし、

残念ながら理解しないまま大人になってしまった人には「大丈夫、今からでもそれは取り戻せる、現に俺は取り戻した」と言う。

大学にさえ行っていない俺でも中学高校で習った中で覚えている幾ばくかだけを最初の足掛かりとして、現在の程度までは取り戻せる、というのは自身の経験が証明している。


とはいっても理由も興味もないまま学び直すのを徒労に感じるのはわかる。しかし、それはそれで問題が明確であるので、その問題を解決してしまえばよい。つまり「数学がわからなければ先に進めない興味の対象」を持てば良いのだ。


自分の場合はSFを書きたくなり、そこに登場させるロケットの数値に「実際に飛ぶ筈である数値的根拠を与えたくて買った本」の内容を理解したいと思った。

何より重要なのは、自分にとってこれは無駄知識であり、理解することを勝利条件としたゲームなのだ、という点である。

自身の力でロケットを設計、製作して現実に飛ばすことなど当時の自分にはあり得なかった。これが仕事で必要なのでやむなく、とかの動機であれば「やらされている」感が尋常ではなかっただろう。学ぶことに義務感や使命感は致命的だ。重要なのは伊達と酔狂を動機とすることなのだ。伊達と酔狂でやる限り人間は無限に学んでいける。それで学んだことの余禄を仕事にでも応用して飯の種にできればさらに良い。

とにかく「この本を一定以上理解すること」という目標が突破口になった。


それで実際に何をやったかといえば、読んでいく中で登場する数式について前提条件をつぶさに読み、その上で数式を読み解いて、理解が及んでいないと感じた箇所についてとにかく調べた。調べた中で不明点があればそこから再帰的に調べて掘り進んだ。

この「再帰的に調べる」というのが重要。

自分が今読んでいるのは応用であり、その応用を自身は理解したいのだ、という認識を持つ。

応用は基礎ができていなければ理解不能であるから、応用を説明されてわからないところこそが一段下の基礎である。

それを調べてわからない箇所があれば、それがさらに一段下の基礎である…という感じで、

「応用の側からわかるところにたどり着くまで基礎の側に掘り進んでいく」方法をとった。

理解の上で呼び出し元に戻ってくるころには基礎も出来上がっている。

これを繰り返すと、回を重ねるごとに掘り進む深度が浅くて済むようになる。

一度掘り進んだ基礎については既に理解しているので、

同じ基礎に立脚するものであれば理解が済んでいる階層にたどり着いたらそれ以上掘る必要がなくなるからだ。


また「自分に理解可能な形で理解する」というのも大事。

たとえば「Σ」という記号が出てきたら「このΣはどう取り扱う記号なのか」といったところから調べた。

この場合調べた結果の理解は「for文的にループで足し算する」みたいな感じだった。つまり、

x=¥sum_{n=0}^{N-1}V_{n}

であれば

int sum_func(int V[], int N)
{
	int n;
	int x = 0;
	for(n = 0; n < N; n++) {
		x += V[n];
	}
	return x;
}

のようなコードになる、というふうに。


プログラムを理解できる、というスキルに数式表現の理解で助けられた点は大きい。数式においてそれぞれの記号が表す値の扱いを、プログラムコードという表現で理解できるわけで、これは下手に日本語で説明されるより確実性の高い方法だ。プログラムが多少なりとも理解できるというだけで、数学を学ぶ上での強力な武器を手にしているのだ、とも言えると思う。


「現時点でわからない」というだけで「自分には理解できない」という結論に至るのは明らかな飛躍であるし、突破口が開ければ学んでいける道もある。そして突破口を作ることは現実に可能だ。「わからないまま」は勿体ない。

トラックバック - http://d.hatena.ne.jp/big-bros/20150629

2015-06-17

[][][] なんとなく書き始めたもの。 04:21

現場で若いエンジニアと話してると、

その子が「文系出身」なエンジニアだったりして、

ゲームを作る現場で必要となる数学の基礎が全然できてなかったりして、

場合によっちゃ数学アレルギー的な反応を見せたりして、

そんな自分でもUnity様が救済してくださると無邪気に過ぎる信仰を抱いていたりして、

そんな彼らを見ていると時々リサリサのように養豚場のブタを見ているような気分になることもあったりして、

時代的にそんな子が一人や二人じゃなさそうな気配も感じたりしたので、

なんとなくこんなのを書き始めてみた。

3D前夜1:予備知識の2D編 - Google スライド

3D前夜2: もうちょっと2D - Google スライド

3D前夜3: 行列 - Google スライド

まあ、実際使える資料にするまでに、いろいろ推敲したり進行練り直したりする必要があるわな。

あと当初3Dプログラマを突貫で育成する資料を書けないかなって思ってたんだけども、さすがに三角関数わかんない段階で何を教えても確実に無駄に終わるので、基礎として「彼らがなんとなく理解できてるつもりになってる2Dをがっつりやる」ところからかな、って感じでこんなのになった。

なんせ「どうしたらいいですかねー」に対し「こうしたらできるよ」って答えようにも、相手がその原理を理解できる素地がないとできないことってのは山のようにあるわけで。

トラックバック - http://d.hatena.ne.jp/big-bros/20150617

2015-05-27

[][][] 購入書籍についてなんとなく。 15:19

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

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

C++11 に対応した形でC++を網羅した書籍を持っておきたいと思っていたので購入。

C++98 との差異についてもコンパクトにまとめられていて大変便利。

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

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

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

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

これだったら2002年出版の

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

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

…を勧めちゃいますね。既に13年前の書籍なので今手に入るかわからないけども。

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

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

トラックバック - http://d.hatena.ne.jp/big-bros/20150527

2015-03-28

[][] Androidの扱いにくいポイント 22:00

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


この統一感に欠け、使うたびにバッドノウハウばかり次々溜まっていく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で組み上げ、後から全体のデフォルトフォントを変更する」という作り方ができなくてめんどくさいんだけども。

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

トラックバック - http://d.hatena.ne.jp/big-bros/20150328

2015-03-20

[][][] 明日は春分の日 22:09

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年目なので、まあ当面は大丈夫だし、昨今は閏秒を挟むなど更に細かな調整が入っており実際にずれるのはまだ遠い先の話。

トラックバック - http://d.hatena.ne.jp/big-bros/20150320
Connection: close