Exemple #1
0
			public void SetLighting(LightSettings lightSettings, CameraBase camera)
			{
				Matrix4x3 cameraM = Matrix4x3.Identity;
				if (lightSettings.IsAnyLightAffixedToCamera)
				{
					// if a light is affixed to the camera, its position is considered to be in camera coordinates
					// but here we need the light in world coordinates
					// cameraM transforms from camera coordinates to world coordinates
					cameraM = camera.InverseLookAtRHMatrix;
				}

				// first ambient light
				var al = lightSettings.AmbientLight;
				SetAmbientLight(al.ColorBelow.Color, al.ColorAbove.Color, al.LightAmplitude, al.IsAffixedToCamera ? cameraM.Transform(al.DirectionBelowToAbove) : al.DirectionBelowToAbove);

				for (int idx = 0; idx < 4; ++idx)
				{
					var l = lightSettings.GetDiscreteLight(idx);
					if (null == l)
					{
						ClearSingleLight(idx);
					}
					else if (l is DirectionalLight)
					{
						var dl = (DirectionalLight)l;
						SetDirectionalLight(
							idx,
							dl.Color.Color,
							dl.LightAmplitude,
							dl.IsAffixedToCamera ? cameraM.Transform(dl.DirectionToLight) : dl.DirectionToLight
							);
					}
					else if (l is PointLight)
					{
						var pl = (PointLight)l;
						SetPointLight(
							idx,
							pl.Color.Color,
							pl.LightAmplitude,
							pl.IsAffixedToCamera ? cameraM.Transform(pl.Position) : pl.Position,
							pl.Range
							);
					}
					else if (l is SpotLight)
					{
						var sl = (SpotLight)l;

						// calculation of SpotCosInnerConeRcp: it is in reality not 1/CosInnerConeAngle, but it is  1/(Cos(InnerConeAngle) - Cos(OuterConeAngle))
						double diffCos = Math.Cos(sl.InnerConeAngle) - Math.Cos(sl.OuterConeAngle);
						double SpotCosInnerConeRcp = diffCos >= 1E-18 ? 1 / diffCos : 1E18;

						SetSpotLight(
							idx,
							sl.Color.Color,
							sl.LightAmplitude,
							sl.IsAffixedToCamera ? cameraM.Transform(sl.Position) : sl.Position,
							sl.IsAffixedToCamera ? cameraM.Transform(sl.DirectionToLight) : sl.DirectionToLight,
							sl.Range,
							Math.Cos(sl.OuterConeAngle),
							SpotCosInnerConeRcp
							);
					}
					else
					{
						throw new NotImplementedException(string.Format("The type of lighting ({0}) is not implemented here."));
					}
				}

				AssembleLights();
			}
Exemple #2
0
		public void SetCamera(CameraBase camera)
		{
			if (null == camera)
				throw new ArgumentNullException(nameof(camera));

			_camera = camera;
		}
		/// <summary>
		/// Handles the mouse up event onto the graph in the controller class.
		/// </summary>
		/// <param name="position">Mouse position. X and Y components are the current relative mouse coordinates, the Z component is the screen's aspect ratio.</param>
		/// <param name="e">MouseEventArgs.</param>
		public virtual void EhView_GraphPanelMouseUp(PointD3D position, MouseButtonEventArgs e)
		{
			_mouseState.OnMouseUp(position, e);

			if (e.ChangedButton == MouseButton.Middle && e.MiddleButton == MouseButtonState.Released)
			{
				_middleButtonPressed_InitialCamera = null;
			}
		}
		/// <summary>
		/// Handles the mouse move event onto the graph in the controller class.
		/// </summary>
		/// <param name="position">Mouse position.</param>
		/// <param name="e">MouseEventArgs.</param>
		public virtual void EhView_GraphPanelMouseMove(PointD3D position, MouseEventArgs e)
		{
			_mouseState.OnMouseMove(position, e);

			if (e.MiddleButton == MouseButtonState.Released)
			{
				_middleButtonPressed_InitialCamera = null;
			}
			else if (null != _middleButtonPressed_InitialCamera)
			{
				switch (_middleButtonCurrentAction)
				{
					case MiddelButtonAction.RotateCamera:
						{
							double dx = position.X - _middleButtonPressed_InitialPosition.X;
							double dy = position.Y - _middleButtonPressed_InitialPosition.Y;
							//Doc.Camera = CameraRotateDegrees(_middleButtonPressed_InitialCamera, dx * 540, -dy * 540);
							Doc.Camera = ModelRotateDegrees(_middleButtonPressed_InitialCamera, _doc.RootLayer.Size, dx * 540, -dy * 540);
						}
						break;

					case MiddelButtonAction.MoveCamera:
						{
							double dx = position.X - _middleButtonPressed_InitialPosition.X;
							double dy = position.Y - _middleButtonPressed_InitialPosition.Y;
							Doc.Camera = CameraMoveRelative(_middleButtonPressed_InitialCamera, dx, dy);
						}
						break;

					case MiddelButtonAction.ZoomCamera:
						{
							double dy = position.Y - _middleButtonPressed_InitialPosition.Y;
							Doc.Camera = CameraZoomByMouseWheel(_middleButtonPressed_InitialCamera, 0.5, 0.5, position.Z, (dy * 5));
						}
						break;
				}
			}
		}
