Linux&gccでのライブラリの作り方

静的ライブラリ

gcc -c hogehoge.c
でオブジェクトファイルを作った後に
ar rcs hogehoge.a hogehoge.o
でhogehoge.oをhogehoge.aに追加する。
hogehoge.aが無ければ勝手に新しく作ってくれる。

動的ライブラリ

gcc -g -Wall -fPIC -c hoge.c
gcc -g -Wall -fPIC -c foo.c
gcc -shared -o libxxx.so hoge.o foo.o
で作れるが、qmake使ってproファイルに
TEMPLATE = lib
って書いた方が簡単だし、相対リンクのシンボリックリンクまで作ってくれて便利。

libpng

OpenGLはちょっとあっちの方に置いといて、libpng触ってます。
libpng.txt、ではなくて日本語訳をしてくださっていた素晴らしい方がいらっしゃったので、そちらを読ませて頂いて進めています。


今のところ日本語訳を読ませて頂いてるからまだ何とかなってますが、これ原文の英語と闘ったらすごく時間掛かりそう。
慣れてないってのもあるけど、中途半端にコードと説明が書いてあるから読んだだけじゃ引数の型すら把握できません。
マニュアルとソースコードを照らし合わせるの必須です。


やってるうちにMSのマニュアルがまともに見えてきた・・・カテゴリ分け以外は。


まぁでも、なんだかんだあれが動かねぇこれが動かねぇやりつつも、読み込みの大筋は把握。
書き込みはほぼ同じ流れらしいので、最大の敵は形式変換か。


最終目的が達成されるまで、あと数日は掛かりそうな感じ。
全部終わったら大雑把なlibpngの使い方でも書きます。

バイトオーダー

今までテキストファイルしか扱ってこなかったんで、初めてまともにバイナリファイルをいじったら見事にバイトオーダーで詰まりました。


x86プロセッサにおいて、メモリ上のデータはリトルエンディアンで並んでいます。
そこにint型の変数xを確保します。
xにバイナリファイルからビッグエンディアンで並んでいる4バイトをstd::ifstreamクラスのreadメソッドで突っ込みます。
読み取ったバイトはバイナリファイルと同じ並びで配置されますが、プロセッサがこのxの内容をint型として扱うときはリトルエンディアンで並んでいる事が期待されて読み取られます。
結果、意図しているByteの並び順とは逆の順番で読み取られます。


見事に引っかかったぜハハハ。
バイトの並びを逆順にする関数作って解決しました。

QtでOpenGL - その3

GLUTによる「手抜き」OpenGL入門
が最後まで終わりました。
図形の描画はともかくとして、視点周りでかなり混乱・・・。
床井先生の書かれてる超基本編だけなら問題は無かったのですが、gluPerspectiveをglFrustumに変更するときにglOrthoと同じようなもん程度の認識でやったらひどいことに。
あれこれググりまくって何とか正射影と透視法射影の違いを理解出来て、とりあえず表示させる分には事なきを得たのですが・・・。
今度は下のURL先で紹介されてる、表示領域のサイズが変わった時に表示内容のサイズが変わらないような処理でまた混乱。
Frequently Asked Questions
URL先の式の検証をした時の文字の置き方が悪かっただけだったんですけどね。
視点からの前方面スクリーンサイズと、想定する表示領域サイズをごちゃ混ぜにして考えるとハマる。必ず分けて考える。


陰影処理とか質感出す処理とか、まず用語からイミフ。
ちゃんとした理解はとりあえず後回しにする。

QtでOpenGL - その2

GLUTによる「手抜き」OpenGL入門
を参考に多分2日目くらい。9.アニメーションまで終わった。
とりあえず立方体を三角関数使って簡単にアニメーションさせて喜べるようになりました。


関数名とかは当該ページを見れば分かるから考え方をメモ。

座標変換プロセス

  1. 図形の空間中の位置を決定する:モデリング変換
  2. 上記空間を視点から見た空間に直す:ビューイング変換(又は視野変換)
  3. その空間をコンピュータ内の空間にあるスクリーンに投影する:透視変換
  4. スクリーン上の図形をディスプレイ上の表示領域に切り出す:ビューポート変換

上記順番で各変換が行われる。

  • モデリング変換はワールド座標系への各座標の配置や線を引いたりなどの3D空間への描画工程(3次元)
  • ビューイング変換はワールド座標系の視点位置を変更する工程(3次元)
  • 透視変換はワールド座標系を視点位置を元に正規化デバイス座標系へと変換する工程(3次元->2次元変換)
  • ビューポート変換は正規化デバイス座標系をデバイス座標系へと変換する工程(2次元)

という解釈で合ってるはず。間違ってたら教えて下さい。
実際にコーディングする際は上記の各変換順序とは逆順に各関数を呼んで指定していくことになる。


モデリング変換とビューイング変換の工程は合わせて「モデルビュー変換」と呼ぶ。
このモデルビュー変換と透視変換の工程をそれぞれ独立させて変換行列を適用していくことが出来る。

  • glMatrixMode(GL_PROJECTION)を指定した以降は透視変換を行う。
  • glMatrixMode(GL_MODELVIEW)を指定した以降はモデルビュー変換を行う。

上記を指定しない場合はモデルビュー変換と透視変換の前後関係を意識しなければならない。
これはすごく面倒なので、必ず上記の指定をして別々に処理を行えるようにする。


QtでアニメーションさせるのってQTimer使ってシグナル送って貰うとか、タイマーイベント使う以外にもっとスマートな方法は無いのだろうか。
ちょっと調べたくらいじゃ出てこなかったけど、きっとに何かあるに違いない。

qmakeを使うときの微妙なtips

書いてから思ったけど、tipsでは無い。1つしか書かないから。


qmake -projectする度に、自分が後からproファイルに追加した変更は消えてしまう。
20文字くらいしか足さないならいいけど、あれこれIncludeパスとか追加したりしたときは追加作業が余りにも面倒。
そんな時は下のシェルスクリプトを使えばいいかもしれない。

#!/bin/sh
qmake -project $1
if [ "$1" != "" && -f $1 ] ; then
    cat pro.add >> $1
fi

pro.addに書いてある内容をproファイルの末尾に追加する。
proファイルの名前を引数に取る。
好みや気分でスクリプトの中身は変えればいいんじゃないでしょうか。