text3d.cpp 9.62 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"
Thery Sylvain's avatar
Thery Sylvain committed
26
#include "Utils/vbo_base.h"
Sylvain Thery's avatar
Sylvain Thery committed
27
#include "Utils/svg.h"
Thery Sylvain's avatar
Thery Sylvain committed
28
#include "Utils/gzstream.h"
29

Sylvain Thery's avatar
Sylvain Thery committed
30 31 32
#include <algorithm>


33 34
namespace CGoGN
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
35

36 37
namespace Utils
{
38 39 40
#include "text3d.vert"
#include "text3d.frag"

41 42

std::string Strings3D::fragmentShaderText2 =
43 44 45 46
"	if (lum == 0.0) discard;\n gl_FragColor = color*lum;\n}";

std::string Strings3D::fragmentShaderText3 =
"	gl_FragColor = mix(backColor,color,lum);\n}";
47

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

49
Strings3D* Strings3D::m_instance0 = NULL;
50

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

Sylvain's avatar
Sylvain committed
52
Strings3D::Strings3D(bool withBackground, const Geom::Vec3f& bgc, bool with_plane) : m_nbChars(0),m_scale(1.0f)
53
{
54
	if (m_instance0 == NULL)
55
	{
56
		m_instance0 = this;
Sylvain Thery's avatar
Sylvain Thery committed
57
		std::string font_filename = Utils::GLSLShader::findFile("font_cgogn.gz");
58 59 60 61
		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
62
		
63 64
		glGenTextures(1, &(*m_idTexture));
		glBindTexture(GL_TEXTURE_2D, *m_idTexture);
65
		glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, WIDTHTEXTURE, HEIGHTTEXTURE, 0, GL_LUMINANCE,  GL_UNSIGNED_BYTE, (GLvoid*)(buff));
66 67
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
68
		delete[] buff;
69
	}
70 71
	else
	{
Sylvain's avatar
Sylvain committed
72
		*m_idTexture = *(m_instance0->m_idTexture);
73
	}
74

75
	std::string glxvert(*GLSLShader::DEFINES_GL);
Sylvain's avatar
Sylvain committed
76
	if (with_plane)
Sylvain Thery's avatar
Sylvain Thery committed
77
		glxvert.append("#define WITH_PLANE 1");
78 79
	glxvert.append(vertexShaderText);

80 81

	std::string glxfrag(*GLSLShader::DEFINES_GL);
82 83 84
	glxfrag.append(fragmentShaderText1);

	if (!withBackground)
85 86 87 88
	{
		glxfrag.append(fragmentShaderText2);
	}
	else
89 90
	{
		std::stringstream ss;
91 92 93 94
		ss << "vec4 backColor = vec4(" <<bgc[0] << "," << bgc[1] << "," << bgc[2] << ",color[3]);\n";
//		ss << "vec4 backColor = vec4(0.2,0.1,0.4);\n";
		glxfrag.append(ss.str());
		glxfrag.append(fragmentShaderText3);
95
	}
96

97
	loadShadersFromMemory(glxvert.c_str(), glxfrag.c_str());
98

99 100 101 102 103 104
	m_vbo1 = new Utils::VBO();
	m_vbo1->setDataSize(4);

	bindVA_VBO("VertexPosition", m_vbo1);

	bind();
105 106 107 108 109
	*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
110 111 112 113 114
	if (with_plane)
	{
		*m_uniform_planeX = glGetUniformLocation(program_handler(), "planeX");
		*m_uniform_planeY = glGetUniformLocation(program_handler(), "planeY");
	}
115
	unbind();
Sylvain Thery's avatar
Sylvain Thery committed
116 117

	m_color = Geom::Vec4f(0.0f,0.0f,0.0f,1.0f);
118
}
119 120 121

void Strings3D::setScale(float scale)
{
122
	bind();
123
	glUniform1f(*m_uniform_scale, scale);
Sylvain Thery's avatar
Sylvain Thery committed
124
	m_scale = scale;
125
	unbind();
126 127
}

Sylvain Thery's avatar
Sylvain Thery committed
128
void Strings3D::setPlane(const Geom::Vec3f& ox, const Geom::Vec3f& oy)
Sylvain's avatar
Sylvain committed
129 130
{
	bind();
Sylvain Thery's avatar
Sylvain Thery committed
131 132
	glUniform3fv(*m_uniform_planeX, 1, ox.data());
	glUniform3fv(*m_uniform_planeY, 1, oy.data());
Sylvain's avatar
Sylvain committed
133 134 135
	unbind();
}

136 137 138 139
Strings3D::~Strings3D()
{
}

Sylvain Thery's avatar
Sylvain Thery committed
140 141 142 143 144 145 146 147
void Strings3D::clear()
{
	m_nbChars=0;
	m_strings.clear();
	m_strTranslate.clear();
	m_strpos.clear();
}

