Exemple #1
0
// eigen-decomposition of a symmetric matrix
void Matrix::eig(Matrix& U, Matrix& lambda, unsigned int iter, bool ignoreError) const
{
	ASSERT(isValid() && isSquare());
	Matrix basic = *this;
	Matrix eigenval(m_rows);

	// 1-dim case
	if (m_rows == 1) { basic(0, 0) = 1.0; eigenval(0) = m_data[0]; return; }

	std::vector<double> oD(m_rows);
	unsigned int i, j, k, l, m;
	double b, c, f, g, h, hh, p, r, s, scale;

	// reduction to tridiagonal form
	for (i=m_rows; i-- > 1;)
	{
		h = 0.0;
		scale = 0.0;
		if (i > 1) for (k = 0; k < i; k++) scale += fabs(basic(i, k));

		if (scale == 0.0) oD[i] = basic(i, i-1);
		else
		{
			for (k = 0; k < i; k++)
			{
				basic(i, k) /= scale;
				h += basic(i, k) * basic(i, k);
			}

			f = basic(i, i-1);
			g = (f > 0.0) ? -::sqrt(h) : ::sqrt(h);
			oD[i] = scale * g;
			h -= f * g;
			basic(i, i-1) = f - g;
			f = 0.0;

			for (j = 0; j < i; j++)
			{
				basic(j, i) = basic(i, j) / (scale * h);
				g = 0.0;
				for (k=0; k <= j; k++) g += basic(j, k) * basic(i, k);
				for (k=j+1; k < i; k++) g += basic(k, j) * basic(i, k);
				f += (oD[j] = g / h) * basic(i, j);
			}
			hh = f / (2.0 * h);

			for (j=0; j < i; j++)
			{
				f = basic(i, j);
				g = oD[j] - hh * f;
				oD[j] = g;
				for (k=0; k <= j; k++) basic(j, k) -= f * oD[k] + g * basic(i, k);
			}

			for (k=i; k--;) basic(i, k) *= scale;
		}
		eigenval(i) = h;
	}
	eigenval(0) = oD[0] = 0.0;

	// accumulation of transformation matrices
	for (i=0; i < m_rows; i++)
	{
		if (eigenval(i) != 0.0)
		{
			for (j=0; j < i; j++)
			{
				g = 0.0;
				for (k = 0; k < i; k++) g += basic(i, k) * basic(k, j);
				for (k = 0; k < i; k++) basic(k, j) -= g * basic(k, i);
			}
		}
		eigenval(i) = basic(i, i);
		basic(i, i) = 1.0;
		for (j=0; j < i; j++) basic(i, j) = basic(j, i) = 0.0;
	}

	// eigenvalues from tridiagonal form
	for (i=1; i < m_rows; i++) oD[i-1] = oD[i];
	oD[m_rows - 1] = 0.0;

	for (l=0; l < m_rows; l++)
	{
		j = 0;
		do
		{
			// look for small sub-diagonal element
			for (m=l; m < m_rows - 1; m++)
			{
				s = fabs(eigenval(m)) + fabs(eigenval(m + 1));
				if (fabs(oD[m]) + s == s) break;
			}
			p = eigenval(l);

			if (m != l)
			{
				if (j++ == iter)
				{
					// Too many iterations --> numerical instability!
					if (ignoreError) break;
					else throw("[Matrix::eig] numerical problems");
				}

				// form shift
				g = (eigenval(l+1) - p) / (2.0 * oD[l]);
				r = ::sqrt(g * g + 1.0);
				g = eigenval(m) - p + oD[l] / (g + ((g > 0.0) ? fabs(r) : -fabs(r)));
				s = 1.0;
				c = 1.0;
				p = 0.0;

				for (i=m; i-- > l;)
				{
					f = s * oD[i];
					b = c * oD[i];
					if (fabs(f) >= fabs(g))
					{
						c = g / f;
						r = ::sqrt(c * c + 1.0);
						oD[i+1] = f * r;
						s = 1.0 / r;
						c *= s;
					}
					else
					{
						s = f / g;
						r = ::sqrt(s * s + 1.0);
						oD[i+1] = g * r;
						c = 1.0 / r;
						s *= c;
					}

					g = eigenval(i+1) - p;
					r = (eigenval(i) - g) * s + 2.0 * c * b;
					p = s * r;
					eigenval(i+1) = g + p;
					g = c * r - b;

					for (k=0; k < m_rows; k++)
					{
						f = basic(k, i+1);
						basic(k, i+1) = s * basic(k, i) + c * f;
						basic(k, i) = c * basic(k, i) - s * f;
					}
				}

				eigenval(l) -= p;
				oD[l] = g;
				oD[m] = 0.0;
			}
		}
		while (m != l);
	}

	// normalize eigenvectors
	for (j=m_rows; j--;)
	{
		s = 0.0;
		for (i=m_rows; i--;) s += basic(i, j) * basic(i, j);
		s = ::sqrt(s);
		for (i=m_rows; i--;) basic(i, j) /= s;
	}

	// sort by eigenvalues
	std::vector<unsigned int> index(m_rows);
	for (i=0; i<m_rows; i++) index[i] = i;
	CmpIndex cmpidx(eigenval, index);
	std::sort(index.begin(), index.end(), cmpidx);
	U.resize(m_rows, m_rows);
	lambda.resize(m_rows);
	for (i=0; i<m_rows; i++)
	{
		j = index[i];
		lambda(i) = eigenval(j);
		for (k=0; k<m_rows; k++) U(k, i) = basic(k, j);
	}
}
Exemple #2
0
	/*if (0 != Model::nSlidingModel)
	{
		// Just the model we're sliding on, if any
		MyScene.m_Objects.at(Model::nSlidingModel - 1)->Render(2, false);
	}
	else* /
	{
		MyScene.Render(Scene::StaticSceneGeometry);
	}

double tt = 0;
double t0 = glfwGetTime();
	uint8 * pPixels = new uint8[4 * nCustomViewportWidth * nCustomViewportHeight]; glReadPixels(0, 0, nCustomViewportWidth, nCustomViewportHeight, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(pPixels));
	float * pDepths = new float[nCustomViewportWidth * nCustomViewportHeight]; glReadPixels(0, 0, nCustomViewportWidth, nCustomViewportHeight, GL_DEPTH_COMPONENT, GL_FLOAT, reinterpret_cast<void *>(pDepths));
tt += glfwGetTime() - t0;

	// Render the selected model
	MyScene.Render(Scene::SelectedObjectBackFace);

t0 = glfwGetTime();
	uint8 * pSPixels = new uint8[4 * nCustomViewportWidth * nCustomViewportHeight]; glReadPixels(0, 0, nCustomViewportWidth, nCustomViewportHeight, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(pSPixels));
	float * pSDepths = new float[nCustomViewportWidth * nCustomViewportHeight]; glReadPixels(0, 0, nCustomViewportWidth, nCustomViewportHeight, GL_DEPTH_COMPONENT, GL_FLOAT, reinterpret_cast<void *>(pSDepths));
tt += glfwGetTime() - t0;
//printf("SnapBackPersp() read pixels in %f secs.\n", tt);

	GLfloat winX, winY;
	GLdouble posX, posY, posZ;
	GLdouble modelMatrix[16]; glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
	GLdouble projMatrix[16]; glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
	GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport);

	float fMinPositiveDistanceSqr = -1;		// Positive distance means away from the camera (i.e. to snap back to background); valid range is (0, +oo)
	Wm5::Vector3d oMoveBackVector(Wm5::Vector3d::ZERO);

	//Model::nSlidingModel = 0;
	uint16 SlidingModel = 0;
	uint16 SlidingTriangle = 0;
	uint16 SelectedTriangle = 0;
	uint32 ClosestPixel = 0;

t0 = glfwGetTime();
	for (uint32 nPixel = 0; nPixel < nCustomViewportWidth * nCustomViewportHeight; ++nPixel)
	{
		uint8 r = pPixels[4 * nPixel + 0];
		uint8 g = pPixels[4 * nPixel + 1];
		uint8 b = pPixels[4 * nPixel + 2];
		uint8 a = pPixels[4 * nPixel + 3];
		float d = pDepths[nPixel];

		uint8 sr = pSPixels[4 * nPixel + 0];
		uint8 sg = pSPixels[4 * nPixel + 1];
		uint8 sb = pSPixels[4 * nPixel + 2];
		uint8 sa = pSPixels[4 * nPixel + 3];
		float sd = pSDepths[nPixel];

		if ((sr+sg) != 0 && (r+g) != 0)
		{
			winX = (GLfloat)(nPixel % nCustomViewportWidth);
			winY = (GLfloat)(nPixel / nCustomViewportWidth);
			gluUnProject(winX, winY, d, modelMatrix, projMatrix, viewport, &posX, &posY, &posZ);
			Wm5::Vector3d oD(posX, posY, posZ);
			gluUnProject(winX, winY, sd, modelMatrix, projMatrix, viewport, &posX, &posY, &posZ);
			Wm5::Vector3d oSD(posX, posY, posZ);
			//printf ("World coords at z= %f (Depth) are (%f, %f, %f)\n", winZ, posX, posY, posZ);

			double dDepthDiffSqr = Wm5::Mathd::Sign(d - sd) * (oD - oSD).SquaredLength();

			if (dDepthDiffSqr >= 0.0 && (dDepthDiffSqr < fMinPositiveDistanceSqr || fMinPositiveDistanceSqr == -1))
			{
				fMinPositiveDistanceSqr = static_cast<float>(dDepthDiffSqr);
				oMoveBackVector = (oD - oSD);

				//Model::nSlidingModel = r;
				//Model::nSlidingTriangle = static_cast<uint32>(g) << 8 | b;
				SlidingModel = static_cast<uint16>(g) << 8 | r;
				SlidingTriangle = static_cast<uint16>(a) << 8 | b;
				SelectedTriangle = static_cast<uint16>(sa) << 8 | sb;
				ClosestPixel = nPixel;
			}
		}
	}
//printf("SnapBackPersp() processed pixels in %f secs.\n", glfwGetTime() - t0);
	delete[] pPixels;
	delete[] pDepths;
	delete[] pSPixels;
	delete[] pSDepths;
//printf("SlidingModel = %d\n SlidingTriangle = %d\n SelectedTriangle = %d\n ClosestPixel = %d\n", SlidingModel, SlidingTriangle, SelectedTriangle, ClosestPixel);

	// Geometry distance correction
	if (fMinPositiveDistanceSqr != -1)
	{
		winX = (GLfloat)(ClosestPixel % nCustomViewportWidth);
		winY = (GLfloat)(ClosestPixel / nCustomViewportWidth);
		gluUnProject(winX, winY, 0, modelMatrix, projMatrix, viewport, &posX, &posY, &posZ);
		Wm5::Vector3d oNearPoint(posX, posY, posZ);
		gluUnProject(winX, winY, 1, modelMatrix, projMatrix, viewport, &posX, &posY, &posZ);
		Wm5::Vector3d oFarPoint(posX, posY, posZ);
		Wm5::Vector3d Direction = oFarPoint - oNearPoint;
		Direction.Normalize();

		Wm5::Line3d Line(oNearPoint, Direction);

		float * pSlidingVertexData = &MyScene.m_Objects.at(SlidingModel - 1)->m_pVertexData[3 * 3 * SlidingTriangle];
		Wm5::Plane3d SlidingPlane(Wm5::Vector3d(pSlidingVertexData[0], pSlidingVertexData[1], pSlidingVertexData[2]) + MyScene.m_Objects.at(SlidingModel - 1)->GetPosition(),
								  Wm5::Vector3d(pSlidingVertexData[3], pSlidingVertexData[4], pSlidingVertexData[5]) + MyScene.m_Objects.at(SlidingModel - 1)->GetPosition(),
								  Wm5::Vector3d(pSlidingVertexData[6], pSlidingVertexData[7], pSlidingVertexData[8]) + MyScene.m_Objects.at(SlidingModel - 1)->GetPosition());

		float * pSelectedVertexData = &MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->m_pVertexData[3 * 3 * SelectedTriangle];
		Wm5::Plane3d SelectedPlane(Wm5::Vector3d(pSelectedVertexData[0], pSelectedVertexData[1], pSelectedVertexData[2]) + MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->GetPosition(),
								   Wm5::Vector3d(pSelectedVertexData[3], pSelectedVertexData[4], pSelectedVertexData[5]) + MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->GetPosition(),
								   Wm5::Vector3d(pSelectedVertexData[6], pSelectedVertexData[7], pSelectedVertexData[8]) + MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->GetPosition());

		Wm5::Vector3d SlidingIntersection, SelectedIntersection;
		{
			Wm5::IntrLine3Plane3d Intersection(Line, SlidingPlane);
			if (Intersection.Find())
				SlidingIntersection = Intersection.GetLine().Origin + Intersection.GetLine().Direction * Intersection.GetLineParameter();
			else
				printf("Error: No sliding intersection!\n");
		}
		{
			Wm5::IntrLine3Plane3d Intersection(Line, SelectedPlane);
			if (Intersection.Find())
				SelectedIntersection = Intersection.GetLine().Origin + Intersection.GetLine().Direction * Intersection.GetLineParameter();
			else
				printf("Error: No selected intersection!\n");
		}

		oMoveBackVector = SlidingIntersection - SelectedIntersection;
		oMoveBackVector += ZoomSelectedModel(-0.001, oMoveBackVector);
	}

	if (fMinPositiveDistanceSqr != -1)
		//MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->MoveBy(oMoveBackVector + ZoomSelectedModel(-0.01, oMoveBackVector));
		MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->MoveBy(oMoveBackVector);

	glViewport(0, 0, nViewportWidth, nViewportHeight);

	glPopMatrix();
}*/
void ClassicMode::SnapPersp(SnapDirection SnapDirection)
{
	glPushMatrix();

	// Set a smaller viewport with same aspect ratio
	uint32 nCustomViewportWidth = std::min<uint32>(400, nViewportWidth);
	//uint32 nCustomViewportWidth = std::min<uint32>(nViewportWidth, nViewportWidth);
	uint32 nCustomViewportHeight = nCustomViewportWidth * nViewportHeight / nViewportWidth;
	glViewport(0, 0, nCustomViewportWidth, nCustomViewportHeight);

	if (Front == SnapDirection)
	{
		// Render only the colliding static scene
		MyScene.Render(Scene::StaticCollidingSceneGeometry);
		//MyScene.Render(Scene::StaticSceneGeometry);
	}
	else if (Back == SnapDirection)
	{
		// Render the static scene
		/*if (0 != Model::nSlidingModel)
		{
			// Just the model we're sliding on, if any
			MyScene.m_Objects.at(Model::nSlidingModel - 1)->Render(2, false);
		}
		else
		{
			MyScene.Render(Scene::StaticSceneGeometry);
		}*/
		MyScene.Render(Scene::StaticSceneGeometry);
	}

double tt = 0;
double t0 = glfwGetTime();
	uint8 * pPixels = new uint8[4 * nCustomViewportWidth * nCustomViewportHeight]; glReadPixels(0, 0, nCustomViewportWidth, nCustomViewportHeight, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(pPixels));
	float * pDepths = new float[nCustomViewportWidth * nCustomViewportHeight]; glReadPixels(0, 0, nCustomViewportWidth, nCustomViewportHeight, GL_DEPTH_COMPONENT, GL_FLOAT, reinterpret_cast<void *>(pDepths));
tt += glfwGetTime() - t0;

	// Render the selected model
	MyScene.Render(Scene::SelectedObjectBackFace);

t0 = glfwGetTime();
	uint8 * pSPixels = new uint8[4 * nCustomViewportWidth * nCustomViewportHeight]; glReadPixels(0, 0, nCustomViewportWidth, nCustomViewportHeight, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(pSPixels));
	float * pSDepths = new float[nCustomViewportWidth * nCustomViewportHeight]; glReadPixels(0, 0, nCustomViewportWidth, nCustomViewportHeight, GL_DEPTH_COMPONENT, GL_FLOAT, reinterpret_cast<void *>(pSDepths));
tt += glfwGetTime() - t0;
//printf("SnapPersp() read pixels in %f secs.\n", tt);

	GLfloat winX, winY;
	GLdouble posX, posY, posZ;
	GLdouble modelMatrix[16]; glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
	GLdouble projMatrix[16]; glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
	GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport);

	double dMinBackDistanceSqr = 0;
	float fMinPositiveDistanceSqr = -1;		// Positive distance means away from the camera (i.e. to snap back to background); valid range is (0, +oo)
	Wm5::Vector3d oMoveVector(Wm5::Vector3d::ZERO);

	//Model::nSlidingModel = 0;
	uint16 SlidingModel = 0;
	uint16 SlidingTriangle = 0;
	uint16 SelectedTriangle = 0;
	uint32 ClosestPixel = 0;

	bool IsObjectVisible = false;

