text3d.cpp 9.17 KB
Newer Older
1
2
3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
20
* Web site: http://cgogn.unistra.fr/                                           *
21
22
23
24
25
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#include "Utils/text3d.h"
26
#include "Utils/vbo.h"
Sylvain Thery's avatar
Sylvain Thery committed
27
#include "Utils/svg.h"
28

29
30
namespace CGoGN
{
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
31

32
33
namespace Utils
{
34
35
36
#include "text3d.vert"
#include "text3d.frag"

37
38
39
40
41

std::string Strings3D::fragmentShaderText2 =
"	gl_FragColor = vec4(color,0.0)*lum;\n"
"}";

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
42

43
Strings3D* Strings3D::m_instance0 = NULL;
44

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
45

Sylvain's avatar
Sylvain committed
46
Strings3D::Strings3D(bool withBackground, const Geom::Vec3f& bgc, bool with_plane) : m_nbChars(0),m_scale(1.0f)
47
{
48
	if (m_instance0 == NULL)
49
	{
50
		m_instance0 = this;
Sylvain Thery's avatar
Sylvain Thery committed
51
		std::string font_filename = Utils::GLSLShader::findFile("font_cgogn.gz");
52
53
54
55
		igzstream fs(font_filename.c_str(), std::ios::in|std::ios::binary);
		char* buff = new char[WIDTHTEXTURE*HEIGHTTEXTURE];
		fs.read(reinterpret_cast<char*>(buff), WIDTHTEXTURE*HEIGHTTEXTURE );
		fs.close();
Sylvain Thery's avatar
Sylvain Thery committed
56
		
57
58
		glGenTextures(1, &(*m_idTexture));
		glBindTexture(GL_TEXTURE_2D, *m_idTexture);
59
		glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, WIDTHTEXTURE, HEIGHTTEXTURE, 0, GL_LUMINANCE,  GL_UNSIGNED_BYTE, (GLvoid*)(buff));
60
61
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
62
		delete[] buff;
63
	}
64
65
	else
	{
Sylvain's avatar
Sylvain committed
66
		*m_idTexture = *(m_instance0->m_idTexture);
67
	}
68

69
	std::string glxvert(*GLSLShader::DEFINES_GL);
Sylvain's avatar
Sylvain committed
70
	if (with_plane)
Sylvain Thery's avatar
Sylvain Thery committed
71
		glxvert.append("#define WITH_PLANE 1");
72
73
74
75
76
77
78
	glxvert.append(vertexShaderText);
	std::string glxfrag(*GLSLShader::DEFINES_GL);

	glxfrag.append(fragmentShaderText1);

	std::string background;
	if (!withBackground)
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
79
		glxfrag.append("if (lum == 0.0) discard;\n");
80
81
82
83
	else if (bgc*bgc > 0.0)
	{
		std::stringstream ss;
		ss << "	if (lum==0.0) gl_FragColor=vec4(";
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
84
		ss << bgc[0] << "," << bgc[1] << "," << bgc[2] << ",0.0);\n		else\n";
85
86
87
88
89
90
		background.append(ss.str());
	}
	glxfrag.append(background);
	glxfrag.append(fragmentShaderText2);

	loadShadersFromMemory(glxvert.c_str(), glxfrag.c_str());
91

92
93
94
95
96
97
	m_vbo1 = new Utils::VBO();
	m_vbo1->setDataSize(4);

	bindVA_VBO("VertexPosition", m_vbo1);

