GRIM: Every material image have its own properties, not shared in all the material.

This commit is contained in:
Giulio Camuffo 2011-07-28 22:21:16 +02:00
parent c3470d9b16
commit 497dabe1b0
7 changed files with 104 additions and 95 deletions

View File

@ -33,7 +33,6 @@ class BitmapData;
class Bitmap;
class CMap;
class Color;
class MaterialData;
class PrimitiveObject;
class Font;
class TextObject;
@ -43,6 +42,7 @@ class Mesh;
class MeshFace;
class Sprite;
class Light;
class Texture;
enum colorFormat {
BM_RGB565 = 1, // Grim Fandango
@ -87,9 +87,9 @@ public:
virtual void disableLights() = 0;
virtual void setupLight(Light *light, int lightId) = 0;
virtual void createMaterial(MaterialData *material, const char *data, const CMap *cmap) = 0;
virtual void selectMaterial(const Material *material) = 0;
virtual void destroyMaterial(MaterialData *material) = 0;
virtual void createMaterial(Texture *material, const char *data, const CMap *cmap) = 0;
virtual void selectMaterial(const Texture *material) = 0;
virtual void destroyMaterial(Texture *material) = 0;
virtual void createBitmap(BitmapData *bitmap) = 0;
virtual void drawBitmap(const Bitmap *bitmap) = 0;
@ -112,8 +112,8 @@ public:
* the arguments specify the distance from the screen-edge to the first
* non-iris pixel.
*
* @param x the width of the Iris
* @param y the height of the Iris
* @param x the width of the Iris
* @param y the height of the Iris
*/
virtual void irisAroundRegion(int x, int y) = 0;

View File

@ -960,53 +960,50 @@ void GfxOpenGL::drawTextObject(TextObject *text) {
void GfxOpenGL::destroyTextObject(TextObject *text) {
}
void GfxOpenGL::createMaterial(MaterialData *material, const char *data, const CMap *cmap) {
material->_textures = new GLuint[material->_numImages];
glGenTextures(material->_numImages, (GLuint *)material->_textures);
void GfxOpenGL::createMaterial(Texture *material, const char *data, const CMap *cmap) {
material->_texture = new GLuint[1];
glGenTextures(1, (GLuint *)material->_texture);
char *texdata = new char[material->_width * material->_height * 4];
for (int i = 0; i < material->_numImages; i++) {
char *texdatapos = texdata;
for (int y = 0; y < material->_height; y++) {
for (int x = 0; x < material->_width; x++) {
uint8 col = *(uint8 *)(data);
if (col == 0) {
memset(texdatapos, 0, 4); // transparent
if (!material->_hasAlpha) {
texdatapos[3] = '\xff'; // fully opaque
}
} else {
memcpy(texdatapos, cmap->_colors + 3 * (col), 3);
char *texdatapos = texdata;
for (int y = 0; y < material->_height; y++) {
for (int x = 0; x < material->_width; x++) {
uint8 col = *(uint8 *)(data);
if (col == 0) {
memset(texdatapos, 0, 4); // transparent
if (!material->_hasAlpha) {
texdatapos[3] = '\xff'; // fully opaque
}
texdatapos += 4;
data++;
} else {
memcpy(texdatapos, cmap->_colors + 3 * (col), 3);
texdatapos[3] = '\xff'; // fully opaque
}
texdatapos += 4;
data++;
}
GLuint *textures = (GLuint *)material->_textures;
glBindTexture(GL_TEXTURE_2D, textures[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, material->_width, material->_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texdata);
data += 24;
}
GLuint *textures = (GLuint *)material->_texture;
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, material->_width, material->_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texdata);
delete[] texdata;
}
void GfxOpenGL::selectMaterial(const Material *material) {
GLuint *textures = (GLuint *)material->getData()->_textures;
glBindTexture(GL_TEXTURE_2D, textures[material->getCurrentImage()]);
void GfxOpenGL::selectMaterial(const Texture *material) {
GLuint *textures = (GLuint *)material->_texture;
glBindTexture(GL_TEXTURE_2D, textures[0]);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(1.0f / material->getData()->_width, 1.0f / material->getData()->_height, 1);
glScalef(1.0f / material->_width, 1.0f / material->_height, 1);
}
void GfxOpenGL::destroyMaterial(MaterialData *material) {
GLuint *textures = (GLuint *)material->_textures;
void GfxOpenGL::destroyMaterial(Texture *material) {
GLuint *textures = (GLuint *)material->_texture;
if (textures) {
glDeleteTextures(material->_numImages, textures);
glDeleteTextures(1, textures);
delete[] textures;
}
}

View File

@ -83,9 +83,9 @@ public:
void disableLights();
void setupLight(Light *light, int lightId);
void createMaterial(MaterialData *material, const char *data, const CMap *cmap);
void selectMaterial(const Material *material);
void destroyMaterial(MaterialData *material);
void createMaterial(Texture *material, const char *data, const CMap *cmap);
void selectMaterial(const Texture *material);
void destroyMaterial(Texture *material);
void createBitmap(BitmapData *bitmap);
void drawBitmap(const Bitmap *bitmap);

View File

@ -803,54 +803,51 @@ void GfxTinyGL::destroyTextObject(TextObject *text) {
}
}
void GfxTinyGL::createMaterial(MaterialData *material, const char *data, const CMap *cmap) {
material->_textures = new TGLuint[material->_numImages];
tglGenTextures(material->_numImages, (TGLuint *)material->_textures);
void GfxTinyGL::createMaterial(Texture *material, const char *data, const CMap *cmap) {
material->_texture = new TGLuint[1];
tglGenTextures(1, (TGLuint *)material->_texture);
char *texdata = new char[material->_width * material->_height * 4];
for (int i = 0; i < material->_numImages; i++) {
char *texdatapos = texdata;
for (int y = 0; y < material->_height; y++) {
for (int x = 0; x < material->_width; x++) {
uint8 col = *(uint8 *)(data);
if (col == 0) {
memset(texdatapos, 0, 4); // transparent
if (!material->_hasAlpha) {
texdatapos[3] = '\xff'; // fully opaque
}
} else {
memcpy(texdatapos, cmap->_colors + 3 * (col), 3);
char *texdatapos = texdata;
for (int y = 0; y < material->_height; y++) {
for (int x = 0; x < material->_width; x++) {
uint8 col = *(uint8 *)(data);
if (col == 0) {
memset(texdatapos, 0, 4); // transparent
if (!material->_hasAlpha) {
texdatapos[3] = '\xff'; // fully opaque
}
texdatapos += 4;
data++;
} else {
memcpy(texdatapos, cmap->_colors + 3 * (col), 3);
texdatapos[3] = '\xff'; // fully opaque
}
texdatapos += 4;
data++;
}
TGLuint *textures = (TGLuint *)material->_textures;
tglBindTexture(TGL_TEXTURE_2D, textures[i]);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_REPEAT);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_T, TGL_REPEAT);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_LINEAR);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_LINEAR);
tglTexImage2D(TGL_TEXTURE_2D, 0, 3, material->_width, material->_height, 0, TGL_RGBA, TGL_UNSIGNED_BYTE, texdata);
data += 24;
}
TGLuint *textures = (TGLuint *)material->_texture;
tglBindTexture(TGL_TEXTURE_2D, textures[0]);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_REPEAT);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_T, TGL_REPEAT);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_LINEAR);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_LINEAR);
tglTexImage2D(TGL_TEXTURE_2D, 0, 3, material->_width, material->_height, 0, TGL_RGBA, TGL_UNSIGNED_BYTE, texdata);
delete[] texdata;
}
void GfxTinyGL::selectMaterial(const Material *material) {
TGLuint *textures = (TGLuint *)material->getData()->_textures;
tglBindTexture(TGL_TEXTURE_2D, textures[material->getCurrentImage()]);
void GfxTinyGL::selectMaterial(const Texture *material) {
TGLuint *textures = (TGLuint *)material->_texture;
tglBindTexture(TGL_TEXTURE_2D, textures[0]);
tglPushMatrix();
tglMatrixMode(TGL_TEXTURE);
tglLoadIdentity();
tglScalef(1.0f / material->getData()->_width, 1.0f / material->getData()->_height, 1);
tglScalef(1.0f / material->_width, 1.0f / material->_height, 1);
tglMatrixMode(TGL_MODELVIEW);
tglPopMatrix();
}
void GfxTinyGL::destroyMaterial(MaterialData *material) {
tglDeleteTextures(material->_numImages, (TGLuint *)material->_textures);
delete[] (TGLuint *)material->_textures;
void GfxTinyGL::destroyMaterial(Texture *material) {
tglDeleteTextures(1, (TGLuint *)material->_texture);
delete[] (TGLuint *)material->_texture;
}
void GfxTinyGL::prepareSmushFrame(int width, int height, byte *bitmap) {

View File

@ -74,9 +74,9 @@ public:
void disableLights();
void setupLight(Light *light, int lightId);
void createMaterial(MaterialData *material, const char *data, const CMap *cmap);
void selectMaterial(const Material *material);
void destroyMaterial(MaterialData *material);
void createMaterial(Texture *material, const char *data, const CMap *cmap);
void selectMaterial(const Texture *material);
void destroyMaterial(Texture *material);
void createBitmap(BitmapData *bitmap);
void drawBitmap(const Bitmap *bitmap);

View File

@ -39,6 +39,7 @@ MaterialData::MaterialData(const Common::String &filename, const char *data, int
error("invalid magic loading texture");
_numImages = READ_LE_UINT32(data + 12);
_textures = new Texture[_numImages];
/* Discovered by diffing orange.mat with pink.mat and blue.mat .
* Actual meaning unknown, so I prefer to use it as an enum-ish
* at the moment, to detect unexpected values.
@ -48,19 +49,22 @@ MaterialData::MaterialData(const Common::String &filename, const char *data, int
data += 16;
else if (offset != 0)
error("Unknown offset: %d", offset);
_width = READ_LE_UINT32(data + 60 + _numImages * 40);
_height = READ_LE_UINT32(data + 64 + _numImages * 40);
_hasAlpha = READ_LE_UINT32(data + 68 + _numImages * 40);
if (_width == 0 || _height == 0) {
if (gDebugLevel == DEBUG_WARN || gDebugLevel == DEBUG_ALL)
warning("skip load texture: bad texture size (%dx%d) for texture %s", _width, _height, _fname.c_str());
return;
data += 60 + _numImages * 40;
for (int i = 0; i < _numImages; ++i) {
Texture *t = _textures + i;
t->_width = READ_LE_UINT32(data);
t->_height = READ_LE_UINT32(data + 4);
t->_hasAlpha = READ_LE_UINT32(data + 8);
if (t->_width == 0 || t->_height == 0) {
if (gDebugLevel == DEBUG_WARN || gDebugLevel == DEBUG_ALL)
warning("skip load texture: bad texture size (%dx%d) for texture %d of material %s",
t->_width, t->_height, i, _fname.c_str());
break;
}
g_driver->createMaterial(t, data + 24, cmap);
data += 24 + t->_width * t->_height;
}
data += 84 + _numImages * 40;
g_driver->createMaterial(this, data, cmap);
}
MaterialData::~MaterialData() {
@ -70,8 +74,12 @@ MaterialData::~MaterialData() {
_materials = NULL;
}
if (_width && _height)
g_driver->destroyMaterial(this);
for (int i = 0; i < _numImages; ++i) {
Texture *t = _textures + i;
if (t->_width && t->_height)
g_driver->destroyMaterial(t);
}
delete[] _textures;
}
MaterialData *MaterialData::getMaterialData(const Common::String &filename, const char *data, int len, CMap *cmap) {
@ -112,8 +120,9 @@ void Material::reload(CMap *cmap) {
}
void Material::select() const {
if (_data->_width && _data->_height)
g_driver->selectMaterial(this);
Texture *t = _data->_textures + _currImage;
if (t->_width && t->_height)
g_driver->selectMaterial(t);
}
Material::~Material() {

View File

@ -28,6 +28,14 @@
namespace Grim {
class Texture {
public:
int _width;
int _height;
bool _hasAlpha;
void *_texture;
};
class MaterialData {
public:
MaterialData(const Common::String &filename, const char *data, int len, CMap *cmap);
@ -39,9 +47,7 @@ public:
Common::String _fname;
const ObjectPtr<CMap> _cmap;
int _numImages;
int _width, _height;
bool _hasAlpha;
void *_textures;
Texture *_textures;
int _refCount;
};