Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
CameraScript.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 
5 using System.Linq;
6 
7 using System.Runtime.InteropServices;
8 using System.Threading.Tasks;
9 using System.Xml.Serialization;
10 using SiliconStudio.Paradox;
11 using SiliconStudio.Paradox.Effects;
12 using SiliconStudio.Paradox.Effects.Modules;
13 using SiliconStudio.Paradox.Engine;
14 using SiliconStudio.Paradox.Games;
15 using SiliconStudio.Paradox.Games.Mathematics;
16 using SiliconStudio.Paradox.Games.MicroThreading;
17 using SiliconStudio.Paradox.Configuration;
18 using SiliconStudio.Paradox.Input;
20 
21 #if NET45
22 using TaskEx = System.Threading.Tasks.Task;
23 #endif
24 
25 namespace ScriptTest2
26 {
27  [ParadoxScript(ScriptFlags.AssemblyStartup)]
28  public class CameraScript : ScriptContext
29  {
30  private Camera camera;
31  bool isModifyingPosition = false;
32  bool isModifyingFov = false;
33  Vector3 fixedPosition = Vector3.Zero;
34  Matrix fixedFreeMatrix = Matrix.Identity;
35  bool viewChanged = true;
36 
38 
39  private Stopwatch clock = new Stopwatch();
40  private bool flyingAround;
41  float pitch = 0;
42  float yaw = 0;
43  float roll = 0;
44  float previousX = 0;
45  float previousY = 0;
46 
47  private Vector3 localVelocity;
48 
49  public CameraScript(IServiceRegistry registry) : base(registry)
50  {
51  Speed = 10.0f;
52  MoveSpeed = 2.0f;
53  }
54 
55  public float Speed { get; set; }
56  public float MoveSpeed { get; set; }
57 
58  public class Config
59  {
60  public Config()
61  {
62  FlyingAround = false;
63  Speed = 5.0f;
64  }
65 
66  [XmlAttribute("flyingAround")]
67  public bool FlyingAround { get; set; }
68 
69  [XmlAttribute("speed")]
70  public float Speed { get; set; }
71  }
72 
73  public async Task AutoswitchCamera(EngineContext engineContext)
74  {
75  bool autoswitch = false;
76  while (true)
77  {
78  // Fetch camera list
79  var cameras = Context.EntityManager.Entities
80  .Where(x => x.ContainsKey(CameraComponent.Key))
81  .Select(x => x.Get(CameraComponent.Key)).ToArray();
82 
83  if (engineContext.InputManager.IsKeyPressed(Keys.F8))
84  {
85  autoswitch = !autoswitch;
86  }
87 
88  int index = Array.IndexOf(cameras, TrackingCamera);
89  if (autoswitch)
90  {
91  if (index == 1)
92  index = 2;
93  else
94  index = 1;
95  TrackingCamera = (index < cameras.Length) ? cameras[index] : null;
96  }
97 
98  await TaskEx.Delay((index == 1) ? 50000 : 10000);
99  }
100  }
101 
102  public Camera Camera
103  {
104  get
105  {
106  return camera;
107  }
108  set
109  {
110  camera = value;
111  }
112  }
113 
114  public override async Task Execute()
115  {
116  var config = AppConfig.GetConfiguration<Config>("CameraScript");
117  flyingAround = config.FlyingAround;
118 
119  //uiControl = Context.RenderContext.UIControl;
120 
121  if (camera == null)
122  {
123  // Near plane and Far plane are swapped in order to increase float precision for far distance as near distance is already having
124  // lots of precisions by the 1/z perspective projection
125  //camera = new Camera(new R32G32B32_Float(200, 0, 200), new R32G32B32_Float(0, 0, 200), 1.2f, 1280.0f / 720.0f, 4000000.0f, 10.0f);
126  var zNear = 10.0f;
127  var zFar = 4000000.0f;
128  if (Context.RenderContext.IsZReverse)
129  {
130  var temp = zNear;
131  zNear = zFar;
132  zFar = temp;
133  }
134  camera = new Camera(new Vector3(200, 0, 200), new Vector3(0, 0, 200), 1.2f, RenderContext.Width, RenderContext.Height, (float)RenderContext.Width / RenderContext.Height, zNear, zFar);
135  camera.Mode = CameraMode.Free;
136  }
137 
138  Speed = config.Speed;
139 
140  //useful when we need to debug something from a specific point of view (we can first get the WorldToCamera value using a breakpoint then set it below)
141  /*Matrix mat = new Matrix();
142  mat.M11 = 0.0267117824f;
143  mat.M12 = -0.9257705f;
144  mat.M13 = -0.377141267f;
145  mat.M14 = 0.0f;
146  mat.M21 = -0.9996432f;
147  mat.M22 = -0.024737807f;
148  mat.M23 = -0.0100777093f;
149  mat.M24 = 0.0f;
150  mat.M31 = 0.0f;
151  mat.M32 = 0.377275884f;
152  mat.M33 = -0.926100969f;
153  mat.M34 = 0.0f;
154  mat.M41 = 531.524963f;
155  mat.M42 = 501.754761f;
156  mat.M43 = 989.462646f;
157  mat.M44 = 1.0f;
158  camera.WorldToCamera = mat;*/
159 
160  //uiControl.MouseWheel += OnUiControlOnMouseWheel;
161  var st = new Stopwatch();
162 
163  st.Start();
164 
165  var viewParameters = Context.RenderContext.RenderPassPlugins.OfType<MainPlugin>().FirstOrDefault().ViewParameters;
166 
167  Context.Scheduler.Add(() => AutoswitchCamera(Context));
168 
169  var lastTime = DateTime.UtcNow;
170  var pauseTime = false;
171  while (true)
172  {
173  await Scheduler.Current.NextFrame();
174 
175  var mousePosition = Context.InputManager.MousePosition;
176 
177  if (Context.InputManager.IsMouseButtonPressed(MouseButton.Right))
178  {
179  camera.Mode = CameraMode.Free;
180  isModifyingPosition = true;
181 
182  pitch = 0;
183  yaw = 0;
184  roll = 0;
185 
186  if (camera.Mode == CameraMode.Free)
187  {
188  fixedFreeMatrix = camera.WorldToCamera;
189  }
190  else
191  {
192  fixedPosition = camera.Position;
193  }
194  }
195  if (Context.InputManager.IsMouseButtonDown(MouseButton.Right))
196  {
197  var deltaX = mousePosition.X - previousX;
198  var deltaY = mousePosition.Y - previousY;
199  if (isModifyingPosition)
200  {
201 
202  yaw += deltaX * Speed / 1000.0f;
203  pitch += deltaY * Speed / 1000.0f;
204 
205  if (camera.Mode == CameraMode.Target)
206  {
207  camera.Position = (Vector3)Vector3.Transform(fixedPosition, Matrix.RotationX(pitch) * Matrix.RotationZ(yaw));
208  Console.WriteLine(camera.Position);
209  }
210  else
211  {
212  camera.WorldToCamera = Camera.YawPitchRoll(camera.Position, fixedFreeMatrix, yaw, -pitch, roll);
213  }
214 
215  //uiControl.Text = "" + camera.Mode;
216 
217  viewChanged = true;
218  }
219  else if (isModifyingFov)
220  {
221  camera.FieldOfView += deltaX / 128.0f;
222  camera.FieldOfView = Math.Max(Math.Min(camera.FieldOfView, (float)Math.PI * 0.9f), 0.01f);
223 
224  viewChanged = true;
225  }
226  }
227  if (Context.InputManager.IsMouseButtonReleased(MouseButton.Right))
228  {
229  isModifyingFov = false;
230  isModifyingPosition = false;
231 
232  if (camera.Mode == CameraMode.Free && flyingAround)
233  {
234  camera.Mode = CameraMode.Target;
235  }
236  }
237 
238  previousX = mousePosition.X;
239  previousY = mousePosition.Y;
240 
241  if (Context.InputManager.IsKeyDown(Keys.LeftAlt) && Context.InputManager.IsKeyPressed(Keys.Enter))
242  Context.RenderContext.GraphicsDevice.IsFullScreen = !Context.RenderContext.GraphicsDevice.IsFullScreen;
243 
244  if (Context.InputManager.IsKeyPressed(Keys.F2))
245  pauseTime = !pauseTime;
246 
247  var currentTime = DateTime.UtcNow;
248  if (!pauseTime)
249  {
250  Context.CurrentTime += currentTime - lastTime;
251  viewParameters.Set(GlobalKeys.Time, (float)Context.CurrentTime.TotalSeconds);
252  var timeStep = (float)(currentTime - lastTime).TotalMilliseconds;
253  viewParameters.Set(GlobalKeys.TimeStep, timeStep);
254  }
255 
256  // Set the pause variable for the rendering
257  Context.RenderContext.IsPaused = pauseTime;
258  lastTime = currentTime;
259 
260  if (Context.InputManager.IsKeyPressed(Keys.Space))
261  {
262  // Fetch camera list
263  var cameras = Context.EntityManager.Entities
264  .Where(x => x.ContainsKey(CameraComponent.Key))
265  .Select(x => x.Get(CameraComponent.Key)).ToArray();
266 
267  // Go to next camera
268  // If no camera or unset, index will be 0, so it will go to first one
269  int index = Array.IndexOf(cameras, TrackingCamera) + 1;
270  TrackingCamera = (index < cameras.Length) ? cameras[index] : null;
271  clock.Restart();
272 
273  //flyingAround = !flyingAround;
274  //if (flyingAround)
275  //{
276  // fixedPosition = camera.Position;
277  // clock.Restart();
278  //}
279  }
280 
281  if (TrackingCamera != null)
282  {
283  Matrix projection, worldToCamera;
284 
285  // Overwrite near/far plane with our camera, as they are not reliable
286  TrackingCamera.NearPlane = camera.NearClipPlane;
287  TrackingCamera.FarPlane = camera.FarClipPlane;
288 
289  TrackingCamera.Calculate(out projection, out worldToCamera);
290 
291  viewParameters.Set(TransformationKeys.View, worldToCamera);
292  viewParameters.Set(TransformationKeys.Projection, projection);
293 
294  // TODO: tracking camera doesn't have proper near/far plane values. Use mouse camera near/far instead.
295  viewParameters.Set(CameraKeys.NearClipPlane, camera.NearClipPlane);
296  viewParameters.Set(CameraKeys.FarClipPlane, camera.FarClipPlane);
297  viewParameters.Set(CameraKeys.FieldOfView, TrackingCamera.VerticalFieldOfView);
298  // Console.WriteLine("FOV:{0}", trackingCamera.VerticalFieldOfView);
299  viewParameters.Set(CameraKeys.ViewSize, new Vector2(camera.Width, camera.Height));
300  viewParameters.Set(CameraKeys.Aspect, TrackingCamera.AspectRatio);
301  viewParameters.Set(CameraKeys.FocusDistance, TrackingCamera.FocusDistance);
302  }
303  else
304  {
305  bool moved = false;
306 
307  var localPosition = new Vector3(0, 0, 0);
308 
309  if (Context.InputManager.IsKeyDown(Keys.Left) || Context.InputManager.IsKeyDown(Keys.A))
310  {
311  localPosition.X -= 1.0f;
312  moved = true;
313  }
314 
315  if (Context.InputManager.IsKeyDown(Keys.Right) || Context.InputManager.IsKeyDown(Keys.D))
316  {
317  localPosition.X += 1.0f;
318  moved = true;
319  }
320 
321  if (Context.InputManager.IsKeyDown(Keys.Up) || Context.InputManager.IsKeyDown(Keys.W))
322  {
323  localPosition.Y -= 1.0f;
324  moved = true;
325  }
326  if (Context.InputManager.IsKeyDown(Keys.Down) || Context.InputManager.IsKeyDown(Keys.S))
327  {
328  localPosition.Y += 1.0f;
329  moved = true;
330  }
331 
332  if (Context.InputManager.IsKeyDown(Keys.R))
333  {
334  roll += 0.1f;
335  }
336 
337  if (Context.InputManager.IsKeyDown(Keys.T))
338  {
339  roll -= 0.1f;
340  }
341 
342  var moveSpeedFactor = Context.InputManager.IsKeyDown(Keys.LeftShift) || Context.InputManager.IsKeyDown(Keys.RightShift) ? 0.1f : 1.0f;
343 
344  localPosition.Normalize();
345  localPosition *= (float)clock.ElapsedTicks * 1000.0f * MoveSpeed * moveSpeedFactor / Stopwatch.Frequency;
346 
347  localVelocity = localVelocity * 0.9f + localPosition * 0.1f;
348 
349  if (localVelocity.Length() > MoveSpeed * 0.001f)
350  {
351 
352  if (camera.Mode == CameraMode.Target)
353  camera.Position = camera.Position + localVelocity;
354  else
355  {
356  var destVector = ((Vector3)camera.WorldToCamera.Column3);
357  var leftRightVector = Vector3.Cross(destVector, Vector3.UnitZ);
358  leftRightVector.Normalize();
359 
360  var newPosition = camera.Position - destVector * localVelocity.Y;
361  newPosition = newPosition - leftRightVector * localVelocity.X;
362  camera.Position = newPosition;
363  }
364 
365  viewChanged = true;
366  }
367 
368  if (flyingAround)
369  {
370  camera.Position = (Vector3)Vector3.Transform(camera.Position, Matrix.RotationZ(clock.ElapsedMilliseconds * Speed / 10000.0f));
371  viewChanged = true;
372  }
373 
374  if (Context.InputManager.IsKeyPressed(Keys.F))
375  {
376  camera.FieldOfView -= 0.1f;
377  viewChanged = true;
378  }
379 
380  if (Context.InputManager.IsKeyPressed(Keys.G))
381  {
382  camera.FieldOfView += 0.1f;
383  viewChanged = true;
384  }
385 
386  //if (viewChanged)
387  {
388  viewParameters.Set(TransformationKeys.View, camera.WorldToCamera);
389  viewParameters.Set(TransformationKeys.Projection, camera.Projection);
390  viewParameters.Set(CameraKeys.NearClipPlane, camera.NearClipPlane);
391  viewParameters.Set(CameraKeys.FarClipPlane, camera.FarClipPlane);
392  viewParameters.Set(CameraKeys.FieldOfView, camera.FieldOfView);
393  //Console.WriteLine("FOV:{0}", camera.FieldOfView);
394  viewParameters.Set(CameraKeys.ViewSize, new Vector2(camera.Width, camera.Height));
395  viewParameters.Set(CameraKeys.Aspect, camera.Aspect);
396  viewParameters.Set(CameraKeys.FocusDistance, 0.0f);
397  //Console.WriteLine("Camera: {0}", camera);
398 
399  }
400 
401  if (Context.InputManager.IsKeyPressed(Keys.I))
402  {
403  var worldToCamera = camera.WorldToCamera;
404  var target = (Vector3)worldToCamera.Column3;
405  Console.WriteLine("camera.Position = new R32G32B32_Float({0}f,{1}f,{2}f); camera.Target = camera.Position + new R32G32B32_Float({3}f, {4}f, {5}f);", camera.Position.X, camera.Position.Y, camera.Position.Z, target.X, target.Y, target.Z);
406  }
407 
408  viewChanged = false;
409  clock.Restart();
410  }
411  }
412  }
413  }
414 }
Camera component.
Definition: Camera.cs:21
float Height
Gets the height of the camera.
Definition: Camera.cs:102
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
Matrix WorldToCamera
Gets or sets the world to camera matrix.
Definition: Camera.cs:249
float Width
Gets the width of the camera.
Definition: Camera.cs:97
MouseButton
Mouse buttons.
Definition: MouseButton.cs:10
Keys
Enumeration for keys.
Definition: Keys.cs:8
SiliconStudio.Core.IServiceRegistry IServiceRegistry
Definition: ModelRenderer.cs:9
override async Task Execute()
async Task AutoswitchCamera(EngineContext engineContext)
Definition: CameraScript.cs:73
System.Threading.Tasks.Task Task
CameraMode Mode
Gets or sets the mode of this camera.
Definition: Camera.cs:231
Describes the camera projection and view.
Thread-local storage context used during rendering.
Plugin used for the main rendering view.
Definition: MainPlugin.cs:15
Vector3 Position
Gets or sets the position.
Definition: Camera.cs:288
CameraComponent TrackingCamera
Definition: CameraScript.cs:37
SiliconStudio.Core.Mathematics.Vector3 Vector3
System.Console Console
CameraMode
Camera mode.
Definition: Camera.cs:12
CameraScript(IServiceRegistry registry)
Definition: CameraScript.cs:49
SiliconStudio.Paradox.Input.Keys Keys
Definition: CameraScript.cs:19