	bind();
98
99
100
101
102
	*m_uniform_position = glGetUniformLocation(program_handler(), "strPos");
	*m_uniform_color = glGetUniformLocation(program_handler(), "color");
	*m_uniform_scale = glGetUniformLocation(program_handler(), "scale");
	*m_uniform_texture = glGetUniformLocation(program_handler(), "FontTexture");
	glUniform1f(*m_uniform_scale, 1.0f);
Sylvain's avatar
Sylvain committed
103
104
105
106
107
	if (with_plane)
	{
		*m_uniform_planeX = glGetUniformLocation(program_handler(), "planeX");
		*m_uniform_planeY = glGetUniformLocation(program_handler(), "planeY");
	}
108
109
	unbind();
}
110
111
112

void Strings3D::setScale(float scale)
{
113
	bind();
114
	glUniform1f(*m_uniform_scale, scale);
Sylvain Thery's avatar
Sylvain Thery committed
115
	m_scale = scale;
116
	unbind();
117
118
}

Sylvain Thery's avatar
Sylvain Thery committed
119
void Strings3D::setPlane(const Geom::Vec3f& ox, const Geom::Vec3f& oy)
Sylvain's avatar
Sylvain committed
120
121
{
	bind();
Sylvain Thery's avatar
Sylvain Thery committed
122
123
	glUniform3fv(*m_uniform_planeX, 1, ox.data());
	glUniform3fv(*m_uniform_planeY, 1, oy.data());
Sylvain's avatar
Sylvain committed
124
125
126
	unbind();
}

127
128
129
130
Strings3D::~Strings3D()
{
}

Sylvain Thery's avatar
Sylvain Thery committed
131
132
133
134
135
136
137
138
void Strings3D::clear()
{
	m_nbChars=0;
	m_strings.clear();
	m_strTranslate.clear();
	m_strpos.clear();
}

139
140
unsigned int Strings3D::addString(const std::string& str)
{
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
141
	unsigned int id = m_strings.size();
142
143
144
145
146
147
148
	m_strings.push_back(str);
	m_nbChars += str.length();
	return id;
}

unsigned int Strings3D::addString(const std::string& str, const Geom::Vec3f& pos)
{
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
149
	unsigned int id = m_strings.size();
150
151
152
153
154
155
156
157
158
159
	m_strings.push_back(str);
	m_nbChars += str.length();
	m_strTranslate.push_back(pos);
	return id;
}

unsigned int Strings3D::sendOneStringToVBO(const std::string& str, float **buffervbo)
{
	unsigned int nbc = str.length();

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
160
	float x = 0.0f;
161
162
163

	float* buffer = *buffervbo;

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
164
	for(unsigned int j = 0; j < nbc; ++j)
165
166
	{
		unsigned int ci = str[j]-32;
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
167
168
169
170
		float u  = float(ci % CHARSPERLINE) / float(CHARSPERLINE);
		float v  = float(ci / CHARSPERLINE) / float(CHARSPERCOL) + 1.0f / HEIGHTTEXTURE;
		float u2 = u + float(REALWIDTHFONT) / float(WIDTHTEXTURE);
		float v2 = v + float(WIDTHFONT - 1) / float(HEIGHTTEXTURE);
171
172
173
174
175
176

		*buffer++ = x;
		*buffer++ = 0;
		*buffer++ = u;
		*buffer++ = v2;

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
177
		float xf = x + float(REALWIDTHFONT) / 25.f;
178
179
180
181
182
183
184

		*buffer++ = xf;
		*buffer++ = 0;
		*buffer++ = u2;
		*buffer++ = v2;

		*buffer++ = xf;
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
185
		*buffer++ = float(WIDTHFONT) / 25.f;
186
187
188
189
		*buffer++ = u2;
		*buffer++ = v;

		*buffer++ = x;
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
190
		*buffer++ = float(WIDTHFONT) / 25.f;
191
192
193
194
195
196
197
198
		*buffer++ = u;
		*buffer++ = v;

		x = xf; // + space ?
	}

	*buffervbo = buffer;

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
199
	return 4 * nbc;
200
201
202
203
204
205
206
}

void Strings3D::sendToVBO()
{
	// send coord / texcoord of strings

	// alloc buffer
207
	m_vbo1->bind();
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
208
209
	glBufferData(GL_ARRAY_BUFFER, m_nbChars * 16 * sizeof(float), 0, GL_STREAM_DRAW);
	float* buffer = reinterpret_cast<float*>(glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE));
210
211

	// fill buffer
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
212
	unsigned int pos = 0; // pos of first index in vbo for current string
213
	unsigned int nbw = m_strings.size();
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
214
	for (unsigned int i = 0; i < nbw; ++i)
215
216
	{
		unsigned int nb = sendOneStringToVBO(m_strings[i], &buffer);
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
217
		m_strpos.push_back(std::pair<unsigned int, unsigned int>(pos, nb));
218
219
220
		pos += nb;
	}

221
	glUnmapBuffer(GL_ARRAY_BUFFER);
222
223
224
225
}

