File: S3OTextureHandler.cpp

package info (click to toggle)
spring 88.0%2Bdfsg1-1.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 41,524 kB
  • sloc: cpp: 343,114; ansic: 38,414; python: 12,257; java: 12,203; awk: 5,748; sh: 1,204; xml: 997; perl: 405; objc: 192; makefile: 181; php: 134; sed: 2
file content (162 lines) | stat: -rwxr-xr-x 4,695 bytes parent folder | download
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();
	}
}