1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom 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
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "WalTextureLoader.h"
21 
22 #include "CollectionUtils.h"
23 #include "Color.h"
24 #include "ByteBuffer.h"
25 #include "Exceptions.h"
26 #include "StringUtils.h"
27 #include "Assets/Palette.h"
28 #include "Assets/Texture.h"
29 #include "Assets/TextureCollection.h"
30 #include "Assets/TextureCollectionSpec.h"
31 #include "IO/DiskFileSystem.h"
32 #include "IO/IOUtils.h"
33 
34 #include <algorithm>
35 
36 namespace TrenchBroom {
37     namespace IO {
WalTextureLoader(const FileSystem & fs,const Assets::Palette & palette)38         WalTextureLoader::WalTextureLoader(const FileSystem& fs, const Assets::Palette& palette) :
39         m_fs(fs),
40         m_palette(palette) {}
41 
doLoadTextureCollection(const Assets::TextureCollectionSpec & spec) const42         Assets::TextureCollection* WalTextureLoader::doLoadTextureCollection(const Assets::TextureCollectionSpec& spec) const {
43             Path::List texturePaths = m_fs.findItems(spec.path(), FileSystem::ExtensionMatcher("wal"));
44             std::sort(texturePaths.begin(), texturePaths.end());
45 
46             Assets::TextureList textures;
47             textures.reserve(texturePaths.size());
48 
49             try {
50                 Path::List::const_iterator it, end;
51                 for (it = texturePaths.begin(), end = texturePaths.end(); it != end; ++it) {
52                     const Path& texturePath = *it;
53                     Assets::Texture* texture = readTexture(texturePath);
54                     textures.push_back(texture);
55                 }
56 
57                 return new Assets::TextureCollection(spec.name(), textures);
58             } catch (...) {
59                 VectorUtils::clearAndDelete(textures);
60                 throw;
61             }
62         }
63 
readTexture(const IO::Path & path) const64         Assets::Texture* WalTextureLoader::readTexture(const IO::Path& path) const {
65             MappedFile::Ptr file = m_fs.openFile(path);
66             const char* cursor = file->begin();
67 
68             advance<char[32]>(cursor);
69             const size_t width = readSize<uint32_t>(cursor);
70             const size_t height = readSize<uint32_t>(cursor);
71             const String textureName = path.suffix(2).deleteExtension().asString('/');
72 
73             Color tempColor, averageColor;
74             Assets::TextureBuffer::List buffers(4);
75             Assets::setMipBufferSize(buffers, width, height);
76 
77             const char* offsetCursor = file->begin() + 32 + 2*sizeof(uint32_t);
78             for (size_t i = 0; i < 4; ++i) {
79                 const size_t divisor = 1 << i;
80                 const size_t offset = IO::readSize<int32_t>(offsetCursor);
81                 const char* mipCursor = file->begin() + offset;
82                 const size_t pixelCount = (width * height) / (divisor * divisor);
83 
84                 m_palette.indexedToRgb(mipCursor, pixelCount, buffers[i], tempColor);
85                 if (i == 0)
86                     averageColor = tempColor;
87             }
88 
89             return new Assets::Texture(textureName, width, height, averageColor, buffers);
90         }
91     }
92 }
93