Exemple #5
0
		/// <summary>
		/// Moves the camera horizontally and vertically.
		/// </summary>
		/// <param name="camera">The camera prior to the movement.</param>
		/// <param name="stepX">The movement in horizontal direction. A value of 1 means movement corresponding to the full width of the scene.</param>
		/// <param name="stepY">The movement in horizontal direction. A value of 1 means movement corresponding to the full height of the scene.</param>
		/// <returns>The new camera after the movement.</returns>
		public static CameraBase CameraMoveRelative(CameraBase camera, double stepX, double stepY)
		{
			VectorD3D xaxis = VectorD3D.CreateNormalized(VectorD3D.CrossProduct(camera.TargetToEyeVectorNormalized, camera.UpVector));
			VectorD3D yaxis = VectorD3D.CreateNormalized(VectorD3D.CrossProduct(camera.TargetToEyeVector, VectorD3D.CrossProduct(camera.TargetToEyeVector, camera.UpVector)));

			if (camera is OrthographicCamera)
			{
				var oldCamera = (OrthographicCamera)camera;
				var shift = (xaxis * stepX + yaxis * stepY) * (oldCamera.WidthAtZNear);
				camera = oldCamera.WithEyeTarget(oldCamera.EyePosition + shift, oldCamera.TargetPosition + shift);
			}
			else if (camera is PerspectiveCamera)
			{
				var oldCamera = (PerspectiveCamera)camera;
				var shift = (xaxis * stepX + yaxis * stepY) * (oldCamera.WidthAtZNear * oldCamera.Distance / oldCamera.ZNear);
				camera = oldCamera.WithEyeTarget(oldCamera.EyePosition + shift, oldCamera.TargetPosition + shift);
			}

			return camera;
		}
		/// <summary>
		/// Handles the mouse down event onto the graph in the controller class.
		/// </summary>
		/// <param name="position">Mouse position. X and Y components are the current relative mouse coordinates, the Z component is the screen's aspect ratio.</param>
		/// <param name="e">MouseEventArgs.</param>
		public virtual void EhView_GraphPanelMouseDown(PointD3D position, MouseButtonEventArgs e)
		{
			_mouseState.OnMouseDown(position, e);

			bool isSHIFTpressed = Keyboard.Modifiers.HasFlag(ModifierKeys.Shift);
			bool isCTRLpressed = Keyboard.Modifiers.HasFlag(ModifierKeys.Control);
			if (e.ChangedButton == MouseButton.Middle && e.MiddleButton == MouseButtonState.Pressed)
			{
				_middleButtonPressed_InitialPosition = position;
				_middleButtonPressed_InitialCamera = _doc.Camera;
				if (!isSHIFTpressed && !isCTRLpressed)
					_middleButtonCurrentAction = MiddelButtonAction.RotateCamera;
				else if (isSHIFTpressed && !isCTRLpressed)
					_middleButtonCurrentAction = MiddelButtonAction.MoveCamera;
				else if (!isSHIFTpressed && isCTRLpressed)
					_middleButtonCurrentAction = MiddelButtonAction.ZoomCamera;
				else
					_middleButtonPressed_InitialCamera = null; // if inconsistent keys, then no action at all
			}
		}
Exemple #7
0
		/// <summary>
		/// Adjusts the zNear and zFar parameter of the camera to make sure that our scene is viewed appropriately, and nothing is cut away.
		/// </summary>
		/// <param name="cam">The cam.</param>
		/// <returns></returns>
		public CameraBase AdjustZNearZFar(CameraBase cam)
		{
			var currentDistanceToRootLayerCenter = ((VectorD3D)(cam.EyePosition - 0.5 * Doc.RootLayer.Size)).Length;
			var rootLayerRadius = 0.5 * Doc.RootLayer.Size.Length;

			double zNear, zFar;
			double rootLayerRadiusTimesFour = 4 * rootLayerRadius;
			if (currentDistanceToRootLayerCenter <= 2 * rootLayerRadius)
			{
				zNear = rootLayerRadius / 100;
				zFar = rootLayerRadiusTimesFour;
			}
			else
			{
				zNear = rootLayerRadius / 2;
				zFar = Math.Max(2 * currentDistanceToRootLayerCenter, rootLayerRadius * 4);
				zFar = rootLayerRadiusTimesFour * Math.Ceiling(zFar / rootLayerRadiusTimesFour);
			}

			return cam.WithZNearZFarWithoutChangingViewAngle(zNear, zFar);
		}
