void Mandelbulbulb4Iteration(CVector3 &z, const cFractal *fractal, sMandelbulbAux &aux)
{
	double rp = pow(aux.r, fractal->bulb.power - 1);

	double angZ = atan2(z.y, z.x) + fractal->bulb.alphaAngleOffset;
	double angY = atan2(z.z, z.x) + fractal->bulb.betaAngleOffset;
	double angX = atan2(z.z, z.y) + fractal->bulb.gammaAngleOffset;

	CRotationMatrix rotM;
	rotM.RotateX(angX * (fractal->bulb.power - 1));
	rotM.RotateY(angY * (fractal->bulb.power - 1));
	rotM.RotateZ(angZ * (fractal->bulb.power - 1));

	z = rotM.RotateVector(z) * rp;
}
CVector3 RenderedImage::CalcPointPersp(const CVector3 &point, const CRotationMatrix &rot, double persp)
{
	CVector3 vect;
	CVector3 out;
	vect = rot.RotateVector(point);
	out.x = vect.x / (1.0 + vect.y * persp);
	out.y = -vect.z / (1.0 + vect.y * persp);
	return out;
}
void RenderedImage::DrawHud(CVector3 rotation)
{
	CRotationMatrix mRotInv;
	mRotInv.RotateY(-rotation.z);
	mRotInv.RotateX(-rotation.y);
	mRotInv.RotateZ(-rotation.x);
	double width = image->GetPreviewWidth();
	double height = image->GetPreviewHeight();
	CVector3 center = CVector3(width * 0.5, height * 0.5, 0.0);

	const int steps = 100;
	const double persp = 0.4;
	CVector3 circlePoint1[steps];
	CVector3 circlePoint2[steps];
	CVector3 circlePoint3[steps];

	for(int i = 0; i<steps; i++)
	{
		double angle = i * 2.0 * M_PI / steps;

		circlePoint1[i].x = cos(angle);
		circlePoint1[i].y = sin(angle);
		circlePoint1[i].z = 0.0;
		circlePoint2[i].x = 0;
		circlePoint2[i].y = sin(angle);
		circlePoint2[i].z = cos(angle);
		circlePoint3[i].x = cos(angle);
		circlePoint3[i].y = 0.0;
		circlePoint3[i].z = sin(angle);
	}
	for(int i = 0; i<steps; i++)
	{
		CVector3 point1, point2;
		int index1 = i;
		int index2 = (i + 1) % steps;
		point1 = CalcPointPersp(circlePoint1[index1], mRotInv, persp) * (height * 0.2) + center;
		point2 = CalcPointPersp(circlePoint1[index2], mRotInv, persp) * (height * 0.2) + center;
		image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (255, 0, 0), 0.5, 1);

		point1 = CalcPointPersp(circlePoint2[index1], mRotInv, persp) * (height * 0.2) + center;
		point2 = CalcPointPersp(circlePoint2[index2], mRotInv, persp) * (height * 0.2) + center;
		image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 255, 0), 0.5, 1);

		point1 = CalcPointPersp(circlePoint3[index1], mRotInv, persp) * (height * 0.2) + center;
		point2 = CalcPointPersp(circlePoint3[index2], mRotInv, persp) * (height * 0.2) + center;
		image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 100, 255), 0.5, 1);
	}

	CVector3 point1, point2;
	point1 = CalcPointPersp(CVector3(1.0, 0.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(-1.0, 0.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (255, 0, 0), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.0, 1.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, -1.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (255, 0, 0), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.9, -0.05, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(1.0, 0.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (255, 0, 0), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.9, 0.05, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(1.0, 0.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (255, 0, 0), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.9, 0.0, 0.05), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(1.0, 0.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (255, 0, 0), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.9, 0.0, -0.05), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(1.0, 0.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (255, 0, 0), 0.5, 1);

	point1 = CalcPointPersp(CVector3(0.0, 0.0, 1.0), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, 0.0, -1.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 255, 0), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.0, 1.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, -1.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 255, 0), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.05, 0.9, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, 1.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 255, 0), 0.5, 1);
	point1 = CalcPointPersp(CVector3(-0.05, 0.9, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, 1.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 255, 0), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.0, 0.9, 0.05), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, 1.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 255, 0), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.0, 0.9, -0.05), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, 1.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 255, 0), 0.5, 1);

	point1 = CalcPointPersp(CVector3(1.0, 0.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(-1.0, 0.0, 0.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 150, 255), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.0, 0.0, 1.0), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, 0.0, 1.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 150, 255), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.05, 0.0, 0.9), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, 0.0, 1.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 150, 255), 0.5, 1);
	point1 = CalcPointPersp(CVector3(-0.05, 0.0, 0.9), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, 0.0, 1.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 150, 255), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.0, 0.05, 0.9), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, 0.0, 1.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 150, 255), 0.5, 1);
	point1 = CalcPointPersp(CVector3(0.0, -0.05, 0.9), mRotInv, persp)  * (height * 0.2) + center;
	point2 = CalcPointPersp(CVector3(0.0, 0.0, 1.0), mRotInv, persp)  * (height * 0.2) + center;
	image->AntiAliasedLine(point1.x, point1.y, point2.x, point2.y, -1.0, -1.0, sRGB8 (0, 150, 255), 0.5, 1);
}
void RenderedImage::Display3DCursor(CVector2<int> screenPoint, double z)
{
	enumClickMode clickMode = (enumClickMode)clickModeData.at(0).toInt();
	if (clickMode == clickPlaceLight)
	{
		z -= frontDist;
	}

	smoothLastZMouse = smoothLastZMouse + (z - smoothLastZMouse) * 0.01;

	if (z > 0 && clickMode != clickFlightSpeedControl)
	{
		if(smoothLastZMouse < 0.0) smoothLastZMouse = 0.0;

		bool legacyCoordinateSystem = gPar->Get<bool>("legacy_coordinate_system");
		double reverse = legacyCoordinateSystem ? -1.0 : 1.0;

		//preparing rotation matrix
		CVector3 rotation = params->Get<CVector3>("camera_rotation") / 180.0 * M_PI;
		CRotationMatrix mRot;
		mRot.RotateZ(rotation.x);
		mRot.RotateX(rotation.y);
		mRot.RotateY(rotation.z);

		double fov = params->Get<double>("fov");

		double sw = image->GetPreviewWidth();
		double sh = image->GetPreviewHeight();

		double aspectRatio = sw / sh;

		CVector2<double> p;
		p.x = (screenPoint.x / sw - 0.5) * aspectRatio;
		p.y = (screenPoint.y / sh - 0.5);

		double scale = smoothLastZMouse / z;

		double boxWidth = 10.0 / sw * scale;
		double boxHeight = 10.0 / sw * scale;
		double boxDepth = 10.0 / sw * scale;

		double boxDepth2 = boxHeight * z * fov;

		double n = 3.0;

		for (int iz = -n; iz <= n; iz++)
		{
			double yy1 = ((p.y + n * boxHeight) / (1.0 - boxDepth * iz * fov) + 0.5) * sh;
			double yy2 = ((p.y - n * boxHeight) / (1.0 - boxDepth * iz * fov) + 0.5) * sh;
			for (int ix = -n; ix <= n; ix++)
			{
				double xx1 = ((p.x + boxWidth * ix) / (1.0 - boxDepth * iz * fov) / aspectRatio + 0.5) * sw;
				unsigned char R = 128 + iz * 40;
				unsigned char G = 128 - iz * 40;
				unsigned char B = 0;
				double opacity = 0.8;
				if (iz == 0 && ix == 0)
				{
					R = G = B = 255;
					opacity = 1.0;
				}
				image->AntiAliasedLine(xx1, yy1, xx1, yy2, z - iz * boxDepth2, z - iz * boxDepth2, sRGB8(R, G, B), opacity, 1);
			}

			double xx1 = ((p.x + n * boxWidth) / (1.0 - boxDepth * iz * fov) / aspectRatio + 0.5) * sw;
			double xx2 = ((p.x - n * boxWidth) / (1.0 - boxDepth * iz * fov) / aspectRatio + 0.5) * sw;
			for (int iy = -n; iy <= n; iy++)
			{
				double yy1 = ((p.y + boxWidth * iy) / (1.0 - boxDepth * iz * fov) + 0.5) * sh;
				unsigned char R = 128 + iz * 40;
				unsigned char G = 128 - iz * 40;
				unsigned char B = 0;
				double opacity = 0.8;

				if (iz == 0 && iy == 0)
				{
					R = G = B = 255;
					opacity = 1.0;
				}

				image->AntiAliasedLine(xx1, yy1, xx2, yy1, z - iz * boxDepth2, z - iz * boxDepth2, sRGB8(R, G, B), opacity, 1);
			}

			if (iz < n)
			{
				for (int ix = -n; ix <= n; ix++)
				{
					for (int iy = -n; iy <= n; iy++)
					{
						double xx1 = ((p.x + boxWidth * ix) / (1.0 - boxDepth * iz * fov) / aspectRatio + 0.5) * sw;
						double yy1 = ((p.y + boxWidth * iy) / (1.0 - boxDepth * iz * fov) + 0.5) * sh;
						double xx2 = ((p.x + boxWidth * ix) / (1.0 - boxDepth * (iz + 1) * fov) / aspectRatio + 0.5) * sw;
						double yy2 = ((p.y + boxWidth * iy) / (1.0 - boxDepth * (iz + 1) * fov) + 0.5) * sh;

						double opacity = 0.8;
						unsigned char R = 128 + iz * 40;
						unsigned char G = 128 - iz * 40;
						unsigned char B = 0;

						if (ix == 0 && iy == 0)
						{
							R = G = B = 255;
							opacity = 1.0;
						}

						image->AntiAliasedLine(xx1, yy1, xx2, yy2, z - iz * boxDepth2, z - (iz + 1) * boxDepth2, sRGB8(R, G, B), opacity, 1);
					}
				}
			}
			if (iz == 0)
			{
				image->AntiAliasedLine(screenPoint.x - sw * 0.3, screenPoint.y, screenPoint.x + sw * 0.3, screenPoint.y, z, z, sRGB8(255, 255, 255), 1.0, 1);
				image->AntiAliasedLine(screenPoint.x, screenPoint.y - sh * 0.3, screenPoint.x, screenPoint.y + sh * 0.3, z, z, sRGB8(255, 255, 255), 1.0, 1);

				if (clickMode == clickPlaceLight)
				{
					double r = 1.5 * (boxWidth * n / aspectRatio);
					if (r > 1.0) r = 1.0;
					image->CircleBorder(screenPoint.x, screenPoint.y, z, r * sw, sRGB8(0, 100, 255), r * 0.1 * sw, 1.0, 1);
				}

			}
		}

		p.y *= -1.0 * reverse;
		params::enumPerspectiveType perspType = (params::enumPerspectiveType) params->Get<int>("perspective_type");
		CVector3 camera = params->Get<CVector3>("camera");
		CVector3 viewVector = CalculateViewVector(p, fov, perspType, mRot);
		CVector3 point = camera + viewVector * z;
		lastCoordinates = point;
	}
	else if(clickMode == clickFlightSpeedControl)
	{
		DrawHud(flightData.rotation);

		//draw small cross
		image->AntiAliasedLine(screenPoint.x - 20, screenPoint.y - 20, screenPoint.x + 20, screenPoint.y + 20, -1, -1, sRGB8(255,255,255), 0.3, 1);
		image->AntiAliasedLine(screenPoint.x + 20, screenPoint.y - 20, screenPoint.x - 20, screenPoint.y + 20, -1, -1, sRGB8(255,255,255), 0.3, 1);
	}
	lastDepth = z;
}