drawer.cpp 8.4 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
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

Sylvain Thery's avatar
Sylvain Thery committed
25
#include "GL/glew.h"
26
#include "Utils/drawer.h"
27 28
#include "Utils/Shaders/shaderColorPerVertex.h"

Thery Sylvain's avatar
Thery Sylvain committed
29
#include "Utils/vbo_base.h"
Sylvain Thery's avatar
Sylvain Thery committed
30
#include "Utils/svg.h"
31 32 33

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

35 36 37
namespace Utils
{

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
38
Drawer::Drawer() : m_currentWidth(1.0f)
39 40 41 42 43 44 45 46 47 48 49 50
{
	m_vboPos = new Utils::VBO();
	m_vboPos->setDataSize(3);

	m_vboCol = new Utils::VBO();
	m_vboCol->setDataSize(3);

	m_shader = new Utils::ShaderColorPerVertex();

	m_shader->setAttributePosition(m_vboPos);
	m_shader->setAttributeColor(m_vboCol);

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
51
	Utils::GLSLShader::registerShader(NULL, m_shader);
52 53 54 55 56 57 58 59 60

	m_dataPos.reserve(128);
	m_dataCol.reserve(128);
	m_begins.reserve(16);
//	m_modes.reserve(16);
}

Drawer::~Drawer()
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
61
	Utils::GLSLShader::unregisterShader(NULL, m_shader);
62 63
	delete m_vboPos;
	delete m_vboCol;
64
	delete m_shader;
65 66
}

67 68 69 70 71
Utils::ShaderColorPerVertex* Drawer::getShader()
{
	return m_shader;
}

72 73
void Drawer::lineWidth(float lw)
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
74
	m_currentWidth = lw;
75 76 77 78
}

void Drawer::pointSize(float ps)
{
79
	m_currentSize = ps;
80 81
}

82
int Drawer::begin(GLenum mode)
83
{
84
	int res = m_begins.size();
85 86 87 88
	if (mode == GL_POINTS)
		m_begins.push_back(PrimParam(m_dataPos.size(), mode, m_currentSize));
	else
		m_begins.push_back(PrimParam(m_dataPos.size(), mode, m_currentWidth));
89
	return res;
90 91 92 93
}

void Drawer::end()
{
CGoGN GIT Supervisor's avatar
CGoGN GIT Supervisor committed
94 95 96
	if (m_begins.empty())
		return;

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
	m_begins.back().nb = m_dataPos.size() - m_begins.back().begin;
}

void Drawer::color(const Geom::Vec3f& col)
{
	if (m_dataPos.size() == m_dataCol.size())
		m_dataCol.push_back(col);
	else
		m_dataCol.back() = col;
}

void Drawer::color3f(float r, float g, float b)
{
	color(Geom::Vec3f(r,g,b));
}

Sylvain Thery's avatar
Sylvain Thery committed
113
unsigned int Drawer::vertex(const Geom::Vec3f& v)
114 115 116 117
{
	if (m_dataPos.size() == m_dataCol.size())
	{
		if (m_dataCol.empty())
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
118
			m_dataCol.push_back(Geom::Vec3f(1.0f, 1.0f, 1.0f));
119 120 121 122
		else
			m_dataCol.push_back( m_dataCol.back());
	}
	m_dataPos.push_back(v);
Sylvain Thery's avatar
Sylvain Thery committed
123
	return  m_dataPos.size()-1;
124 125
}

Sylvain Thery's avatar
Sylvain Thery committed
126
unsigned int Drawer::vertex3f(float r, float g, float b)
127
{
Sylvain Thery's avatar
Sylvain Thery committed
128
	return vertex(Geom::Vec3f(r,g,b));
129 130 131 132 133 134 135 136 137 138 139 140 141
}

void Drawer::newList(GLenum comp)
{
	m_compile = comp;
	m_dataPos.clear();
	m_dataCol.clear();
	m_begins.clear();
}

void Drawer::endList()
{
	unsigned int nbElts = m_dataPos.size();
CGoGN GIT Supervisor's avatar
CGoGN GIT Supervisor committed
142 143 144
	
	if (nbElts == 0)
		return;
145 146

	m_vboPos->bind();
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
147
	glBufferData(GL_ARRAY_BUFFER, nbElts * sizeof(Geom::Vec3f), &(m_dataPos[0]), GL_STREAM_DRAW);
148 149

	m_vboCol->bind();
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
150
	glBufferData(GL_ARRAY_BUFFER, nbElts * sizeof(Geom::Vec3f), &(m_dataCol[0]), GL_STREAM_DRAW);
151 152 153 154 155 156 157 158 159 160 161

	// free memory
	std::vector<Geom::Vec3f> tempo;
	tempo.swap(m_dataPos);
	std::vector<Geom::Vec3f> tempo2;
	tempo2.swap(m_dataCol);

	if (m_compile != GL_COMPILE)
		callList();
}

Sylvain Thery's avatar
Sylvain Thery committed
162 163 164 165 166 167 168 169 170 171 172 173 174 175

void Drawer::updatePositions(unsigned int first, unsigned int nb, const Geom::Vec3f* P)
{
	m_vboPos->bind();
	glBufferSubData(GL_ARRAY_BUFFER, first * sizeof(Geom::Vec3f), nb * sizeof(Geom::Vec3f), P);
}

void Drawer::updatePositions(unsigned int first, unsigned int nb, const float* P)
{
	m_vboPos->bind();
	glBufferSubData(GL_ARRAY_BUFFER, first * 3 * sizeof(float), nb * 3 * sizeof(float), P);
}