Exemple #8
0
		public static CameraBase ModelRotateDegrees(CameraBase cam, VectorD3D rootLayerSize, double stepX, double stepY)
		{
			double angleRadianZ = stepX * Math.PI / 180.0;
			double angleRadianX = stepY * Math.PI / 180.0;
			var shift = 0.5 * rootLayerSize;

			var l = cam.LookAtRHMatrix;

			// in the world coordinate space: i) translate to root layer center, ii) rotate around z-axis and iii) translate back
			var m01 = Matrix4x3.NewTranslation(-shift);
			var m02 = Matrix4x3.NewRotationFromAxisAndAngleRadian(new VectorD3D(0, 0, 1), angleRadianZ, PointD3D.Empty);
			var m03 = Matrix4x3.NewTranslation(shift);
			var mstart = m01.WithAppendedTransformation(m02).WithAppendedTransformation(m03);

			// in LookAt coordinate space: i) translate to root layer center, ii) rotate around x-axis and iii) translate back
			var diff11 = (VectorD3D)cam.LookAtRHMatrix.Transform((PointD3D)shift);
			var m11 = Matrix4x3.NewTranslation(-diff11);
			var m12 = Matrix4x3.NewRotationFromAxisAndAngleRadian(new VectorD3D(1, 0, 0), angleRadianX, PointD3D.Empty);
			var m13 = Matrix4x3.NewTranslation(diff11);
			var mend = m11.WithAppendedTransformation(m12).WithAppendedTransformation(m13);

			var t = mstart.WithAppendedTransformation(l).WithAppendedTransformation(mend);
			return cam.WithLookAtRHMatrix(t);
		}
Exemple #9
0
		/// <summary>
		/// Rotates the camera.
		/// </summary>
		/// <param name="cam">Initial camera, i.e. camera prior to the rotation</param>
		/// <param name="stepX">The rotation around the vertical axis in degrees.</param>
		/// <param name="stepY">The rotation around the horizontal axis in degrees.</param>
		public static CameraBase CameraRotateDegrees(CameraBase cam, double stepX, double stepY)
		{
			// the axis to turn the camera around is in case of stepY the Cross of UpVector and eyeVector
			// in case of stepX it is the cross of the Upvector and the cross of UpVector and eyeVector

			if (stepX != 0)
			{
				double angleRadian = stepX * Math.PI / 180.0;
				VectorD3D axis = VectorD3D.CreateNormalized(VectorD3D.CrossProduct(cam.TargetToEyeVector, VectorD3D.CrossProduct(cam.TargetToEyeVector, cam.UpVector)));
				var matrix = Matrix4x3.NewRotationFromAxisAndAngleRadian(axis, angleRadian, cam.TargetPosition);

				var newEye = matrix.Transform(cam.EyePosition);
				var newUp = matrix.Transform(cam.UpVector);
				cam = cam.WithUpEye(newUp, newEye);
			}

			if (stepY != 0)
			{
				double angleRadian = stepY * Math.PI / 180.0;
				VectorD3D axis = VectorD3D.CreateNormalized(VectorD3D.CrossProduct(cam.TargetToEyeVectorNormalized, cam.UpVector));
				var matrix = Matrix4x3.NewRotationFromAxisAndAngleRadian(axis, angleRadian, cam.TargetPosition);

				var newEye = matrix.Transform(cam.EyePosition);
				var newUp = matrix.Transform(cam.UpVector);
				cam = cam.WithUpEye(newUp, newEye);
			}

			return cam;
		}
