mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 05:38:56 +00:00
GRIM: Make Material implicitly shared. Cleaned up Model a lot.
This commit is contained in:
parent
111d0454fd
commit
cabd0d583f
@ -635,7 +635,7 @@ public:
|
||||
~MaterialComponent() { }
|
||||
|
||||
private:
|
||||
MaterialPtr _mat;
|
||||
Material *_mat;
|
||||
Common::String _filename;
|
||||
int _num;
|
||||
};
|
||||
@ -986,7 +986,7 @@ void MaterialComponent::init() {
|
||||
Model *model = p->getModel();
|
||||
for (int i = 0; i < model->_numMaterials; ++i) {
|
||||
if (_filename.compareToIgnoreCase(model->_materials[i]->getFilename()) == 0) {
|
||||
_mat = model->_materials[i].object();
|
||||
_mat = model->_materials[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ namespace Grim {
|
||||
struct Shadow;
|
||||
class SaveGame;
|
||||
class BitmapData;
|
||||
class MaterialData;
|
||||
class PrimitiveObject;
|
||||
class Font;
|
||||
class TextObject;
|
||||
@ -78,9 +79,9 @@ public:
|
||||
virtual void disableLights() = 0;
|
||||
virtual void setupLight(Scene::Light *light, int lightId) = 0;
|
||||
|
||||
virtual void createMaterial(Material *material, const char *data, const CMap *cmap) = 0;
|
||||
virtual void createMaterial(MaterialData *material, const char *data, const CMap *cmap) = 0;
|
||||
virtual void selectMaterial(const Material *material) = 0;
|
||||
virtual void destroyMaterial(Material *material) = 0;
|
||||
virtual void destroyMaterial(MaterialData *material) = 0;
|
||||
|
||||
virtual void createBitmap(BitmapData *bitmap) = 0;
|
||||
virtual void drawBitmap(const Bitmap *bitmap) = 0;
|
||||
|
@ -958,7 +958,7 @@ void GfxOpenGL::drawTextObject(TextObject *text) {
|
||||
void GfxOpenGL::destroyTextObject(TextObject *text) {
|
||||
}
|
||||
|
||||
void GfxOpenGL::createMaterial(Material *material, const char *data, const CMap *cmap) {
|
||||
void GfxOpenGL::createMaterial(MaterialData *material, const char *data, const CMap *cmap) {
|
||||
material->_textures = new GLuint[material->_numImages];
|
||||
glGenTextures(material->_numImages, (GLuint *)material->_textures);
|
||||
char *texdata = new char[material->_width * material->_height * 4];
|
||||
@ -991,14 +991,14 @@ void GfxOpenGL::createMaterial(Material *material, const char *data, const CMap
|
||||
}
|
||||
|
||||
void GfxOpenGL::selectMaterial(const Material *material) {
|
||||
GLuint *textures = (GLuint *)material->_textures;
|
||||
glBindTexture(GL_TEXTURE_2D, textures[material->_currImage]);
|
||||
GLuint *textures = (GLuint *)material->getData()->_textures;
|
||||
glBindTexture(GL_TEXTURE_2D, textures[material->getCurrentImage()]);
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glScalef(1.0f / material->_width, 1.0f / material->_height, 1);
|
||||
glScalef(1.0f / material->getData()->_width, 1.0f / material->getData()->_height, 1);
|
||||
}
|
||||
|
||||
void GfxOpenGL::destroyMaterial(Material *material) {
|
||||
void GfxOpenGL::destroyMaterial(MaterialData *material) {
|
||||
GLuint *textures = (GLuint *)material->_textures;
|
||||
if (textures) {
|
||||
glDeleteTextures(material->_numImages, textures);
|
||||
|
@ -79,9 +79,9 @@ public:
|
||||
void disableLights();
|
||||
void setupLight(Scene::Light *light, int lightId);
|
||||
|
||||
void createMaterial(Material *material, const char *data, const CMap *cmap);
|
||||
void createMaterial(MaterialData *material, const char *data, const CMap *cmap);
|
||||
void selectMaterial(const Material *material);
|
||||
void destroyMaterial(Material *material);
|
||||
void destroyMaterial(MaterialData *material);
|
||||
|
||||
void createBitmap(BitmapData *bitmap);
|
||||
void drawBitmap(const Bitmap *bitmap);
|
||||
|
@ -801,7 +801,7 @@ void GfxTinyGL::destroyTextObject(TextObject *text) {
|
||||
}
|
||||
}
|
||||
|
||||
void GfxTinyGL::createMaterial(Material *material, const char *data, const CMap *cmap) {
|
||||
void GfxTinyGL::createMaterial(MaterialData *material, const char *data, const CMap *cmap) {
|
||||
material->_textures = new TGLuint[material->_numImages];
|
||||
tglGenTextures(material->_numImages, (TGLuint *)material->_textures);
|
||||
char *texdata = new char[material->_width * material->_height * 4];
|
||||
@ -833,17 +833,17 @@ void GfxTinyGL::createMaterial(Material *material, const char *data, const CMap
|
||||
}
|
||||
|
||||
void GfxTinyGL::selectMaterial(const Material *material) {
|
||||
TGLuint *textures = (TGLuint *)material->_textures;
|
||||
tglBindTexture(TGL_TEXTURE_2D, textures[material->_currImage]);
|
||||
TGLuint *textures = (TGLuint *)material->getData()->_textures;
|
||||
tglBindTexture(TGL_TEXTURE_2D, textures[material->getCurrentImage()]);
|
||||
tglPushMatrix();
|
||||
tglMatrixMode(TGL_TEXTURE);
|
||||
tglLoadIdentity();
|
||||
tglScalef(1.0f / material->_width, 1.0f / material->_height, 1);
|
||||
tglScalef(1.0f / material->getData()->_width, 1.0f / material->getData()->_height, 1);
|
||||
tglMatrixMode(TGL_MODELVIEW);
|
||||
tglPopMatrix();
|
||||
}
|
||||
|
||||
void GfxTinyGL::destroyMaterial(Material *material) {
|
||||
void GfxTinyGL::destroyMaterial(MaterialData *material) {
|
||||
tglDeleteTextures(material->_numImages, (TGLuint *)material->_textures);
|
||||
delete[] (TGLuint *)material->_textures;
|
||||
}
|
||||
|
@ -70,9 +70,9 @@ public:
|
||||
void disableLights();
|
||||
void setupLight(Scene::Light *light, int lightId);
|
||||
|
||||
void createMaterial(Material *material, const char *data, const CMap *cmap);
|
||||
void createMaterial(MaterialData *material, const char *data, const CMap *cmap);
|
||||
void selectMaterial(const Material *material);
|
||||
void destroyMaterial(Material *material);
|
||||
void destroyMaterial(MaterialData *material);
|
||||
|
||||
void createBitmap(BitmapData *bitmap);
|
||||
void drawBitmap(const Bitmap *bitmap);
|
||||
|
@ -25,26 +25,28 @@
|
||||
#include "engines/grim/grim.h"
|
||||
#include "engines/grim/material.h"
|
||||
#include "engines/grim/gfx_base.h"
|
||||
#include "engines/grim/resource.h"
|
||||
#include "engines/grim/colormap.h"
|
||||
|
||||
namespace Grim {
|
||||
|
||||
Material::Material(const Common::String &filename, const char *data, int len, CMap *cmap) :
|
||||
Object(), _fname(filename), _cmap(cmap) {
|
||||
Common::List<MaterialData *> *MaterialData::_materials = NULL;
|
||||
|
||||
MaterialData::MaterialData(const Common::String &filename, const char *data, int len, CMap *cmap) :
|
||||
_fname(filename), _cmap(cmap), _refCount(1) {
|
||||
|
||||
if (len < 4 || memcmp(data, "MAT ", 4) != 0)
|
||||
error("invalid magic loading texture");
|
||||
|
||||
_numImages = READ_LE_UINT32(data + 12);
|
||||
_currImage = 0;
|
||||
/* 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.
|
||||
*/
|
||||
uint32 offset = READ_LE_UINT32(data + 0x4c);
|
||||
if (offset == 0x8)
|
||||
data += 16;
|
||||
data += 16;
|
||||
else if (offset != 0)
|
||||
error("Unknown offset: %d", offset);
|
||||
error("Unknown offset: %d", offset);
|
||||
_width = READ_LE_UINT32(data + 60 + _numImages * 40);
|
||||
_height = READ_LE_UINT32(data + 64 + _numImages * 40);
|
||||
|
||||
@ -59,18 +61,66 @@ Material::Material(const Common::String &filename, const char *data, int len, CM
|
||||
g_driver->createMaterial(this, data, cmap);
|
||||
}
|
||||
|
||||
MaterialData::~MaterialData() {
|
||||
_materials->remove(this);
|
||||
if (_materials->empty()) {
|
||||
delete _materials;
|
||||
_materials = NULL;
|
||||
}
|
||||
|
||||
if (_width && _height)
|
||||
g_driver->destroyMaterial(this);
|
||||
}
|
||||
|
||||
MaterialData *MaterialData::getMaterialData(const Common::String &filename, const char *data, int len, CMap *cmap) {
|
||||
if (!_materials) {
|
||||
_materials = new Common::List<MaterialData *>();
|
||||
}
|
||||
|
||||
for (Common::List<MaterialData *>::iterator i = _materials->begin(); i != _materials->end(); ++i) {
|
||||
MaterialData *m = *i;
|
||||
if (m->_fname == filename && *m->_cmap == *cmap) {
|
||||
++m->_refCount;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
MaterialData *m = new MaterialData(filename, data, len, cmap);
|
||||
_materials->push_back(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
Material::Material(const Common::String &filename, const char *data, int len, CMap *cmap) :
|
||||
Object(), _currImage(0) {
|
||||
_data = MaterialData::getMaterialData(filename, data, len, cmap);
|
||||
}
|
||||
|
||||
void Material::select() const {
|
||||
if (_width == 0 || _height == 0)
|
||||
return;
|
||||
g_driver->selectMaterial(this);
|
||||
if (_data->_width && _data->_height)
|
||||
g_driver->selectMaterial(this);
|
||||
}
|
||||
|
||||
Material::~Material() {
|
||||
if (g_resourceloader)
|
||||
g_resourceloader->uncacheMaterial(this);
|
||||
if (_width == 0 || _height == 0)
|
||||
return;
|
||||
g_driver->destroyMaterial(this);
|
||||
--_data->_refCount;
|
||||
if (_data->_refCount < 1) {
|
||||
delete _data;
|
||||
}
|
||||
}
|
||||
|
||||
int Material::getNumImages() const {
|
||||
return _data->_numImages;
|
||||
}
|
||||
|
||||
int Material::getCurrentImage() const {
|
||||
return _currImage;
|
||||
}
|
||||
|
||||
const Common::String &Material::getFilename() const {
|
||||
return _data->_fname;
|
||||
}
|
||||
|
||||
MaterialData *Material::getData() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
} // end of namespace Grim
|
||||
|
@ -27,11 +27,24 @@
|
||||
|
||||
namespace Grim {
|
||||
|
||||
class CMAp;
|
||||
class MaterialData {
|
||||
public:
|
||||
MaterialData(const Common::String &filename, const char *data, int len, CMap *cmap);
|
||||
~MaterialData();
|
||||
|
||||
static MaterialData *getMaterialData(const Common::String &filename, const char *data, int len, CMap *cmap);
|
||||
static Common::List<MaterialData *> *_materials;
|
||||
|
||||
Common::String _fname;
|
||||
const ObjectPtr<CMap> _cmap;
|
||||
int _numImages;
|
||||
int _width, _height;
|
||||
void *_textures;
|
||||
int _refCount;
|
||||
};
|
||||
|
||||
class Material : public Object {
|
||||
public:
|
||||
Material() { _width = 0; }
|
||||
// Load a texture from the given data.
|
||||
Material(const Common::String &filename, const char *data, int len, CMap *cmap);
|
||||
|
||||
@ -41,18 +54,16 @@ public:
|
||||
// Set which image in an animated texture to use
|
||||
void setNumber(int n) { _currImage = n; }
|
||||
|
||||
int getNumImages() const { return _numImages; }
|
||||
int getCurrentImage() const { return _currImage; }
|
||||
const Common::String &getFilename() { return _fname; }
|
||||
int getNumImages() const;
|
||||
int getCurrentImage() const;
|
||||
const Common::String &getFilename() const;
|
||||
MaterialData *getData() const;
|
||||
|
||||
~Material();
|
||||
|
||||
Common::String _fname;
|
||||
|
||||
const ObjectPtr<CMap> _cmap;
|
||||
int _numImages, _currImage;
|
||||
int _width, _height;
|
||||
void *_textures;
|
||||
private:
|
||||
MaterialData *_data;
|
||||
int _currImage;
|
||||
};
|
||||
|
||||
} // end of namespace Grim
|
||||
|
@ -60,15 +60,11 @@ Model::Model(const Common::String &filename, const char *data, int len, CMap *cm
|
||||
void Model::reload(CMap *cmap) {
|
||||
// Load the new colormap
|
||||
for (int i = 0; i < _numMaterials; i++) {
|
||||
_materials[i] = g_resourceloader->getMaterial(_materialNames[i], cmap);
|
||||
}
|
||||
Material **materials = new Material*[_numMaterials];
|
||||
for (int j = 0; j < _numMaterials; ++j) {
|
||||
materials[j] = _materials[j];
|
||||
delete _materials[i];
|
||||
_materials[i] = g_resourceloader->loadMaterial(_materialNames[i], cmap);
|
||||
}
|
||||
for (int i = 0; i < _numGeosets; i++)
|
||||
_geosets[i].changeMaterials(materials);
|
||||
delete[] materials;
|
||||
_geosets[i].changeMaterials(_materials);
|
||||
}
|
||||
|
||||
void Model::loadEMI(Common::MemoryReadStream &ms) {
|
||||
@ -83,7 +79,7 @@ void Model::loadEMI(Common::MemoryReadStream &ms) {
|
||||
ms.seek(48, SEEK_CUR);
|
||||
|
||||
_numMaterials = ms.readUint32LE();
|
||||
_materials = new MaterialPtr[_numMaterials];
|
||||
_materials = new Material*[_numMaterials];
|
||||
_materialNames = new char[_numMaterials][32];
|
||||
for (int i = 0; i < _numMaterials; i++) {
|
||||
nameLength = ms.readUint32LE();
|
||||
@ -94,7 +90,7 @@ void Model::loadEMI(Common::MemoryReadStream &ms) {
|
||||
if (memcmp(_materialNames[i], "specialty", 9) == 0) {
|
||||
_materials[i] = 0;
|
||||
} else {
|
||||
_materials[i] = g_resourceloader->getMaterial(_materialNames[i], 0);
|
||||
_materials[i] = g_resourceloader->loadMaterial(_materialNames[i], 0);
|
||||
}
|
||||
ms.seek(4, SEEK_CUR);
|
||||
}
|
||||
@ -106,24 +102,19 @@ void Model::loadEMI(Common::MemoryReadStream &ms) {
|
||||
void Model::loadBinary(const char *&data, CMap *cmap) {
|
||||
_numMaterials = READ_LE_UINT32(data + 4);
|
||||
data += 8;
|
||||
_materials = new MaterialPtr[_numMaterials];
|
||||
_materials = new Material*[_numMaterials];
|
||||
_materialNames = new char[_numMaterials][32];
|
||||
for (int i = 0; i < _numMaterials; i++) {
|
||||
strcpy(_materialNames[i], data);
|
||||
_materials[i] = g_resourceloader->getMaterial(_materialNames[i], cmap);
|
||||
_materials[i] = g_resourceloader->loadMaterial(_materialNames[i], cmap);
|
||||
data += 32;
|
||||
}
|
||||
data += 32; // skip name
|
||||
_numGeosets = READ_LE_UINT32(data + 4);
|
||||
data += 8;
|
||||
_geosets = new Geoset[_numGeosets];
|
||||
Material **materials = new Material*[_numMaterials];
|
||||
for (int j = 0; j < _numMaterials; ++j) {
|
||||
materials[j] = _materials[j];
|
||||
}
|
||||
for (int i = 0; i < _numGeosets; i++)
|
||||
_geosets[i].loadBinary(data, materials);
|
||||
delete[] materials;
|
||||
_geosets[i].loadBinary(data, _materials);
|
||||
_numHierNodes = READ_LE_UINT32(data + 4);
|
||||
data += 8;
|
||||
_rootHierNode = new HierNode[_numHierNodes];
|
||||
@ -334,14 +325,14 @@ void Model::loadText(TextSplitter *ts, CMap *cmap) {
|
||||
ts->scanString("3do %d.%d", 2, &major, &minor);
|
||||
ts->expectString("section: modelresource");
|
||||
ts->scanString("materials %d", 1, &_numMaterials);
|
||||
_materials = new MaterialPtr[_numMaterials];
|
||||
_materials = new Material*[_numMaterials];
|
||||
_materialNames = new char[_numMaterials][32];
|
||||
for (int i = 0; i < _numMaterials; i++) {
|
||||
char materialName[32];
|
||||
int num;
|
||||
|
||||
ts->scanString("%d: %32s", 2, &num, materialName);
|
||||
_materials[num] = g_resourceloader->getMaterial(materialName, cmap);
|
||||
_materials[num] = g_resourceloader->loadMaterial(materialName, cmap);
|
||||
strcpy(_materialNames[num], materialName);
|
||||
}
|
||||
|
||||
@ -350,16 +341,11 @@ void Model::loadText(TextSplitter *ts, CMap *cmap) {
|
||||
ts->scanString("insert offset %f %f %f", 3, &_insertOffset.x(), &_insertOffset.y(), &_insertOffset.z());
|
||||
ts->scanString("geosets %d", 1, &_numGeosets);
|
||||
_geosets = new Geoset[_numGeosets];
|
||||
Material **materials = new Material*[_numMaterials];
|
||||
for (int j = 0; j < _numMaterials; ++j) {
|
||||
materials[j] = _materials[j];
|
||||
}
|
||||
for (int i = 0; i < _numGeosets; i++) {
|
||||
int num;
|
||||
ts->scanString("geoset %d", 1, &num);
|
||||
_geosets[num].loadText(ts, materials);
|
||||
_geosets[num].loadText(ts, _materials);
|
||||
}
|
||||
delete[] materials;
|
||||
|
||||
ts->expectString("section: hierarchydef");
|
||||
ts->scanString("hierarchy nodes %d", 1, &_numHierNodes);
|
||||
|
@ -148,7 +148,7 @@ public:
|
||||
|
||||
int _numMaterials;
|
||||
char (*_materialNames)[32];
|
||||
ObjectPtr<Material> *_materials;
|
||||
Material **_materials;
|
||||
Graphics::Vector3d _insertOffset;
|
||||
int _numGeosets;
|
||||
Geoset *_geosets;
|
||||
|
@ -101,7 +101,6 @@ ResourceLoader::~ResourceLoader() {
|
||||
delete r.resPtr;
|
||||
}
|
||||
clearList(_labs);
|
||||
clearList(_materials);
|
||||
clearList(_models);
|
||||
clearList(_colormaps);
|
||||
clearList(_keyframeAnims);
|
||||
@ -341,7 +340,6 @@ Material *ResourceLoader::loadMaterial(const Common::String &filename, CMap *c)
|
||||
}
|
||||
|
||||
Material *result = new Material(fname, b->getData(), b->getLen(), c);
|
||||
_materials.push_back(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -382,10 +380,6 @@ void ResourceLoader::uncache(const char *filename) {
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceLoader::uncacheMaterial(Material *mat) {
|
||||
_materials.remove(mat);
|
||||
}
|
||||
|
||||
void ResourceLoader::uncacheModel(Model *m) {
|
||||
_models.remove(m);
|
||||
}
|
||||
@ -406,19 +400,6 @@ void ResourceLoader::uncacheLipSync(LipSync *s) {
|
||||
_lipsyncs.remove(s);
|
||||
}
|
||||
|
||||
MaterialPtr ResourceLoader::getMaterial(const char *fname, CMap *c) {
|
||||
Common::String filename = fname;
|
||||
filename.toLowercase();
|
||||
for (Common::List<Material *>::const_iterator i = _materials.begin(); i != _materials.end(); ++i) {
|
||||
Material *m = *i;
|
||||
if (filename.equals(m->_fname) && *m->_cmap == *c) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
return loadMaterial(fname, c);
|
||||
}
|
||||
|
||||
ModelPtr ResourceLoader::getModel(const Common::String &fname, CMap *c) {
|
||||
Common::String filename = fname;
|
||||
filename.toLowercase();
|
||||
|
@ -73,13 +73,11 @@ public:
|
||||
bool getFileExists(const Common::String &filename) const;
|
||||
int getFileLength(const char *filename) const;
|
||||
|
||||
MaterialPtr getMaterial(const char *filename, CMap *c);
|
||||
ModelPtr getModel(const Common::String &fname, CMap *c);
|
||||
CMapPtr getColormap(const Common::String &fname);
|
||||
KeyframeAnimPtr getKeyframe(const Common::String &fname);
|
||||
FontPtr getFont(const Common::String &fname);
|
||||
LipSyncPtr getLipSync(const Common::String &fname);
|
||||
void uncacheMaterial(Material *m);
|
||||
void uncacheModel(Model *m);
|
||||
void uncacheColormap(CMap *c);
|
||||
void uncacheKeyframe(KeyframeAnim *kf);
|
||||
@ -105,7 +103,6 @@ private:
|
||||
bool _cacheDirty;
|
||||
int32 _cacheMemorySize;
|
||||
|
||||
Common::List<Material *> _materials;
|
||||
Common::List<Model *> _models;
|
||||
Common::List<CMap *> _colormaps;
|
||||
Common::List<KeyframeAnim *> _keyframeAnims;
|
||||
|
Loading…
Reference in New Issue
Block a user