176
void Drawer::callList(float opacity)
177 178 179 180
{
	if (m_begins.empty())
		return;

Sylvain Thery's avatar
Sylvain Thery committed
181 182
	m_shader->setOpacity(opacity);

183 184 185 186 187 188 189 190 191 192 193 194
	m_shader->enableVertexAttribs();
	for (std::vector<PrimParam>::iterator pp = m_begins.begin(); pp != m_begins.end(); ++pp)
	{
		if (pp->mode == GL_POINTS)
			glPointSize(pp->width);
		if ((pp->mode == GL_LINES) || (pp->mode == GL_LINE_LOOP))
			glLineWidth(pp->width);
		glDrawArrays(pp->mode, pp->begin, pp->nb);
	}
 	m_shader->disableVertexAttribs();
}

Sylvain Thery's avatar
Sylvain Thery committed
195

196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
void Drawer::callSubList(int index, float opacity)
{
	if (index >= int(m_begins.size()))
		return;

	m_shader->setOpacity(opacity);

	m_shader->enableVertexAttribs();

	PrimParam* pp = & (m_begins[index]);

	if (pp->mode == GL_POINTS)
		glPointSize(pp->width);
	if ((pp->mode == GL_LINES) || (pp->mode == GL_LINE_LOOP))
		glLineWidth(pp->width);
	glDrawArrays(pp->mode, pp->begin, pp->nb);

	m_shader->disableVertexAttribs();
}

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
void Drawer::callSubLists(int first, int nb, float opacity)
{
	m_shader->setOpacity(opacity);
	m_shader->enableVertexAttribs();

	int last = first+nb;
	for (int i = first; i< last; ++i)
		if (i < int(m_begins.size()))
		{
			PrimParam* pp = & (m_begins[i]);

			if (pp->mode == GL_POINTS)
				glPointSize(pp->width);
			if ((pp->mode == GL_LINES) || (pp->mode == GL_LINE_LOOP))
				glLineWidth(pp->width);
			glDrawArrays(pp->mode, pp->begin, pp->nb);
		}

	m_shader->disableVertexAttribs();
}

237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
void Drawer::callSubLists(std::vector<int> indices, float opacity)
{
	m_shader->setOpacity(opacity);

	m_shader->enableVertexAttribs();

	for (std::vector<int>::iterator it = indices.begin(); it != indices.end(); ++it)
		if (*it < int(m_begins.size()))
		{
			PrimParam* pp = & (m_begins[*it]);

			if (pp->mode == GL_POINTS)
				glPointSize(pp->width);
			if ((pp->mode == GL_LINES) || (pp->mode == GL_LINE_LOOP))
				glLineWidth(pp->width);
			glDrawArrays(pp->mode, pp->begin, pp->nb);
		}

	m_shader->disableVertexAttribs();
}

Sylvain Thery's avatar
Sylvain Thery committed
258

Sylvain Thery's avatar
Sylvain Thery committed
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 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
void Drawer::toSVG(Utils::SVG::SVGOut& svg)
{
	const Geom::Vec3f* ptrP = reinterpret_cast<Geom::Vec3f*>(m_vboPos->lockPtr());
	const Geom::Vec3f* ptrC = reinterpret_cast<Geom::Vec3f*>(m_vboCol->lockPtr());

	for (std::vector<PrimParam>::iterator pp = m_begins.begin(); pp != m_begins.end(); ++pp)
	{
		svg.setWidth(pp->width);
		if (pp->mode == GL_POINTS)
		{
			unsigned int end = pp->begin + pp->nb;
			svg.beginPoints();
			for (unsigned int i=pp->begin; i<end; ++i)
				svg.addPoint(ptrP[i], ptrC[i]);
			svg.endPoints();
		}

		if (pp->mode == GL_LINES)
		{
			unsigned int end = pp->begin + pp->nb;
			svg.beginLines();
			for (unsigned int i=pp->begin; i<end; i+=2)
				svg.addLine(ptrP[i], ptrP[i+1], ptrC[i]);
			svg.endLines();
		}

		if ((pp->mode == GL_LINE_LOOP) || (pp->mode == GL_POLYGON))
		{
			unsigned int end = pp->begin + pp->nb-1;
			svg.beginLines();
			for (unsigned int i=pp->begin; i<=end; ++i)
				svg.addLine(ptrP[i], ptrP[i+1], ptrC[i]);
			svg.addLine(ptrP[end], ptrP[pp->begin], ptrC[end]);
			svg.endLines();
		}
		if (pp->mode == GL_TRIANGLES)
		{
			unsigned int end = pp->begin + pp->nb;
			svg.beginLines();
			for (unsigned int i=pp->begin; i<end; i+=3)
			{
				svg.addLine(ptrP[i],   ptrP[i+1], ptrC[i]);
				svg.addLine(ptrP[i+1], ptrP[i+2], ptrC[i+1]);
				svg.addLine(ptrP[i+2], ptrP[i],   ptrC[i+2]);
			}
			svg.endLines();
		}
		if (pp->mode == GL_QUADS)
		{
			unsigned int end = pp->begin + pp->nb;
			svg.beginLines();
			for (unsigned int i=pp->begin; i<end; i+=4)
			{
				svg.addLine(ptrP[i],   ptrP[i+1], ptrC[i]);
				svg.addLine(ptrP[i+1], ptrP[i+2], ptrC[i+1]);
				svg.addLine(ptrP[i+2], ptrP[i+3], ptrC[i+2]);
				svg.addLine(ptrP[i+3], ptrP[i],   ptrC[i+3]);
			}
			svg.endLines();
		}
	}

	m_vboPos->releasePtr();
	m_vboCol->releasePtr();
}

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
325
} // namespace Utils
326

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