EMI: Add support for clamping sprite textures and repeating other textures.

This commit is contained in:
Joseph Jezak 2014-06-17 21:58:21 -04:00
parent 29ddd3b3e9
commit df3d63fc24
18 changed files with 40 additions and 28 deletions

View file

@ -284,10 +284,10 @@ Material *EMICostume::findMaterial(const Common::String &name) {
return nullptr; return nullptr;
} }
Material *EMICostume::loadMaterial(const Common::String &name) { Material *EMICostume::loadMaterial(const Common::String &name, bool clamp) {
Material *mat = findMaterial(name); Material *mat = findMaterial(name);
if (!mat) { if (!mat) {
mat = g_resourceloader->loadMaterial(name.c_str(), nullptr); mat = g_resourceloader->loadMaterial(name.c_str(), nullptr, clamp);
_materials.push_back(mat); _materials.push_back(mat);
} }
return mat; return mat;

View file

@ -52,7 +52,7 @@ public:
void saveState(SaveGame *state) const override; void saveState(SaveGame *state) const override;
bool restoreState(SaveGame *state) override; bool restoreState(SaveGame *state) override;
Material *loadMaterial(const Common::String &name); Material *loadMaterial(const Common::String &name, bool clamp);
Material *findMaterial(const Common::String &name); Material *findMaterial(const Common::String &name);
void setWearChoreActive(bool isActive); void setWearChoreActive(bool isActive);

View file

@ -249,7 +249,7 @@ void EMIModel::prepareTextures() {
for (uint32 i = 0; i < _numTextures; i++) { for (uint32 i = 0; i < _numTextures; i++) {
// HACK: As we dont know what specialty-textures are yet, we skip loading them // HACK: As we dont know what specialty-textures are yet, we skip loading them
if (!_texNames[i].contains("specialty")) if (!_texNames[i].contains("specialty"))
_mats[i] = _costume->loadMaterial(_texNames[i]); _mats[i] = _costume->loadMaterial(_texNames[i], false);
else else
_mats[i] = g_driver->getSpecialtyTexture(_texNames[i][9] - '0'); _mats[i] = g_driver->getSpecialtyTexture(_texNames[i][9] - '0');
} }

View file

@ -125,7 +125,7 @@ void SpecialtyMaterial::create(const char *data, int width, int height) {
_texture->_height = height; _texture->_height = height;
_texture->_bpp = 4; _texture->_bpp = 4;
_texture->_colorFormat = BM_RGBA; _texture->_colorFormat = BM_RGBA;
g_driver->createMaterial(_texture, data, nullptr); g_driver->createMaterial(_texture, data, nullptr, false);
} }
Math::Matrix4 GfxBase::makeLookMatrix(const Math::Vector3d& pos, const Math::Vector3d& interest, const Math::Vector3d& up) { Math::Matrix4 GfxBase::makeLookMatrix(const Math::Vector3d& pos, const Math::Vector3d& interest, const Math::Vector3d& up) {

View file

@ -147,7 +147,7 @@ public:
virtual void setupLight(Light *light, int lightId) = 0; virtual void setupLight(Light *light, int lightId) = 0;
virtual void turnOffLight(int lightId) = 0; virtual void turnOffLight(int lightId) = 0;
virtual void createMaterial(Texture *material, const char *data, const CMap *cmap) = 0; virtual void createMaterial(Texture *material, const char *data, const CMap *cmap, bool clamp) = 0;
virtual void selectMaterial(const Texture *material) = 0; virtual void selectMaterial(const Texture *material) = 0;
virtual void destroyMaterial(Texture *material) = 0; virtual void destroyMaterial(Texture *material) = 0;

View file

@ -1293,7 +1293,7 @@ void GfxOpenGL::drawTextObject(const TextObject *text) {
void GfxOpenGL::destroyTextObject(TextObject *text) { void GfxOpenGL::destroyTextObject(TextObject *text) {
} }
void GfxOpenGL::createMaterial(Texture *material, const char *data, const CMap *cmap) { void GfxOpenGL::createMaterial(Texture *material, const char *data, const CMap *cmap, bool clamp) {
material->_texture = new GLuint[1]; material->_texture = new GLuint[1];
glGenTextures(1, (GLuint *)material->_texture); glGenTextures(1, (GLuint *)material->_texture);
char *texdata = new char[material->_width * material->_height * 4]; char *texdata = new char[material->_width * material->_height * 4];
@ -1337,7 +1337,7 @@ void GfxOpenGL::createMaterial(Texture *material, const char *data, const CMap *
glBindTexture(GL_TEXTURE_2D, textures[0]); glBindTexture(GL_TEXTURE_2D, textures[0]);
//Remove darkened lines in EMI intro //Remove darkened lines in EMI intro
if (g_grim->getGameType() == GType_MONKEY4) { if (g_grim->getGameType() == GType_MONKEY4 && clamp) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else { } else {

View file

@ -87,7 +87,7 @@ public:
void setupLight(Light *light, int lightId) override; void setupLight(Light *light, int lightId) override;
void turnOffLight(int lightId) override; void turnOffLight(int lightId) override;
void createMaterial(Texture *material, const char *data, const CMap *cmap) override; void createMaterial(Texture *material, const char *data, const CMap *cmap, bool clamp) override;
void selectMaterial(const Texture *material) override; void selectMaterial(const Texture *material) override;
void destroyMaterial(Texture *material) override; void destroyMaterial(Texture *material) override;

View file

@ -873,7 +873,7 @@ void GfxOpenGLS::turnOffLight(int lightId) {
} }
void GfxOpenGLS::createMaterial(Texture *material, const char *data, const CMap *cmap) { void GfxOpenGLS::createMaterial(Texture *material, const char *data, const CMap *cmap, bool clamp) {
material->_texture = new GLuint[1]; material->_texture = new GLuint[1];
glGenTextures(1, (GLuint *)material->_texture); glGenTextures(1, (GLuint *)material->_texture);
char *texdata = new char[material->_width * material->_height * 4]; char *texdata = new char[material->_width * material->_height * 4];
@ -927,7 +927,7 @@ void GfxOpenGLS::createMaterial(Texture *material, const char *data, const CMap
glBindTexture(GL_TEXTURE_2D, textures[0]); glBindTexture(GL_TEXTURE_2D, textures[0]);
//Remove darkened lines in EMI intro //Remove darkened lines in EMI intro
if (g_grim->getGameType() == GType_MONKEY4) { if (g_grim->getGameType() == GType_MONKEY4 && clamp) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else { } else {

View file

@ -90,7 +90,7 @@ public:
virtual void setupLight(Light *light, int lightId); virtual void setupLight(Light *light, int lightId);
virtual void turnOffLight(int lightId); virtual void turnOffLight(int lightId);
virtual void createMaterial(Texture *material, const char *data, const CMap *cmap); virtual void createMaterial(Texture *material, const char *data, const CMap *cmap, bool clamp);
virtual void selectMaterial(const Texture *material); virtual void selectMaterial(const Texture *material);
virtual void destroyMaterial(Texture *material); virtual void destroyMaterial(Texture *material);

View file

@ -1241,7 +1241,7 @@ void GfxTinyGL::destroyTextObject(TextObject *text) {
} }
} }
void GfxTinyGL::createMaterial(Texture *material, const char *data, const CMap *cmap) { void GfxTinyGL::createMaterial(Texture *material, const char *data, const CMap *cmap, bool clamp) {
material->_texture = new TGLuint[1]; material->_texture = new TGLuint[1];
tglGenTextures(1, (TGLuint *)material->_texture); tglGenTextures(1, (TGLuint *)material->_texture);
char *texdata = new char[material->_width * material->_height * 4]; char *texdata = new char[material->_width * material->_height * 4];
@ -1282,8 +1282,17 @@ void GfxTinyGL::createMaterial(Texture *material, const char *data, const CMap *
TGLuint *textures = (TGLuint *)material->_texture; TGLuint *textures = (TGLuint *)material->_texture;
tglBindTexture(TGL_TEXTURE_2D, textures[0]); 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); // FIXME: TinyGL only supports TGL_REPEAT
// Remove darkened lines in EMI intro
// if (g_grim->getGameType() == GType_MONKEY4 && clamp) {
// tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_CLAMP);
// tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_T, TGL_CLAMP);
// } else {
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_MAG_FILTER, TGL_LINEAR);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_LINEAR); tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_LINEAR);
tglTexImage2D(TGL_TEXTURE_2D, 0, 3, material->_width, material->_height, 0, format, TGL_UNSIGNED_BYTE, texdata); tglTexImage2D(TGL_TEXTURE_2D, 0, 3, material->_width, material->_height, 0, format, TGL_UNSIGNED_BYTE, texdata);

View file

@ -83,7 +83,7 @@ public:
void setupLight(Light *light, int lightId); void setupLight(Light *light, int lightId);
void turnOffLight(int lightId); void turnOffLight(int lightId);
void createMaterial(Texture *material, const char *data, const CMap *cmap); void createMaterial(Texture *material, const char *data, const CMap *cmap, bool clamp);
void selectMaterial(const Texture *material); void selectMaterial(const Texture *material);
void destroyMaterial(Texture *material); void destroyMaterial(Texture *material);

View file

@ -413,7 +413,8 @@ void GrimEngine::handleDebugLoadResource() {
} else if (strstr(buf, ".mat")) { } else if (strstr(buf, ".mat")) {
CMap *cmap = g_resourceloader->loadColormap("item.cmp"); CMap *cmap = g_resourceloader->loadColormap("item.cmp");
warning("Default colormap applied to resources loaded in this fashion"); warning("Default colormap applied to resources loaded in this fashion");
resource = (void *)g_resourceloader->loadMaterial(buf, cmap); // Default to repeating the texture as in GRIM
resource = (void *)g_resourceloader->loadMaterial(buf, cmap, false);
} else { } else {
warning("Resource type not understood"); warning("Resource type not understood");
} }

View file

@ -200,9 +200,10 @@ MaterialData *MaterialData::getMaterialData(const Common::String &filename, Comm
return m; return m;
} }
Material::Material(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap) : Material::Material(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap, bool clamp) :
Object(), _currImage(0) { Object(), _currImage(0) {
_data = MaterialData::getMaterialData(filename, data, cmap); _data = MaterialData::getMaterialData(filename, data, cmap);
_clampTexture = clamp;
} }
Material::Material() : Material::Material() :
@ -216,7 +217,7 @@ void Material::reload(CMap *cmap) {
delete _data; delete _data;
} }
Material *m = g_resourceloader->loadMaterial(fname, cmap); Material *m = g_resourceloader->loadMaterial(fname, cmap, _clampTexture);
// Steal the data from the new material and discard it. // Steal the data from the new material and discard it.
_data = m->_data; _data = m->_data;
++_data->_refCount; ++_data->_refCount;
@ -227,7 +228,7 @@ void Material::select() const {
Texture *t = _data->_textures + _currImage; Texture *t = _data->_textures + _currImage;
if (t->_width && t->_height) { if (t->_width && t->_height) {
if (!t->_texture) { if (!t->_texture) {
g_driver->createMaterial(t, t->_data, _data->_cmap); g_driver->createMaterial(t, t->_data, _data->_cmap, _clampTexture);
delete[] t->_data; delete[] t->_data;
t->_data = nullptr; t->_data = nullptr;
} }

View file

@ -62,7 +62,7 @@ private:
class Material : public Object { class Material : public Object {
public: public:
// Load a texture from the given data. // Load a texture from the given data.
Material(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap); Material(const Common::String &filename, Common::SeekableReadStream *data, CMap *cmap, bool clamp);
void reload(CMap *cmap); void reload(CMap *cmap);
// Load this texture into the GL context // Load this texture into the GL context
@ -85,6 +85,7 @@ protected:
private: private:
MaterialData *_data; MaterialData *_data;
int _currImage; int _currImage;
bool _clampTexture;
}; };
} // end of namespace Grim } // end of namespace Grim

View file

@ -246,7 +246,7 @@ void Model::loadMaterial(int index, CMap *cmap) {
if (mat && cmap->getFilename() == _cmap->getFilename()) { if (mat && cmap->getFilename() == _cmap->getFilename()) {
_materials[index] = mat; _materials[index] = mat;
} else { } else {
_materials[index] = g_resourceloader->loadMaterial(_materialNames[index], cmap); _materials[index] = g_resourceloader->loadMaterial(_materialNames[index], cmap, false);
} }
_materialsShared[index] = false; _materialsShared[index] = false;
} }

View file

@ -401,7 +401,7 @@ LipSync *ResourceLoader::loadLipSync(const Common::String &filename) {
return result; return result;
} }
Material *ResourceLoader::loadMaterial(const Common::String &filename, CMap *c) { Material *ResourceLoader::loadMaterial(const Common::String &filename, CMap *c, bool clamp) {
Common::String fname = fixFilename(filename, false); Common::String fname = fixFilename(filename, false);
fname.toLowercase(); fname.toLowercase();
Common::SeekableReadStream *stream; Common::SeekableReadStream *stream;
@ -413,13 +413,13 @@ Material *ResourceLoader::loadMaterial(const Common::String &filename, CMap *c)
if (g_grim->getGameType() == GType_MONKEY4 && g_grim->getGameFlags() & ADGF_DEMO) { if (g_grim->getGameType() == GType_MONKEY4 && g_grim->getGameFlags() & ADGF_DEMO) {
const Common::String replacement("fx/candle.sprb"); const Common::String replacement("fx/candle.sprb");
warning("Could not find material %s, using %s instead", filename.c_str(), replacement.c_str()); warning("Could not find material %s, using %s instead", filename.c_str(), replacement.c_str());
return loadMaterial(replacement, nullptr); return loadMaterial(replacement, nullptr, clamp);
} else { } else {
error("Could not find material %s", filename.c_str()); error("Could not find material %s", filename.c_str());
} }
} }
Material *result = new Material(fname, stream, c); Material *result = new Material(fname, stream, c, clamp);
delete stream; delete stream;
return result; return result;

View file

@ -63,7 +63,7 @@ public:
Costume *loadCostume(const Common::String &fname, Costume *prevCost); Costume *loadCostume(const Common::String &fname, Costume *prevCost);
Font *loadFont(const Common::String &fname); Font *loadFont(const Common::String &fname);
KeyframeAnim *loadKeyframe(const Common::String &fname); KeyframeAnim *loadKeyframe(const Common::String &fname);
Material *loadMaterial(const Common::String &fname, CMap *c); Material *loadMaterial(const Common::String &fname, CMap *c, bool clamp);
Model *loadModel(const Common::String &fname, CMap *c, Model *parent = NULL); Model *loadModel(const Common::String &fname, CMap *c, Model *parent = NULL);
EMIModel *loadModelEMI(const Common::String &fname, EMICostume *costume); EMIModel *loadModelEMI(const Common::String &fname, EMICostume *costume);
LipSync *loadLipSync(const Common::String &fname); LipSync *loadLipSync(const Common::String &fname);

View file

@ -46,7 +46,7 @@ void Sprite::draw() const {
void Sprite::loadGrim(const Common::String &name, const char *comma, CMap *cmap) { void Sprite::loadGrim(const Common::String &name, const char *comma, CMap *cmap) {
int width, height, x, y, z; int width, height, x, y, z;
sscanf(comma, ",%d,%d,%d,%d,%d", &width, &height, &x, &y, &z); sscanf(comma, ",%d,%d,%d,%d,%d", &width, &height, &x, &y, &z);
_material = g_resourceloader->loadMaterial(name, cmap); _material = g_resourceloader->loadMaterial(name, cmap, true);
_width = (float)width / 100.0f; _width = (float)width / 100.0f;
_height = (float)height / 100.0f; _height = (float)height / 100.0f;
_pos.set((float)x / 100.0f, (float)y / 100.0f, (float)z / 100.0f); _pos.set((float)x / 100.0f, (float)y / 100.0f, (float)z / 100.0f);
@ -73,7 +73,7 @@ void Sprite::loadBinary(Common::SeekableReadStream *stream, EMICostume *costume)
offX = get_float(data + 8); offX = get_float(data + 8);
offY = get_float(data + 12); offY = get_float(data + 12);
_material = costume->loadMaterial(texname); _material = costume->loadMaterial(texname, true);
_width = width; _width = width;
_height = height; _height = height;
_next = nullptr; _next = nullptr;