Exemple #10
0
		protected static CameraBase CameraZoomByMouseWheel(CameraBase camera, double relX, double relY, double aspectRatio, double delta)
		{
			if (camera is OrthographicCamera)
			{
				var cam = camera as OrthographicCamera;
				var eye = cam.TargetToEyeVectorNormalized;
				var up = cam.UpVectorPerpendicularToEyeVectorNormalized;
				var widthBefore = cam.WidthAtZNear;
				var widthAfter = widthBefore * Math.Pow(2, delta);

				var tam1h = relX - 0.5;
				var tbm1h = relY - 0.5;

				var shift = new VectorD3D(
					-(widthAfter - widthBefore) * (aspectRatio * tbm1h * up.X + eye.Z * tam1h * up.Y - eye.Y * tam1h * up.Z),
					(widthAfter - widthBefore) * (eye.Z * tam1h * up.X - aspectRatio * tbm1h * up.Y - eye.X * tam1h * up.Z),
					-(widthAfter - widthBefore) * (eye.Y * tam1h * up.X - eye.X * tam1h * up.Y + aspectRatio * tbm1h * up.Z)
					);

				var oldCamera = (OrthographicCamera)camera;
				var newCamera = ((OrthographicCamera)camera).WithEyeTargetWidth(oldCamera.EyePosition + shift, oldCamera.TargetPosition + shift, widthAfter);
				return newCamera;
			}
			else if (camera is PerspectiveCamera)
			{
				double rx = 2 * relX - 1;
				double ry = 2 * relY - 1;
				double distanceFactor = Math.Pow(2, delta);
				camera = ((PerspectiveCamera)camera).ZoomByGettingCloserToTarget(distanceFactor, rx, ry, aspectRatio);
			}

			return camera;
		}
Exemple #11
0
		/// <summary>
		/// Gets the principal coordinate system that results of the camera facing a layer. The plane of the layer that best faced the camera is used for the calculations.
		/// The normal of that layer is returned as z-axis, the vector that best matches the up-vector of the camera is becoming the y-axis,
		/// and the x-axis results from the z-axis and the y-axis.
		/// </summary>
		/// <param name="camera">The camera.</param>
		/// <param name="activeLayer">The active layer of the graph document.</param>
		/// <param name="transformation">Matrix that contains the principal axes as described above. The axes coordinates are in the coordinates of the layer provided in the argument <paramref name="activeLayer"/>.</param>
		/// <exception cref="InvalidProgramException">There should always be a plane of a rectangle that can be hit!</exception>
		public static void GetCoordinateSystemBasedOnLayerPlaneFacingTheCamera(CameraBase camera, HostLayer activeLayer, out Matrix3x3 transformation)
		{
			PointD3D hitposition = new PointD3D(0.5, 0.5, 1); // this hit position is arbitrary, every other position should work similarly

			var activeLayerTransformation = activeLayer.TransformationFromRootToHere();

			var hitData = new HitTestPointData(camera.GetHitRayMatrix(hitposition));

			hitData = hitData.NewFromAdditionalTransformation(activeLayerTransformation); // now hitdata are in layer cos

			var targetToEye = hitData.WorldTransformation.Transform(camera.TargetToEyeVectorNormalized); // targetToEye in layer coordinates
			var upEye = hitData.WorldTransformation.Transform(camera.UpVectorPerpendicularToEyeVectorNormalized); // camera up vector in layer coordinates

			// get the face which has the best dot product between the eye vector of the camera and the plane's normal
			var layerRect = new RectangleD3D(PointD3D.Empty, activeLayer.Size);
			double maxval = double.MinValue;
			PlaneD3D maxPlane = PlaneD3D.Empty;
			foreach (var plane in layerRect.Planes)
			{
				double val = VectorD3D.DotProduct(plane.Normal, targetToEye);
				if (val > maxval)
				{
					maxval = val;
					maxPlane = plane;
				}
			}

			//	bool isHit = hitData.IsPlaneHitByRay(maxPlane, out hitPointOnPlaneInActiveLayerCoordinates); // hitPointOnPlane is in layer coordinates too

			//	if (!isHit)
			//	throw new InvalidProgramException("There should always be a plane of a rectangle that can be hit!");

			VectorD3D zaxis = maxPlane.Normal;
			VectorD3D yaxis = upEye;

			// Find y axis perpendicular to zaxis
			maxval = double.MinValue;
			foreach (var plane in layerRect.Planes)
			{
				double val = VectorD3D.DotProduct(plane.Normal, upEye);
				if (val > maxval && 0 == VectorD3D.DotProduct(plane.Normal, zaxis))
				{
					maxval = val;
					yaxis = plane.Normal;
				}
			}
			var xaxis = VectorD3D.CrossProduct(yaxis, zaxis);

			// now we have all information about the spatial position and orientation of the text:
			// hitPointOnPlane is the position of the text
			// maxPlane.Normal is the face orientation of the text
			// maxUpVector is the up orientation of the text

			xaxis = xaxis.Normalized;
			yaxis = yaxis.Normalized;
			zaxis = zaxis.Normalized;

			transformation = new Matrix3x3(
				xaxis.X, yaxis.X, zaxis.X,
				xaxis.Y, yaxis.Y, zaxis.Y,
				xaxis.Z, yaxis.Z, zaxis.Z
				);
		}