void Strings3D::predraw(const Geom::Vec3f& color)
{
226
	bind();
227
228
	glUniform1i(*m_uniform_texture, 0);
	glUniform3fv(*m_uniform_color, 1, color.data());
229
230

	glActiveTextureARB(GL_TEXTURE0_ARB);
231
	glBindTexture(GL_TEXTURE_2D, *m_idTexture);
232
233
234
235
	glEnable(GL_TEXTURE_2D);

	glDisable(GL_LIGHTING);

236
	enableVertexAttribs();
237
238
}

239
240
241
242
243
244
void Strings3D::changeColor(const Geom::Vec3f& color)
{
	bind();
	glUniform3fv(*m_uniform_color, 1, color.data());
}

245
246
void Strings3D::postdraw()
{
247
248
	disableVertexAttribs();
	unbind();
249
250
251
252
}

void Strings3D::draw(unsigned int idSt, const Geom::Vec3f& pos)
{
253
	glUniform3fv(*m_uniform_position, 1, pos.data());
254
255
256
257
258
	glDrawArrays(GL_QUADS, m_strpos[idSt].first , m_strpos[idSt].second );
}

void Strings3D::drawAll(const Geom::Vec3f& color)
{
Sylvain's avatar
Sylvain committed
259
260
261
262
263
	unsigned int nb = m_strpos.size();
	//  nothing to do if no string !
	if (nb == 0)
		return;

264
265
266
	predraw(color);
	if (m_strpos.size() != m_strTranslate.size())
	{
267
		CGoGNerr << "Strings3D: for drawAll use exclusively addString with position"<< CGoGNendl;
268
269
		return;
	}
Sylvain's avatar
Sylvain committed
270
		
271
272
	for (unsigned int idSt=0; idSt<nb; ++idSt)
	{
273
		glUniform3fv(*m_uniform_position, 1, m_strTranslate[idSt].data());
274
275
276
277
278
		glDrawArrays(GL_QUADS, m_strpos[idSt].first , m_strpos[idSt].second );
	}
	postdraw();
}

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
void Strings3D::updateString(unsigned int idSt, const std::string& str)
{
	unsigned int firstIndex = m_strpos[idSt].first;
	unsigned int nbIndices = m_strpos[idSt].second;

	unsigned int nbc = std::min((unsigned int)(str.length()), nbIndices/4);


	m_vbo1->bind();
	float* buffer = reinterpret_cast<float*>(glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE));

	buffer += firstIndex*4;
	float x = 0.0f;
	for(unsigned int j = 0; j < nbc; ++j)
	{
		unsigned int ci = str[j]-32;
		float u  = float(ci % CHARSPERLINE) / float(CHARSPERLINE);
		float v  = float(ci / CHARSPERLINE) / float(CHARSPERCOL) + 1.0f / HEIGHTTEXTURE;
		float u2 = u + float(REALWIDTHFONT) / float(WIDTHTEXTURE);
		float v2 = v + float(WIDTHFONT - 1) / float(HEIGHTTEXTURE);

		*buffer++ = x;
		*buffer++ = 0;
		*buffer++ = u;
		*buffer++ = v2;

		float xf = x + float(REALWIDTHFONT) / 25.f;

		*buffer++ = xf;
		*buffer++ = 0;
		*buffer++ = u2;
		*buffer++ = v2;

		*buffer++ = xf;
		*buffer++ = float(WIDTHFONT) / 25.f;
		*buffer++ = u2;
		*buffer++ = v;

		*buffer++ = x;
		*buffer++ = float(WIDTHFONT) / 25.f;
		*buffer++ = u;
		*buffer++ = v;

		x = xf; // + space ?
	}
	glUnmapBuffer(GL_ARRAY_BUFFER);
}



Sylvain Thery's avatar
Sylvain Thery committed
329
330
331
332
333
334
335
336
337
void Strings3D::toSVG(Utils::SVG::SVGOut& svg)
{
	svg.beginStrings(m_scale);
	unsigned int nb = m_strings.size();
	for(unsigned int i=0; i<nb; ++i)
		svg.addString(m_strTranslate[i],m_strings[i]);
	svg.endStrings();
}

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
338
} // namespace Utils
339

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
340
} // namespace CGoGN