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
Shinya Kitaoka 6f0974
	int m, mCount = meshImage.meshes().size();
Shinya Kitaoka 6f0974
	for (m = 0; m != mCount; ++m) {
Shinya Kitaoka 6f0974
		const TTextureMesh &mesh = *meshImage.meshes()[m];
Shinya Kitaoka 6f0974
		const tcg::list<ttexturevertex> &vertices = mesh.vertices();</ttexturevertex>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Draw the mesh wireframe
Shinya Kitaoka 6f0974
		TTextureMesh::faces_container::const_iterator ft, fEnd = mesh.faces().end();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
		for (ft = mesh.faces().begin(); ft != fEnd; ++ft) {
Toshihiro Shimizu 890ddd
			int v0, v1, v2;
Shinya Kitaoka 6f0974
			mesh.faceVertices(ft.index(), v0, v1, v2);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
			const TTextureVertex &p0 = vertices[v0];
Shinya Kitaoka 6f0974
			const TTextureVertex &p1 = vertices[v1];
Shinya Kitaoka 6f0974
			const TTextureVertex &p2 = vertices[v2];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
			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
Shinya Kitaoka 6f0974
	// Draw faces according to the group's sorted faces list
Shinya Kitaoka 6f0974
	typedef std::vector<std::pair<int, int="">> SortedFacesVector;</std::pair<int,>
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
	const SortedFacesVector &sortedFaces = group->m_sortedFaces;
Toshihiro Shimizu 890ddd
	const std::vector<ttexturemeshp> &meshes = meshImage.meshes();</ttexturemeshp>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 7bc906
	int m = -1;
Shinya Kitaoka 6f0974
	const TTextureMesh *mesh;
Shinya Kitaoka 6f0974
	const double *dstCoords;
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
	int v0, v1, v2;
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
	// Draw each face individually. Change tile and mesh data only if they change
Shinya Kitaoka 6f0974
	SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end());
Shinya Kitaoka 6f0974
	for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) {
Shinya Kitaoka 6f0974
		int f = sft->first, m_ = sft->second;
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
		if (m != m_) {
Shinya Kitaoka 6f0974
			m = m_;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			mesh = meshes[m].getPointer();
Shinya Kitaoka 42bfb6
			dstCoords = group->m_datas[m].m_output.get();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
		mesh->faceVertices(f, v0, v1, v2);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
		const double *d0 = dstCoords + (v0 << 1), *d1 = dstCoords + (v1 << 1), *d2 = dstCoords + (v2 << 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
		colorFunction.faceColor(f, m);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
		colorFunction.vertexColor(v0, m), glVertex2d(*d0, *(d0 + 1));
Shinya Kitaoka 6f0974
		colorFunction.vertexColor(v1, m), glVertex2d(*d1, *(d1 + 1));
Shinya Kitaoka 6f0974
		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>
Shinya Kitaoka 42bfb6
				*meshes[m], (const TPointD *)group->m_datas[m].m_output.get(), 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
{
Shinya Kitaoka 6f0974
	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
Shinya Kitaoka 6f0974
	// Prepare variables
Shinya Kitaoka 6f0974
	const std::vector<ttexturemeshp> &meshes = meshImage.meshes();</ttexturemeshp>
Shinya Kitaoka 6f0974
	const TTextureMesh *mesh;
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
	typedef std::vector<std::pair<int, int="">> SortedFacesVector;</std::pair<int,>
Shinya Kitaoka 6f0974
	const SortedFacesVector &sortedFaces = group.m_sortedFaces;
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
	const MeshTexturizer::TextureData *td = texData.m_textureData;
Shinya Kitaoka 6f0974
	int t, tCount = td->m_tileDatas.size();
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
	GLuint texId = -1;
Shinya Kitaoka 6f0974
	int m = -1;
Shinya Kitaoka 6f0974
	const double *dstCoords;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
	int v0, v1, v2;
Shinya Kitaoka 6f0974
	int e1ovi, e2ovi; // Edge X's Other Vertex Index (see below)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Prepare each tile's affine
Shinya Kitaoka 6f0974
	std::vector<taffine> tileAff(tCount);</taffine>
Shinya Kitaoka 6f0974
	for (t = 0; t != tCount; ++t) {
Shinya Kitaoka 6f0974
		const TileData &tileData = td->m_tileDatas[t];
Shinya Kitaoka 6f0974
		const TRectD &tileRect = tileData.m_tileGeometry;
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
		tileAff[t] = TScale(1.0 / (tileRect.x1 - tileRect.x0), 1.0 / (tileRect.y1 - tileRect.y0)) *
Shinya Kitaoka 6f0974
					 TTranslation(-tileRect.x0, -tileRect.y0) *
Shinya Kitaoka 6f0974
					 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
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
	SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end());
Shinya Kitaoka 6f0974
	for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) {
Shinya Kitaoka 6f0974
		int f = sft->first, m_ = sft->second;
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
		if (m != m_) {
Toshihiro Shimizu 890ddd
			// Change mesh if different from current
Shinya Kitaoka 6f0974
			m = m_;
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
			mesh = meshes[m].getPointer();
Shinya Kitaoka 42bfb6
			dstCoords = group.m_datas[m].m_output.get();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Draw each face
Shinya Kitaoka 6f0974
		const TTextureMesh::face_type &fc = mesh->face(f);
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
		const TTextureMesh::edge_type &ed0 = mesh->edge(fc.edge(0)),
Shinya Kitaoka 6f0974
									  &ed1 = mesh->edge(fc.edge(1)),
Shinya Kitaoka 6f0974
									  &ed2 = mesh->edge(fc.edge(2));
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
		{
Shinya Kitaoka 6f0974
			v0 = ed0.vertex(0);
Shinya Kitaoka 6f0974
			v1 = ed0.vertex(1);
Shinya Kitaoka 6f0974
			v2 = ed1.vertex((ed1.vertex(0) == v0) | (ed1.vertex(0) == v1));
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
			e1ovi = (ed1.vertex(0) == v1) | (ed1.vertex(1) == v1); // ed1 and ed2 will refer to vertexes
Shinya Kitaoka 6f0974
			e2ovi = 1 - e1ovi;									   // with index 2 and these.
Shinya Kitaoka 6f0974
		}
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
		const TPointD &p0 = mesh->vertex(v0).P(), &p1 = mesh->vertex(v1).P(), &p2 = mesh->vertex(v2).P();
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
		for (t = 0; t != tCount; ++t) {
Shinya Kitaoka 6f0974
			// Draw face against tile
Shinya Kitaoka 6f0974
			const TileData &tileData = td->m_tileDatas[t];
Shinya Kitaoka 6f0974
Toshihiro Shimizu 890ddd
			// Map each face vertex to tile coordinates
Shinya Kitaoka 6f0974
			TPointD s[3] = {tileAff[t] * p0, tileAff[t] * p1, tileAff[t] * p2};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Test the face bbox - tile intersection
Shinya Kitaoka 12c444
			if (
Shinya Kitaoka 12c444
				std::min({s[0].x, s[1].x, s[2].x}) > 1.0 ||
Shinya Kitaoka 12c444
				std::min({s[0].y, s[1].y, s[2].y}) > 1.0 ||
Shinya Kitaoka 12c444
				std::max({s[0].x, s[1].x, s[2].x}) < 0.0 ||
Shinya Kitaoka 12c444
				std::max({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
Shinya Kitaoka 6f0974
			if (tileData.m_textureId != texId) {
Toshihiro Shimizu 890ddd
				texId = tileData.m_textureId;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
				glBindTexture(GL_TEXTURE_2D, tileData.m_textureId); // This must be OUTSIDE a glBegin/glEnd block
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
			const double *d[3] = {dstCoords + (v0 << 1),
Shinya Kitaoka 6f0974
								  dstCoords + (v1 << 1),
Shinya Kitaoka 6f0974
								  dstCoords + (v2 << 1)};
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
			/*
Shinya Kitaoka 6f0974
        Now, draw primitives. A note about pixel arithmetic, here.
Shinya Kitaoka 6f0974
        
Shinya Kitaoka 6f0974
        Since line antialiasing in OpenGL just manipulates output fragments' alpha components,
Shinya Kitaoka 6f0974
        we must require that the input texture is NONPREMULTIPLIED.
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
        Furthermore, this function does not rely on the assumption that the output alpha component
Shinya Kitaoka 6f0974
        is discarded (as it happens when drawing on screen). This means that just using a simple
Shinya Kitaoka 6f0974
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) is not an option, since this way THE INPUT
Shinya Kitaoka 6f0974
        SRC ALPHA GETS MULTIPLIED BY ITSELF - see glBlendFunc's docs - and that shows.
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
        The solution is to separate the rendering of RGB and M components - the formers use
Shinya Kitaoka 6f0974
        GL_SRC_ALPHA, while the latter uses GL_ONE. The result is a PREMULTIPLIED image.
Shinya Kitaoka 6f0974
      */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// First, draw antialiased face edges on the mesh border.
Shinya Kitaoka 6f0974
			bool drawEd0 = (ed0.facesCount() < 2),
Shinya Kitaoka 6f0974
				 drawEd1 = (ed1.facesCount() < 2),
Shinya Kitaoka 6f0974
				 drawEd2 = (ed2.facesCount() < 2);
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Shinya Kitaoka 6f0974
			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
			glBegin(GL_LINES);
Shinya Kitaoka 6f0974
			{
Shinya Kitaoka 6f0974
				if (drawEd0) {
Shinya Kitaoka 6f0974
					glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
Shinya Kitaoka 6f0974
					glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
Shinya Kitaoka 6f0974
				}
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
				if (drawEd1) {
Shinya Kitaoka 6f0974
					glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1));
Shinya Kitaoka 6f0974
					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
Shinya Kitaoka 6f0974
				}
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
				if (drawEd2) {
Shinya Kitaoka 6f0974
					glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1));
Shinya Kitaoka 6f0974
					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
Shinya Kitaoka 6f0974
				}
Shinya Kitaoka 6f0974
			}
Shinya Kitaoka 6f0974
			glEnd();
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
			glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Shinya Kitaoka 6f0974
			glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
Shinya Kitaoka 6f0974
Toshihiro Shimizu 890ddd
			glBegin(GL_LINES);
Toshihiro Shimizu 890ddd
			{
Shinya Kitaoka 6f0974
				if (drawEd0) {
Shinya Kitaoka 6f0974
					glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
Shinya Kitaoka 6f0974
					glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
				if (drawEd1) {
Shinya Kitaoka 6f0974
					glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1));
Shinya Kitaoka 6f0974
					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6f0974
				if (drawEd2) {
Shinya Kitaoka 6f0974
					glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1));
Shinya Kitaoka 6f0974
					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
Shinya Kitaoka 6f0974
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Shinya Kitaoka 6f0974
			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
			glBegin(GL_TRIANGLES);
Shinya Kitaoka 6f0974
			{
Shinya Kitaoka 6f0974
				glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
Shinya Kitaoka 6f0974
				glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
Shinya Kitaoka 6f0974
				glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
Shinya Kitaoka 6f0974
			}
Shinya Kitaoka 6f0974
			glEnd();
Shinya Kitaoka 6f0974
Shinya Kitaoka 6f0974
			glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Shinya Kitaoka 6f0974
			glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
Shinya Kitaoka 6f0974
Toshihiro Shimizu 890ddd
			glBegin(GL_TRIANGLES);
Toshihiro Shimizu 890ddd
			{
Shinya Kitaoka 6f0974
				glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
Shinya Kitaoka 6f0974
				glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
Shinya Kitaoka 6f0974
				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
}