t0 = glfwGetTime();
	for (uint32 nPixel = 0; nPixel < nCustomViewportWidth * nCustomViewportHeight; ++nPixel)
	{
		uint8 r = pPixels[4 * nPixel + 0];
		uint8 g = pPixels[4 * nPixel + 1];
		uint8 b = pPixels[4 * nPixel + 2];
		uint8 a = pPixels[4 * nPixel + 3];
		float d = pDepths[nPixel];

		uint8 sr = pSPixels[4 * nPixel + 0];
		uint8 sg = pSPixels[4 * nPixel + 1];
		uint8 sb = pSPixels[4 * nPixel + 2];
		uint8 sa = pSPixels[4 * nPixel + 3];
		float sd = pSDepths[nPixel];

		if ((sr+sg) != 0 && (r+g) != 0)
		{
			winX = (GLfloat)(nPixel % nCustomViewportWidth);
			winY = (GLfloat)(nPixel / nCustomViewportWidth);
			gluUnProject(winX, winY, d, modelMatrix, projMatrix, viewport, &posX, &posY, &posZ);
			Wm5::Vector3d oD(posX, posY, posZ);
			gluUnProject(winX, winY, sd, modelMatrix, projMatrix, viewport, &posX, &posY, &posZ);
			Wm5::Vector3d oSD(posX, posY, posZ);
			//printf ("World coords at z= %f (Depth) are (%f, %f, %f)\n", winZ, posX, posY, posZ);

			double dDepthDiffSqr = Wm5::Mathd::Sign(d - sd) * (oD - oSD).SquaredLength();

			if (Front == SnapDirection)
			{
				if (dDepthDiffSqr < dMinBackDistanceSqr)
				{
					dMinBackDistanceSqr = dDepthDiffSqr;
					oMoveVector = (oD - oSD);

					//Model::nSlidingModel = r;
					//Model::nSlidingTriangle = static_cast<uint32>(g) << 8 | b;
					SlidingModel = static_cast<uint16>(g) << 8 | r;
					SlidingTriangle = static_cast<uint16>(a) << 8 | b;
					SelectedTriangle = static_cast<uint16>(sa) << 8 | sb;
					ClosestPixel = nPixel;
				}
			}
			else if (Back == SnapDirection)
			{
				if (dDepthDiffSqr >= 0.0 && (dDepthDiffSqr < fMinPositiveDistanceSqr || fMinPositiveDistanceSqr == -1))
				{
					fMinPositiveDistanceSqr = static_cast<float>(dDepthDiffSqr);
					oMoveVector = (oD - oSD);

					//Model::nSlidingModel = r;
					//Model::nSlidingTriangle = static_cast<uint32>(g) << 8 | b;
					SlidingModel = static_cast<uint16>(g) << 8 | r;
					SlidingTriangle = static_cast<uint16>(a) << 8 | b;
					SelectedTriangle = static_cast<uint16>(sa) << 8 | sb;
					ClosestPixel = nPixel;
				}
			}

			if (!IsObjectVisible && dDepthDiffSqr >= 0) IsObjectVisible = true;
		}
		else if (!IsObjectVisible && (sr+sg) != 0 && (r+g) == 0)
		{
			IsObjectVisible = true;
		}
	}

	// TODO: Get rid of code duplication and double calculation
	// If object isn't visible, do a Front snap
	if (Back == SnapDirection && !IsObjectVisible)
	{
		SnapDirection = Front;

		for (uint32 nPixel = 0; nPixel < nCustomViewportWidth * nCustomViewportHeight; ++nPixel)
		{
			uint8 r = pPixels[4 * nPixel + 0];
			uint8 g = pPixels[4 * nPixel + 1];
			uint8 b = pPixels[4 * nPixel + 2];
			uint8 a = pPixels[4 * nPixel + 3];
			float d = pDepths[nPixel];

			uint8 sr = pSPixels[4 * nPixel + 0];
			uint8 sg = pSPixels[4 * nPixel + 1];
			uint8 sb = pSPixels[4 * nPixel + 2];
			uint8 sa = pSPixels[4 * nPixel + 3];
			float sd = pSDepths[nPixel];

			if ((sr+sg) != 0 && (r+g) != 0)
			{
				winX = (GLfloat)(nPixel % nCustomViewportWidth);
				winY = (GLfloat)(nPixel / nCustomViewportWidth);
				gluUnProject(winX, winY, d, modelMatrix, projMatrix, viewport, &posX, &posY, &posZ);
				Wm5::Vector3d oD(posX, posY, posZ);
				gluUnProject(winX, winY, sd, modelMatrix, projMatrix, viewport, &posX, &posY, &posZ);
				Wm5::Vector3d oSD(posX, posY, posZ);
				//printf ("World coords at z= %f (Depth) are (%f, %f, %f)\n", winZ, posX, posY, posZ);

				double dDepthDiffSqr = Wm5::Mathd::Sign(d - sd) * (oD - oSD).SquaredLength();

				if (dDepthDiffSqr < dMinBackDistanceSqr)
				{
					dMinBackDistanceSqr = dDepthDiffSqr;
					oMoveVector = (oD - oSD);

					//Model::nSlidingModel = r;
					//Model::nSlidingTriangle = static_cast<uint32>(g) << 8 | b;
					SlidingModel = static_cast<uint16>(g) << 8 | r;
					SlidingTriangle = static_cast<uint16>(a) << 8 | b;
					SelectedTriangle = static_cast<uint16>(sa) << 8 | sb;
					ClosestPixel = nPixel;
				}
			}
		}
	}
