Friday, October 30, 2009

LibTIFFのTIFFOpenの設定によるファイルアクセスの挙動の違い

LibTiffというライブラリを使ってプログラムすることがあるが,TIFFOpen関数のモードの設定の"r"と"r+"の違いではまったことがあったので,メモ.
環境はwindows xp pro, visual studio 2008 vc++.

TIFF* TIFFOpen(const char *filename, const char *mode)
この関数はfilenameであるファイルのアドレス,modeであるファイルアクセスのモードを設定することで,tiffファイルを開く機能が実装されている.
それで,modeの違いでちょっとした挙動の違いを示す.
"r"は読み込み,"w"は書き込み,"a"は追記とリファレンス(http://www.remotesensing.org/libtiff/man/index.html)のTIFFOpenの項目には記述してあるのだが,それ以外にも,"r+"などが設定できる.
今回は"r"と"r+"の若干の違いについて気付いたので,メモっとく.
TIFF* tiff = TIFFOpen(filename, "r");
TIFFClose(tiff);
とするとtiffはアクセスができなくなっているが,他のファイルからfilenameのファイルにアクセスしようとしてもアクセスエラーがでる.
たとえば,
TIFF* tiff = TIFFOpen("filename.tiff", "r");
TIFFClose(tiff);
system("del filename.tiff");
としても,filename.tiffは消えない.

つまりは,複数の実行ファイルをひとつの一括したようなプログラムでtiffを読む場合,この読み込みでは,一番最初に読んだやつだけがアクセス可能となり,それ以降ではCloseしているのにも関わらず,アクセス不可能となる.

一方,
TIFF* tiff = TIFFOpen("filename.tiff", "r+");
TIFFClose(tiff);
とした場合は,このfilename.tiffはどれからもアクセス可能になっている.つまり,
TIFF* tiff = TIFFOpen("filename.tiff", "r");
TIFFClose(tiff);
system("del filename.tiff");
とすると,filename.tiffは消える.

つまり複数の実行ファイルをまとめたようなプログラムでは,どいつもこいつもfilename.tiffにはアクセス可能となっている.Closeしているので,これが正しい形に思える.
セキュリティの違いで組みかたを変えればよいと思うが,この違いを知らないと,ずっとはまることになる.

ちなみに私は3時間くらいはまっていた.

openGLの光源の位置設定でありがちなミス

openGLでの光源の位置は,4つの要素配列を使って設定するべし.

void glLightfv(GLenum light, Glenum pname, const GLfloat *params)
この関数を使って光源を設定する.
lightにはGL_LIGHT0からGL_LIGHT7までの8個のライトの名前を入れる.
pnameにはGL_POSITION,GL_SPOT_DIRECTION,GL_AMBIENT,GL_DIFFUSE,GL_SPECULARなどから設定したいパラメータの名前を入れる.
paramsには設定するパラメータを入れる.

この設定でGL_POSITIONは4要素の配列で設定しないと思いもしないレンダリング結果が出てくることが多い.
3要素のx,y,zだけを設定した気になっていると,4要素目が0と見なされて,平行光源の光源の方向設定していることになる.
スポットライトを設定しているはずなのに,平行光となり,予想していた絵と全然違うということになる.
回避するためには,4要素[x,y,z,w]の配列を用意して,wは0以外の値(私は1を入れている)を入れてglLightfvを呼んでやる.

覚えている間は,ミスることはないけど,たまにしかライティングのコードを書かない私のような間抜けは,同じミスを繰り返す.
ちなみに私は,こんな設定の話をすっかり忘れて1日くらいはまったことがある.昨日くらいの話だけど.