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
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "System/mmgr.h"
#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)
// 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()
{
s3oTextures.push_back(new S3oTex());
s3oTextures.push_back(new S3oTex());
if (GML::SimEnabled() && GML::ShareLists())
DoUpdateDraw();
}
CS3OTextureHandler::~CS3OTextureHandler()
{
for (int i = 0; i < s3oTextures.size(); ++i){
glDeleteTextures (1, &s3oTextures[i]->tex1);
glDeleteTextures (1, &s3oTextures[i]->tex2);
delete s3oTextures[i];
}
}
void CS3OTextureHandler::LoadS3OTexture(S3DModel* model) {
model->textureType = GML::SimEnabled() && !GML::ShareLists() && GML::IsSimThread() ? -1 : LoadS3OTextureNow(model);
}
void CS3OTextureHandler::Update() {
}
int CS3OTextureHandler::LoadS3OTextureNow(const S3DModel* model)
{
GML_RECMUTEX_LOCK(model); // LoadS3OTextureNow
LOG_S(LOG_SECTION_TEXTURE,
"Load S3O texture now (Flip Y Axis: %s, Invert Team Alpha: %s)",
model->flipTexY ? "yes" : "no",
model->invertTexAlpha ? "yes" : "no");
const string totalName = model->tex1 + model->tex2;
if (s3oTextureNames.find(totalName) != s3oTextureNames.end()) {
if (GML::SimEnabled() && GML::ShareLists() && !GML::IsSimThread())
DoUpdateDraw();
return s3oTextureNames[totalName];
}
CBitmap tex1bm;
CBitmap tex2bm;
S3oTex* tex = new S3oTex();
if (!tex1bm.Load(std::string("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
tex1bm.channels = 4;
tex1bm.Alloc(1, 1);
tex1bm.mem[0] = 255;
tex1bm.mem[1] = 0;
tex1bm.mem[2] = 0;
tex1bm.mem[3] = 255;
}
if (model->flipTexY) tex1bm.ReverseYAxis();
if (model->invertTexAlpha) tex1bm.InvertAlpha();
tex->num = s3oTextures.size();
tex->tex1 = tex1bm.CreateTexture(true);
tex->tex1SizeX = tex1bm.xsize;
tex->tex1SizeY = tex1bm.ysize;
// No error checking here... other code relies on an empty texture
// being generated if it couldn't be loaded.
// Also many map features specify a tex2 but don't ship it with the map,
// so throwing here would cause maps to break.
if (!tex2bm.Load(std::string("unittextures/" + model->tex2))) {
tex2bm.channels = 4;
tex2bm.Alloc(1, 1);
tex2bm.mem[0] = 0; // self-illum
tex2bm.mem[1] = 0; // spec+refl
tex2bm.mem[2] = 0; // unused
tex2bm.mem[3] = 255; // team-color
}
if (model->flipTexY) tex2bm.ReverseYAxis();
tex->tex2 = tex2bm.CreateTexture(true);
tex->tex2SizeX = tex2bm.xsize;
tex->tex2SizeY = tex2bm.ysize;
s3oTextures.push_back(tex);
s3oTextureNames[totalName] = tex->num;
if (GML::SimEnabled() && GML::ShareLists() && !GML::IsSimThread())
DoUpdateDraw();
return tex->num;
}
inline void DoSetS3oTexture(int num, std::vector<CS3OTextureHandler::S3oTex *>& s3oTex) {
if (shadowHandler->inShadowPass) {
glBindTexture(GL_TEXTURE_2D, s3oTex[num]->tex2);
} else {
glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, s3oTex[num]->tex1);
glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, s3oTex[num]->tex2);
}
}
void CS3OTextureHandler::SetS3oTexture(int num)
{
if (GML::SimEnabled() && GML::ShareLists()) {
if (!GML::IsSimThread()) {
DoSetS3oTexture(num, s3oTexturesDraw);
return;
}
// it seems this is only accessed by draw thread, but just in case..
GML_RECMUTEX_LOCK(model); // SetS3oTexture
DoSetS3oTexture(num, s3oTextures);
}
else {
DoSetS3oTexture(num, s3oTextures);
}
}
void CS3OTextureHandler::UpdateDraw() {
if (GML::SimEnabled() && GML::ShareLists()) {
GML_RECMUTEX_LOCK(model); // UpdateDraw
DoUpdateDraw();
}
}
|