148 149
unsigned int Strings3D::addString(const std::string& str)
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
150
	unsigned int id = m_strings.size();
151 152 153 154 155 156 157
	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
158
	unsigned int id = m_strings.size();
159 160 161 162 163 164 165 166 167 168
	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
169
	float x = 0.0f;
170 171 172

	float* buffer = *buffervbo;

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
173
	for(unsigned int j = 0; j < nbc; ++j)
174 175
	{
		unsigned int ci = str[j]-32;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
176 177 178 179
		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);
180 181 182 183 184 185

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

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
186
		float xf = x + float(REALWIDTHFONT) / 25.f;
187 188 189 190 191 192 193

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

		*buffer++ = xf;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
194
		*buffer++ = float(WIDTHFONT) / 25.f;
195 196 197 198
		*buffer++ = u2;
		*buffer++ = v;

		*buffer++ = x;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
199
		*buffer++ = float(WIDTHFONT) / 25.f;
200 201 202 203 204 205 206 207
		*buffer++ = u;
		*buffer++ = v;

		x = xf; // + space ?
	}

	*buffervbo = buffer;

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
208
	return 4 * nbc;
209 210 211 212 213 214 215
}

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

	// alloc buffer
216
	m_vbo1->bind();
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
217 218
	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));
219 220

	// fill buffer
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
221
	unsigned int pos = 0; // pos of first index in vbo for current string
222
	unsigned int nbw = m_strings.size();
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
223
	for (unsigned int i = 0; i < nbw; ++i)
224 225
	{
		unsigned int nb = sendOneStringToVBO(m_strings[i], &buffer);
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
226
		m_strpos.push_back(std::pair<unsigned int, unsigned int>(pos, nb));
227 228 229
		pos += nb;
	}

230
	glUnmapBuffer(GL_ARRAY_BUFFER);
231 232
}

233
void Strings3D::predraw(const Geom::Vec4f& color)
234
{
235
	m_color = color;
236
	bind();
237
	glUniform1i(*m_uniform_texture, 0);
238
	glUniform4fv(*m_uniform_color, 1, color.data());
239 240

	glActiveTextureARB(GL_TEXTURE0_ARB);
241
	glBindTexture(GL_TEXTURE_2D, *m_idTexture);
242 243 244 245
	glEnable(GL_TEXTURE_2D);

	glDisable(GL_LIGHTING);

246
	enableVertexAttribs();
247 248
}

249
void Strings3D::changeColor(const Geom::Vec4f& color)
250
{
251
	m_color = color;
252
	bind();
253 254 255 256 257 258 259 260
	glUniform4fv(*m_uniform_color, 1, color.data());
}

void Strings3D::changeOpacity(float op)
{
	m_color[3] = op;
	bind();
	glUniform4fv(*m_uniform_color, 1, m_color.data());
261 262
}

263 264
void Strings3D::postdraw()
{
265 266
	disableVertexAttribs();
	unbind();
267 268 269 270
}

void Strings3D::draw(unsigned int idSt, const Geom::Vec3f& pos)
{
271
	glUniform3fv(*m_uniform_position, 1, pos.data());
272 273 274
	glDrawArrays(GL_QUADS, m_strpos[idSt].first , m_strpos[idSt].second );
}

275
void Strings3D::drawAll(const Geom::Vec4f& color)
276
{
277
	m_color = color;
Sylvain's avatar
Sylvain committed
278 279 280 281 282
	unsigned int nb = m_strpos.size();
	//  nothing to do if no string !
	if (nb == 0)
		return;

283 284 285
	predraw(color);
	if (m_strpos.size() != m_strTranslate.size())
	{
286
		CGoGNerr << "Strings3D: for drawAll use exclusively addString with position"<< CGoGNendl;
287 288
		return;
	}
Sylvain's avatar
Sylvain committed
289
		
290 291
	for (unsigned int idSt=0; idSt<nb; ++idSt)
	{
292
		glUniform3fv(*m_uniform_position, 1, m_strTranslate[idSt].data());
293 294 295 296 297
		glDrawArrays(GL_QUADS, m_strpos[idSt].first , m_strpos[idSt].second );
	}
	postdraw();
}

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 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
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
348 349
void Strings3D::toSVG(Utils::SVG::SVGOut& svg)
{
350 351
	Utils::SVG::SvgGroup* svg1 = new Utils::SVG::SvgGroup("strings3D", svg.m_model, svg.m_proj);
	svg1->beginStrings(m_scale);
Sylvain Thery's avatar
Sylvain Thery committed
352 353
	unsigned int nb = m_strings.size();
	for(unsigned int i=0; i<nb; ++i)
354 355 356 357
		svg1->addString(m_strTranslate[i],m_strings[i]);
	svg1->endStrings();

	svg.addGroup(svg1);
Sylvain Thery's avatar
Sylvain Thery committed
358 359
}

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
360
} // namespace Utils
361

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