1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "S3OTextureHandler.h"
#include "System/FileSystem/FileHandler.h"
#include "System/FileSystem/SimpleParser.h"
#include "Rendering/ShadowHandler.h"
#include "Rendering/UnitDrawer.h"
#include "Rendering/Models/3DModel.h"
#include "Rendering/Textures/Bitmap.h"
#include "System/Util.h"
#include "System/Exceptions.h"
#include "System/Log/ILog.h"
#include "System/Platform/Threading.h"
#include <algorithm>
#include <cctype>
#include <set>
#include <sstream>
#define LOG_SECTION_TEXTURE "Texture"
LOG_REGISTER_SECTION_GLOBAL(LOG_SECTION_TEXTURE)
#ifdef LOG_SECTION_CURRENT
#undef LOG_SECTION_CURRENT
#endif
#define LOG_SECTION_CURRENT LOG_SECTION_TEXTURE
#define TEX_MAT_UID(pTxID, sTxID) ((boost::uint64_t(pTxID) << 32u) | sTxID)
#define TEX_TBL_UID(pIter, sIter) TEX_MAT_UID((pIter->second).texID, (sIter->second).texID)
// The S3O texture handler uses two textures.
// The first contains diffuse color (RGB) and teamcolor (A)
// The second contains glow (R), reflectivity (G) and 1-bit Alpha (A).
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CS3OTextureHandler* texturehandlerS3O = NULL;
CS3OTextureHandler::CS3OTextureHandler()
{
// dummies
textures.push_back(new S3OTexMat());
textures.push_back(new S3OTexMat());
}
CS3OTextureHandler::~CS3OTextureHandler()
{
for (int i = 0; i < textures.size(); ++i){
glDeleteTextures(1, &textures[i]->tex1);
glDeleteTextures(1, &textures[i]->tex2);
delete textures[i];
}
}
void CS3OTextureHandler::LoadS3OTexture(S3DModel* model) {
model->textureType = LoadS3OTextureNow(model);
}
int CS3OTextureHandler::LoadS3OTextureNow(const S3DModel* model)
{
LOG_L(L_INFO, "Load S3O texture now (Flip Y Axis: %s, Invert Team Alpha: %s)",
model->invertTexYAxis ? "yes" : "no",
model->invertTexAlpha ? "yes" : "no");
CBitmap texBitMaps[2];
TextureCacheIt texCacheIters[2] = {
textureCache.find(model->tex1),
textureCache.find(model->tex2),
};
TextureTableIt texTableIter;
if (texCacheIters[0] == textureCache.end()) {
if (!texBitMaps[0].Load(model->tex1)) {
if (!texBitMaps[0].Load("unittextures/" + model->tex1)) {
LOG_L(L_WARNING, "[%s] could not load texture \"%s\" from model \"%s\"",
__FUNCTION__, model->tex1.c_str(), model->name.c_str());
// file not found (or headless build), set single pixel to red so unit is visible
texBitMaps[0].AllocDummy(SColor(255, 0, 0, 255));
}
}
if (model->invertTexAlpha)
texBitMaps[0].InvertAlpha();
if (model->invertTexYAxis)
texBitMaps[0].ReverseYAxis();
textureCache[model->tex1] = {
texBitMaps[0].CreateTexture(true),
static_cast<unsigned int>(texBitMaps[0].xsize),
static_cast<unsigned int>(texBitMaps[0].ysize)
};
}
if (texCacheIters[1] == textureCache.end()) {
if (!texBitMaps[1].Load(model->tex2)) {
if (!texBitMaps[1].Load("unittextures/" + model->tex2)) {
texBitMaps[1].AllocDummy(SColor(0, 0, 0, 255));
}
}
if (model->invertTexYAxis)
texBitMaps[1].ReverseYAxis();
textureCache[model->tex2] = {
texBitMaps[1].CreateTexture(true),
static_cast<unsigned int>(texBitMaps[1].xsize),
static_cast<unsigned int>(texBitMaps[1].ysize)
};
}
if (texCacheIters[0] == textureCache.end() || texCacheIters[1] == textureCache.end()) {
// at least one texture was newly loaded, create new material
// (note: at this point the cache has grown to contain both)
return (InsertTextureMat(model)->num);
}
if ((texTableIter = textureTable.find(TEX_TBL_UID(texCacheIters[0], texCacheIters[1]))) == textureTable.end()) {
// both textures were already loaded as parts of other models
// one possible example where this can happen would be e.g.:
// model 1 uses textures A and B and gets loaded 1st
// model 2 uses textures B and C and gets loaded 2nd
// model 3 uses textures A and C and gets loaded 3rd
// --> (A,C) is a new pair consisting of old textures
return (InsertTextureMat(model)->num);
}
return ((texTableIter->second)->num);
}
CS3OTextureHandler::S3OTexMat* CS3OTextureHandler::InsertTextureMat(const S3DModel* model)
{
const CachedS3OTex& tex1 = textureCache[model->tex1];
const CachedS3OTex& tex2 = textureCache[model->tex2];
S3OTexMat* texMat = new S3OTexMat();
texMat->num = textures.size();
texMat->tex1 = tex1.texID;
texMat->tex2 = tex2.texID;
texMat->tex1SizeX = tex1.xsize;
texMat->tex1SizeY = tex1.ysize;
texMat->tex2SizeX = tex2.xsize;
texMat->tex2SizeY = tex2.ysize;
textures.push_back(texMat);
textureTable[TEX_MAT_UID(texMat->tex1, texMat->tex2)] = texMat;
return texMat;
}
inline void DoSetTexture(const CS3OTextureHandler::S3OTexMat* texMat) {
if (shadowHandler->inShadowPass) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texMat->tex2);
} else {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texMat->tex2);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texMat->tex1);
}
}
void CS3OTextureHandler::SetS3oTexture(int num)
{
DoSetTexture(textures[num]);
}
void CS3OTextureHandler::UpdateDraw() {
}
|