text3d.cpp 7.84 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
66
67
	else
	{
		*m_idTexture = *(this->m_idTexture);
	}
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
}

void Strings3D::postdraw()
{
241
242
	disableVertexAttribs();
	unbind();
243
244
245
246
}

void Strings3D::draw(unsigned int idSt, const Geom::Vec3f& pos)
{
247
	glUniform3fv(*m_uniform_position, 1, pos.data());
248
249
250
251
252
253
254
255
	glDrawArrays(GL_QUADS, m_strpos[idSt].first , m_strpos[idSt].second );
}

void Strings3D::drawAll(const Geom::Vec3f& color)
{
	predraw(color);
	if (m_strpos.size() != m_strTranslate.size())
	{
256
		CGoGNerr << "Strings3D: for drawAll use exclusively addString with position"<< CGoGNendl;
257
258
259
260
261
262
		return;
	}

	unsigned int nb = m_strpos.size();
	for (unsigned int idSt=0; idSt<nb; ++idSt)
	{
263
		glUniform3fv(*m_uniform_position, 1, m_strTranslate[idSt].data());
264
265
266
267
268
		glDrawArrays(GL_QUADS, m_strpos[idSt].first , m_strpos[idSt].second );
	}
	postdraw();
}

Sylvain Thery's avatar
Sylvain Thery committed
269
270
271
272
273
274
275
276
277
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
278
} // namespace Utils
279

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