Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzExt includes
Toshihiro Shimizu 890ddd
#include "ext/ttexturesstorage.h"
Toshihiro Shimizu 890ddd
#include "ext/plasticdeformerstorage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_iterator_ops.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/meshutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
//    Templated drawing functions
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct NoColorFunction {
Toshihiro Shimizu 890ddd
	void faceColor(int f, int m) {}
Toshihiro Shimizu 890ddd
	void edgeColor(int e, int m) {}
Toshihiro Shimizu 890ddd
	void vertexColor(int v, int m) {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename colorfunction="" pointtype,="" typename="" verticescontainer,=""></typename>
Toshihiro Shimizu 890ddd
inline void tglDrawEdges(const TTextureMesh &mesh, const VerticesContainer &vertices,
Toshihiro Shimizu 890ddd
						 ColorFunction colorFunction)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Draw the mesh wireframe
Toshihiro Shimizu 890ddd
	glBegin(GL_LINES);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTextureMesh::edges_container::const_iterator et, eEnd = mesh.edges().end();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (et = mesh.edges().begin(); et != eEnd; ++et) {
Toshihiro Shimizu 890ddd
		const TTextureMesh::edge_type &ed = *et;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int v0 = ed.vertex(0), v1 = ed.vertex(1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const PointType &p0 = vertices[v0];
Toshihiro Shimizu 890ddd
		const PointType &p1 = vertices[v1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		colorFunction.edgeColor(et.index(), -1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		colorFunction.vertexColor(v0, -1);
Toshihiro Shimizu 890ddd
		glVertex2d(tcg::point_traits<pointtype>::x(p0), tcg::point_traits<pointtype>::y(p0));</pointtype></pointtype>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		colorFunction.vertexColor(v1, -1);
Toshihiro Shimizu 890ddd
		glVertex2d(tcg::point_traits<pointtype>::x(p1), tcg::point_traits<pointtype>::y(p1));</pointtype></pointtype>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glEnd();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename colorfunction=""></typename>
Toshihiro Shimizu 890ddd
inline void tglDrawFaces(const TMeshImage &meshImage, ColorFunction colorFunction)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	glBegin(GL_TRIANGLES);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m, mCount = meshImage.meshes().size();
Toshihiro Shimizu 890ddd
	for (m = 0; m != mCount; ++m) {
Toshihiro Shimizu 890ddd
		const TTextureMesh &mesh = *meshImage.meshes()[m];
Toshihiro Shimizu 890ddd
		const tcg::list<ttexturevertex> &vertices = mesh.vertices();</ttexturevertex>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Draw the mesh wireframe
Toshihiro Shimizu 890ddd
		TTextureMesh::faces_container::const_iterator ft, fEnd = mesh.faces().end();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (ft = mesh.faces().begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
			int v0, v1, v2;
Toshihiro Shimizu 890ddd
			mesh.faceVertices(ft.index(), v0, v1, v2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			const TTextureVertex &p0 = vertices[v0];
Toshihiro Shimizu 890ddd
			const TTextureVertex &p1 = vertices[v1];
Toshihiro Shimizu 890ddd
			const TTextureVertex &p2 = vertices[v2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			colorFunction.faceColor(ft.index(), m);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			colorFunction.vertexColor(v0, m), glVertex2d(p0.P().x, p0.P().y);
Toshihiro Shimizu 890ddd
			colorFunction.vertexColor(v1, m), glVertex2d(p1.P().x, p1.P().y);
Toshihiro Shimizu 890ddd
			colorFunction.vertexColor(v2, m), glVertex2d(p2.P().x, p2.P().y);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glEnd();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename colorfunction=""></typename>
Toshihiro Shimizu 890ddd
inline void tglDrawFaces(const TMeshImage &meshImage, const PlasticDeformerDataGroup *group,
Toshihiro Shimizu 890ddd
						 ColorFunction colorFunction)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	glBegin(GL_TRIANGLES);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Draw faces according to the group's sorted faces list
Toshihiro Shimizu 890ddd
	typedef std::vector<std::pair<int, int="">> SortedFacesVector;</std::pair<int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const SortedFacesVector &sortedFaces = group->m_sortedFaces;
Toshihiro Shimizu 890ddd
	const std::vector<ttexturemeshp> &meshes = meshImage.meshes();</ttexturemeshp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m = -1;
Toshihiro Shimizu 890ddd
	const TTextureMesh *mesh;
Toshihiro Shimizu 890ddd
	const double *dstCoords;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int v0, v1, v2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Draw each face individually. Change tile and mesh data only if they change
Toshihiro Shimizu 890ddd
	SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end());
Toshihiro Shimizu 890ddd
	for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) {
Toshihiro Shimizu 890ddd
		int f = sft->first, m_ = sft->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m != m_) {
Toshihiro Shimizu 890ddd
			m = m_;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			mesh = meshes[m].getPointer();
Toshihiro Shimizu 890ddd
			dstCoords = group->m_datas[m].m_output;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		mesh->faceVertices(f, v0, v1, v2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const double *d0 = dstCoords + (v0 << 1), *d1 = dstCoords + (v1 << 1), *d2 = dstCoords + (v2 << 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		colorFunction.faceColor(f, m);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		colorFunction.vertexColor(v0, m), glVertex2d(*d0, *(d0 + 1));
Toshihiro Shimizu 890ddd
		colorFunction.vertexColor(v1, m), glVertex2d(*d1, *(d1 + 1));
Toshihiro Shimizu 890ddd
		colorFunction.vertexColor(v2, m), glVertex2d(*d2, *(d2 + 1));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glEnd();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
//    Mesh Image Utility  functions implementation
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void transform(const TMeshImageP &meshImage, const TAffine &aff)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const std::vector<ttexturemeshp> &meshes = meshImage->meshes();</ttexturemeshp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m, mCount = meshes.size();
Toshihiro Shimizu 890ddd
	for (m = 0; m != mCount; ++m) {
Toshihiro Shimizu 890ddd
		TTextureMesh &mesh = *meshes[m];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		tcg::list<ttexturemesh::vertex_type> &vertices = mesh.vertices();</ttexturemesh::vertex_type>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		tcg::list<ttexturemesh::vertex_type>::iterator vt, vEnd(vertices.end());</ttexturemesh::vertex_type>
Toshihiro Shimizu 890ddd
		for (vt = vertices.begin(); vt != vEnd; ++vt)
Toshihiro Shimizu 890ddd
			vt->P() = aff * vt->P();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tglDrawEdges(const TMeshImage &mi, const PlasticDeformerDataGroup *group)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const std::vector<ttexturemeshp> &meshes = mi.meshes();</ttexturemeshp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m, mCount = meshes.size();
Toshihiro Shimizu 890ddd
	if (group) {
Toshihiro Shimizu 890ddd
		for (m = 0; m != mCount; ++m)
Toshihiro Shimizu 890ddd
			tglDrawEdges<const *,="" nocolorfunction="" tpointd="" tpointd,="">(</const>
Toshihiro Shimizu 890ddd
				*meshes[m], (const TPointD *)group->m_datas[m].m_output, NoColorFunction());
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		for (m = 0; m != mCount; ++m) {
Toshihiro Shimizu 890ddd
			const TTextureMesh &mesh = *meshes[m];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			tglDrawEdges<tcg::list<ttexturemesh::vertex_type>, TTextureVertex, NoColorFunction>(</tcg::list<ttexturemesh::vertex_type>
Toshihiro Shimizu 890ddd
				mesh, mesh.vertices(), NoColorFunction());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tglDrawFaces(const TMeshImage &image, const PlasticDeformerDataGroup *group)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (group)
Toshihiro Shimizu 890ddd
		tglDrawFaces(image, group, NoColorFunction());
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		tglDrawFaces(image, NoColorFunction());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
//    Colored drawing functions
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct LinearColorFunction {
Toshihiro Shimizu 890ddd
	typedef double (*ValueFunc)(const LinearColorFunction *cf, int m, int primitive);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	const TMeshImage &m_meshImg;
Toshihiro Shimizu 890ddd
	const PlasticDeformerDataGroup *m_group;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double m_min, m_max;
Toshihiro Shimizu 890ddd
	double *m_cMin, *m_cMax;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double m_dt;
Toshihiro Shimizu 890ddd
	bool m_degenerate;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ValueFunc m_func;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	LinearColorFunction(const TMeshImage &meshImg,
Toshihiro Shimizu 890ddd
						const PlasticDeformerDataGroup *group,
Toshihiro Shimizu 890ddd
						double min, double max,
Toshihiro Shimizu 890ddd
						double *cMin, double *cMax,
Toshihiro Shimizu 890ddd
						ValueFunc func)
Toshihiro Shimizu 890ddd
		: m_meshImg(meshImg), m_group(group), m_min(min), m_max(max), m_cMin(cMin), m_cMax(cMax), m_dt(max - min), m_degenerate(m_dt < 1e-4), m_func(func)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void operator()(int primitive, int m)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_degenerate) {
Toshihiro Shimizu 890ddd
			glColor4d(0.5 * (m_cMin[0] + m_cMax[0]),
Toshihiro Shimizu 890ddd
					  0.5 * (m_cMin[1] + m_cMax[1]),
Toshihiro Shimizu 890ddd
					  0.5 * (m_cMin[2] + m_cMax[2]),
Toshihiro Shimizu 890ddd
					  0.5 * (m_cMin[3] + m_cMax[3]));
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double val = m_func(this, m, primitive);
Toshihiro Shimizu 890ddd
		double t = (val - m_min) / m_dt, one_t = (m_max - val) / m_dt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glColor4d(one_t * m_cMin[0] + t * m_cMax[0],
Toshihiro Shimizu 890ddd
				  one_t * m_cMin[1] + t * m_cMax[1],
Toshihiro Shimizu 890ddd
				  one_t * m_cMin[2] + t * m_cMax[2],
Toshihiro Shimizu 890ddd
				  one_t * m_cMin[3] + t * m_cMax[3]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct LinearVertexColorFunction : public LinearColorFunction, public NoColorFunction {
Toshihiro Shimizu 890ddd
	LinearVertexColorFunction(const TMeshImage &meshImg,
Toshihiro Shimizu 890ddd
							  const PlasticDeformerDataGroup *group,
Toshihiro Shimizu 890ddd
							  double min, double max,
Toshihiro Shimizu 890ddd
							  double *cMin, double *cMax,
Toshihiro Shimizu 890ddd
							  ValueFunc func)
Toshihiro Shimizu 890ddd
		: LinearColorFunction(meshImg, group, min, max, cMin, cMax, func) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void vertexColor(int v, int m) { operator()(v, m); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct LinearFaceColorFunction : public LinearColorFunction, public NoColorFunction {
Toshihiro Shimizu 890ddd
	LinearFaceColorFunction(const TMeshImage &meshImg,
Toshihiro Shimizu 890ddd
							const PlasticDeformerDataGroup *group,
Toshihiro Shimizu 890ddd
							double min, double max,
Toshihiro Shimizu 890ddd
							double *cMin, double *cMax,
Toshihiro Shimizu 890ddd
							ValueFunc func)
Toshihiro Shimizu 890ddd
		: LinearColorFunction(meshImg, group, min, max, cMin, cMax, func) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void faceColor(int v, int m) { operator()(v, m); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tglDrawSO(const TMeshImage &image, double minColor[4], double maxColor[4],
Toshihiro Shimizu 890ddd
			   const PlasticDeformerDataGroup *group, bool deformedDomain)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		static double returnSO(const LinearColorFunction *cf, int m, int f)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			return cf->m_group->m_datas[m].m_so[f];
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double min = 0.0, max = 0.0;
Toshihiro Shimizu 890ddd
	if (group)
Toshihiro Shimizu 890ddd
		min = group->m_soMin, max = group->m_soMax;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	LinearFaceColorFunction colorFunction(image, group, min, max, minColor, maxColor, locals::returnSO);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (group && deformedDomain)
Toshihiro Shimizu 890ddd
		tglDrawFaces(image, group, colorFunction);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		tglDrawFaces(image, colorFunction);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tglDrawRigidity(const TMeshImage &image, double minColor[4], double maxColor[4],
Toshihiro Shimizu 890ddd
					 const PlasticDeformerDataGroup *group, bool deformedDomain)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		static double returnRigidity(const LinearColorFunction *cf, int m, int v)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			return cf->m_meshImg.meshes()[m]->vertex(v).P().rigidity;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	LinearVertexColorFunction colorFunction(image, group,
Toshihiro Shimizu 890ddd
											1.0, 1e4, minColor, maxColor, locals::returnRigidity);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (group && deformedDomain)
Toshihiro Shimizu 890ddd
		tglDrawFaces(image, group, colorFunction);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		tglDrawFaces(image, colorFunction);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Texturized drawing  implementation
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void tglDraw(const TMeshImage &meshImage,
Toshihiro Shimizu 890ddd
			 const DrawableTextureData &texData, const TAffine &meshToTexAff,
Toshihiro Shimizu 890ddd
			 const PlasticDeformerDataGroup &group)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	typedef MeshTexturizer::TextureData::TileData TileData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Prepare OpenGL
Toshihiro Shimizu 890ddd
	glPushAttrib(GL_COLOR_BUFFER_BIT | GL_LINE_BIT | GL_HINT_BIT); // Preserve original status bits
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glEnable(GL_BLEND);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glEnable(GL_LINE_SMOOTH);
Toshihiro Shimizu 890ddd
	glLineWidth(1.0f);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Prepare variables
Toshihiro Shimizu 890ddd
	const std::vector<ttexturemeshp> &meshes = meshImage.meshes();</ttexturemeshp>
Toshihiro Shimizu 890ddd
	const TTextureMesh *mesh;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typedef std::vector<std::pair<int, int="">> SortedFacesVector;</std::pair<int,>
Toshihiro Shimizu 890ddd
	const SortedFacesVector &sortedFaces = group.m_sortedFaces;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const MeshTexturizer::TextureData *td = texData.m_textureData;
Toshihiro Shimizu 890ddd
	int t, tCount = td->m_tileDatas.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	GLuint texId = -1;
Toshihiro Shimizu 890ddd
	int m = -1;
Toshihiro Shimizu 890ddd
	const double *dstCoords;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int v0, v1, v2;
Toshihiro Shimizu 890ddd
	int e1ovi, e2ovi; // Edge X's Other Vertex Index (see below)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Prepare each tile's affine
Toshihiro Shimizu 890ddd
	std::vector<taffine> tileAff(tCount);</taffine>
Toshihiro Shimizu 890ddd
	for (t = 0; t != tCount; ++t) {
Toshihiro Shimizu 890ddd
		const TileData &tileData = td->m_tileDatas[t];
Toshihiro Shimizu 890ddd
		const TRectD &tileRect = tileData.m_tileGeometry;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		tileAff[t] = TScale(1.0 / (tileRect.x1 - tileRect.x0), 1.0 / (tileRect.y1 - tileRect.y0)) *
Toshihiro Shimizu 890ddd
					 TTranslation(-tileRect.x0, -tileRect.y0) *
Toshihiro Shimizu 890ddd
					 meshToTexAff;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Draw each face individually, according to the group's sorted faces list.
Toshihiro Shimizu 890ddd
	// Change tile and mesh data only if they change - improves performance
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end());
Toshihiro Shimizu 890ddd
	for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) {
Toshihiro Shimizu 890ddd
		int f = sft->first, m_ = sft->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m != m_) {
Toshihiro Shimizu 890ddd
			// Change mesh if different from current
Toshihiro Shimizu 890ddd
			m = m_;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			mesh = meshes[m].getPointer();
Toshihiro Shimizu 890ddd
			dstCoords = group.m_datas[m].m_output;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Draw each face
Toshihiro Shimizu 890ddd
		const TTextureMesh::face_type &fc = mesh->face(f);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const TTextureMesh::edge_type &ed0 = mesh->edge(fc.edge(0)),
Toshihiro Shimizu 890ddd
									  &ed1 = mesh->edge(fc.edge(1)),
Toshihiro Shimizu 890ddd
									  &ed2 = mesh->edge(fc.edge(2));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			v0 = ed0.vertex(0);
Toshihiro Shimizu 890ddd
			v1 = ed0.vertex(1);
Toshihiro Shimizu 890ddd
			v2 = ed1.vertex((ed1.vertex(0) == v0) | (ed1.vertex(0) == v1));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			e1ovi = (ed1.vertex(0) == v1) | (ed1.vertex(1) == v1); // ed1 and ed2 will refer to vertexes
Toshihiro Shimizu 890ddd
			e2ovi = 1 - e1ovi;									   // with index 2 and these.
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const TPointD &p0 = mesh->vertex(v0).P(), &p1 = mesh->vertex(v1).P(), &p2 = mesh->vertex(v2).P();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (t = 0; t != tCount; ++t) {
Toshihiro Shimizu 890ddd
			// Draw face against tile
Toshihiro Shimizu 890ddd
			const TileData &tileData = td->m_tileDatas[t];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Map each face vertex to tile coordinates
Toshihiro Shimizu 890ddd
			TPointD s[3] = {tileAff[t] * p0, tileAff[t] * p1, tileAff[t] * p2};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Test the face bbox - tile intersection
Toshihiro Shimizu 890ddd
			if (tmin(s[0].x, s[1].x, s[2].x) > 1.0 ||
Toshihiro Shimizu 890ddd
				tmin(s[0].y, s[1].y, s[2].y) > 1.0 ||
Toshihiro Shimizu 890ddd
				tmax(s[0].x, s[1].x, s[2].x) < 0.0 ||
Toshihiro Shimizu 890ddd
				tmax(s[0].y, s[1].y, s[2].y) < 0.0)
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// If the tile has changed, interrupt the glBegin/glEnd block and bind the
Toshihiro Shimizu 890ddd
			// OpenGL texture corresponding to the new tile
Toshihiro Shimizu 890ddd
			if (tileData.m_textureId != texId) {
Toshihiro Shimizu 890ddd
				texId = tileData.m_textureId;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				glBindTexture(GL_TEXTURE_2D, tileData.m_textureId); // This must be OUTSIDE a glBegin/glEnd block
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			const double *d[3] = {dstCoords + (v0 << 1),
Toshihiro Shimizu 890ddd
								  dstCoords + (v1 << 1),
Toshihiro Shimizu 890ddd
								  dstCoords + (v2 << 1)};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			/*
Toshihiro Shimizu 890ddd
        Now, draw primitives. A note about pixel arithmetic, here.
Toshihiro Shimizu 890ddd
        
Toshihiro Shimizu 890ddd
        Since line antialiasing in OpenGL just manipulates output fragments' alpha components,
Toshihiro Shimizu 890ddd
        we must require that the input texture is NONPREMULTIPLIED.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
        Furthermore, this function does not rely on the assumption that the output alpha component
Toshihiro Shimizu 890ddd
        is discarded (as it happens when drawing on screen). This means that just using a simple
Toshihiro Shimizu 890ddd
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) is not an option, since this way THE INPUT
Toshihiro Shimizu 890ddd
        SRC ALPHA GETS MULTIPLIED BY ITSELF - see glBlendFunc's docs - and that shows.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
        The solution is to separate the rendering of RGB and M components - the formers use
Toshihiro Shimizu 890ddd
        GL_SRC_ALPHA, while the latter uses GL_ONE. The result is a PREMULTIPLIED image.
Toshihiro Shimizu 890ddd
      */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// First, draw antialiased face edges on the mesh border.
Toshihiro Shimizu 890ddd
			bool drawEd0 = (ed0.facesCount() < 2),
Toshihiro Shimizu 890ddd
				 drawEd1 = (ed1.facesCount() < 2),
Toshihiro Shimizu 890ddd
				 drawEd2 = (ed2.facesCount() < 2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Toshihiro Shimizu 890ddd
			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glBegin(GL_LINES);
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				if (drawEd0) {
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (drawEd1) {
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1));
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (drawEd2) {
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1));
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			glEnd();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Toshihiro Shimizu 890ddd
			glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glBegin(GL_LINES);
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				if (drawEd0) {
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (drawEd1) {
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1));
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (drawEd2) {
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1));
Toshihiro Shimizu 890ddd
					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			glEnd();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Finally, draw the face
Toshihiro Shimizu 890ddd
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Toshihiro Shimizu 890ddd
			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glBegin(GL_TRIANGLES);
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
Toshihiro Shimizu 890ddd
				glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
Toshihiro Shimizu 890ddd
				glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			glEnd();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Toshihiro Shimizu 890ddd
			glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			glBegin(GL_TRIANGLES);
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
Toshihiro Shimizu 890ddd
				glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
Toshihiro Shimizu 890ddd
				glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			glEnd();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glPopAttrib();
Toshihiro Shimizu 890ddd
}