2
// Copyright (C) 1997 - 2007, Paul C. Gregory
4
// Contact: pgregory@aqsis.org
6
// This library is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public
8
// License as published by the Free Software Foundation; either
9
// version 2 of the License, or (at your option) any later version.
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
// General Public License for more details.
16
// You should have received a copy of the GNU General Public
17
// License along with this library; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
* \brief Texture cache implementation.
24
* \author Chris Foster [ chris42f (at) gmail (dot) com ]
27
#include "texturecache.h"
29
#include <aqsis/util/exception.h>
30
#include <aqsis/util/file.h>
31
#include <aqsis/tex/filtering/ienvironmentsampler.h>
32
#include <aqsis/tex/filtering/iocclusionsampler.h>
33
#include <aqsis/tex/filtering/ishadowsampler.h>
34
#include <aqsis/tex/io/itiledtexinputfile.h>
35
#include <aqsis/tex/filtering/itexturesampler.h>
36
#include <aqsis/util/logging.h>
37
#include <aqsis/util/sstring.h>
38
#include <aqsis/tex/texexception.h>
42
//------------------------------------------------------------------------------
43
// IqTextureCache creation function.
45
boost::shared_ptr<IqTextureCache> IqTextureCache::create(
46
TqSearchPathCallback searchPathCallback)
48
return boost::shared_ptr<IqTextureCache>(
49
new CqTextureCache(searchPathCallback));
52
//------------------------------------------------------------------------------
55
CqTextureCache::CqTextureCache(TqSearchPathCallback searchPathCallback)
62
m_searchPathCallback(searchPathCallback)
65
IqTextureSampler& CqTextureCache::findTextureSampler(const char* name)
67
return findSampler(m_textureCache, name);
70
IqEnvironmentSampler& CqTextureCache::findEnvironmentSampler(const char* name)
72
return findSampler(m_environmentCache, name);
75
IqShadowSampler& CqTextureCache::findShadowSampler(const char* name)
77
return findSampler(m_shadowCache, name);
80
IqOcclusionSampler& CqTextureCache::findOcclusionSampler(const char* name)
82
return findSampler(m_occlusionCache, name);
85
void CqTextureCache::flush()
87
m_textureCache.clear();
88
m_environmentCache.clear();
89
m_shadowCache.clear();
90
m_occlusionCache.clear();
91
m_texFileCache.clear();
94
const CqTexFileHeader* CqTextureCache::textureInfo(const char* name)
96
boost::shared_ptr<IqTiledTexInputFile> file;
99
file = getTextureFile(name);
100
return &(file->header());
102
catch(XqInvalidFile& /*e*/)
108
void CqTextureCache::setCurrToWorldMatrix(const CqMatrix& currToWorld)
110
m_currToWorld = currToWorld;
113
//--------------------------------------------------
115
template<typename SamplerT>
116
SamplerT& CqTextureCache::findSampler(
117
std::map<TqUlong, boost::shared_ptr<SamplerT> >& samplerMap,
120
TqUlong hash = CqString::hash(name);
121
typename std::map<TqUlong, boost::shared_ptr<SamplerT> >::const_iterator
122
texIter = samplerMap.find(hash);
123
if(texIter != samplerMap.end())
125
// The desired texture sampler is already created - return it.
126
return *(texIter->second);
130
// Couldn't find in the currently open texture samplers - create a new
132
boost::shared_ptr<SamplerT> newTex;
135
// Find the file in the current file cache.
136
newTex = newSamplerFromFile<SamplerT>(getTextureFile(name));
138
catch(XqInvalidFile& e)
140
Aqsis::log() << error
141
<< "Invalid texture file - " << e.what() << "\n";
142
newTex = SamplerT::createDummy();
144
catch(XqBadTexture& e)
146
Aqsis::log() << error
147
<< "Bad texture file - " << e.what() << "\n";
148
newTex = SamplerT::createDummy();
150
samplerMap[CqString::hash(name)] = newTex;
155
boost::shared_ptr<IqTiledTexInputFile> CqTextureCache::getTextureFile(
158
TqUlong hash = CqString::hash(name);
159
std::map<TqUlong, boost::shared_ptr<IqTiledTexInputFile> >::const_iterator
160
fileIter = m_texFileCache.find(hash);
161
if(fileIter != m_texFileCache.end())
162
// File exists in the cache; return it.
163
return fileIter->second;
164
// Else try to open the file and store it in the cache before returning it.
165
boostfs::path fullName = findFile(name, m_searchPathCallback());
166
boost::shared_ptr<IqTiledTexInputFile> file;
169
file = IqTiledTexInputFile::open(fullName);
171
catch(XqBadTexture& e)
173
file = IqTiledTexInputFile::openAny(fullName);
174
/// \todo Make sure this warning doesn't apply to files used only for
175
/// the textureInfo() function...
176
Aqsis::log() << warning << "Could not open file as a tiled texture: "
177
<< e.what() << ". Rendering will continue, but may be slower.\n";
179
m_texFileCache[hash] = file;
183
template<typename SamplerT>
184
boost::shared_ptr<SamplerT> CqTextureCache::newSamplerFromFile(
185
const boost::shared_ptr<IqTiledTexInputFile>& file)
187
return SamplerT::create(file);
190
// Special case of newSamplerFromFile() for shadow and occlusion maps - they
191
// need access to the camera->world transformation matrix.
193
boost::shared_ptr<IqShadowSampler>
194
CqTextureCache::newSamplerFromFile(const boost::shared_ptr<IqTiledTexInputFile>& file)
196
return IqShadowSampler::create(file, m_currToWorld);
199
boost::shared_ptr<IqOcclusionSampler>
200
CqTextureCache::newSamplerFromFile(const boost::shared_ptr<IqTiledTexInputFile>& file)
202
return IqOcclusionSampler::create(file, m_currToWorld);