//printf("SnapPersp() processed pixels in %f secs.\n", glfwGetTime() - t0);
	delete[] pPixels;
	delete[] pDepths;
	delete[] pSPixels;
	delete[] pSDepths;
//printf("SlidingModel = %d\n SlidingTriangle = %d\n SelectedTriangle = %d\n ClosestPixel = %d\n", SlidingModel, SlidingTriangle, SelectedTriangle, ClosestPixel);

	// Geometry distance correction
	if (dMinBackDistanceSqr != 0 || fMinPositiveDistanceSqr != -1)
	{
		winX = (GLfloat)(ClosestPixel % nCustomViewportWidth);
		winY = (GLfloat)(ClosestPixel / nCustomViewportWidth);
		gluUnProject(winX, winY, 0, modelMatrix, projMatrix, viewport, &posX, &posY, &posZ);
		Wm5::Vector3d oNearPoint(posX, posY, posZ);
		gluUnProject(winX, winY, 1, modelMatrix, projMatrix, viewport, &posX, &posY, &posZ);
		Wm5::Vector3d oFarPoint(posX, posY, posZ);
		Wm5::Vector3d Direction = oFarPoint - oNearPoint;
		Direction.Normalize();

		Wm5::Line3d Line(oNearPoint, Direction);

		/*float * pSlidingVertexData = &MyScene.m_Objects.at(SlidingModel - 1)->m_pVertexData[3 * 3 * SlidingTriangle];
		Wm5::Plane3d SlidingPlane(Wm5::Vector3d(pSlidingVertexData[0], pSlidingVertexData[1], pSlidingVertexData[2]) + MyScene.m_Objects.at(SlidingModel - 1)->GetPosition(),
								  Wm5::Vector3d(pSlidingVertexData[3], pSlidingVertexData[4], pSlidingVertexData[5]) + MyScene.m_Objects.at(SlidingModel - 1)->GetPosition(),
								  Wm5::Vector3d(pSlidingVertexData[6], pSlidingVertexData[7], pSlidingVertexData[8]) + MyScene.m_Objects.at(SlidingModel - 1)->GetPosition());

		float * pSelectedVertexData = &MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->m_pVertexData[3 * 3 * SelectedTriangle];
		Wm5::Plane3d SelectedPlane(Wm5::Vector3d(pSelectedVertexData[0], pSelectedVertexData[1], pSelectedVertexData[2]) + MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->GetPosition(),
								   Wm5::Vector3d(pSelectedVertexData[3], pSelectedVertexData[4], pSelectedVertexData[5]) + MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->GetPosition(),
								   Wm5::Vector3d(pSelectedVertexData[6], pSelectedVertexData[7], pSelectedVertexData[8]) + MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->GetPosition());*/
		Wm5::Triangle3d SlidingTriangle3 = MyScene.GetObject(SlidingModel).GetTriangle(SlidingTriangle);
		Wm5::Plane3d SlidingPlane(SlidingTriangle3.V[0], SlidingTriangle3.V[1], SlidingTriangle3.V[2]);
		Wm5::Triangle3d SelectedTriangle3 = MyScene.GetSelectedObject().GetTriangle(SelectedTriangle);
		Wm5::Plane3d SelectedPlane(SelectedTriangle3.V[0], SelectedTriangle3.V[1], SelectedTriangle3.V[2]);

		Wm5::Vector3d SlidingIntersection, SelectedIntersection;
		{
			Wm5::IntrLine3Plane3d Intersection(Line, SlidingPlane);
			if (Intersection.Find())
				SlidingIntersection = Intersection.GetLine().Origin + Intersection.GetLine().Direction * Intersection.GetLineParameter();
			else
				printf("Error: No sliding intersection!\n");
		}
		{
			Wm5::IntrLine3Plane3d Intersection(Line, SelectedPlane);
			if (Intersection.Find())
				SelectedIntersection = Intersection.GetLine().Origin + Intersection.GetLine().Direction * Intersection.GetLineParameter();
			else
				printf("Error: No selected intersection!\n");
		}

		oMoveVector = SlidingIntersection - SelectedIntersection;
		oMoveVector += ZoomSelectedModel(-0.001, oMoveVector);
	}

	MyScene.m_Objects.at(MyScene.GetSelectedObjectId() - 1)->MoveBy(oMoveVector);

	glViewport(0, 0, nViewportWidth, nViewportHeight);

	glPopMatrix();
}