GLKMatrix4MakeOrtho の使い方を勘違いしていた件
Normalized Device Coordinate
OpenGL などでは、最終的なデバイスの上での表示座標は NDC(Normalized Device Coordinate)で X座標、Y座標も-1.0
〜1.0
の範囲で表現できます。実際の表示エリアが、縦長か横長かに関係なく、-1.0
〜1.0
で、中心が 0.0
となります。
さすがに、アプリがこのNDCを意識してコーディングするのは不便なので、3Dでは GLKMatrix4MakePerspective
など、2D なら GLKMatrix4MakeOrtho
を利用して、4x4 の Matrix(行列) を求め、この Matrix を 座標 の Vector と乗算して座標変換すれば、View の座標を NDC に変換する事ができます。
NDCの座標 = その行列(4x4) * Viewの座標(x,y,z,w)
行列の演算
Swift を使っているなら、行列の演算は * オペレータを使って実装したいですね。4x4 の行列同士の乗算の結果は 4x4 の行列になりますし、4x4 と 1x4 の行列の乗算の結果は 1x4 の行列になります。
func * (l: GLKMatrix4, r: GLKMatrix4) -> GLKMatrix4 {
return GLKMatrix4Multiply(l, r)
}
func * (l: GLKMatrix4, r: GLKVector4) -> GLKVector4 {
return GLKMatrix4MultiplyVector4(l, r)
}
GLKMatrix4MakeOrtho
GLKMatrix4MakeOrtho
では View の上下左右を指定します。ドキュメントでは以下のような記述になっています。
func GLKMatrix4MakeOrtho(left: Float, _ right: Float, _ bottom: Float, _ top: Float, _ nearZ: Float, _ farZ: Float) -> GLKMatrix4
Parameters | description |
---|---|
left | The left coordinate of the projection volume in eye coordinates. |
right | The right coordinate of the projection volume in eye coordinates. |
bottom | The bottom coordinate of the projection volume in eye coordinates. |
top | The top coordinate of the projection volume in eye coordinates. |
nearZ | The near coordinate of the projection volume in eye coordinates. |
farZ | The far coordinate of the projection volume in eye coordinates. |
よって、nearZ
と farZ
をちょっと置いておいて、例えば画面のサイズが 1024x768 の場合、左下を原点にした場合と中心を原点にした場合のそれぞれをコードと図で表現すると以下のようになります。
1. 左下を原点にした場合
let matrix = GLKMatrix4MakeOrtho(0, 1024, 768, 0, -1, 1)
2. 中心を原点にした場合
let matrix = GLKMatrix4MakeOrtho(-512, 512, -384, 384, -1, 1)
勘違い
私はこれで、View の座標を NDC座標系に変換できると思っていたので、先の図の説明に使った座標系の座標と GLKMatrix4MakeOrtho
の行列を演算すれば、簡単に座標の変換ができると思い込んでいました。が、
実は、二つのどちらの行列も原点 (0, 0)
は View の中心に変換され、どちらにしようと結果が同じ結果が得られるという残念な結果に気がつきました。もっと早く気がついていれば楽になっていたのですがね。「右」とか「左」とか指定するならそう思っちゃうじゃないですかぁ。
let t1 = GLKMatrix4MakeOrtho(-512, 512, -384, 384, -1, 1)
let t2 = GLKMatrix4MakeOrtho(0, 1024, 768, 0, -1, 1)
// 座標 (-512, -384) → (-1, -1)
t1 * GLKVector4Make(-512, -384, 0, 0) // "[-1.0, -1.0, -0.0, 0.0 ]"
t2 * GLKVector4Make(-512, -384, 0, 0) // "[-1.0, -1.0, -0.0, 0.0 ]"
// 座標 (0, 0) → (0, 0)
t1 * GLKVector4Make(0, 0, 0, 0) // "[0.0, 0.0, 0.0, 0.0 ]"
t2 * GLKVector4Make(0, 0, 0, 0) // "[0.0, 0.0, 0.0, 0.0 ]"
// 座標 (512, 384) → (1, 1)
t1 * GLKVector4Make(512, 384, 0, 0) // "[1.0, 1.0, 0.0, 0.0 ]"
t2 * GLKVector4Make(512, 384, 0, 0) // "[1.0, 1.0, 0.0, 0.0 ]"
上下反転させたい場合
さて、最後に、GLKMatrix4MakeOrtho
で top
と bottom
を入れ替えると(0
と 768
の順番に注意)、上下を反転させて変換できるようになります。
let t3 = GLKMatrix4MakeOrtho(0, 1024, 768, 0, -1, 1)
t3 * GLKVector4Make(-512, -384, 0, 0) // "[-1.0, 1.0, -0.0, 0.0 ]"
t3 * GLKVector4Make(0, 0, 0, 0) // "[0.0, 0.0, 0.0, 0.0 ]"
t3 * GLKVector4Make(512, 384, 0, 0) // "[1.0, -1.0, 0.0, 0.0 ]"
全体像はまだまだ
ここでは、GLKMatrix4MakeOrtho のみを扱ったが、 Model座標→ワールド座標など、全体を見れば一部の説明に過ぎないので注意されたい。
ハードルはやはり高い
GPU を使うプログラミング は門外漢(ES 1.1はかじった事があるけど)なので、単純に Core Graphics を使う場合などに比べて、何かとハードルが高い。間違いや勘違いの指摘など気がついたら教えていただければ幸いです。
Author And Source
この問題について(GLKMatrix4MakeOrtho の使い方を勘違いしていた件), 我々は、より多くの情報をここで見つけました https://qiita.com/codelynx/items/0c067976edc0afe17ebc著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .