/home/lindsay/xeolabs/xeogl-next/xeogl/src/loop.js
API Docs for:

File: /home/lindsay/xeolabs/xeogl-next/xeogl/src/loop.js

  1. import {stats} from './stats.js';
  2. import {core} from './core.js';
  3. import {tasks} from './tasks.js';
  4.  
  5. const scenesRenderInfo = {}; // Used for throttling FPS for each Scene
  6.  
  7. const tickEvent = {
  8. sceneId: null,
  9. time: null,
  10. startTime: null,
  11. prevTime: null,
  12. deltaTime: null
  13. };
  14.  
  15. const taskBudget = 10; // Millisecs we're allowed to spend on tasks in each frame
  16. const fpsSamples = [];
  17. const numFPSSamples = 30;
  18.  
  19. let lastTime = 0;
  20. let elapsedTime;
  21. let totalFPS = 0;
  22.  
  23. const frame = function () {
  24. let time = Date.now();
  25. if (lastTime > 0) { // Log FPS stats
  26. elapsedTime = time - lastTime;
  27. var newFPS = 1000 / elapsedTime; // Moving average of FPS
  28. totalFPS += newFPS;
  29. fpsSamples.push(newFPS);
  30. if (fpsSamples.length >= numFPSSamples) {
  31. totalFPS -= fpsSamples.shift();
  32. }
  33. stats.frame.fps = Math.round(totalFPS / fpsSamples.length);
  34. }
  35. runTasks(time);
  36. fireTickEvents(time);
  37. renderScenes();
  38. lastTime = time;
  39. window.requestAnimationFrame(frame);
  40. };
  41.  
  42. function runTasks(time) { // Process as many enqueued tasks as we can within the per-frame task budget
  43. const tasksRun = tasks.runTasks(time + taskBudget);
  44. const tasksScheduled = tasks.getNumTasks();
  45. stats.frame.tasksRun = tasksRun;
  46. stats.frame.tasksScheduled = tasksScheduled;
  47. stats.frame.tasksBudget = taskBudget;
  48. }
  49.  
  50. function fireTickEvents(time) { // Fire tick event on each Scene
  51. tickEvent.time = time;
  52. for (var id in core.scenes) {
  53. if (core.scenes.hasOwnProperty(id)) {
  54. var scene = core.scenes[id];
  55. tickEvent.sceneId = id;
  56. tickEvent.startTime = scene.startTime;
  57. tickEvent.deltaTime = tickEvent.prevTime != null ? tickEvent.time - tickEvent.prevTime : 0;
  58. /**
  59. * Fired on each game loop iteration.
  60. *
  61. * @event tick
  62. * @param {String} sceneID The ID of this Scene.
  63. * @param {Number} startTime The time in seconds since 1970 that this Scene was instantiated.
  64. * @param {Number} time The time in seconds since 1970 of this "tick" event.
  65. * @param {Number} prevTime The time of the previous "tick" event from this Scene.
  66. * @param {Number} deltaTime The time in seconds since the previous "tick" event from this Scene.
  67. */
  68. scene.fire("tick", tickEvent, true);
  69. }
  70. }
  71. tickEvent.prevTime = time;
  72. }
  73.  
  74. function renderScenes() {
  75. const scenes = core.scenes;
  76. const forceRender = false;
  77. let scene;
  78. let renderInfo;
  79. let ticksPerRender;
  80. let id;
  81. for (id in scenes) {
  82. if (scenes.hasOwnProperty(id)) {
  83. scene = scenes[id];
  84. renderInfo = scenesRenderInfo[id];
  85. if (!renderInfo) {
  86. renderInfo = scenesRenderInfo[id] = {}; // FIXME
  87. }
  88. ticksPerRender = scene.ticksPerRender;
  89. if (renderInfo.ticksPerRender !== ticksPerRender) {
  90. renderInfo.ticksPerRender = ticksPerRender;
  91. renderInfo.renderCountdown = ticksPerRender;
  92. }
  93. if (--renderInfo.renderCountdown === 0) {
  94. scene.render(forceRender);
  95. renderInfo.renderCountdown = ticksPerRender;
  96. }
  97. }
  98. }
  99. }
  100.  
  101. window.requestAnimationFrame(frame);
  102.  
  103. const loop = {};
  104.  
  105. export{loop};
  106.  
  107.  
  108.