/* Copyright (C) 2003 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * * Copyright (C) 2004, 2006 Mekensleep * * Mekensleep * 24 rue vieille du temple * 75004 Paris * licensing@mekensleep.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Authors: * Cedric PINSON * Loic Dachary * Igor Kravtchenko * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef USE_NPROFILE #include #else // USE_NPROFILE #define NPROFILE_SAMPLE(a) #endif // USE_NPROFILE #include #include #include #include #include #include #include #include #include #include #include using namespace osgCal; extern std::map > g_filename2texture; class TextureInformation : public osg::Referenced { std::string _name; protected: ~TextureInformation() {} public: TextureInformation(const std::string& name=""):_name(name){} const std::string& getName() const { return _name;} void setName(const std::string& name) { _name=name;} }; CoreModel::CoreModel() : #if CAL3D_VERSION >= 10 _calCoreModel("no name"), #else // CAL3D_VERSION >= 10 _calCoreModel(), #endif // CAL3D_VERSION >= 10 _collisionDefault(false), _version(0), _notify(osg::getNotifyLevel()) {} CoreModel::CoreModel(const CoreModel& model, const osg::CopyOp& copyop) : Object(model, copyop), #if CAL3D_VERSION >= 10 _calCoreModel("no name"), #else // CAL3D_VERSION >= 10 _calCoreModel(), #endif // CAL3D_VERSION >= 10 _collisionDefault(model._collisionDefault), _version(model._version), _notify(osg::getNotifyLevel()) { } CoreModel::~CoreModel() { #if CAL3D_VERSION < 10 _calCoreModel.destroy(); #endif // CAL3D_VERSION < 10 for(std::map::iterator i = _name2Normal.begin(); i != _name2Normal.end(); i++) { delete [] (i->second); i->second = NULL; } } void CoreModel::garbageCollect(void) { // remove textures if no other object references them std::vector texturesIds; for(CoreMaterialId2Textures2D::iterator i = _coreMaterialId2Textures.begin(); i != _coreMaterialId2Textures.end(); i++) texturesIds.push_back(i->first); for (int i = 0; i < (int)texturesIds.size(); i++) { CoreMaterialId2Textures2D::iterator t = _coreMaterialId2Textures.find(texturesIds[i]); Textures2D& textures = t->second; bool bErase = false; if (textures.empty()) bErase = true; else { if (!textures[0].valid()) bErase = true; else bErase = textures[0]->referenceCount() < 2 ? true : false; } if (bErase) { if(textures.size() > 0 && textures[0].valid()) { int reference_count = textures[0]->referenceCount(); // sanity check for (Textures2D::iterator j = textures.begin(); j != textures.end(); j++) if ((*j)->referenceCount() != reference_count) { CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__); return; } } _coreMaterialId2Textures.erase(t); } } } CoreModel::Textures2D* CoreModel::getTextures2D(const std::string& name) { int coreMaterialId = _calCoreModel.getCoreMaterialId(name); if(coreMaterialId < 0) return 0; return getTextures2D(coreMaterialId); } CoreModel::Textures2D* CoreModel::getTextures2D(int coreMaterialId) { CalCoreMaterial *pCoreMaterial = _calCoreModel.getCoreMaterial(coreMaterialId); if (pCoreMaterial == NULL) return NULL; if (_coreMaterialId2Textures.find(coreMaterialId) == _coreMaterialId2Textures.end()) { if (pCoreMaterial == NULL) { CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__); return NULL; } Textures2D textures; int mapId; for(mapId = 0; mapId < pCoreMaterial->getMapCount(); mapId++) { std::string strFilename = pCoreMaterial->getMapFilename(mapId); osg::Texture2D *texture = g_filename2texture[strFilename].get(); if (!texture) { osg::Image *img = osgDB::readImageFile(strFilename); if(img == NULL) { std::cerr << "CoreModel::getTextures2D image " << strFilename << " not found or format not supported\n"; CalError::setLastError(CalError::FILE_NOT_FOUND, __FILE__, __LINE__); return 0; } texture = new osg::Texture2D(); texture->setImage(img); texture->setUnRefImageDataAfterApply(true); texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST); texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR); texture->setUseHardwareMipMapGeneration(false); texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); TextureInformation *ti = new TextureInformation(strFilename); texture->setUserData(ti); g_filename2texture[strFilename] = texture; } textures.push_back(texture); } _coreMaterialId2Textures[coreMaterialId] = textures; } return &_coreMaterialId2Textures[coreMaterialId]; } bool CoreModel::getTexturesNameFromMaterialID(int _coreMaterialId, std::vector &_res) { CalCoreMaterial *pCoreMaterial = _calCoreModel.getCoreMaterial(_coreMaterialId); if (pCoreMaterial == NULL) return false; int mapId; for(mapId = 0; mapId < pCoreMaterial->getMapCount(); mapId++) { std::string strFilename = pCoreMaterial->getMapFilename(mapId); _res.push_back(strFilename); } return true; } bool CoreModel::SubUsingMeshId(int coreMeshId) { int nb=0; std::map::iterator it; it=_mReferenceCountCoreMeshIds.find(coreMeshId); if (it==_mReferenceCountCoreMeshIds.end()) { osg::notify(osg::FATAL) << "CoreModel::SubUsingMeshId: coreMeshId " << coreMeshId << " not found in list of referenced coreMeshId" << std::endl; return false; } nb=(*it).second; if(nb==1) { _mReferenceCountCoreMeshIds.erase(it); if (_calCoreModel.unloadCoreMesh(coreMeshId) < 0) { osg::notify(osg::FATAL) << "CoreModel::SubUsingMeshId: failed to unload coreMeshId " << coreMeshId << ":" << CalError::getLastErrorDescription() << std::endl; return false; } } else { if(_notify > osg::NOTICE) osg::notify(osg::DEBUG_INFO) << "CoreModel::SubUsingMeshId: " << nb << " references on coreMeshId " << coreMeshId << std::endl; } return true; } bool CoreModel::AddUsingMeshId(int coreMeshId) { if(_mReferenceCountCoreMeshIds.find(coreMeshId) == _mReferenceCountCoreMeshIds.end()) _mReferenceCountCoreMeshIds[coreMeshId] = 0; _mReferenceCountCoreMeshIds[coreMeshId]++; if(_notify > osg::NOTICE) osg::notify(osg::DEBUG_INFO) << "CoreModel::AddUsingMeshId: " << _mReferenceCountCoreMeshIds[coreMeshId] << " references on coreMeshId " << coreMeshId << std::endl; return true; }