2009年7月10日金曜日

ちょっと修正


前回のソースをちょっとだけ修正しました。
面単位で毎回テクスチャの設定をするのはあんまりなので、下のように修正しました。






void Model::draw() const {
int lastImgIdx = -1;
for (unsigned int faceIdx = 0; faceIdx < numFaces; faceIdx++) {
Face *f = &faces[faceIdx];
bool useTexture;
// テクスチャの準備
if (f->imgIdx >= 0) {
glEnable(GL_TEXTURE_2D);
if (f->imgIdx != lastImgIdx) {
const Image *img = images.at(f->imgIdx);
img->setup();
lastImgIdx = f->imgIdx;
}
useTexture = true;
} else {
glDisable(GL_TEXTURE_2D);
lastImgIdx = -1;
useTexture = false;
}
:

lastImageIdxというフラグを使って面が参照している画像が変わった場合だけテクスチャを切り替えるようにしました。画像が1つだけならimg->setup()も1回しか呼ばれないことになります。あまりスマートじゃないですがとりあえず...

それから、前回のソースにまずいところがありました。ilLoadImage()で画像を読み込んで、glTexImage2D()に、ilGetData()から得られるポインタをそのまま渡していましたが、画像が複数になるとこれではうまくいきません。(後からロードした画像データで最初の画像データが無効になる?) そのため、ilLoadImage()で読み込んだ画像を、自分で確保した領域にコピーしておく必要があります。
Imageクラスに、

unsigned char *data;

というメンバ変数を追加し、

bool loadImage(const std::string& path) {
bool res;
ILuint image;
ilGenImages(1, &image);
ilBindImage(image);
if (ilLoadImage((wchar_t *)path.c_str())) {
width = ilGetInteger(IL_IMAGE_WIDTH);
height = ilGetInteger(IL_IMAGE_HEIGHT);
if(ilGetInteger(IL_IMAGE_ORIGIN) != IL_ORIGIN_LOWER_LEFT) {
iluFlipImage();
}
data = new unsigned char[width * height * 4];
ilCopyPixels(0, 0, 0, width, height, 1, IL_RGBA, IL_UNSIGNED_BYTE, data);
res = true;
} else {
ILenum err = ilGetError();
std::cerr << iluErrorString(err) << std::endl;
res = false;
}
ilDeleteImage(image);
return res;
}
と、ilCopyPixels()でコピーするようにしました。また、ilGenImages() で取得したimage(識別子)は画像のコピーが終わってしまえば不要なので、関数内で生成し、終わったら削除するようにしました。glTexImage2D()の呼び出しは次のように、

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

dataを直接渡しています。

上の画像は2枚のテクスチャを別の面に割り当てたものです。

0 件のコメント: