Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "pins.h"
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
#define ISNAN _isnan
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
extern "C" int isnan(double);
Toshihiro Shimizu 890ddd
#define ISNAN isnan
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool lineIntersection(const TPointD &P, const TPointD &R,
Toshihiro Shimizu 890ddd
					  const TPointD &Q, const TPointD &S, TPointD &ret);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool lineIntersection(const TPointD &P, const TPointD &R,
Toshihiro Shimizu 890ddd
					  const TPointD &Q, const TPointD &S, TPointD &ret)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD u = R - P;
Toshihiro Shimizu 890ddd
	TPointD v = S - Q;
Toshihiro Shimizu 890ddd
	double r;
Toshihiro Shimizu 890ddd
	if (u.y * v.x - u.x * v.y != 0) {
Toshihiro Shimizu 890ddd
		r = (P.x * u.y - Q.x * u.y + u.x * (Q.y - P.y)) / (u.y * v.x - u.x * v.y);
Toshihiro Shimizu 890ddd
		assert(!ISNAN(r));
Toshihiro Shimizu 890ddd
		ret = Q + v * r;
Toshihiro Shimizu 890ddd
		assert(!ISNAN(ret.x) && !ISNAN(ret.y));
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		ret = P;
Toshihiro Shimizu 890ddd
		assert(!ISNAN(ret.x) && !ISNAN(ret.y));
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef checkErrorsByGL
Toshihiro Shimizu 890ddd
#define checkErrorsByGL                      \
Toshihiro Shimizu 890ddd
	{                                        \
Toshihiro Shimizu 890ddd
		GLenum err = glGetError();           \
Toshihiro Shimizu 890ddd
		assert(err != GL_INVALID_ENUM);      \
Toshihiro Shimizu 890ddd
		assert(err != GL_INVALID_VALUE);     \
Toshihiro Shimizu 890ddd
		assert(err != GL_INVALID_OPERATION); \
Toshihiro Shimizu 890ddd
		assert(err != GL_STACK_OVERFLOW);    \
Toshihiro Shimizu 890ddd
		assert(err != GL_STACK_UNDERFLOW);   \
Toshihiro Shimizu 890ddd
		assert(err != GL_OUT_OF_MEMORY);     \
Toshihiro Shimizu 890ddd
		assert(err == GL_NO_ERROR);          \
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ---------------------------------------- --------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void subCompute(TRasterFxPort &m_input, TTile &tile, double frame, const TRenderSettings &ri,
Toshihiro Shimizu 890ddd
				TPointD p00, TPointD p01, TPointD p11, TPointD p10, int details, bool wireframe,
Toshihiro Shimizu 890ddd
				TDimension m_offScreenSize, bool isCast)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPixel32 bgColor;
Toshihiro Shimizu 890ddd
	TRectD outBBox, inBBox;
Toshihiro Shimizu 890ddd
	outBBox = inBBox = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy()));
Toshihiro Shimizu 890ddd
	m_input->getBBox(frame, inBBox, ri);
Toshihiro Shimizu 890ddd
	if (inBBox == TConsts::infiniteRectD) // e' uno zerario
Toshihiro Shimizu 890ddd
		inBBox = outBBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int inBBoxLx = (int)inBBox.getLx() / ri.m_shrinkX;
Toshihiro Shimizu 890ddd
	int inBBoxLy = (int)inBBox.getLy() / ri.m_shrinkY;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (inBBox.isEmpty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (p00 == p01 && p00 == p10 && p00 == p11 && !isCast) // significa che non c'e' deformazione
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_input->compute(tile, frame, ri);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRaster32P rasIn;
Toshihiro Shimizu 890ddd
	TPointD rasInPos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!wireframe) {
Toshihiro Shimizu 890ddd
		if (ri.m_bpp == 64 || ri.m_bpp == 48) {
Toshihiro Shimizu 890ddd
			TRaster64P aux = TRaster64P(inBBoxLx, inBBoxLy);
Toshihiro Shimizu 890ddd
			rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY);
Toshihiro Shimizu 890ddd
			TTile tmp(aux, rasInPos);
Toshihiro Shimizu 890ddd
			m_input->compute(tmp, frame, ri);
Toshihiro Shimizu 890ddd
			rasIn = TRaster32P(inBBoxLx, inBBoxLy);
Toshihiro Shimizu 890ddd
			TRop::convert(rasIn, aux);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY);
Toshihiro Shimizu 890ddd
			TTile tmp(TRaster32P(inBBoxLx, inBBoxLy), rasInPos);
Toshihiro Shimizu 890ddd
			m_input->allocateAndCompute(tmp, rasInPos, TDimension(inBBoxLx, inBBoxLy), TRaster32P(), frame, ri);
Toshihiro Shimizu 890ddd
			rasIn = tmp.getRaster();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	unsigned int texWidth = 2;
Toshihiro Shimizu 890ddd
	unsigned int texHeight = 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (texWidth < (unsigned int)inBBoxLx)
Toshihiro Shimizu 890ddd
		texWidth = texWidth << 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (texHeight < (unsigned int)inBBoxLy)
Toshihiro Shimizu 890ddd
		texHeight = texHeight << 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (texWidth > 1024 || texHeight > 1024) //avevo usato la costante GL_MAX_TEXTURE_SIZE invece di 1024, ma non funzionava!
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		inBBoxLx = inBBoxLx >> 1;
Toshihiro Shimizu 890ddd
		inBBoxLy = inBBoxLy >> 1;
Toshihiro Shimizu 890ddd
		texWidth = texWidth >> 1;
Toshihiro Shimizu 890ddd
		texHeight = texHeight >> 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (rasIn->getLx() != inBBoxLx || rasIn->getLy() != inBBoxLy) {
Toshihiro Shimizu 890ddd
		TRaster32P rasOut = TRaster32P(inBBoxLx, inBBoxLy);
Toshihiro Shimizu 890ddd
		TRop::resample(rasOut, rasIn, TScale((double)rasOut->getLx() / rasIn->getLx(), (double)rasOut->getLy() / rasIn->getLy()));
Toshihiro Shimizu 890ddd
		rasIn = rasOut;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int rasterWidth = tile.getRaster()->getLx() + 2;
Toshihiro Shimizu 890ddd
	int rasterHeight = tile.getRaster()->getLy() + 2;
Toshihiro Shimizu 890ddd
	assert(rasterWidth > 0);
Toshihiro Shimizu 890ddd
	assert(rasterHeight > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD clippingRect = TRectD(tile.m_pos,
Toshihiro Shimizu 890ddd
								 TDimensionD(tile.getRaster()->getLx(),
Toshihiro Shimizu 890ddd
											 tile.getRaster()->getLy()));
Toshihiro Shimizu 890ddd
#if CREATE_GL_CONTEXT_ONE_TIME
Toshihiro Shimizu 890ddd
	int ret = wglMakeCurrent(m_offScreenGL.m_offDC, m_offScreenGL.m_hglRC);
Toshihiro Shimizu 890ddd
	assert(ret == TRUE);
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	TOfflineGL offScreenRendering(TDimension(rasterWidth, rasterHeight));
Shinya Kitaoka 9f5a1b
	//#ifdef _WIN32
Toshihiro Shimizu 890ddd
	offScreenRendering.makeCurrent();
Toshihiro Shimizu 890ddd
//#else
Toshihiro Shimizu 890ddd
//#if defined(LINUX) || defined(MACOSX)
Toshihiro Shimizu 890ddd
// offScreenRendering.m_offlineGL->makeCurrent();
Toshihiro Shimizu 890ddd
//#endif
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	checkErrorsByGL
Toshihiro Shimizu 890ddd
		// disabilito quello che non mi serve per le texture
Toshihiro Shimizu 890ddd
		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
Toshihiro Shimizu 890ddd
	glDisable(GL_DITHER);
Toshihiro Shimizu 890ddd
	glDisable(GL_DEPTH_TEST);
Toshihiro Shimizu 890ddd
	glCullFace(GL_FRONT);
Toshihiro Shimizu 890ddd
	glDisable(GL_STENCIL_TEST);
Toshihiro Shimizu 890ddd
	glDisable(GL_LOGIC_OP);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// creo la texture in base all'immagine originale
Toshihiro Shimizu 890ddd
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
Toshihiro Shimizu 890ddd
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
Toshihiro Shimizu 890ddd
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Toshihiro Shimizu 890ddd
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Toshihiro Shimizu 890ddd
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	checkErrorsByGL
Toshihiro Shimizu 890ddd
#if !CREATE_GL_CONTEXT_ONE_TIME
Toshihiro Shimizu 890ddd
		TRaster32P rasaux;
Toshihiro Shimizu 890ddd
	if (!wireframe) {
Toshihiro Shimizu 890ddd
		TRaster32P texture(texWidth, texHeight);
Toshihiro Shimizu 890ddd
		texture->clear();
Toshihiro Shimizu 890ddd
		rasaux = texture;
Toshihiro Shimizu 890ddd
		rasaux->lock();
Toshihiro Shimizu 890ddd
		texture->copy(rasIn);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
Toshihiro Shimizu 890ddd
		glTexImage2D(GL_TEXTURE_2D,
Toshihiro Shimizu 890ddd
					 0,
Toshihiro Shimizu 890ddd
					 4,
Toshihiro Shimizu 890ddd
					 texWidth,
Toshihiro Shimizu 890ddd
					 texHeight,
Toshihiro Shimizu 890ddd
					 0,
Toshihiro Shimizu 890ddd
					 GL_RGBA,
Toshihiro Shimizu 890ddd
					 GL_UNSIGNED_BYTE,
Toshihiro Shimizu 890ddd
					 texture->getRawData());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		unsigned int texWidth = 1024;
Toshihiro Shimizu 890ddd
	unsigned int texHeight = 1024;
Toshihiro Shimizu 890ddd
	rasaux = rasIn;
Toshihiro Shimizu 890ddd
	rasaux->lock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glTexSubImage2D(GL_TEXTURE_2D, 0,
Toshihiro Shimizu 890ddd
					0, 0,
Toshihiro Shimizu 890ddd
					rasIn->getLx(), rasIn->getLy(),
Toshihiro Shimizu 890ddd
					GL_RGBA,
Toshihiro Shimizu 890ddd
					GL_UNSIGNED_BYTE,
Toshihiro Shimizu 890ddd
					rasIn->getRawData());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	checkErrorsByGL
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glEnable(GL_TEXTURE_2D);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips
Toshihiro Shimizu 890ddd
	glMatrixMode(GL_PROJECTION);
Toshihiro Shimizu 890ddd
	glLoadIdentity();
Toshihiro Shimizu 890ddd
	glOrtho(-rasterWidth * 0.5, rasterWidth * 0.5, -rasterHeight * 0.5, rasterHeight * 0.5, -1, 1);
Toshihiro Shimizu 890ddd
	glViewport(0, 0, rasterWidth, rasterHeight);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glMatrixMode(GL_MODELVIEW);
Toshihiro Shimizu 890ddd
	glLoadIdentity();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Toshihiro Shimizu 890ddd
	glClear(GL_COLOR_BUFFER_BIT);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// do OpenGL draw
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double lwTex = (double)(inBBoxLx - 1) / (double)(texWidth - 1);
Toshihiro Shimizu 890ddd
	double lhTex = (double)(inBBoxLy - 1) / (double)(texHeight - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD tex00 = TPointD(0.0, 0.0);
Toshihiro Shimizu 890ddd
	TPointD tex10 = TPointD(lwTex, 0.0);
Toshihiro Shimizu 890ddd
	TPointD tex11 = TPointD(lwTex, lhTex);
Toshihiro Shimizu 890ddd
	TPointD tex01 = TPointD(0.0, lhTex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	GLenum polygonStyle;
Toshihiro Shimizu 890ddd
	if (wireframe) {
Toshihiro Shimizu 890ddd
		polygonStyle = GL_LINE;
Toshihiro Shimizu 890ddd
		glDisable(GL_TEXTURE_2D);
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		polygonStyle = GL_FILL;
Toshihiro Shimizu 890ddd
	checkErrorsByGL
Toshihiro Shimizu 890ddd
		p00.x /= ri.m_shrinkX;
Toshihiro Shimizu 890ddd
	p00.y /= ri.m_shrinkY;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p10.x /= ri.m_shrinkX;
Toshihiro Shimizu 890ddd
	p10.y /= ri.m_shrinkY;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p11.x /= ri.m_shrinkX;
Toshihiro Shimizu 890ddd
	p11.y /= ri.m_shrinkY;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p01.x /= ri.m_shrinkX;
Toshihiro Shimizu 890ddd
	p01.y /= ri.m_shrinkY;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD translate = TPointD(tile.m_pos.x + tile.getRaster()->getLx() * 0.5,
Toshihiro Shimizu 890ddd
								tile.m_pos.y + tile.getRaster()->getLy() * 0.5);
Toshihiro Shimizu 890ddd
	glTranslated(-translate.x, -translate.y, 0.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// disegno il poligono
Toshihiro Shimizu 890ddd
	double dist_p00_p01 = tdistance2(p00, p01);
Toshihiro Shimizu 890ddd
	double dist_p10_p11 = tdistance2(p10, p11);
Toshihiro Shimizu 890ddd
	double dist_p01_p11 = tdistance2(p01, p11);
Toshihiro Shimizu 890ddd
	double dist_p00_p10 = tdistance2(p00, p10);
Toshihiro Shimizu 890ddd
	bool vertical = (dist_p00_p01 == dist_p10_p11);
Toshihiro Shimizu 890ddd
	bool horizontal = (dist_p00_p10 == dist_p01_p11);
Toshihiro Shimizu 890ddd
	if (vertical && horizontal)
Toshihiro Shimizu 890ddd
		details = 1;
Toshihiro Shimizu 890ddd
	glPolygonMode(GL_FRONT_AND_BACK, polygonStyle);
Toshihiro Shimizu 890ddd
	subdivision(p00, p10, p11, p01,
Toshihiro Shimizu 890ddd
				tex00, tex10, tex11, tex01,
Toshihiro Shimizu 890ddd
				clippingRect,
Toshihiro Shimizu 890ddd
				details);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!wireframe) {
Toshihiro Shimizu 890ddd
		// abilito l'antialiasing delle linee
Toshihiro Shimizu 890ddd
		glEnable(GL_LINE_SMOOTH);
Toshihiro Shimizu 890ddd
		glEnable(GL_BLEND);
Toshihiro Shimizu 890ddd
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Toshihiro Shimizu 890ddd
		glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// disegno il bordo del poligono
Toshihiro Shimizu 890ddd
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Toshihiro Shimizu 890ddd
		glBegin(GL_QUADS);
Toshihiro Shimizu 890ddd
		glTexCoord2d(tex00.x, tex00.y);
Toshihiro Shimizu 890ddd
		tglVertex(p00);
Toshihiro Shimizu 890ddd
		glTexCoord2d(tex10.x, tex10.y);
Toshihiro Shimizu 890ddd
		tglVertex(p10);
Toshihiro Shimizu 890ddd
		glTexCoord2d(tex11.x, tex11.y);
Toshihiro Shimizu 890ddd
		tglVertex(p11);
Toshihiro Shimizu 890ddd
		glTexCoord2d(tex01.x, tex01.y);
Toshihiro Shimizu 890ddd
		tglVertex(p01);
Toshihiro Shimizu 890ddd
		glEnd();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// disabilito l'antialiasing per le linee
Toshihiro Shimizu 890ddd
		glDisable(GL_LINE_SMOOTH);
Toshihiro Shimizu 890ddd
		glDisable(GL_BLEND);
Toshihiro Shimizu 890ddd
		glDisableClientState(GL_VERTEX_ARRAY);
Toshihiro Shimizu 890ddd
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Toshihiro Shimizu 890ddd
		glDisable(GL_TEXTURE_2D);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// force to finish
Toshihiro Shimizu 890ddd
	glFlush();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// rimetto il disegno dei poligoni a GL_FILL
Toshihiro Shimizu 890ddd
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// metto il frame buffer nel raster del tile
Toshihiro Shimizu 890ddd
	glPixelStorei(GL_UNPACK_ROW_LENGTH, rasterWidth);
Toshihiro Shimizu 890ddd
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRaster32P newRas(tile.getRaster()->getLx(), tile.getRaster()->getLy());
Toshihiro Shimizu 890ddd
	newRas->lock();
Toshihiro Shimizu 890ddd
	glReadPixels(1, 1,
Toshihiro Shimizu 890ddd
				 newRas->getLx(), newRas->getLy(),
Toshihiro Shimizu 890ddd
				 GL_RGBA, GL_UNSIGNED_BYTE, (void *)newRas->getRawData());
Toshihiro Shimizu 890ddd
	newRas->unlock();
Toshihiro Shimizu 890ddd
	checkErrorsByGL
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		rasaux->unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tile.getRaster()->copy(newRas);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void subdivision(const TPointD &p00,
Toshihiro Shimizu 890ddd
				 const TPointD &p10,
Toshihiro Shimizu 890ddd
				 const TPointD &p11,
Toshihiro Shimizu 890ddd
				 const TPointD &p01,
Toshihiro Shimizu 890ddd
				 const TPointD &tex00,
Toshihiro Shimizu 890ddd
				 const TPointD &tex10,
Toshihiro Shimizu 890ddd
				 const TPointD &tex11,
Toshihiro Shimizu 890ddd
				 const TPointD &tex01,
Toshihiro Shimizu 890ddd
				 const TRectD &clippingRect,
Toshihiro Shimizu 890ddd
				 int details)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (details == 1) {
Toshihiro Shimizu 890ddd
		glBegin(GL_QUADS);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glTexCoord2d(tex00.x, tex00.y);
Toshihiro Shimizu 890ddd
		tglVertex(p00);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glTexCoord2d(tex10.x, tex10.y);
Toshihiro Shimizu 890ddd
		tglVertex(p10);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glTexCoord2d(tex11.x, tex11.y);
Toshihiro Shimizu 890ddd
		tglVertex(p11);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glTexCoord2d(tex01.x, tex01.y);
Toshihiro Shimizu 890ddd
		tglVertex(p01);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glEnd();
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		TPointD A = p00;
Toshihiro Shimizu 890ddd
		TPointD B = p10;
Toshihiro Shimizu 890ddd
		TPointD C = p11;
Toshihiro Shimizu 890ddd
		TPointD D = p01;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
     *     D                L2               C
Toshihiro Shimizu 890ddd
     *     +----------------+----------------+
Toshihiro Shimizu 890ddd
     *     |                |                |
Toshihiro Shimizu 890ddd
     *     |                |                |
Toshihiro Shimizu 890ddd
     *     |                |                |
Toshihiro Shimizu 890ddd
     *     |                |                |
Toshihiro Shimizu 890ddd
     *     |                |                |
Toshihiro Shimizu 890ddd
     *  H1 +----------------+----------------+ H2
Toshihiro Shimizu 890ddd
     *     |                | M              |
Toshihiro Shimizu 890ddd
     *     |                |                |
Toshihiro Shimizu 890ddd
     *     |                |                |
Toshihiro Shimizu 890ddd
     *     |                |                |
Toshihiro Shimizu 890ddd
     *     |                |                |
Toshihiro Shimizu 890ddd
     *     +----------------+----------------+
Toshihiro Shimizu 890ddd
     *     A                L1               B
Toshihiro Shimizu 890ddd
     *
Toshihiro Shimizu 890ddd
     */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPointD M, L1, L2, H1, H2, P1, P2;
Toshihiro Shimizu 890ddd
		bool intersection;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// M
Toshihiro Shimizu 890ddd
		intersection = lineIntersection(A, C, B, D, M);
Toshihiro Shimizu 890ddd
		assert(intersection);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// P1 (punto di fuga)
Toshihiro Shimizu 890ddd
		intersection = lineIntersection(D, C, A, B, P1);
Toshihiro Shimizu 890ddd
		if (!intersection) {
Toshihiro Shimizu 890ddd
			P1.x = 0.5 * (A.x + D.x);
Toshihiro Shimizu 890ddd
			P1.y = 0.5 * (A.y + D.y);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		// H1
Toshihiro Shimizu 890ddd
		intersection = lineIntersection(A, D, P1, M, H1);
Toshihiro Shimizu 890ddd
		assert(intersection);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// H2
Toshihiro Shimizu 890ddd
		intersection = lineIntersection(B, C, P1, M, H2);
Toshihiro Shimizu 890ddd
		assert(intersection);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// P2 (punto di fuga)
Toshihiro Shimizu 890ddd
		intersection = lineIntersection(A, D, B, C, P2);
Toshihiro Shimizu 890ddd
		if (!intersection) {
Toshihiro Shimizu 890ddd
			P2.x = 0.5 * (A.x + B.x);
Toshihiro Shimizu 890ddd
			P2.y = 0.5 * (A.y + B.y);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		// L1
Toshihiro Shimizu 890ddd
		intersection = lineIntersection(A, B, P2, M, L1);
Toshihiro Shimizu 890ddd
		assert(intersection);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// L2
Toshihiro Shimizu 890ddd
		intersection = lineIntersection(D, C, P2, M, L2);
Toshihiro Shimizu 890ddd
		assert(intersection);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPointD texA = (tex00 + tex10) * 0.5;
Toshihiro Shimizu 890ddd
		TPointD texB = (tex10 + tex11) * 0.5;
Toshihiro Shimizu 890ddd
		TPointD texC = (tex11 + tex01) * 0.5;
Toshihiro Shimizu 890ddd
		TPointD texD = (tex01 + tex00) * 0.5;
Toshihiro Shimizu 890ddd
		TPointD texM = (texA + texC) * 0.5;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		details--;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 12c444
		TRectD r1 = TRectD(
Shinya Kitaoka 12c444
			std::min({A.x, L1.x, M.x, H1.x}), std::min({A.y, L1.y, M.y, H1.y}),
Shinya Kitaoka 12c444
			std::max({A.x, L1.x, M.x, H1.x}), std::max({A.y, L1.y, M.y, H1.y}));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 12c444
		TRectD r2 = TRectD(
Shinya Kitaoka 12c444
			std::min({L1.x, B.x, H2.x, M.x}), std::min({L1.y, B.y, H2.y, M.y}),
Shinya Kitaoka 12c444
			std::max({L1.x, B.x, H2.x, M.x}), std::max({L1.y, B.y, H2.y, M.y}));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 12c444
		TRectD r3 = TRectD(
Shinya Kitaoka 12c444
			std::min({M.x, H2.x, C.x, L2.x}), std::min({M.y, H2.y, C.y, L2.y}),
Shinya Kitaoka 12c444
			std::max({M.x, H2.x, C.x, L2.x}), std::max({M.y, H2.y, C.y, L2.y}));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 12c444
		TRectD r4 = TRectD(
Shinya Kitaoka 12c444
			std::min({H1.x, M.x, L2.x, D.x}), std::min({H1.y, M.y, L2.y, D.y}),
Shinya Kitaoka 12c444
			std::max({H1.x, M.x, L2.x, D.x}), std::max({H1.y, M.y, L2.y, D.y}));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (r1.overlaps(clippingRect))
Toshihiro Shimizu 890ddd
			subdivision(A, L1, M, H1, tex00, texA, texM, texD, clippingRect, details);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (r2.overlaps(clippingRect))
Toshihiro Shimizu 890ddd
			subdivision(L1, B, H2, M, texA, tex10, texB, texM, clippingRect, details);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (r3.overlaps(clippingRect))
Toshihiro Shimizu 890ddd
			subdivision(M, H2, C, L2, texM, texB, tex11, texC, clippingRect, details);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (r4.overlaps(clippingRect))
Toshihiro Shimizu 890ddd
			subdivision(H1, M, L2, D, texD, texM, texC, tex01, clippingRect, details);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
// ------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
#define TINY 1.0e-20
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int splitMatrix(double **a, int n, int *index)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i, imax = 0, j, k;
Toshihiro Shimizu 890ddd
	double big, dum, sum, temp;
Toshihiro Shimizu 890ddd
	double *vv, d;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vv = new double[n];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	d = 1.00;
Toshihiro Shimizu 890ddd
	for (i = 0; i < n; i++) {
Toshihiro Shimizu 890ddd
		big = 0.0;
Toshihiro Shimizu 890ddd
		for (j = 0; j < n; j++)
Toshihiro Shimizu 890ddd
			if ((temp = fabs(a[i][j])) > big)
Toshihiro Shimizu 890ddd
				big = temp;
Toshihiro Shimizu 890ddd
		if (big == 0.0) {
Toshihiro Shimizu 890ddd
			/*printf("aho, sta matrice e 'vota!!\n");*/
Toshihiro Shimizu 890ddd
			return 0;
Toshihiro Shimizu 890ddd
			//exit(0);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		vv[i] = 1.0 / big;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	for (j = 0; j < n; j++) {
Toshihiro Shimizu 890ddd
		for (i = 0; i < j; i++) {
Toshihiro Shimizu 890ddd
			sum = a[i][j];
Toshihiro Shimizu 890ddd
			for (k = 0; k < i; k++)
Toshihiro Shimizu 890ddd
				sum -= a[i][k] * a[k][j];
Toshihiro Shimizu 890ddd
			a[i][j] = sum;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		big = 0.0;
Toshihiro Shimizu 890ddd
		for (i = j; i < n; i++) {
Toshihiro Shimizu 890ddd
			sum = a[i][j];
Toshihiro Shimizu 890ddd
			for (k = 0; k < j; k++)
Toshihiro Shimizu 890ddd
				sum -= a[i][k] * a[k][j];
Toshihiro Shimizu 890ddd
			a[i][j] = sum;
Toshihiro Shimizu 890ddd
			if ((dum = vv[i] * fabs(sum)) >= big) {
Toshihiro Shimizu 890ddd
				big = dum;
Toshihiro Shimizu 890ddd
				imax = i;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (j != imax) {
Toshihiro Shimizu 890ddd
			for (k = 0; k < n; k++) {
Toshihiro Shimizu 890ddd
				dum = a[imax][k];
Toshihiro Shimizu 890ddd
				a[imax][k] = a[j][k];
Toshihiro Shimizu 890ddd
				a[j][k] = dum;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			d = -d;
Toshihiro Shimizu 890ddd
			vv[imax] = vv[j];
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		index[j] = imax;
Toshihiro Shimizu 890ddd
		if (fabsf(a[j][j]) <= TINY && (j != n - 1)) {
Toshihiro Shimizu 890ddd
			/*printf("Cazzo, E' singolare %f!\n", a[j][j] );*/
Toshihiro Shimizu 890ddd
			return imax + 1;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (j != n - 1) {
Toshihiro Shimizu 890ddd
			dum = 1.0 / a[j][j];
Toshihiro Shimizu 890ddd
			for (i = j + 1; i < n; i++)
Toshihiro Shimizu 890ddd
				a[i][j] *= dum;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	delete vv;
Toshihiro Shimizu 890ddd
	return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void buildMatrixes(const FourPoints &ss, const FourPoints &dd,
Toshihiro Shimizu 890ddd
				   double **a, double *b)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	TPointD s[4], d[4];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	s[0] = ss.m_p00, s[1] = ss.m_p01, s[2] = ss.m_p10, s[3] = ss.m_p11;
Toshihiro Shimizu 890ddd
	d[0] = dd.m_p00, d[1] = dd.m_p01, d[2] = dd.m_p10, d[3] = dd.m_p11;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < 4; i++) {
Toshihiro Shimizu 890ddd
		a[i][0] = a[i + 4][3] = s[i].x;
Toshihiro Shimizu 890ddd
		a[i][1] = a[i + 4][4] = s[i].y;
Toshihiro Shimizu 890ddd
		a[i][2] = a[i + 4][5] = 1;
Toshihiro Shimizu 890ddd
		a[i][3] = a[i + 4][0] = 0;
Toshihiro Shimizu 890ddd
		a[i][4] = a[i + 4][1] = 0;
Toshihiro Shimizu 890ddd
		a[i][5] = a[i + 4][2] = 0;
Toshihiro Shimizu 890ddd
		a[i][6] = -s[i].x * d[i].x;
Toshihiro Shimizu 890ddd
		a[i + 4][6] = -s[i].x * d[i].y;
Toshihiro Shimizu 890ddd
		a[i][7] = -s[i].y * d[i].x;
Toshihiro Shimizu 890ddd
		a[i + 4][7] = -s[i].y * d[i].y;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		b[i] = d[i].x;
Toshihiro Shimizu 890ddd
		b[i + 4] = d[i].y;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void computeSolutions(double **a, int *index, double *b)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i, ii = 0, ip, j;
Toshihiro Shimizu 890ddd
	double sum;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < 8; i++) {
Toshihiro Shimizu 890ddd
		ip = index[i];
Toshihiro Shimizu 890ddd
		sum = b[ip];
Toshihiro Shimizu 890ddd
		b[ip] = b[i];
Toshihiro Shimizu 890ddd
		if (ii)
Toshihiro Shimizu 890ddd
			for (j = ii - 1; j <= i - 1; j++)
Toshihiro Shimizu 890ddd
				sum -= a[i][j] * b[j];
Toshihiro Shimizu 890ddd
		else if (sum)
Toshihiro Shimizu 890ddd
			ii = i + 1;
Toshihiro Shimizu 890ddd
		b[i] = sum;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	for (i = 7; i >= 0; i--) {
Toshihiro Shimizu 890ddd
		sum = b[i];
Toshihiro Shimizu 890ddd
		for (j = i + 1; j < 8; j++)
Toshihiro Shimizu 890ddd
			sum -= a[i][j] * b[j];
Toshihiro Shimizu 890ddd
		b[i] = sum / a[i][i];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void solveSystems(double **a, double *bx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int index[255], i, count = 0, bad_line;
Toshihiro Shimizu 890ddd
	double **atmp;
Toshihiro Shimizu 890ddd
	int n = 8;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	atmp = new double *[n];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < n; i++) {
Toshihiro Shimizu 890ddd
		atmp[i] = new double[n];
Toshihiro Shimizu 890ddd
		memcpy(atmp[i], a[i], n * sizeof(double));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while ((bad_line = splitMatrix(atmp, n, index)) != 0 && n > 0) {
Toshihiro Shimizu 890ddd
		/*printf("la riga %d fa schifo!\n", bad_line);*/
Toshihiro Shimizu 890ddd
		/*bad_lines[count] = bad_line;*/
Toshihiro Shimizu 890ddd
		for (i = bad_line - 1; i < n - 1; i++)
Toshihiro Shimizu 890ddd
			memcpy(atmp[i], a[i + 1], n * sizeof(a[i + 1]));
Toshihiro Shimizu 890ddd
		n--;
Toshihiro Shimizu 890ddd
		count++;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (count == 0)
Toshihiro Shimizu 890ddd
		computeSolutions(atmp, index, bx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < n; i++)
Toshihiro Shimizu 890ddd
		delete atmp[i];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	delete atmp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void computeTransformation(const FourPoints &s, const FourPoints &d,
Toshihiro Shimizu 890ddd
						   TAffine &aff, TPointD &perspectDen)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double **a, *b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	a = new double *[8];
Toshihiro Shimizu 890ddd
	for (i = 0; i < 8; i++)
Toshihiro Shimizu 890ddd
		a[i] = new double[8];
Toshihiro Shimizu 890ddd
	b = new double[8];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	buildMatrixes(s, d, a, b);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	solveSystems(a, b);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	aff.a11 = b[0];
Toshihiro Shimizu 890ddd
	aff.a12 = b[1];
Toshihiro Shimizu 890ddd
	aff.a13 = b[2];
Toshihiro Shimizu 890ddd
	aff.a21 = b[3];
Toshihiro Shimizu 890ddd
	aff.a22 = b[4];
Toshihiro Shimizu 890ddd
	aff.a23 = b[5];
Toshihiro Shimizu 890ddd
	perspectDen.x = b[6];
Toshihiro Shimizu 890ddd
	perspectDen.y = b[7];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < 8; i++)
Toshihiro Shimizu 890ddd
		delete a[i];
Toshihiro Shimizu 890ddd
	delete b;
Toshihiro Shimizu 890ddd
	delete a;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FourPoints computeTransformed(const FourPoints &pointsFrom, const FourPoints &pointsTo, const FourPoints &from)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TAffine aff;
Toshihiro Shimizu 890ddd
	TPointD perspectiveDen;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	computeTransformation(pointsFrom, pointsTo, aff, perspectiveDen);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double den;
Toshihiro Shimizu 890ddd
	FourPoints fp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	den = perspectiveDen.x * from.m_p00.x + perspectiveDen.y * from.m_p00.y + 1;
Toshihiro Shimizu 890ddd
	assert(den != 0);
Toshihiro Shimizu 890ddd
	fp.m_p00 = (1.0 / den) * (aff * from.m_p00);
Toshihiro Shimizu 890ddd
	den = perspectiveDen.x * from.m_p01.x + perspectiveDen.y * from.m_p01.y + 1;
Toshihiro Shimizu 890ddd
	assert(den != 0);
Toshihiro Shimizu 890ddd
	fp.m_p01 = (1.0 / den) * (aff * from.m_p01);
Toshihiro Shimizu 890ddd
	den = perspectiveDen.x * from.m_p10.x + perspectiveDen.y * from.m_p10.y + 1;
Toshihiro Shimizu 890ddd
	assert(den != 0);
Toshihiro Shimizu 890ddd
	fp.m_p10 = (1.0 / den) * (aff * from.m_p10);
Toshihiro Shimizu 890ddd
	den = perspectiveDen.x * from.m_p11.x + perspectiveDen.y * from.m_p11.y + 1;
Toshihiro Shimizu 890ddd
	assert(den != 0);
Toshihiro Shimizu 890ddd
	fp.m_p11 = (1.0 / den) * (aff * from.m_p11);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return fp;
Toshihiro Shimizu 890ddd
}