babylon.scene.js 116 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520
  1. var __extends = (this && this.__extends) || function (d, b) {
  2. for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
  3. function __() { this.constructor = d; }
  4. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  5. };
  6. var BABYLON;
  7. (function (BABYLON) {
  8. var PointerEventTypes = (function () {
  9. function PointerEventTypes() {
  10. }
  11. Object.defineProperty(PointerEventTypes, "POINTERDOWN", {
  12. get: function () {
  13. return PointerEventTypes._POINTERDOWN;
  14. },
  15. enumerable: true,
  16. configurable: true
  17. });
  18. Object.defineProperty(PointerEventTypes, "POINTERUP", {
  19. get: function () {
  20. return PointerEventTypes._POINTERUP;
  21. },
  22. enumerable: true,
  23. configurable: true
  24. });
  25. Object.defineProperty(PointerEventTypes, "POINTERMOVE", {
  26. get: function () {
  27. return PointerEventTypes._POINTERMOVE;
  28. },
  29. enumerable: true,
  30. configurable: true
  31. });
  32. Object.defineProperty(PointerEventTypes, "POINTERWHEEL", {
  33. get: function () {
  34. return PointerEventTypes._POINTERWHEEL;
  35. },
  36. enumerable: true,
  37. configurable: true
  38. });
  39. Object.defineProperty(PointerEventTypes, "POINTERPICK", {
  40. get: function () {
  41. return PointerEventTypes._POINTERPICK;
  42. },
  43. enumerable: true,
  44. configurable: true
  45. });
  46. PointerEventTypes._POINTERDOWN = 0x01;
  47. PointerEventTypes._POINTERUP = 0x02;
  48. PointerEventTypes._POINTERMOVE = 0x04;
  49. PointerEventTypes._POINTERWHEEL = 0x08;
  50. PointerEventTypes._POINTERPICK = 0x10;
  51. return PointerEventTypes;
  52. }());
  53. BABYLON.PointerEventTypes = PointerEventTypes;
  54. var PointerInfoBase = (function () {
  55. function PointerInfoBase(type, event) {
  56. this.type = type;
  57. this.event = event;
  58. }
  59. return PointerInfoBase;
  60. }());
  61. BABYLON.PointerInfoBase = PointerInfoBase;
  62. /**
  63. * This class is used to store pointer related info for the onPrePointerObservable event.
  64. * Set the skipOnPointerObservable property to true if you want the engine to stop any process after this event is triggered, even not calling onPointerObservable
  65. */
  66. var PointerInfoPre = (function (_super) {
  67. __extends(PointerInfoPre, _super);
  68. function PointerInfoPre(type, event, localX, localY) {
  69. _super.call(this, type, event);
  70. this.skipOnPointerObservable = false;
  71. this.localPosition = new BABYLON.Vector2(localX, localY);
  72. }
  73. return PointerInfoPre;
  74. }(PointerInfoBase));
  75. BABYLON.PointerInfoPre = PointerInfoPre;
  76. /**
  77. * This type contains all the data related to a pointer event in Babylon.js.
  78. * The event member is an instance of PointerEvent for all types except PointerWheel and is of type MouseWheelEvent when type equals PointerWheel. The different event types can be found in the PointerEventTypes class.
  79. */
  80. var PointerInfo = (function (_super) {
  81. __extends(PointerInfo, _super);
  82. function PointerInfo(type, event, pickInfo) {
  83. _super.call(this, type, event);
  84. this.pickInfo = pickInfo;
  85. }
  86. return PointerInfo;
  87. }(PointerInfoBase));
  88. BABYLON.PointerInfo = PointerInfo;
  89. /**
  90. * Represents a scene to be rendered by the engine.
  91. * @see http://doc.babylonjs.com/page.php?p=21911
  92. */
  93. var Scene = (function () {
  94. /**
  95. * @constructor
  96. * @param {BABYLON.Engine} engine - the engine to be used to render this scene.
  97. */
  98. function Scene(engine) {
  99. // Members
  100. this.autoClear = true;
  101. this.clearColor = new BABYLON.Color3(0.2, 0.2, 0.3);
  102. this.ambientColor = new BABYLON.Color3(0, 0, 0);
  103. this.forceWireframe = false;
  104. this.forcePointsCloud = false;
  105. this.forceShowBoundingBoxes = false;
  106. this.animationsEnabled = true;
  107. this.constantlyUpdateMeshUnderPointer = false;
  108. this.useRightHandedSystem = false;
  109. this.hoverCursor = "pointer";
  110. // Events
  111. /**
  112. * An event triggered when the scene is disposed.
  113. * @type {BABYLON.Observable}
  114. */
  115. this.onDisposeObservable = new BABYLON.Observable();
  116. /**
  117. * An event triggered before rendering the scene
  118. * @type {BABYLON.Observable}
  119. */
  120. this.onBeforeRenderObservable = new BABYLON.Observable();
  121. /**
  122. * An event triggered after rendering the scene
  123. * @type {BABYLON.Observable}
  124. */
  125. this.onAfterRenderObservable = new BABYLON.Observable();
  126. /**
  127. * An event triggered when the scene is ready
  128. * @type {BABYLON.Observable}
  129. */
  130. this.onReadyObservable = new BABYLON.Observable();
  131. /**
  132. * An event triggered before rendering a camera
  133. * @type {BABYLON.Observable}
  134. */
  135. this.onBeforeCameraRenderObservable = new BABYLON.Observable();
  136. /**
  137. * An event triggered after rendering a camera
  138. * @type {BABYLON.Observable}
  139. */
  140. this.onAfterCameraRenderObservable = new BABYLON.Observable();
  141. /**
  142. * An event triggered when a camera is created
  143. * @type {BABYLON.Observable}
  144. */
  145. this.onNewCameraAddedObservable = new BABYLON.Observable();
  146. /**
  147. * An event triggered when a camera is removed
  148. * @type {BABYLON.Observable}
  149. */
  150. this.onCameraRemovedObservable = new BABYLON.Observable();
  151. /**
  152. * An event triggered when a light is created
  153. * @type {BABYLON.Observable}
  154. */
  155. this.onNewLightAddedObservable = new BABYLON.Observable();
  156. /**
  157. * An event triggered when a light is removed
  158. * @type {BABYLON.Observable}
  159. */
  160. this.onLightRemovedObservable = new BABYLON.Observable();
  161. /**
  162. * An event triggered when a geometry is created
  163. * @type {BABYLON.Observable}
  164. */
  165. this.onNewGeometryAddedObservable = new BABYLON.Observable();
  166. /**
  167. * An event triggered when a geometry is removed
  168. * @type {BABYLON.Observable}
  169. */
  170. this.onGeometryRemovedObservable = new BABYLON.Observable();
  171. /**
  172. * An event triggered when a mesh is created
  173. * @type {BABYLON.Observable}
  174. */
  175. this.onNewMeshAddedObservable = new BABYLON.Observable();
  176. /**
  177. * An event triggered when a mesh is removed
  178. * @type {BABYLON.Observable}
  179. */
  180. this.onMeshRemovedObservable = new BABYLON.Observable();
  181. // Animations
  182. this.animations = [];
  183. /**
  184. * This observable event is triggered when any mouse event registered during Scene.attach() is called BEFORE the 3D engine to process anything (mesh/sprite picking for instance).
  185. * You have the possibility to skip the 3D Engine process and the call to onPointerObservable by setting PointerInfoBase.skipOnPointerObservable to true
  186. */
  187. this.onPrePointerObservable = new BABYLON.Observable();
  188. /**
  189. * Observable event triggered each time an input event is received from the rendering canvas
  190. */
  191. this.onPointerObservable = new BABYLON.Observable();
  192. this.cameraToUseForPointers = null; // Define this parameter if you are using multiple cameras and you want to specify which one should be used for pointer position
  193. this._startingPointerPosition = new BABYLON.Vector2(0, 0);
  194. this._startingPointerTime = 0;
  195. // Fog
  196. /**
  197. * is fog enabled on this scene.
  198. * @type {boolean}
  199. */
  200. this.fogEnabled = true;
  201. this.fogMode = Scene.FOGMODE_NONE;
  202. this.fogColor = new BABYLON.Color3(0.2, 0.2, 0.3);
  203. this.fogDensity = 0.1;
  204. this.fogStart = 0;
  205. this.fogEnd = 1000.0;
  206. // Lights
  207. /**
  208. * is shadow enabled on this scene.
  209. * @type {boolean}
  210. */
  211. this.shadowsEnabled = true;
  212. /**
  213. * is light enabled on this scene.
  214. * @type {boolean}
  215. */
  216. this.lightsEnabled = true;
  217. /**
  218. * All of the lights added to this scene.
  219. * @see BABYLON.Light
  220. * @type {BABYLON.Light[]}
  221. */
  222. this.lights = new Array();
  223. // Cameras
  224. /**
  225. * All of the cameras added to this scene.
  226. * @see BABYLON.Camera
  227. * @type {BABYLON.Camera[]}
  228. */
  229. this.cameras = new Array();
  230. this.activeCameras = new Array();
  231. // Meshes
  232. /**
  233. * All of the (abstract) meshes added to this scene.
  234. * @see BABYLON.AbstractMesh
  235. * @type {BABYLON.AbstractMesh[]}
  236. */
  237. this.meshes = new Array();
  238. // Geometries
  239. this._geometries = new Array();
  240. this.materials = new Array();
  241. this.multiMaterials = new Array();
  242. this.defaultMaterial = new BABYLON.StandardMaterial("default material", this);
  243. // Textures
  244. this.texturesEnabled = true;
  245. this.textures = new Array();
  246. // Particles
  247. this.particlesEnabled = true;
  248. this.particleSystems = new Array();
  249. // Sprites
  250. this.spritesEnabled = true;
  251. this.spriteManagers = new Array();
  252. // Layers
  253. this.layers = new Array();
  254. this.highlightLayers = new Array();
  255. // Skeletons
  256. this.skeletonsEnabled = true;
  257. this.skeletons = new Array();
  258. // Lens flares
  259. this.lensFlaresEnabled = true;
  260. this.lensFlareSystems = new Array();
  261. // Collisions
  262. this.collisionsEnabled = true;
  263. this.gravity = new BABYLON.Vector3(0, -9.807, 0);
  264. // Postprocesses
  265. this.postProcessesEnabled = true;
  266. // Customs render targets
  267. this.renderTargetsEnabled = true;
  268. this.dumpNextRenderTargets = false;
  269. this.customRenderTargets = new Array();
  270. // Imported meshes
  271. this.importedMeshesFiles = new Array();
  272. // Probes
  273. this.probesEnabled = true;
  274. this.reflectionProbes = new Array();
  275. this._actionManagers = new Array();
  276. this._meshesForIntersections = new BABYLON.SmartArray(256);
  277. // Procedural textures
  278. this.proceduralTexturesEnabled = true;
  279. this._proceduralTextures = new Array();
  280. this.soundTracks = new Array();
  281. this._audioEnabled = true;
  282. this._headphone = false;
  283. // Performance counters
  284. this._totalMeshesCounter = new BABYLON.PerfCounter();
  285. this._totalLightsCounter = new BABYLON.PerfCounter();
  286. this._totalMaterialsCounter = new BABYLON.PerfCounter();
  287. this._totalTexturesCounter = new BABYLON.PerfCounter();
  288. this._totalVertices = new BABYLON.PerfCounter();
  289. this._activeIndices = new BABYLON.PerfCounter();
  290. this._activeParticles = new BABYLON.PerfCounter();
  291. this._lastFrameDuration = new BABYLON.PerfCounter();
  292. this._evaluateActiveMeshesDuration = new BABYLON.PerfCounter();
  293. this._renderTargetsDuration = new BABYLON.PerfCounter();
  294. this._particlesDuration = new BABYLON.PerfCounter();
  295. this._renderDuration = new BABYLON.PerfCounter();
  296. this._spritesDuration = new BABYLON.PerfCounter();
  297. this._activeBones = new BABYLON.PerfCounter();
  298. this._renderId = 0;
  299. this._executeWhenReadyTimeoutId = -1;
  300. this._intermediateRendering = false;
  301. this._toBeDisposed = new BABYLON.SmartArray(256);
  302. this._pendingData = []; //ANY
  303. this._activeMeshes = new BABYLON.SmartArray(256);
  304. this._processedMaterials = new BABYLON.SmartArray(256);
  305. this._renderTargets = new BABYLON.SmartArray(256);
  306. this._activeParticleSystems = new BABYLON.SmartArray(256);
  307. this._activeSkeletons = new BABYLON.SmartArray(32);
  308. this._softwareSkinnedMeshes = new BABYLON.SmartArray(32);
  309. this._activeAnimatables = new Array();
  310. this._transformMatrix = BABYLON.Matrix.Zero();
  311. this._edgesRenderers = new BABYLON.SmartArray(16);
  312. this._uniqueIdCounter = 0;
  313. this._engine = engine;
  314. engine.scenes.push(this);
  315. this._renderingManager = new BABYLON.RenderingManager(this);
  316. this.postProcessManager = new BABYLON.PostProcessManager(this);
  317. this.postProcessRenderPipelineManager = new BABYLON.PostProcessRenderPipelineManager();
  318. this._boundingBoxRenderer = new BABYLON.BoundingBoxRenderer(this);
  319. if (BABYLON.OutlineRenderer) {
  320. this._outlineRenderer = new BABYLON.OutlineRenderer(this);
  321. }
  322. this.attachControl();
  323. if (BABYLON.SoundTrack) {
  324. this.mainSoundTrack = new BABYLON.SoundTrack(this, { mainTrack: true });
  325. }
  326. //simplification queue
  327. if (BABYLON.SimplificationQueue) {
  328. this.simplificationQueue = new BABYLON.SimplificationQueue();
  329. }
  330. //collision coordinator initialization. For now legacy per default.
  331. this.workerCollisions = false; //(!!Worker && (!!BABYLON.CollisionWorker || BABYLON.WorkerIncluded));
  332. }
  333. Object.defineProperty(Scene, "FOGMODE_NONE", {
  334. get: function () {
  335. return Scene._FOGMODE_NONE;
  336. },
  337. enumerable: true,
  338. configurable: true
  339. });
  340. Object.defineProperty(Scene, "FOGMODE_EXP", {
  341. get: function () {
  342. return Scene._FOGMODE_EXP;
  343. },
  344. enumerable: true,
  345. configurable: true
  346. });
  347. Object.defineProperty(Scene, "FOGMODE_EXP2", {
  348. get: function () {
  349. return Scene._FOGMODE_EXP2;
  350. },
  351. enumerable: true,
  352. configurable: true
  353. });
  354. Object.defineProperty(Scene, "FOGMODE_LINEAR", {
  355. get: function () {
  356. return Scene._FOGMODE_LINEAR;
  357. },
  358. enumerable: true,
  359. configurable: true
  360. });
  361. Object.defineProperty(Scene.prototype, "onDispose", {
  362. set: function (callback) {
  363. if (this._onDisposeObserver) {
  364. this.onDisposeObservable.remove(this._onDisposeObserver);
  365. }
  366. this._onDisposeObserver = this.onDisposeObservable.add(callback);
  367. },
  368. enumerable: true,
  369. configurable: true
  370. });
  371. Object.defineProperty(Scene.prototype, "beforeRender", {
  372. set: function (callback) {
  373. if (this._onBeforeRenderObserver) {
  374. this.onBeforeRenderObservable.remove(this._onBeforeRenderObserver);
  375. }
  376. this._onBeforeRenderObserver = this.onBeforeRenderObservable.add(callback);
  377. },
  378. enumerable: true,
  379. configurable: true
  380. });
  381. Object.defineProperty(Scene.prototype, "afterRender", {
  382. set: function (callback) {
  383. if (this._onAfterRenderObserver) {
  384. this.onAfterRenderObservable.remove(this._onAfterRenderObserver);
  385. }
  386. this._onAfterRenderObserver = this.onAfterRenderObservable.add(callback);
  387. },
  388. enumerable: true,
  389. configurable: true
  390. });
  391. Object.defineProperty(Scene.prototype, "beforeCameraRender", {
  392. set: function (callback) {
  393. if (this._onBeforeCameraRenderObserver) {
  394. this.onBeforeCameraRenderObservable.remove(this._onBeforeCameraRenderObserver);
  395. }
  396. this._onBeforeCameraRenderObserver = this.onBeforeCameraRenderObservable.add(callback);
  397. },
  398. enumerable: true,
  399. configurable: true
  400. });
  401. Object.defineProperty(Scene.prototype, "afterCameraRender", {
  402. set: function (callback) {
  403. if (this._onAfterCameraRenderObserver) {
  404. this.onAfterCameraRenderObservable.remove(this._onAfterCameraRenderObserver);
  405. }
  406. this._onAfterCameraRenderObserver = this.onAfterCameraRenderObservable.add(callback);
  407. },
  408. enumerable: true,
  409. configurable: true
  410. });
  411. Object.defineProperty(Scene.prototype, "unTranslatedPointer", {
  412. get: function () {
  413. return new BABYLON.Vector2(this._unTranslatedPointerX, this._unTranslatedPointerY);
  414. },
  415. enumerable: true,
  416. configurable: true
  417. });
  418. Object.defineProperty(Scene.prototype, "debugLayer", {
  419. // Properties
  420. get: function () {
  421. if (!this._debugLayer) {
  422. this._debugLayer = new BABYLON.DebugLayer(this);
  423. }
  424. return this._debugLayer;
  425. },
  426. enumerable: true,
  427. configurable: true
  428. });
  429. Object.defineProperty(Scene.prototype, "workerCollisions", {
  430. get: function () {
  431. return this._workerCollisions;
  432. },
  433. set: function (enabled) {
  434. enabled = (enabled && !!Worker);
  435. this._workerCollisions = enabled;
  436. if (this.collisionCoordinator) {
  437. this.collisionCoordinator.destroy();
  438. }
  439. this.collisionCoordinator = enabled ? new BABYLON.CollisionCoordinatorWorker() : new BABYLON.CollisionCoordinatorLegacy();
  440. this.collisionCoordinator.init(this);
  441. },
  442. enumerable: true,
  443. configurable: true
  444. });
  445. Object.defineProperty(Scene.prototype, "SelectionOctree", {
  446. get: function () {
  447. return this._selectionOctree;
  448. },
  449. enumerable: true,
  450. configurable: true
  451. });
  452. Object.defineProperty(Scene.prototype, "meshUnderPointer", {
  453. /**
  454. * The mesh that is currently under the pointer.
  455. * @return {BABYLON.AbstractMesh} mesh under the pointer/mouse cursor or null if none.
  456. */
  457. get: function () {
  458. return this._pointerOverMesh;
  459. },
  460. enumerable: true,
  461. configurable: true
  462. });
  463. Object.defineProperty(Scene.prototype, "pointerX", {
  464. /**
  465. * Current on-screen X position of the pointer
  466. * @return {number} X position of the pointer
  467. */
  468. get: function () {
  469. return this._pointerX;
  470. },
  471. enumerable: true,
  472. configurable: true
  473. });
  474. Object.defineProperty(Scene.prototype, "pointerY", {
  475. /**
  476. * Current on-screen Y position of the pointer
  477. * @return {number} Y position of the pointer
  478. */
  479. get: function () {
  480. return this._pointerY;
  481. },
  482. enumerable: true,
  483. configurable: true
  484. });
  485. Scene.prototype.getCachedMaterial = function () {
  486. return this._cachedMaterial;
  487. };
  488. Scene.prototype.getBoundingBoxRenderer = function () {
  489. return this._boundingBoxRenderer;
  490. };
  491. Scene.prototype.getOutlineRenderer = function () {
  492. return this._outlineRenderer;
  493. };
  494. Scene.prototype.getEngine = function () {
  495. return this._engine;
  496. };
  497. Scene.prototype.getTotalVertices = function () {
  498. return this._totalVertices.current;
  499. };
  500. Object.defineProperty(Scene.prototype, "totalVerticesPerfCounter", {
  501. get: function () {
  502. return this._totalVertices;
  503. },
  504. enumerable: true,
  505. configurable: true
  506. });
  507. Scene.prototype.getActiveIndices = function () {
  508. return this._activeIndices.current;
  509. };
  510. Object.defineProperty(Scene.prototype, "totalActiveIndicesPerfCounter", {
  511. get: function () {
  512. return this._activeIndices;
  513. },
  514. enumerable: true,
  515. configurable: true
  516. });
  517. Scene.prototype.getActiveParticles = function () {
  518. return this._activeParticles.current;
  519. };
  520. Object.defineProperty(Scene.prototype, "activeParticlesPerfCounter", {
  521. get: function () {
  522. return this._activeParticles;
  523. },
  524. enumerable: true,
  525. configurable: true
  526. });
  527. Scene.prototype.getActiveBones = function () {
  528. return this._activeBones.current;
  529. };
  530. Object.defineProperty(Scene.prototype, "activeBonesPerfCounter", {
  531. get: function () {
  532. return this._activeBones;
  533. },
  534. enumerable: true,
  535. configurable: true
  536. });
  537. // Stats
  538. Scene.prototype.getLastFrameDuration = function () {
  539. return this._lastFrameDuration.current;
  540. };
  541. Object.defineProperty(Scene.prototype, "lastFramePerfCounter", {
  542. get: function () {
  543. return this._lastFrameDuration;
  544. },
  545. enumerable: true,
  546. configurable: true
  547. });
  548. Scene.prototype.getEvaluateActiveMeshesDuration = function () {
  549. return this._evaluateActiveMeshesDuration.current;
  550. };
  551. Object.defineProperty(Scene.prototype, "evaluateActiveMeshesDurationPerfCounter", {
  552. get: function () {
  553. return this._evaluateActiveMeshesDuration;
  554. },
  555. enumerable: true,
  556. configurable: true
  557. });
  558. Scene.prototype.getActiveMeshes = function () {
  559. return this._activeMeshes;
  560. };
  561. Scene.prototype.getRenderTargetsDuration = function () {
  562. return this._renderTargetsDuration.current;
  563. };
  564. Scene.prototype.getRenderDuration = function () {
  565. return this._renderDuration.current;
  566. };
  567. Object.defineProperty(Scene.prototype, "renderDurationPerfCounter", {
  568. get: function () {
  569. return this._renderDuration;
  570. },
  571. enumerable: true,
  572. configurable: true
  573. });
  574. Scene.prototype.getParticlesDuration = function () {
  575. return this._particlesDuration.current;
  576. };
  577. Object.defineProperty(Scene.prototype, "particlesDurationPerfCounter", {
  578. get: function () {
  579. return this._particlesDuration;
  580. },
  581. enumerable: true,
  582. configurable: true
  583. });
  584. Scene.prototype.getSpritesDuration = function () {
  585. return this._spritesDuration.current;
  586. };
  587. Object.defineProperty(Scene.prototype, "spriteDuractionPerfCounter", {
  588. get: function () {
  589. return this._spritesDuration;
  590. },
  591. enumerable: true,
  592. configurable: true
  593. });
  594. Scene.prototype.getAnimationRatio = function () {
  595. return this._animationRatio;
  596. };
  597. Scene.prototype.getRenderId = function () {
  598. return this._renderId;
  599. };
  600. Scene.prototype.incrementRenderId = function () {
  601. this._renderId++;
  602. };
  603. Scene.prototype._updatePointerPosition = function (evt) {
  604. var canvasRect = this._engine.getRenderingCanvasClientRect();
  605. this._pointerX = evt.clientX - canvasRect.left;
  606. this._pointerY = evt.clientY - canvasRect.top;
  607. this._unTranslatedPointerX = this._pointerX;
  608. this._unTranslatedPointerY = this._pointerY;
  609. if (this.cameraToUseForPointers) {
  610. this._pointerX = this._pointerX - this.cameraToUseForPointers.viewport.x * this._engine.getRenderWidth();
  611. this._pointerY = this._pointerY - this.cameraToUseForPointers.viewport.y * this._engine.getRenderHeight();
  612. }
  613. };
  614. // Pointers handling
  615. /**
  616. * Attach events to the canvas (To handle actionManagers triggers and raise onPointerMove, onPointerDown and onPointerUp
  617. * @param attachUp defines if you want to attach events to pointerup
  618. * @param attachDown defines if you want to attach events to pointerdown
  619. * @param attachMove defines if you want to attach events to pointermove
  620. */
  621. Scene.prototype.attachControl = function (attachUp, attachDown, attachMove) {
  622. var _this = this;
  623. if (attachUp === void 0) { attachUp = true; }
  624. if (attachDown === void 0) { attachDown = true; }
  625. if (attachMove === void 0) { attachMove = true; }
  626. var spritePredicate = function (sprite) {
  627. return sprite.isPickable && sprite.actionManager && sprite.actionManager.hasPointerTriggers;
  628. };
  629. this._onPointerMove = function (evt) {
  630. _this._updatePointerPosition(evt);
  631. // PreObservable support
  632. if (_this.onPrePointerObservable.hasObservers()) {
  633. var type = evt.type === "mousewheel" || evt.type === "DOMMouseScroll" ? PointerEventTypes.POINTERWHEEL : PointerEventTypes.POINTERMOVE;
  634. var pi = new PointerInfoPre(type, evt, _this._unTranslatedPointerX, _this._unTranslatedPointerY);
  635. _this.onPrePointerObservable.notifyObservers(pi, type);
  636. if (pi.skipOnPointerObservable) {
  637. return;
  638. }
  639. }
  640. if (!_this.cameraToUseForPointers && !_this.activeCamera) {
  641. return;
  642. }
  643. var canvas = _this._engine.getRenderingCanvas();
  644. if (!_this.pointerMovePredicate) {
  645. _this.pointerMovePredicate = function (mesh) { return mesh.isPickable && mesh.isVisible && mesh.isReady() && (_this.constantlyUpdateMeshUnderPointer || mesh.actionManager !== null && mesh.actionManager !== undefined); };
  646. }
  647. // Meshes
  648. var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this.pointerMovePredicate, false, _this.cameraToUseForPointers);
  649. if (pickResult.hit && pickResult.pickedMesh) {
  650. _this.setPointerOverSprite(null);
  651. _this.setPointerOverMesh(pickResult.pickedMesh);
  652. if (_this._pointerOverMesh.actionManager && _this._pointerOverMesh.actionManager.hasPointerTriggers) {
  653. canvas.style.cursor = _this.hoverCursor;
  654. }
  655. else {
  656. canvas.style.cursor = "";
  657. }
  658. }
  659. else {
  660. _this.setPointerOverMesh(null);
  661. // Sprites
  662. pickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, spritePredicate, false, _this.cameraToUseForPointers);
  663. if (pickResult.hit && pickResult.pickedSprite) {
  664. canvas.style.cursor = _this.hoverCursor;
  665. _this.setPointerOverSprite(pickResult.pickedSprite);
  666. }
  667. else {
  668. _this.setPointerOverSprite(null);
  669. // Restore pointer
  670. canvas.style.cursor = "";
  671. }
  672. }
  673. if (_this.onPointerMove) {
  674. _this.onPointerMove(evt, pickResult);
  675. }
  676. if (_this.onPointerObservable.hasObservers()) {
  677. var type = evt.type === "mousewheel" || evt.type === "DOMMouseScroll" ? PointerEventTypes.POINTERWHEEL : PointerEventTypes.POINTERMOVE;
  678. var pi = new PointerInfo(type, evt, pickResult);
  679. _this.onPointerObservable.notifyObservers(pi, type);
  680. }
  681. };
  682. this._onPointerDown = function (evt) {
  683. _this._updatePointerPosition(evt);
  684. // PreObservable support
  685. if (_this.onPrePointerObservable.hasObservers()) {
  686. var type = PointerEventTypes.POINTERDOWN;
  687. var pi = new PointerInfoPre(type, evt, _this._unTranslatedPointerX, _this._unTranslatedPointerY);
  688. _this.onPrePointerObservable.notifyObservers(pi, type);
  689. if (pi.skipOnPointerObservable) {
  690. return;
  691. }
  692. }
  693. if (!_this.cameraToUseForPointers && !_this.activeCamera) {
  694. return;
  695. }
  696. _this._startingPointerPosition.x = _this._pointerX;
  697. _this._startingPointerPosition.y = _this._pointerY;
  698. _this._startingPointerTime = new Date().getTime();
  699. if (!_this.pointerDownPredicate) {
  700. _this.pointerDownPredicate = function (mesh) {
  701. return mesh.isPickable && mesh.isVisible && mesh.isReady() && (!mesh.actionManager || mesh.actionManager.hasPointerTriggers);
  702. };
  703. }
  704. // Meshes
  705. _this._pickedDownMesh = null;
  706. var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this.pointerDownPredicate, false, _this.cameraToUseForPointers);
  707. if (pickResult.hit && pickResult.pickedMesh) {
  708. if (pickResult.pickedMesh.actionManager) {
  709. _this._pickedDownMesh = pickResult.pickedMesh;
  710. if (pickResult.pickedMesh.actionManager.hasPickTriggers) {
  711. switch (evt.button) {
  712. case 0:
  713. pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnLeftPickTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh, evt));
  714. break;
  715. case 1:
  716. pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnCenterPickTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh, evt));
  717. break;
  718. case 2:
  719. pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnRightPickTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh, evt));
  720. break;
  721. }
  722. pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPickDownTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh, evt));
  723. }
  724. if (pickResult.pickedMesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnLongPressTrigger)) {
  725. var that = _this;
  726. window.setTimeout(function () {
  727. var pickResult = that.pick(that._unTranslatedPointerX, that._unTranslatedPointerY, function (mesh) { return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnLongPressTrigger); }, false, that.cameraToUseForPointers);
  728. if (pickResult.hit && pickResult.pickedMesh) {
  729. if (pickResult.pickedMesh.actionManager) {
  730. if (that._startingPointerTime !== 0 && ((new Date().getTime() - that._startingPointerTime) > BABYLON.ActionManager.LongPressDelay) && (Math.abs(that._startingPointerPosition.x - that._pointerX) < BABYLON.ActionManager.DragMovementThreshold && Math.abs(that._startingPointerPosition.y - that._pointerY) < BABYLON.ActionManager.DragMovementThreshold)) {
  731. that._startingPointerTime = 0;
  732. pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnLongPressTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh, evt));
  733. }
  734. }
  735. }
  736. }, BABYLON.ActionManager.LongPressDelay);
  737. }
  738. }
  739. }
  740. if (_this.onPointerDown) {
  741. _this.onPointerDown(evt, pickResult);
  742. }
  743. if (_this.onPointerObservable.hasObservers()) {
  744. var type = PointerEventTypes.POINTERDOWN;
  745. var pi = new PointerInfo(type, evt, pickResult);
  746. _this.onPointerObservable.notifyObservers(pi, type);
  747. }
  748. // Sprites
  749. _this._pickedDownSprite = null;
  750. if (_this.spriteManagers.length > 0) {
  751. pickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, spritePredicate, false, _this.cameraToUseForPointers);
  752. if (pickResult.hit && pickResult.pickedSprite) {
  753. if (pickResult.pickedSprite.actionManager) {
  754. _this._pickedDownSprite = pickResult.pickedSprite;
  755. switch (evt.button) {
  756. case 0:
  757. pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnLeftPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
  758. break;
  759. case 1:
  760. pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnCenterPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
  761. break;
  762. case 2:
  763. pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnRightPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
  764. break;
  765. }
  766. pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickDownTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
  767. }
  768. }
  769. }
  770. };
  771. this._onPointerUp = function (evt) {
  772. _this._updatePointerPosition(evt);
  773. // PreObservable support
  774. if (_this.onPrePointerObservable.hasObservers()) {
  775. var type = PointerEventTypes.POINTERUP;
  776. var pi = new PointerInfoPre(type, evt, _this._unTranslatedPointerX, _this._unTranslatedPointerY);
  777. _this.onPrePointerObservable.notifyObservers(pi, type);
  778. if (pi.skipOnPointerObservable) {
  779. return;
  780. }
  781. }
  782. if (!_this.cameraToUseForPointers && !_this.activeCamera) {
  783. return;
  784. }
  785. if (!_this.pointerUpPredicate) {
  786. _this.pointerUpPredicate = function (mesh) {
  787. return mesh.isPickable && mesh.isVisible && mesh.isReady() && (!mesh.actionManager || (mesh.actionManager.hasPickTriggers || mesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnLongPressTrigger)));
  788. };
  789. }
  790. // Meshes
  791. var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this.pointerUpPredicate, false, _this.cameraToUseForPointers);
  792. if (pickResult.hit && pickResult.pickedMesh) {
  793. if (_this._pickedDownMesh != null && pickResult.pickedMesh == _this._pickedDownMesh) {
  794. if (_this.onPointerPick) {
  795. _this.onPointerPick(evt, pickResult);
  796. }
  797. if (_this.onPointerObservable.hasObservers()) {
  798. var type = PointerEventTypes.POINTERPICK;
  799. var pi = new PointerInfo(type, evt, pickResult);
  800. _this.onPointerObservable.notifyObservers(pi, type);
  801. }
  802. }
  803. if (pickResult.pickedMesh.actionManager) {
  804. pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh, evt));
  805. if (Math.abs(_this._startingPointerPosition.x - _this._pointerX) < BABYLON.ActionManager.DragMovementThreshold && Math.abs(_this._startingPointerPosition.y - _this._pointerY) < BABYLON.ActionManager.DragMovementThreshold) {
  806. pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh, evt));
  807. }
  808. }
  809. }
  810. if (_this._pickedDownMesh && _this._pickedDownMesh !== pickResult.pickedMesh) {
  811. _this._pickedDownMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, BABYLON.ActionEvent.CreateNew(_this._pickedDownMesh, evt));
  812. }
  813. if (_this.onPointerUp) {
  814. _this.onPointerUp(evt, pickResult);
  815. }
  816. if (_this.onPointerObservable.hasObservers()) {
  817. var type = PointerEventTypes.POINTERUP;
  818. var pi = new PointerInfo(type, evt, pickResult);
  819. _this.onPointerObservable.notifyObservers(pi, type);
  820. }
  821. _this._startingPointerTime = 0;
  822. // Sprites
  823. if (_this.spriteManagers.length > 0) {
  824. pickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, spritePredicate, false, _this.cameraToUseForPointers);
  825. if (pickResult.hit && pickResult.pickedSprite) {
  826. if (pickResult.pickedSprite.actionManager) {
  827. pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
  828. if (Math.abs(_this._startingPointerPosition.x - _this._pointerX) < BABYLON.ActionManager.DragMovementThreshold && Math.abs(_this._startingPointerPosition.y - _this._pointerY) < BABYLON.ActionManager.DragMovementThreshold) {
  829. pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
  830. }
  831. }
  832. }
  833. if (_this._pickedDownSprite && _this._pickedDownSprite !== pickResult.pickedSprite) {
  834. _this._pickedDownSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, BABYLON.ActionEvent.CreateNewFromSprite(_this._pickedDownSprite, _this, evt));
  835. }
  836. }
  837. };
  838. this._onKeyDown = function (evt) {
  839. if (_this.actionManager) {
  840. _this.actionManager.processTrigger(BABYLON.ActionManager.OnKeyDownTrigger, BABYLON.ActionEvent.CreateNewFromScene(_this, evt));
  841. }
  842. };
  843. this._onKeyUp = function (evt) {
  844. if (_this.actionManager) {
  845. _this.actionManager.processTrigger(BABYLON.ActionManager.OnKeyUpTrigger, BABYLON.ActionEvent.CreateNewFromScene(_this, evt));
  846. }
  847. };
  848. var eventPrefix = BABYLON.Tools.GetPointerPrefix();
  849. var canvas = this._engine.getRenderingCanvas();
  850. if (attachMove) {
  851. canvas.addEventListener(eventPrefix + "move", this._onPointerMove, false);
  852. // Wheel
  853. canvas.addEventListener('mousewheel', this._onPointerMove, false);
  854. canvas.addEventListener('DOMMouseScroll', this._onPointerMove, false);
  855. }
  856. if (attachDown) {
  857. canvas.addEventListener(eventPrefix + "down", this._onPointerDown, false);
  858. }
  859. if (attachUp) {
  860. canvas.addEventListener(eventPrefix + "up", this._onPointerUp, false);
  861. }
  862. canvas.tabIndex = 1;
  863. canvas.addEventListener("keydown", this._onKeyDown, false);
  864. canvas.addEventListener("keyup", this._onKeyUp, false);
  865. };
  866. Scene.prototype.detachControl = function () {
  867. var eventPrefix = BABYLON.Tools.GetPointerPrefix();
  868. var canvas = this._engine.getRenderingCanvas();
  869. canvas.removeEventListener(eventPrefix + "move", this._onPointerMove);
  870. canvas.removeEventListener(eventPrefix + "down", this._onPointerDown);
  871. canvas.removeEventListener(eventPrefix + "up", this._onPointerUp);
  872. // Wheel
  873. canvas.removeEventListener('mousewheel', this._onPointerMove);
  874. canvas.removeEventListener('DOMMouseScroll', this._onPointerMove);
  875. canvas.removeEventListener("keydown", this._onKeyDown);
  876. canvas.removeEventListener("keyup", this._onKeyUp);
  877. };
  878. // Ready
  879. Scene.prototype.isReady = function () {
  880. if (this._pendingData.length > 0) {
  881. return false;
  882. }
  883. var index;
  884. for (index = 0; index < this._geometries.length; index++) {
  885. var geometry = this._geometries[index];
  886. if (geometry.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADING) {
  887. return false;
  888. }
  889. }
  890. for (index = 0; index < this.meshes.length; index++) {
  891. var mesh = this.meshes[index];
  892. if (!mesh.isReady()) {
  893. return false;
  894. }
  895. var mat = mesh.material;
  896. if (mat) {
  897. if (!mat.isReady(mesh)) {
  898. return false;
  899. }
  900. }
  901. }
  902. return true;
  903. };
  904. Scene.prototype.resetCachedMaterial = function () {
  905. this._cachedMaterial = null;
  906. };
  907. Scene.prototype.registerBeforeRender = function (func) {
  908. this.onBeforeRenderObservable.add(func);
  909. };
  910. Scene.prototype.unregisterBeforeRender = function (func) {
  911. this.onBeforeRenderObservable.removeCallback(func);
  912. };
  913. Scene.prototype.registerAfterRender = function (func) {
  914. this.onAfterRenderObservable.add(func);
  915. };
  916. Scene.prototype.unregisterAfterRender = function (func) {
  917. this.onAfterRenderObservable.removeCallback(func);
  918. };
  919. Scene.prototype._addPendingData = function (data) {
  920. this._pendingData.push(data);
  921. };
  922. Scene.prototype._removePendingData = function (data) {
  923. var index = this._pendingData.indexOf(data);
  924. if (index !== -1) {
  925. this._pendingData.splice(index, 1);
  926. }
  927. };
  928. Scene.prototype.getWaitingItemsCount = function () {
  929. return this._pendingData.length;
  930. };
  931. /**
  932. * Registers a function to be executed when the scene is ready.
  933. * @param {Function} func - the function to be executed.
  934. */
  935. Scene.prototype.executeWhenReady = function (func) {
  936. var _this = this;
  937. this.onReadyObservable.add(func);
  938. if (this._executeWhenReadyTimeoutId !== -1) {
  939. return;
  940. }
  941. this._executeWhenReadyTimeoutId = setTimeout(function () {
  942. _this._checkIsReady();
  943. }, 150);
  944. };
  945. Scene.prototype._checkIsReady = function () {
  946. var _this = this;
  947. if (this.isReady()) {
  948. this.onReadyObservable.notifyObservers(this);
  949. this.onReadyObservable.clear();
  950. this._executeWhenReadyTimeoutId = -1;
  951. return;
  952. }
  953. this._executeWhenReadyTimeoutId = setTimeout(function () {
  954. _this._checkIsReady();
  955. }, 150);
  956. };
  957. // Animations
  958. /**
  959. * Will start the animation sequence of a given target
  960. * @param target - the target
  961. * @param {number} from - from which frame should animation start
  962. * @param {number} to - till which frame should animation run.
  963. * @param {boolean} [loop] - should the animation loop
  964. * @param {number} [speedRatio] - the speed in which to run the animation
  965. * @param {Function} [onAnimationEnd] function to be executed when the animation ended.
  966. * @param {BABYLON.Animatable} [animatable] an animatable object. If not provided a new one will be created from the given params.
  967. * @return {BABYLON.Animatable} the animatable object created for this animation
  968. * @see BABYLON.Animatable
  969. * @see http://doc.babylonjs.com/page.php?p=22081
  970. */
  971. Scene.prototype.beginAnimation = function (target, from, to, loop, speedRatio, onAnimationEnd, animatable) {
  972. if (speedRatio === void 0) { speedRatio = 1.0; }
  973. this.stopAnimation(target);
  974. if (!animatable) {
  975. animatable = new BABYLON.Animatable(this, target, from, to, loop, speedRatio, onAnimationEnd);
  976. }
  977. // Local animations
  978. if (target.animations) {
  979. animatable.appendAnimations(target, target.animations);
  980. }
  981. // Children animations
  982. if (target.getAnimatables) {
  983. var animatables = target.getAnimatables();
  984. for (var index = 0; index < animatables.length; index++) {
  985. this.beginAnimation(animatables[index], from, to, loop, speedRatio, onAnimationEnd, animatable);
  986. }
  987. }
  988. animatable.reset();
  989. return animatable;
  990. };
  991. Scene.prototype.beginDirectAnimation = function (target, animations, from, to, loop, speedRatio, onAnimationEnd) {
  992. if (speedRatio === undefined) {
  993. speedRatio = 1.0;
  994. }
  995. var animatable = new BABYLON.Animatable(this, target, from, to, loop, speedRatio, onAnimationEnd, animations);
  996. return animatable;
  997. };
  998. Scene.prototype.getAnimatableByTarget = function (target) {
  999. for (var index = 0; index < this._activeAnimatables.length; index++) {
  1000. if (this._activeAnimatables[index].target === target) {
  1001. return this._activeAnimatables[index];
  1002. }
  1003. }
  1004. return null;
  1005. };
  1006. Object.defineProperty(Scene.prototype, "Animatables", {
  1007. get: function () {
  1008. return this._activeAnimatables;
  1009. },
  1010. enumerable: true,
  1011. configurable: true
  1012. });
  1013. /**
  1014. * Will stop the animation of the given target
  1015. * @param target - the target
  1016. * @see beginAnimation
  1017. */
  1018. Scene.prototype.stopAnimation = function (target) {
  1019. var animatable = this.getAnimatableByTarget(target);
  1020. if (animatable) {
  1021. animatable.stop();
  1022. }
  1023. };
  1024. Scene.prototype._animate = function () {
  1025. if (!this.animationsEnabled || this._activeAnimatables.length === 0) {
  1026. return;
  1027. }
  1028. if (!this._animationStartDate) {
  1029. if (this._pendingData.length > 0) {
  1030. return;
  1031. }
  1032. this._animationStartDate = BABYLON.Tools.Now;
  1033. }
  1034. // Getting time
  1035. var now = BABYLON.Tools.Now;
  1036. var delay = now - this._animationStartDate;
  1037. for (var index = 0; index < this._activeAnimatables.length; index++) {
  1038. this._activeAnimatables[index]._animate(delay);
  1039. }
  1040. };
  1041. // Matrix
  1042. Scene.prototype.getViewMatrix = function () {
  1043. return this._viewMatrix;
  1044. };
  1045. Scene.prototype.getProjectionMatrix = function () {
  1046. return this._projectionMatrix;
  1047. };
  1048. Scene.prototype.getTransformMatrix = function () {
  1049. return this._transformMatrix;
  1050. };
  1051. Scene.prototype.setTransformMatrix = function (view, projection) {
  1052. this._viewMatrix = view;
  1053. this._projectionMatrix = projection;
  1054. this._viewMatrix.multiplyToRef(this._projectionMatrix, this._transformMatrix);
  1055. // Update frustum
  1056. if (!this._frustumPlanes) {
  1057. this._frustumPlanes = BABYLON.Frustum.GetPlanes(this._transformMatrix);
  1058. }
  1059. else {
  1060. BABYLON.Frustum.GetPlanesToRef(this._transformMatrix, this._frustumPlanes);
  1061. }
  1062. };
  1063. // Methods
  1064. Scene.prototype.addMesh = function (newMesh) {
  1065. newMesh.uniqueId = this._uniqueIdCounter++;
  1066. var position = this.meshes.push(newMesh);
  1067. //notify the collision coordinator
  1068. this.collisionCoordinator.onMeshAdded(newMesh);
  1069. this.onNewMeshAddedObservable.notifyObservers(newMesh);
  1070. };
  1071. Scene.prototype.removeMesh = function (toRemove) {
  1072. var index = this.meshes.indexOf(toRemove);
  1073. if (index !== -1) {
  1074. // Remove from the scene if mesh found
  1075. this.meshes.splice(index, 1);
  1076. }
  1077. //notify the collision coordinator
  1078. this.collisionCoordinator.onMeshRemoved(toRemove);
  1079. this.onMeshRemovedObservable.notifyObservers(toRemove);
  1080. return index;
  1081. };
  1082. Scene.prototype.removeSkeleton = function (toRemove) {
  1083. var index = this.skeletons.indexOf(toRemove);
  1084. if (index !== -1) {
  1085. // Remove from the scene if mesh found
  1086. this.skeletons.splice(index, 1);
  1087. }
  1088. return index;
  1089. };
  1090. Scene.prototype.removeLight = function (toRemove) {
  1091. var index = this.lights.indexOf(toRemove);
  1092. if (index !== -1) {
  1093. // Remove from the scene if mesh found
  1094. this.lights.splice(index, 1);
  1095. }
  1096. this.onLightRemovedObservable.notifyObservers(toRemove);
  1097. return index;
  1098. };
  1099. Scene.prototype.removeCamera = function (toRemove) {
  1100. var index = this.cameras.indexOf(toRemove);
  1101. if (index !== -1) {
  1102. // Remove from the scene if mesh found
  1103. this.cameras.splice(index, 1);
  1104. }
  1105. // Remove from activeCameras
  1106. var index2 = this.activeCameras.indexOf(toRemove);
  1107. if (index2 !== -1) {
  1108. // Remove from the scene if mesh found
  1109. this.activeCameras.splice(index2, 1);
  1110. }
  1111. // Reset the activeCamera
  1112. if (this.activeCamera === toRemove) {
  1113. if (this.cameras.length > 0) {
  1114. this.activeCamera = this.cameras[0];
  1115. }
  1116. else {
  1117. this.activeCamera = null;
  1118. }
  1119. }
  1120. this.onCameraRemovedObservable.notifyObservers(toRemove);
  1121. return index;
  1122. };
  1123. Scene.prototype.addLight = function (newLight) {
  1124. newLight.uniqueId = this._uniqueIdCounter++;
  1125. var position = this.lights.push(newLight);
  1126. this.onNewLightAddedObservable.notifyObservers(newLight);
  1127. };
  1128. Scene.prototype.addCamera = function (newCamera) {
  1129. newCamera.uniqueId = this._uniqueIdCounter++;
  1130. var position = this.cameras.push(newCamera);
  1131. this.onNewCameraAddedObservable.notifyObservers(newCamera);
  1132. };
  1133. /**
  1134. * Switch active camera
  1135. * @param {Camera} newCamera - new active camera
  1136. * @param {boolean} attachControl - call attachControl for the new active camera (default: true)
  1137. */
  1138. Scene.prototype.switchActiveCamera = function (newCamera, attachControl) {
  1139. if (attachControl === void 0) { attachControl = true; }
  1140. var canvas = this._engine.getRenderingCanvas();
  1141. this.activeCamera.detachControl(canvas);
  1142. this.activeCamera = newCamera;
  1143. if (attachControl) {
  1144. newCamera.attachControl(canvas);
  1145. }
  1146. };
  1147. /**
  1148. * sets the active camera of the scene using its ID
  1149. * @param {string} id - the camera's ID
  1150. * @return {BABYLON.Camera|null} the new active camera or null if none found.
  1151. * @see activeCamera
  1152. */
  1153. Scene.prototype.setActiveCameraByID = function (id) {
  1154. var camera = this.getCameraByID(id);
  1155. if (camera) {
  1156. this.activeCamera = camera;
  1157. return camera;
  1158. }
  1159. return null;
  1160. };
  1161. /**
  1162. * sets the active camera of the scene using its name
  1163. * @param {string} name - the camera's name
  1164. * @return {BABYLON.Camera|null} the new active camera or null if none found.
  1165. * @see activeCamera
  1166. */
  1167. Scene.prototype.setActiveCameraByName = function (name) {
  1168. var camera = this.getCameraByName(name);
  1169. if (camera) {
  1170. this.activeCamera = camera;
  1171. return camera;
  1172. }
  1173. return null;
  1174. };
  1175. /**
  1176. * get a material using its id
  1177. * @param {string} the material's ID
  1178. * @return {BABYLON.Material|null} the material or null if none found.
  1179. */
  1180. Scene.prototype.getMaterialByID = function (id) {
  1181. for (var index = 0; index < this.materials.length; index++) {
  1182. if (this.materials[index].id === id) {
  1183. return this.materials[index];
  1184. }
  1185. }
  1186. return null;
  1187. };
  1188. /**
  1189. * get a material using its name
  1190. * @param {string} the material's name
  1191. * @return {BABYLON.Material|null} the material or null if none found.
  1192. */
  1193. Scene.prototype.getMaterialByName = function (name) {
  1194. for (var index = 0; index < this.materials.length; index++) {
  1195. if (this.materials[index].name === name) {
  1196. return this.materials[index];
  1197. }
  1198. }
  1199. return null;
  1200. };
  1201. Scene.prototype.getLensFlareSystemByName = function (name) {
  1202. for (var index = 0; index < this.lensFlareSystems.length; index++) {
  1203. if (this.lensFlareSystems[index].name === name) {
  1204. return this.lensFlareSystems[index];
  1205. }
  1206. }
  1207. return null;
  1208. };
  1209. Scene.prototype.getLensFlareSystemByID = function (id) {
  1210. for (var index = 0; index < this.lensFlareSystems.length; index++) {
  1211. if (this.lensFlareSystems[index].id === id) {
  1212. return this.lensFlareSystems[index];
  1213. }
  1214. }
  1215. return null;
  1216. };
  1217. Scene.prototype.getCameraByID = function (id) {
  1218. for (var index = 0; index < this.cameras.length; index++) {
  1219. if (this.cameras[index].id === id) {
  1220. return this.cameras[index];
  1221. }
  1222. }
  1223. return null;
  1224. };
  1225. Scene.prototype.getCameraByUniqueID = function (uniqueId) {
  1226. for (var index = 0; index < this.cameras.length; index++) {
  1227. if (this.cameras[index].uniqueId === uniqueId) {
  1228. return this.cameras[index];
  1229. }
  1230. }
  1231. return null;
  1232. };
  1233. /**
  1234. * get a camera using its name
  1235. * @param {string} the camera's name
  1236. * @return {BABYLON.Camera|null} the camera or null if none found.
  1237. */
  1238. Scene.prototype.getCameraByName = function (name) {
  1239. for (var index = 0; index < this.cameras.length; index++) {
  1240. if (this.cameras[index].name === name) {
  1241. return this.cameras[index];
  1242. }
  1243. }
  1244. return null;
  1245. };
  1246. /**
  1247. * get a bone using its id
  1248. * @param {string} the bone's id
  1249. * @return {BABYLON.Bone|null} the bone or null if not found
  1250. */
  1251. Scene.prototype.getBoneByID = function (id) {
  1252. for (var skeletonIndex = 0; skeletonIndex < this.skeletons.length; skeletonIndex++) {
  1253. var skeleton = this.skeletons[skeletonIndex];
  1254. for (var boneIndex = 0; boneIndex < skeleton.bones.length; boneIndex++) {
  1255. if (skeleton.bones[boneIndex].id === id) {
  1256. return skeleton.bones[boneIndex];
  1257. }
  1258. }
  1259. }
  1260. return null;
  1261. };
  1262. /**
  1263. * get a bone using its id
  1264. * @param {string} the bone's name
  1265. * @return {BABYLON.Bone|null} the bone or null if not found
  1266. */
  1267. Scene.prototype.getBoneByName = function (name) {
  1268. for (var skeletonIndex = 0; skeletonIndex < this.skeletons.length; skeletonIndex++) {
  1269. var skeleton = this.skeletons[skeletonIndex];
  1270. for (var boneIndex = 0; boneIndex < skeleton.bones.length; boneIndex++) {
  1271. if (skeleton.bones[boneIndex].name === name) {
  1272. return skeleton.bones[boneIndex];
  1273. }
  1274. }
  1275. }
  1276. return null;
  1277. };
  1278. /**
  1279. * get a light node using its name
  1280. * @param {string} the light's name
  1281. * @return {BABYLON.Light|null} the light or null if none found.
  1282. */
  1283. Scene.prototype.getLightByName = function (name) {
  1284. for (var index = 0; index < this.lights.length; index++) {
  1285. if (this.lights[index].name === name) {
  1286. return this.lights[index];
  1287. }
  1288. }
  1289. return null;
  1290. };
  1291. /**
  1292. * get a light node using its ID
  1293. * @param {string} the light's id
  1294. * @return {BABYLON.Light|null} the light or null if none found.
  1295. */
  1296. Scene.prototype.getLightByID = function (id) {
  1297. for (var index = 0; index < this.lights.length; index++) {
  1298. if (this.lights[index].id === id) {
  1299. return this.lights[index];
  1300. }
  1301. }
  1302. return null;
  1303. };
  1304. /**
  1305. * get a light node using its scene-generated unique ID
  1306. * @param {number} the light's unique id
  1307. * @return {BABYLON.Light|null} the light or null if none found.
  1308. */
  1309. Scene.prototype.getLightByUniqueID = function (uniqueId) {
  1310. for (var index = 0; index < this.lights.length; index++) {
  1311. if (this.lights[index].uniqueId === uniqueId) {
  1312. return this.lights[index];
  1313. }
  1314. }
  1315. return null;
  1316. };
  1317. /**
  1318. * get a particle system by id
  1319. * @param id {number} the particle system id
  1320. * @return {BABYLON.ParticleSystem|null} the corresponding system or null if none found.
  1321. */
  1322. Scene.prototype.getParticleSystemByID = function (id) {
  1323. for (var index = 0; index < this.particleSystems.length; index++) {
  1324. if (this.particleSystems[index].id === id) {
  1325. return this.particleSystems[index];
  1326. }
  1327. }
  1328. return null;
  1329. };
  1330. /**
  1331. * get a geometry using its ID
  1332. * @param {string} the geometry's id
  1333. * @return {BABYLON.Geometry|null} the geometry or null if none found.
  1334. */
  1335. Scene.prototype.getGeometryByID = function (id) {
  1336. for (var index = 0; index < this._geometries.length; index++) {
  1337. if (this._geometries[index].id === id) {
  1338. return this._geometries[index];
  1339. }
  1340. }
  1341. return null;
  1342. };
  1343. /**
  1344. * add a new geometry to this scene.
  1345. * @param {BABYLON.Geometry} geometry - the geometry to be added to the scene.
  1346. * @param {boolean} [force] - force addition, even if a geometry with this ID already exists
  1347. * @return {boolean} was the geometry added or not
  1348. */
  1349. Scene.prototype.pushGeometry = function (geometry, force) {
  1350. if (!force && this.getGeometryByID(geometry.id)) {
  1351. return false;
  1352. }
  1353. this._geometries.push(geometry);
  1354. //notify the collision coordinator
  1355. this.collisionCoordinator.onGeometryAdded(geometry);
  1356. this.onNewGeometryAddedObservable.notifyObservers(geometry);
  1357. return true;
  1358. };
  1359. /**
  1360. * Removes an existing geometry
  1361. * @param {BABYLON.Geometry} geometry - the geometry to be removed from the scene.
  1362. * @return {boolean} was the geometry removed or not
  1363. */
  1364. Scene.prototype.removeGeometry = function (geometry) {
  1365. var index = this._geometries.indexOf(geometry);
  1366. if (index > -1) {
  1367. this._geometries.splice(index, 1);
  1368. //notify the collision coordinator
  1369. this.collisionCoordinator.onGeometryDeleted(geometry);
  1370. this.onGeometryRemovedObservable.notifyObservers(geometry);
  1371. return true;
  1372. }
  1373. return false;
  1374. };
  1375. Scene.prototype.getGeometries = function () {
  1376. return this._geometries;
  1377. };
  1378. /**
  1379. * Get the first added mesh found of a given ID
  1380. * @param {string} id - the id to search for
  1381. * @return {BABYLON.AbstractMesh|null} the mesh found or null if not found at all.
  1382. */
  1383. Scene.prototype.getMeshByID = function (id) {
  1384. for (var index = 0; index < this.meshes.length; index++) {
  1385. if (this.meshes[index].id === id) {
  1386. return this.meshes[index];
  1387. }
  1388. }
  1389. return null;
  1390. };
  1391. Scene.prototype.getMeshesByID = function (id) {
  1392. return this.meshes.filter(function (m) {
  1393. return m.id === id;
  1394. });
  1395. };
  1396. /**
  1397. * Get a mesh with its auto-generated unique id
  1398. * @param {number} uniqueId - the unique id to search for
  1399. * @return {BABYLON.AbstractMesh|null} the mesh found or null if not found at all.
  1400. */
  1401. Scene.prototype.getMeshByUniqueID = function (uniqueId) {
  1402. for (var index = 0; index < this.meshes.length; index++) {
  1403. if (this.meshes[index].uniqueId === uniqueId) {
  1404. return this.meshes[index];
  1405. }
  1406. }
  1407. return null;
  1408. };
  1409. /**
  1410. * Get a the last added mesh found of a given ID
  1411. * @param {string} id - the id to search for
  1412. * @return {BABYLON.AbstractMesh|null} the mesh found or null if not found at all.
  1413. */
  1414. Scene.prototype.getLastMeshByID = function (id) {
  1415. for (var index = this.meshes.length - 1; index >= 0; index--) {
  1416. if (this.meshes[index].id === id) {
  1417. return this.meshes[index];
  1418. }
  1419. }
  1420. return null;
  1421. };
  1422. /**
  1423. * Get a the last added node (Mesh, Camera, Light) found of a given ID
  1424. * @param {string} id - the id to search for
  1425. * @return {BABYLON.Node|null} the node found or null if not found at all.
  1426. */
  1427. Scene.prototype.getLastEntryByID = function (id) {
  1428. var index;
  1429. for (index = this.meshes.length - 1; index >= 0; index--) {
  1430. if (this.meshes[index].id === id) {
  1431. return this.meshes[index];
  1432. }
  1433. }
  1434. for (index = this.cameras.length - 1; index >= 0; index--) {
  1435. if (this.cameras[index].id === id) {
  1436. return this.cameras[index];
  1437. }
  1438. }
  1439. for (index = this.lights.length - 1; index >= 0; index--) {
  1440. if (this.lights[index].id === id) {
  1441. return this.lights[index];
  1442. }
  1443. }
  1444. return null;
  1445. };
  1446. Scene.prototype.getNodeByID = function (id) {
  1447. var mesh = this.getMeshByID(id);
  1448. if (mesh) {
  1449. return mesh;
  1450. }
  1451. var light = this.getLightByID(id);
  1452. if (light) {
  1453. return light;
  1454. }
  1455. var camera = this.getCameraByID(id);
  1456. if (camera) {
  1457. return camera;
  1458. }
  1459. var bone = this.getBoneByID(id);
  1460. return bone;
  1461. };
  1462. Scene.prototype.getNodeByName = function (name) {
  1463. var mesh = this.getMeshByName(name);
  1464. if (mesh) {
  1465. return mesh;
  1466. }
  1467. var light = this.getLightByName(name);
  1468. if (light) {
  1469. return light;
  1470. }
  1471. var camera = this.getCameraByName(name);
  1472. if (camera) {
  1473. return camera;
  1474. }
  1475. var bone = this.getBoneByName(name);
  1476. return bone;
  1477. };
  1478. Scene.prototype.getMeshByName = function (name) {
  1479. for (var index = 0; index < this.meshes.length; index++) {
  1480. if (this.meshes[index].name === name) {
  1481. return this.meshes[index];
  1482. }
  1483. }
  1484. return null;
  1485. };
  1486. Scene.prototype.getSoundByName = function (name) {
  1487. var index;
  1488. if (BABYLON.AudioEngine) {
  1489. for (index = 0; index < this.mainSoundTrack.soundCollection.length; index++) {
  1490. if (this.mainSoundTrack.soundCollection[index].name === name) {
  1491. return this.mainSoundTrack.soundCollection[index];
  1492. }
  1493. }
  1494. for (var sdIndex = 0; sdIndex < this.soundTracks.length; sdIndex++) {
  1495. for (index = 0; index < this.soundTracks[sdIndex].soundCollection.length; index++) {
  1496. if (this.soundTracks[sdIndex].soundCollection[index].name === name) {
  1497. return this.soundTracks[sdIndex].soundCollection[index];
  1498. }
  1499. }
  1500. }
  1501. }
  1502. return null;
  1503. };
  1504. Scene.prototype.getLastSkeletonByID = function (id) {
  1505. for (var index = this.skeletons.length - 1; index >= 0; index--) {
  1506. if (this.skeletons[index].id === id) {
  1507. return this.skeletons[index];
  1508. }
  1509. }
  1510. return null;
  1511. };
  1512. Scene.prototype.getSkeletonById = function (id) {
  1513. for (var index = 0; index < this.skeletons.length; index++) {
  1514. if (this.skeletons[index].id === id) {
  1515. return this.skeletons[index];
  1516. }
  1517. }
  1518. return null;
  1519. };
  1520. Scene.prototype.getSkeletonByName = function (name) {
  1521. for (var index = 0; index < this.skeletons.length; index++) {
  1522. if (this.skeletons[index].name === name) {
  1523. return this.skeletons[index];
  1524. }
  1525. }
  1526. return null;
  1527. };
  1528. Scene.prototype.isActiveMesh = function (mesh) {
  1529. return (this._activeMeshes.indexOf(mesh) !== -1);
  1530. };
  1531. Scene.prototype._evaluateSubMesh = function (subMesh, mesh) {
  1532. if (mesh.alwaysSelectAsActiveMesh || mesh.subMeshes.length === 1 || subMesh.isInFrustum(this._frustumPlanes)) {
  1533. var material = subMesh.getMaterial();
  1534. if (mesh.showSubMeshesBoundingBox) {
  1535. this._boundingBoxRenderer.renderList.push(subMesh.getBoundingInfo().boundingBox);
  1536. }
  1537. if (material) {
  1538. // Render targets
  1539. if (material.getRenderTargetTextures) {
  1540. if (this._processedMaterials.indexOf(material) === -1) {
  1541. this._processedMaterials.push(material);
  1542. this._renderTargets.concatWithNoDuplicate(material.getRenderTargetTextures());
  1543. }
  1544. }
  1545. // Dispatch
  1546. this._activeIndices.addCount(subMesh.indexCount, false);
  1547. this._renderingManager.dispatch(subMesh);
  1548. }
  1549. }
  1550. };
  1551. Scene.prototype._isInIntermediateRendering = function () {
  1552. return this._intermediateRendering;
  1553. };
  1554. Scene.prototype._evaluateActiveMeshes = function () {
  1555. this.activeCamera._activeMeshes.reset();
  1556. this._activeMeshes.reset();
  1557. this._renderingManager.reset();
  1558. this._processedMaterials.reset();
  1559. this._activeParticleSystems.reset();
  1560. this._activeSkeletons.reset();
  1561. this._softwareSkinnedMeshes.reset();
  1562. this._boundingBoxRenderer.reset();
  1563. this._edgesRenderers.reset();
  1564. // Meshes
  1565. var meshes;
  1566. var len;
  1567. if (this._selectionOctree) {
  1568. var selection = this._selectionOctree.select(this._frustumPlanes);
  1569. meshes = selection.data;
  1570. len = selection.length;
  1571. }
  1572. else {
  1573. len = this.meshes.length;
  1574. meshes = this.meshes;
  1575. }
  1576. for (var meshIndex = 0; meshIndex < len; meshIndex++) {
  1577. var mesh = meshes[meshIndex];
  1578. if (mesh.isBlocked) {
  1579. continue;
  1580. }
  1581. this._totalVertices.addCount(mesh.getTotalVertices(), false);
  1582. if (!mesh.isReady() || !mesh.isEnabled()) {
  1583. continue;
  1584. }
  1585. mesh.computeWorldMatrix();
  1586. // Intersections
  1587. if (mesh.actionManager && mesh.actionManager.hasSpecificTriggers([BABYLON.ActionManager.OnIntersectionEnterTrigger, BABYLON.ActionManager.OnIntersectionExitTrigger])) {
  1588. this._meshesForIntersections.pushNoDuplicate(mesh);
  1589. }
  1590. // Switch to current LOD
  1591. var meshLOD = mesh.getLOD(this.activeCamera);
  1592. if (!meshLOD) {
  1593. continue;
  1594. }
  1595. mesh._preActivate();
  1596. if (mesh.alwaysSelectAsActiveMesh || mesh.isVisible && mesh.visibility > 0 && ((mesh.layerMask & this.activeCamera.layerMask) !== 0) && mesh.isInFrustum(this._frustumPlanes)) {
  1597. this._activeMeshes.push(mesh);
  1598. this.activeCamera._activeMeshes.push(mesh);
  1599. mesh._activate(this._renderId);
  1600. this._activeMesh(mesh, meshLOD);
  1601. }
  1602. }
  1603. // Particle systems
  1604. this._particlesDuration.beginMonitoring();
  1605. var beforeParticlesDate = BABYLON.Tools.Now;
  1606. if (this.particlesEnabled) {
  1607. BABYLON.Tools.StartPerformanceCounter("Particles", this.particleSystems.length > 0);
  1608. for (var particleIndex = 0; particleIndex < this.particleSystems.length; particleIndex++) {
  1609. var particleSystem = this.particleSystems[particleIndex];
  1610. if (!particleSystem.isStarted()) {
  1611. continue;
  1612. }
  1613. if (!particleSystem.emitter.position || (particleSystem.emitter && particleSystem.emitter.isEnabled())) {
  1614. this._activeParticleSystems.push(particleSystem);
  1615. particleSystem.animate();
  1616. }
  1617. }
  1618. BABYLON.Tools.EndPerformanceCounter("Particles", this.particleSystems.length > 0);
  1619. }
  1620. this._particlesDuration.endMonitoring(false);
  1621. };
  1622. Scene.prototype._activeMesh = function (sourceMesh, mesh) {
  1623. if (mesh.skeleton && this.skeletonsEnabled) {
  1624. if (this._activeSkeletons.pushNoDuplicate(mesh.skeleton)) {
  1625. mesh.skeleton.prepare();
  1626. }
  1627. if (!mesh.computeBonesUsingShaders) {
  1628. this._softwareSkinnedMeshes.pushNoDuplicate(mesh);
  1629. }
  1630. }
  1631. if (sourceMesh.showBoundingBox || this.forceShowBoundingBoxes) {
  1632. this._boundingBoxRenderer.renderList.push(sourceMesh.getBoundingInfo().boundingBox);
  1633. }
  1634. if (sourceMesh._edgesRenderer) {
  1635. this._edgesRenderers.push(sourceMesh._edgesRenderer);
  1636. }
  1637. if (mesh && mesh.subMeshes) {
  1638. // Submeshes Octrees
  1639. var len;
  1640. var subMeshes;
  1641. if (mesh._submeshesOctree && mesh.useOctreeForRenderingSelection) {
  1642. var intersections = mesh._submeshesOctree.select(this._frustumPlanes);
  1643. len = intersections.length;
  1644. subMeshes = intersections.data;
  1645. }
  1646. else {
  1647. subMeshes = mesh.subMeshes;
  1648. len = subMeshes.length;
  1649. }
  1650. for (var subIndex = 0; subIndex < len; subIndex++) {
  1651. var subMesh = subMeshes[subIndex];
  1652. this._evaluateSubMesh(subMesh, mesh);
  1653. }
  1654. }
  1655. };
  1656. Scene.prototype.updateTransformMatrix = function (force) {
  1657. this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix(force));
  1658. };
  1659. Scene.prototype._renderForCamera = function (camera) {
  1660. var engine = this._engine;
  1661. var startTime = BABYLON.Tools.Now;
  1662. this.activeCamera = camera;
  1663. if (!this.activeCamera)
  1664. throw new Error("Active camera not set");
  1665. BABYLON.Tools.StartPerformanceCounter("Rendering camera " + this.activeCamera.name);
  1666. // Viewport
  1667. engine.setViewport(this.activeCamera.viewport);
  1668. // Camera
  1669. this.resetCachedMaterial();
  1670. this._renderId++;
  1671. this.updateTransformMatrix();
  1672. this.onBeforeCameraRenderObservable.notifyObservers(this.activeCamera);
  1673. // Meshes
  1674. this._evaluateActiveMeshesDuration.beginMonitoring();
  1675. BABYLON.Tools.StartPerformanceCounter("Active meshes evaluation");
  1676. this._evaluateActiveMeshes();
  1677. this._evaluateActiveMeshesDuration.endMonitoring(false);
  1678. BABYLON.Tools.EndPerformanceCounter("Active meshes evaluation");
  1679. // Software skinning
  1680. for (var softwareSkinnedMeshIndex = 0; softwareSkinnedMeshIndex < this._softwareSkinnedMeshes.length; softwareSkinnedMeshIndex++) {
  1681. var mesh = this._softwareSkinnedMeshes.data[softwareSkinnedMeshIndex];
  1682. mesh.applySkeleton(mesh.skeleton);
  1683. }
  1684. // Render targets
  1685. this._renderTargetsDuration.beginMonitoring();
  1686. var beforeRenderTargetDate = BABYLON.Tools.Now;
  1687. if (this.renderTargetsEnabled && this._renderTargets.length > 0) {
  1688. this._intermediateRendering = true;
  1689. BABYLON.Tools.StartPerformanceCounter("Render targets", this._renderTargets.length > 0);
  1690. for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
  1691. var renderTarget = this._renderTargets.data[renderIndex];
  1692. if (renderTarget._shouldRender()) {
  1693. this._renderId++;
  1694. var hasSpecialRenderTargetCamera = renderTarget.activeCamera && renderTarget.activeCamera !== this.activeCamera;
  1695. renderTarget.render(hasSpecialRenderTargetCamera, this.dumpNextRenderTargets);
  1696. }
  1697. }
  1698. BABYLON.Tools.EndPerformanceCounter("Render targets", this._renderTargets.length > 0);
  1699. this._intermediateRendering = false;
  1700. this._renderId++;
  1701. engine.restoreDefaultFramebuffer(); // Restore back buffer
  1702. }
  1703. this._renderTargetsDuration.endMonitoring(false);
  1704. // Prepare Frame
  1705. this.postProcessManager._prepareFrame();
  1706. this._renderDuration.beginMonitoring();
  1707. // Backgrounds
  1708. var layerIndex;
  1709. var layer;
  1710. if (this.layers.length) {
  1711. engine.setDepthBuffer(false);
  1712. for (layerIndex = 0; layerIndex < this.layers.length; layerIndex++) {
  1713. layer = this.layers[layerIndex];
  1714. if (layer.isBackground) {
  1715. layer.render();
  1716. }
  1717. }
  1718. engine.setDepthBuffer(true);
  1719. }
  1720. // Render
  1721. BABYLON.Tools.StartPerformanceCounter("Main render");
  1722. // Activate HighlightLayer stencil
  1723. var stencilState = this._engine.getStencilBuffer();
  1724. var renderhighlights = false;
  1725. if (this.highlightLayers && this.highlightLayers.length > 0) {
  1726. for (var i = 0; i < this.highlightLayers.length; i++) {
  1727. if (this.highlightLayers[i].shouldRender()) {
  1728. renderhighlights = true;
  1729. this._engine.setStencilBuffer(true);
  1730. break;
  1731. }
  1732. }
  1733. }
  1734. this._renderingManager.render(null, null, true, true);
  1735. // Restore HighlightLayer stencil
  1736. if (renderhighlights) {
  1737. this._engine.setStencilBuffer(stencilState);
  1738. }
  1739. BABYLON.Tools.EndPerformanceCounter("Main render");
  1740. // Bounding boxes
  1741. this._boundingBoxRenderer.render();
  1742. // Edges
  1743. for (var edgesRendererIndex = 0; edgesRendererIndex < this._edgesRenderers.length; edgesRendererIndex++) {
  1744. this._edgesRenderers.data[edgesRendererIndex].render();
  1745. }
  1746. // Lens flares
  1747. if (this.lensFlaresEnabled) {
  1748. BABYLON.Tools.StartPerformanceCounter("Lens flares", this.lensFlareSystems.length > 0);
  1749. for (var lensFlareSystemIndex = 0; lensFlareSystemIndex < this.lensFlareSystems.length; lensFlareSystemIndex++) {
  1750. var lensFlareSystem = this.lensFlareSystems[lensFlareSystemIndex];
  1751. if ((camera.layerMask & lensFlareSystem.layerMask) !== 0) {
  1752. lensFlareSystem.render();
  1753. }
  1754. }
  1755. BABYLON.Tools.EndPerformanceCounter("Lens flares", this.lensFlareSystems.length > 0);
  1756. }
  1757. // Foregrounds
  1758. if (this.layers.length) {
  1759. engine.setDepthBuffer(false);
  1760. for (layerIndex = 0; layerIndex < this.layers.length; layerIndex++) {
  1761. layer = this.layers[layerIndex];
  1762. if (!layer.isBackground) {
  1763. layer.render();
  1764. }
  1765. }
  1766. engine.setDepthBuffer(true);
  1767. }
  1768. // Highlight Layer
  1769. if (renderhighlights) {
  1770. engine.setDepthBuffer(false);
  1771. for (var i = 0; i < this.highlightLayers.length; i++) {
  1772. if (this.highlightLayers[i].shouldRender()) {
  1773. this.highlightLayers[i].render();
  1774. }
  1775. }
  1776. engine.setDepthBuffer(true);
  1777. }
  1778. this._renderDuration.endMonitoring(false);
  1779. // Finalize frame
  1780. this.postProcessManager._finalizeFrame(camera.isIntermediate);
  1781. // Update camera
  1782. this.activeCamera._updateFromScene();
  1783. // Reset some special arrays
  1784. this._renderTargets.reset();
  1785. this.onAfterCameraRenderObservable.notifyObservers(this.activeCamera);
  1786. BABYLON.Tools.EndPerformanceCounter("Rendering camera " + this.activeCamera.name);
  1787. };
  1788. Scene.prototype._processSubCameras = function (camera) {
  1789. if (camera.cameraRigMode === BABYLON.Camera.RIG_MODE_NONE) {
  1790. this._renderForCamera(camera);
  1791. return;
  1792. }
  1793. // rig cameras
  1794. for (var index = 0; index < camera._rigCameras.length; index++) {
  1795. this._renderForCamera(camera._rigCameras[index]);
  1796. }
  1797. this.activeCamera = camera;
  1798. this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix());
  1799. // Update camera
  1800. this.activeCamera._updateFromScene();
  1801. };
  1802. Scene.prototype._checkIntersections = function () {
  1803. for (var index = 0; index < this._meshesForIntersections.length; index++) {
  1804. var sourceMesh = this._meshesForIntersections.data[index];
  1805. for (var actionIndex = 0; actionIndex < sourceMesh.actionManager.actions.length; actionIndex++) {
  1806. var action = sourceMesh.actionManager.actions[actionIndex];
  1807. if (action.trigger === BABYLON.ActionManager.OnIntersectionEnterTrigger || action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
  1808. var parameters = action.getTriggerParameter();
  1809. var otherMesh = parameters instanceof BABYLON.AbstractMesh ? parameters : parameters.mesh;
  1810. var areIntersecting = otherMesh.intersectsMesh(sourceMesh, parameters.usePreciseIntersection);
  1811. var currentIntersectionInProgress = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
  1812. if (areIntersecting && currentIntersectionInProgress === -1) {
  1813. if (action.trigger === BABYLON.ActionManager.OnIntersectionEnterTrigger) {
  1814. action._executeCurrent(BABYLON.ActionEvent.CreateNew(sourceMesh, null, otherMesh));
  1815. sourceMesh._intersectionsInProgress.push(otherMesh);
  1816. }
  1817. else if (action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
  1818. sourceMesh._intersectionsInProgress.push(otherMesh);
  1819. }
  1820. }
  1821. else if (!areIntersecting && currentIntersectionInProgress > -1) {
  1822. //They intersected, and now they don't.
  1823. //is this trigger an exit trigger? execute an event.
  1824. if (action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
  1825. action._executeCurrent(BABYLON.ActionEvent.CreateNew(sourceMesh, null, otherMesh));
  1826. }
  1827. //if this is an exit trigger, or no exit trigger exists, remove the id from the intersection in progress array.
  1828. if (!sourceMesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnIntersectionExitTrigger) || action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
  1829. sourceMesh._intersectionsInProgress.splice(currentIntersectionInProgress, 1);
  1830. }
  1831. }
  1832. }
  1833. }
  1834. }
  1835. };
  1836. Scene.prototype.render = function () {
  1837. this._lastFrameDuration.beginMonitoring();
  1838. this._particlesDuration.fetchNewFrame();
  1839. this._spritesDuration.fetchNewFrame();
  1840. this._activeParticles.fetchNewFrame();
  1841. this._renderDuration.fetchNewFrame();
  1842. this._renderTargetsDuration.fetchNewFrame();
  1843. this._evaluateActiveMeshesDuration.fetchNewFrame();
  1844. this._totalVertices.fetchNewFrame();
  1845. this._activeIndices.fetchNewFrame();
  1846. this._activeBones.fetchNewFrame();
  1847. this.getEngine().drawCallsPerfCounter.fetchNewFrame();
  1848. this._meshesForIntersections.reset();
  1849. this.resetCachedMaterial();
  1850. BABYLON.Tools.StartPerformanceCounter("Scene rendering");
  1851. // Actions
  1852. if (this.actionManager) {
  1853. this.actionManager.processTrigger(BABYLON.ActionManager.OnEveryFrameTrigger, null);
  1854. }
  1855. //Simplification Queue
  1856. if (this.simplificationQueue && !this.simplificationQueue.running) {
  1857. this.simplificationQueue.executeNext();
  1858. }
  1859. // Animations
  1860. var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime));
  1861. this._animationRatio = deltaTime * (60.0 / 1000.0);
  1862. this._animate();
  1863. // Physics
  1864. if (this._physicsEngine) {
  1865. BABYLON.Tools.StartPerformanceCounter("Physics");
  1866. this._physicsEngine._step(deltaTime / 1000.0);
  1867. BABYLON.Tools.EndPerformanceCounter("Physics");
  1868. }
  1869. // Before render
  1870. this.onBeforeRenderObservable.notifyObservers(this);
  1871. // Customs render targets
  1872. this._renderTargetsDuration.beginMonitoring();
  1873. var beforeRenderTargetDate = BABYLON.Tools.Now;
  1874. var engine = this.getEngine();
  1875. var currentActiveCamera = this.activeCamera;
  1876. if (this.renderTargetsEnabled) {
  1877. BABYLON.Tools.StartPerformanceCounter("Custom render targets", this.customRenderTargets.length > 0);
  1878. for (var customIndex = 0; customIndex < this.customRenderTargets.length; customIndex++) {
  1879. var renderTarget = this.customRenderTargets[customIndex];
  1880. if (renderTarget._shouldRender()) {
  1881. this._renderId++;
  1882. this.activeCamera = renderTarget.activeCamera || this.activeCamera;
  1883. if (!this.activeCamera)
  1884. throw new Error("Active camera not set");
  1885. // Viewport
  1886. engine.setViewport(this.activeCamera.viewport);
  1887. // Camera
  1888. this.updateTransformMatrix();
  1889. renderTarget.render(currentActiveCamera !== this.activeCamera, this.dumpNextRenderTargets);
  1890. }
  1891. }
  1892. BABYLON.Tools.EndPerformanceCounter("Custom render targets", this.customRenderTargets.length > 0);
  1893. this._renderId++;
  1894. }
  1895. if (this.customRenderTargets.length > 0) {
  1896. engine.restoreDefaultFramebuffer();
  1897. }
  1898. this._renderTargetsDuration.endMonitoring();
  1899. this.activeCamera = currentActiveCamera;
  1900. // Procedural textures
  1901. if (this.proceduralTexturesEnabled) {
  1902. BABYLON.Tools.StartPerformanceCounter("Procedural textures", this._proceduralTextures.length > 0);
  1903. for (var proceduralIndex = 0; proceduralIndex < this._proceduralTextures.length; proceduralIndex++) {
  1904. var proceduralTexture = this._proceduralTextures[proceduralIndex];
  1905. if (proceduralTexture._shouldRender()) {
  1906. proceduralTexture.render();
  1907. }
  1908. }
  1909. BABYLON.Tools.EndPerformanceCounter("Procedural textures", this._proceduralTextures.length > 0);
  1910. }
  1911. // Clear
  1912. this._engine.clear(this.clearColor, this.autoClear || this.forceWireframe || this.forcePointsCloud, true, true);
  1913. // Shadows
  1914. if (this.shadowsEnabled) {
  1915. for (var lightIndex = 0; lightIndex < this.lights.length; lightIndex++) {
  1916. var light = this.lights[lightIndex];
  1917. var shadowGenerator = light.getShadowGenerator();
  1918. if (light.isEnabled() && shadowGenerator && shadowGenerator.getShadowMap().getScene().textures.indexOf(shadowGenerator.getShadowMap()) !== -1) {
  1919. this._renderTargets.push(shadowGenerator.getShadowMap());
  1920. }
  1921. }
  1922. }
  1923. // Depth renderer
  1924. if (this._depthRenderer) {
  1925. this._renderTargets.push(this._depthRenderer.getDepthMap());
  1926. }
  1927. // HighlightLayer
  1928. if (this.highlightLayers && this.highlightLayers.length > 0) {
  1929. for (var i = 0; i < this.highlightLayers.length; i++) {
  1930. if (this.highlightLayers[i].shouldRender()) {
  1931. this._renderTargets.push(this.highlightLayers[i]._mainTexture);
  1932. }
  1933. }
  1934. }
  1935. // RenderPipeline
  1936. this.postProcessRenderPipelineManager.update();
  1937. // Multi-cameras?
  1938. if (this.activeCameras.length > 0) {
  1939. var currentRenderId = this._renderId;
  1940. for (var cameraIndex = 0; cameraIndex < this.activeCameras.length; cameraIndex++) {
  1941. this._renderId = currentRenderId;
  1942. if (cameraIndex > 0) {
  1943. this._engine.clear(0, false, true, true);
  1944. }
  1945. this._processSubCameras(this.activeCameras[cameraIndex]);
  1946. }
  1947. }
  1948. else {
  1949. if (!this.activeCamera) {
  1950. throw new Error("No camera defined");
  1951. }
  1952. this._processSubCameras(this.activeCamera);
  1953. }
  1954. // Intersection checks
  1955. this._checkIntersections();
  1956. // Update the audio listener attached to the camera
  1957. if (BABYLON.AudioEngine) {
  1958. this._updateAudioParameters();
  1959. }
  1960. // After render
  1961. if (this.afterRender) {
  1962. this.afterRender();
  1963. }
  1964. this.onAfterRenderObservable.notifyObservers(this);
  1965. // Cleaning
  1966. for (var index = 0; index < this._toBeDisposed.length; index++) {
  1967. this._toBeDisposed.data[index].dispose();
  1968. this._toBeDisposed[index] = null;
  1969. }
  1970. this._toBeDisposed.reset();
  1971. if (this.dumpNextRenderTargets) {
  1972. this.dumpNextRenderTargets = false;
  1973. }
  1974. BABYLON.Tools.EndPerformanceCounter("Scene rendering");
  1975. this._lastFrameDuration.endMonitoring();
  1976. this._totalMeshesCounter.addCount(this.meshes.length, true);
  1977. this._totalLightsCounter.addCount(this.lights.length, true);
  1978. this._totalMaterialsCounter.addCount(this.materials.length, true);
  1979. this._totalTexturesCounter.addCount(this.textures.length, true);
  1980. this._activeBones.addCount(0, true);
  1981. this._activeIndices.addCount(0, true);
  1982. this._activeParticles.addCount(0, true);
  1983. };
  1984. Scene.prototype._updateAudioParameters = function () {
  1985. if (!this.audioEnabled || (this.mainSoundTrack.soundCollection.length === 0 && this.soundTracks.length === 1)) {
  1986. return;
  1987. }
  1988. var listeningCamera;
  1989. var audioEngine = BABYLON.Engine.audioEngine;
  1990. if (this.activeCameras.length > 0) {
  1991. listeningCamera = this.activeCameras[0];
  1992. }
  1993. else {
  1994. listeningCamera = this.activeCamera;
  1995. }
  1996. if (listeningCamera && audioEngine.canUseWebAudio) {
  1997. audioEngine.audioContext.listener.setPosition(listeningCamera.position.x, listeningCamera.position.y, listeningCamera.position.z);
  1998. var mat = BABYLON.Matrix.Invert(listeningCamera.getViewMatrix());
  1999. var cameraDirection = BABYLON.Vector3.TransformNormal(new BABYLON.Vector3(0, 0, -1), mat);
  2000. cameraDirection.normalize();
  2001. audioEngine.audioContext.listener.setOrientation(cameraDirection.x, cameraDirection.y, cameraDirection.z, 0, 1, 0);
  2002. var i;
  2003. for (i = 0; i < this.mainSoundTrack.soundCollection.length; i++) {
  2004. var sound = this.mainSoundTrack.soundCollection[i];
  2005. if (sound.useCustomAttenuation) {
  2006. sound.updateDistanceFromListener();
  2007. }
  2008. }
  2009. for (i = 0; i < this.soundTracks.length; i++) {
  2010. for (var j = 0; j < this.soundTracks[i].soundCollection.length; j++) {
  2011. sound = this.soundTracks[i].soundCollection[j];
  2012. if (sound.useCustomAttenuation) {
  2013. sound.updateDistanceFromListener();
  2014. }
  2015. }
  2016. }
  2017. }
  2018. };
  2019. Object.defineProperty(Scene.prototype, "audioEnabled", {
  2020. // Audio
  2021. get: function () {
  2022. return this._audioEnabled;
  2023. },
  2024. set: function (value) {
  2025. this._audioEnabled = value;
  2026. if (BABYLON.AudioEngine) {
  2027. if (this._audioEnabled) {
  2028. this._enableAudio();
  2029. }
  2030. else {
  2031. this._disableAudio();
  2032. }
  2033. }
  2034. },
  2035. enumerable: true,
  2036. configurable: true
  2037. });
  2038. Scene.prototype._disableAudio = function () {
  2039. var i;
  2040. for (i = 0; i < this.mainSoundTrack.soundCollection.length; i++) {
  2041. this.mainSoundTrack.soundCollection[i].pause();
  2042. }
  2043. for (i = 0; i < this.soundTracks.length; i++) {
  2044. for (var j = 0; j < this.soundTracks[i].soundCollection.length; j++) {
  2045. this.soundTracks[i].soundCollection[j].pause();
  2046. }
  2047. }
  2048. };
  2049. Scene.prototype._enableAudio = function () {
  2050. var i;
  2051. for (i = 0; i < this.mainSoundTrack.soundCollection.length; i++) {
  2052. if (this.mainSoundTrack.soundCollection[i].isPaused) {
  2053. this.mainSoundTrack.soundCollection[i].play();
  2054. }
  2055. }
  2056. for (i = 0; i < this.soundTracks.length; i++) {
  2057. for (var j = 0; j < this.soundTracks[i].soundCollection.length; j++) {
  2058. if (this.soundTracks[i].soundCollection[j].isPaused) {
  2059. this.soundTracks[i].soundCollection[j].play();
  2060. }
  2061. }
  2062. }
  2063. };
  2064. Object.defineProperty(Scene.prototype, "headphone", {
  2065. get: function () {
  2066. return this._headphone;
  2067. },
  2068. set: function (value) {
  2069. this._headphone = value;
  2070. if (BABYLON.AudioEngine) {
  2071. if (this._headphone) {
  2072. this._switchAudioModeForHeadphones();
  2073. }
  2074. else {
  2075. this._switchAudioModeForNormalSpeakers();
  2076. }
  2077. }
  2078. },
  2079. enumerable: true,
  2080. configurable: true
  2081. });
  2082. Scene.prototype._switchAudioModeForHeadphones = function () {
  2083. this.mainSoundTrack.switchPanningModelToHRTF();
  2084. for (var i = 0; i < this.soundTracks.length; i++) {
  2085. this.soundTracks[i].switchPanningModelToHRTF();
  2086. }
  2087. };
  2088. Scene.prototype._switchAudioModeForNormalSpeakers = function () {
  2089. this.mainSoundTrack.switchPanningModelToEqualPower();
  2090. for (var i = 0; i < this.soundTracks.length; i++) {
  2091. this.soundTracks[i].switchPanningModelToEqualPower();
  2092. }
  2093. };
  2094. Scene.prototype.enableDepthRenderer = function () {
  2095. if (this._depthRenderer) {
  2096. return this._depthRenderer;
  2097. }
  2098. this._depthRenderer = new BABYLON.DepthRenderer(this);
  2099. return this._depthRenderer;
  2100. };
  2101. Scene.prototype.disableDepthRenderer = function () {
  2102. if (!this._depthRenderer) {
  2103. return;
  2104. }
  2105. this._depthRenderer.dispose();
  2106. this._depthRenderer = null;
  2107. };
  2108. Scene.prototype.freezeMaterials = function () {
  2109. for (var i = 0; i < this.materials.length; i++) {
  2110. this.materials[i].freeze();
  2111. }
  2112. };
  2113. Scene.prototype.unfreezeMaterials = function () {
  2114. for (var i = 0; i < this.materials.length; i++) {
  2115. this.materials[i].unfreeze();
  2116. }
  2117. };
  2118. Scene.prototype.dispose = function () {
  2119. this.beforeRender = null;
  2120. this.afterRender = null;
  2121. this.skeletons = [];
  2122. this._boundingBoxRenderer.dispose();
  2123. if (this._depthRenderer) {
  2124. this._depthRenderer.dispose();
  2125. }
  2126. // Debug layer
  2127. if (this._debugLayer) {
  2128. this._debugLayer.hide();
  2129. }
  2130. // Events
  2131. this.onDisposeObservable.notifyObservers(this);
  2132. this.onDisposeObservable.clear();
  2133. this.onBeforeRenderObservable.clear();
  2134. this.onAfterRenderObservable.clear();
  2135. this.detachControl();
  2136. // Release sounds & sounds tracks
  2137. if (BABYLON.AudioEngine) {
  2138. this.disposeSounds();
  2139. }
  2140. // Detach cameras
  2141. var canvas = this._engine.getRenderingCanvas();
  2142. var index;
  2143. for (index = 0; index < this.cameras.length; index++) {
  2144. this.cameras[index].detachControl(canvas);
  2145. }
  2146. // Release lights
  2147. while (this.lights.length) {
  2148. this.lights[0].dispose();
  2149. }
  2150. // Release meshes
  2151. while (this.meshes.length) {
  2152. this.meshes[0].dispose(true);
  2153. }
  2154. // Release cameras
  2155. while (this.cameras.length) {
  2156. this.cameras[0].dispose();
  2157. }
  2158. // Release materials
  2159. while (this.materials.length) {
  2160. this.materials[0].dispose();
  2161. }
  2162. // Release particles
  2163. while (this.particleSystems.length) {
  2164. this.particleSystems[0].dispose();
  2165. }
  2166. // Release sprites
  2167. while (this.spriteManagers.length) {
  2168. this.spriteManagers[0].dispose();
  2169. }
  2170. // Release layers
  2171. while (this.layers.length) {
  2172. this.layers[0].dispose();
  2173. }
  2174. while (this.highlightLayers.length) {
  2175. this.highlightLayers[0].dispose();
  2176. }
  2177. // Release textures
  2178. while (this.textures.length) {
  2179. this.textures[0].dispose();
  2180. }
  2181. // Post-processes
  2182. this.postProcessManager.dispose();
  2183. // Physics
  2184. if (this._physicsEngine) {
  2185. this.disablePhysicsEngine();
  2186. }
  2187. // Remove from engine
  2188. index = this._engine.scenes.indexOf(this);
  2189. if (index > -1) {
  2190. this._engine.scenes.splice(index, 1);
  2191. }
  2192. this._engine.wipeCaches();
  2193. };
  2194. // Release sounds & sounds tracks
  2195. Scene.prototype.disposeSounds = function () {
  2196. this.mainSoundTrack.dispose();
  2197. for (var scIndex = 0; scIndex < this.soundTracks.length; scIndex++) {
  2198. this.soundTracks[scIndex].dispose();
  2199. }
  2200. };
  2201. // Octrees
  2202. Scene.prototype.getWorldExtends = function () {
  2203. var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
  2204. var max = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
  2205. for (var index = 0; index < this.meshes.length; index++) {
  2206. var mesh = this.meshes[index];
  2207. mesh.computeWorldMatrix(true);
  2208. var minBox = mesh.getBoundingInfo().boundingBox.minimumWorld;
  2209. var maxBox = mesh.getBoundingInfo().boundingBox.maximumWorld;
  2210. BABYLON.Tools.CheckExtends(minBox, min, max);
  2211. BABYLON.Tools.CheckExtends(maxBox, min, max);
  2212. }
  2213. return {
  2214. min: min,
  2215. max: max
  2216. };
  2217. };
  2218. Scene.prototype.createOrUpdateSelectionOctree = function (maxCapacity, maxDepth) {
  2219. if (maxCapacity === void 0) { maxCapacity = 64; }
  2220. if (maxDepth === void 0) { maxDepth = 2; }
  2221. if (!this._selectionOctree) {
  2222. this._selectionOctree = new BABYLON.Octree(BABYLON.Octree.CreationFuncForMeshes, maxCapacity, maxDepth);
  2223. }
  2224. var worldExtends = this.getWorldExtends();
  2225. // Update octree
  2226. this._selectionOctree.update(worldExtends.min, worldExtends.max, this.meshes);
  2227. return this._selectionOctree;
  2228. };
  2229. // Picking
  2230. Scene.prototype.createPickingRay = function (x, y, world, camera, cameraViewSpace) {
  2231. if (cameraViewSpace === void 0) { cameraViewSpace = false; }
  2232. var engine = this._engine;
  2233. if (!camera) {
  2234. if (!this.activeCamera)
  2235. throw new Error("Active camera not set");
  2236. camera = this.activeCamera;
  2237. }
  2238. var cameraViewport = camera.viewport;
  2239. var viewport = cameraViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
  2240. // Moving coordinates to local viewport world
  2241. x = x / this._engine.getHardwareScalingLevel() - viewport.x;
  2242. y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
  2243. return BABYLON.Ray.CreateNew(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), cameraViewSpace ? BABYLON.Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
  2244. // return BABYLON.Ray.CreateNew(x / window.devicePixelRatio, y / window.devicePixelRatio, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
  2245. };
  2246. Scene.prototype.createPickingRayInCameraSpace = function (x, y, camera) {
  2247. var engine = this._engine;
  2248. if (!camera) {
  2249. if (!this.activeCamera)
  2250. throw new Error("Active camera not set");
  2251. camera = this.activeCamera;
  2252. }
  2253. var cameraViewport = camera.viewport;
  2254. var viewport = cameraViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
  2255. var identity = BABYLON.Matrix.Identity();
  2256. // Moving coordinates to local viewport world
  2257. x = x / this._engine.getHardwareScalingLevel() - viewport.x;
  2258. y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
  2259. return BABYLON.Ray.CreateNew(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
  2260. };
  2261. Scene.prototype._internalPick = function (rayFunction, predicate, fastCheck) {
  2262. var pickingInfo = null;
  2263. for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
  2264. var mesh = this.meshes[meshIndex];
  2265. if (predicate) {
  2266. if (!predicate(mesh)) {
  2267. continue;
  2268. }
  2269. }
  2270. else if (!mesh.isEnabled() || !mesh.isVisible || !mesh.isPickable) {
  2271. continue;
  2272. }
  2273. var world = mesh.getWorldMatrix();
  2274. var ray = rayFunction(world);
  2275. var result = mesh.intersects(ray, fastCheck);
  2276. if (!result || !result.hit)
  2277. continue;
  2278. if (!fastCheck && pickingInfo != null && result.distance >= pickingInfo.distance)
  2279. continue;
  2280. pickingInfo = result;
  2281. if (fastCheck) {
  2282. break;
  2283. }
  2284. }
  2285. return pickingInfo || new BABYLON.PickingInfo();
  2286. };
  2287. Scene.prototype._internalPickSprites = function (ray, predicate, fastCheck, camera) {
  2288. var pickingInfo = null;
  2289. camera = camera || this.activeCamera;
  2290. if (this.spriteManagers.length > 0) {
  2291. for (var spriteIndex = 0; spriteIndex < this.spriteManagers.length; spriteIndex++) {
  2292. var spriteManager = this.spriteManagers[spriteIndex];
  2293. if (!spriteManager.isPickable) {
  2294. continue;
  2295. }
  2296. var result = spriteManager.intersects(ray, camera, predicate, fastCheck);
  2297. if (!result || !result.hit)
  2298. continue;
  2299. if (!fastCheck && pickingInfo != null && result.distance >= pickingInfo.distance)
  2300. continue;
  2301. pickingInfo = result;
  2302. if (fastCheck) {
  2303. break;
  2304. }
  2305. }
  2306. }
  2307. return pickingInfo || new BABYLON.PickingInfo();
  2308. };
  2309. Scene.prototype.pick = function (x, y, predicate, fastCheck, camera) {
  2310. var _this = this;
  2311. /// <summary>Launch a ray to try to pick a mesh in the scene</summary>
  2312. /// <param name="x">X position on screen</param>
  2313. /// <param name="y">Y position on screen</param>
  2314. /// <param name="predicate">Predicate function used to determine eligible meshes. Can be set to null. In this case, a mesh must be enabled, visible and with isPickable set to true</param>
  2315. /// <param name="fastCheck">Launch a fast check only using the bounding boxes. Can be set to null.</param>
  2316. /// <param name="camera">camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used</param>
  2317. return this._internalPick(function (world) { return _this.createPickingRay(x, y, world, camera); }, predicate, fastCheck);
  2318. };
  2319. Scene.prototype.pickSprite = function (x, y, predicate, fastCheck, camera) {
  2320. /// <summary>Launch a ray to try to pick a mesh in the scene</summary>
  2321. /// <param name="x">X position on screen</param>
  2322. /// <param name="y">Y position on screen</param>
  2323. /// <param name="predicate">Predicate function used to determine eligible sprites. Can be set to null. In this case, a sprite must have isPickable set to true</param>
  2324. /// <param name="fastCheck">Launch a fast check only using the bounding boxes. Can be set to null.</param>
  2325. /// <param name="camera">camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used</param>
  2326. return this._internalPickSprites(this.createPickingRayInCameraSpace(x, y, camera), predicate, fastCheck, camera);
  2327. };
  2328. Scene.prototype.pickWithRay = function (ray, predicate, fastCheck) {
  2329. var _this = this;
  2330. return this._internalPick(function (world) {
  2331. if (!_this._pickWithRayInverseMatrix) {
  2332. _this._pickWithRayInverseMatrix = BABYLON.Matrix.Identity();
  2333. }
  2334. world.invertToRef(_this._pickWithRayInverseMatrix);
  2335. return BABYLON.Ray.Transform(ray, _this._pickWithRayInverseMatrix);
  2336. }, predicate, fastCheck);
  2337. };
  2338. Scene.prototype.setPointerOverMesh = function (mesh) {
  2339. if (this._pointerOverMesh === mesh) {
  2340. return;
  2341. }
  2342. if (this._pointerOverMesh && this._pointerOverMesh.actionManager) {
  2343. this._pointerOverMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPointerOutTrigger, BABYLON.ActionEvent.CreateNew(this._pointerOverMesh));
  2344. }
  2345. this._pointerOverMesh = mesh;
  2346. if (this._pointerOverMesh && this._pointerOverMesh.actionManager) {
  2347. this._pointerOverMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPointerOverTrigger, BABYLON.ActionEvent.CreateNew(this._pointerOverMesh));
  2348. }
  2349. };
  2350. Scene.prototype.getPointerOverMesh = function () {
  2351. return this._pointerOverMesh;
  2352. };
  2353. Scene.prototype.setPointerOverSprite = function (sprite) {
  2354. if (this._pointerOverSprite === sprite) {
  2355. return;
  2356. }
  2357. if (this._pointerOverSprite && this._pointerOverSprite.actionManager) {
  2358. this._pointerOverSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPointerOutTrigger, BABYLON.ActionEvent.CreateNewFromSprite(this._pointerOverSprite, this));
  2359. }
  2360. this._pointerOverSprite = sprite;
  2361. if (this._pointerOverSprite && this._pointerOverSprite.actionManager) {
  2362. this._pointerOverSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPointerOverTrigger, BABYLON.ActionEvent.CreateNewFromSprite(this._pointerOverSprite, this));
  2363. }
  2364. };
  2365. Scene.prototype.getPointerOverSprite = function () {
  2366. return this._pointerOverSprite;
  2367. };
  2368. // Physics
  2369. Scene.prototype.getPhysicsEngine = function () {
  2370. return this._physicsEngine;
  2371. };
  2372. /**
  2373. * Enables physics to the current scene
  2374. * @param {BABYLON.Vector3} [gravity] - the scene's gravity for the physics engine
  2375. * @param {BABYLON.IPhysicsEnginePlugin} [plugin] - The physics engine to be used. defaults to OimoJS.
  2376. * @return {boolean} was the physics engine initialized
  2377. */
  2378. Scene.prototype.enablePhysics = function (gravity, plugin) {
  2379. if (this._physicsEngine) {
  2380. return true;
  2381. }
  2382. try {
  2383. this._physicsEngine = new BABYLON.PhysicsEngine(gravity, plugin);
  2384. return true;
  2385. }
  2386. catch (e) {
  2387. BABYLON.Tools.Error(e.message);
  2388. return false;
  2389. }
  2390. };
  2391. Scene.prototype.disablePhysicsEngine = function () {
  2392. if (!this._physicsEngine) {
  2393. return;
  2394. }
  2395. this._physicsEngine.dispose();
  2396. this._physicsEngine = undefined;
  2397. };
  2398. Scene.prototype.isPhysicsEnabled = function () {
  2399. return this._physicsEngine !== undefined;
  2400. };
  2401. /**
  2402. *
  2403. * Sets the gravity of the physics engine (and NOT of the scene)
  2404. * @param {BABYLON.Vector3} [gravity] - the new gravity to be used
  2405. */
  2406. Scene.prototype.setGravity = function (gravity) {
  2407. BABYLON.Tools.Warn("Deprecated, please use 'scene.getPhysicsEngine().setGravity()'");
  2408. if (!this._physicsEngine) {
  2409. return;
  2410. }
  2411. this._physicsEngine.setGravity(gravity);
  2412. };
  2413. /**
  2414. * Legacy support, using the new API
  2415. * @Deprecated
  2416. */
  2417. Scene.prototype.createCompoundImpostor = function (parts, options) {
  2418. BABYLON.Tools.Warn("Scene.createCompoundImpostor is deprecated. Please use PhysicsImpostor parent/child");
  2419. if (parts.parts) {
  2420. options = parts;
  2421. parts = parts.parts;
  2422. }
  2423. var mainMesh = parts[0].mesh;
  2424. mainMesh.physicsImpostor = new BABYLON.PhysicsImpostor(mainMesh, parts[0].impostor, options, this);
  2425. for (var index = 1; index < parts.length; index++) {
  2426. var mesh = parts[index].mesh;
  2427. if (mesh.parent !== mainMesh) {
  2428. mesh.position = mesh.position.subtract(mainMesh.position);
  2429. mesh.parent = mainMesh;
  2430. }
  2431. mesh.physicsImpostor = new BABYLON.PhysicsImpostor(mesh, parts[index].impostor, options, this);
  2432. }
  2433. mainMesh.physicsImpostor.forceUpdate();
  2434. };
  2435. Scene.prototype.deleteCompoundImpostor = function (compound) {
  2436. var mesh = compound.parts[0].mesh;
  2437. mesh.physicsImpostor.dispose();
  2438. mesh.physicsImpostor = null;
  2439. };
  2440. // Misc.
  2441. Scene.prototype.createDefaultCameraOrLight = function () {
  2442. // Light
  2443. if (this.lights.length === 0) {
  2444. new BABYLON.HemisphericLight("default light", BABYLON.Vector3.Up(), this);
  2445. }
  2446. // Camera
  2447. if (!this.activeCamera) {
  2448. var camera = new BABYLON.FreeCamera("default camera", BABYLON.Vector3.Zero(), this);
  2449. // Compute position
  2450. var worldExtends = this.getWorldExtends();
  2451. var worldCenter = worldExtends.min.add(worldExtends.max.subtract(worldExtends.min).scale(0.5));
  2452. camera.position = new BABYLON.Vector3(worldCenter.x, worldCenter.y, worldExtends.min.z - (worldExtends.max.z - worldExtends.min.z));
  2453. camera.setTarget(worldCenter);
  2454. this.activeCamera = camera;
  2455. }
  2456. };
  2457. // Tags
  2458. Scene.prototype._getByTags = function (list, tagsQuery, forEach) {
  2459. if (tagsQuery === undefined) {
  2460. // returns the complete list (could be done with BABYLON.Tags.MatchesQuery but no need to have a for-loop here)
  2461. return list;
  2462. }
  2463. var listByTags = [];
  2464. forEach = forEach || (function (item) { return; });
  2465. for (var i in list) {
  2466. var item = list[i];
  2467. if (BABYLON.Tags.MatchesQuery(item, tagsQuery)) {
  2468. listByTags.push(item);
  2469. forEach(item);
  2470. }
  2471. }
  2472. return listByTags;
  2473. };
  2474. Scene.prototype.getMeshesByTags = function (tagsQuery, forEach) {
  2475. return this._getByTags(this.meshes, tagsQuery, forEach);
  2476. };
  2477. Scene.prototype.getCamerasByTags = function (tagsQuery, forEach) {
  2478. return this._getByTags(this.cameras, tagsQuery, forEach);
  2479. };
  2480. Scene.prototype.getLightsByTags = function (tagsQuery, forEach) {
  2481. return this._getByTags(this.lights, tagsQuery, forEach);
  2482. };
  2483. Scene.prototype.getMaterialByTags = function (tagsQuery, forEach) {
  2484. return this._getByTags(this.materials, tagsQuery, forEach).concat(this._getByTags(this.multiMaterials, tagsQuery, forEach));
  2485. };
  2486. /**
  2487. * Overrides the default sort function applied in the renderging group to prepare the meshes.
  2488. * This allowed control for front to back rendering or reversly depending of the special needs.
  2489. *
  2490. * @param renderingGroupId The rendering group id corresponding to its index
  2491. * @param opaqueSortCompareFn The opaque queue comparison function use to sort.
  2492. * @param alphaTestSortCompareFn The alpha test queue comparison function use to sort.
  2493. * @param transparentSortCompareFn The transparent queue comparison function use to sort.
  2494. */
  2495. Scene.prototype.setRenderingOrder = function (renderingGroupId, opaqueSortCompareFn, alphaTestSortCompareFn, transparentSortCompareFn) {
  2496. if (opaqueSortCompareFn === void 0) { opaqueSortCompareFn = null; }
  2497. if (alphaTestSortCompareFn === void 0) { alphaTestSortCompareFn = null; }
  2498. if (transparentSortCompareFn === void 0) { transparentSortCompareFn = null; }
  2499. this._renderingManager.setRenderingOrder(renderingGroupId, opaqueSortCompareFn, alphaTestSortCompareFn, transparentSortCompareFn);
  2500. };
  2501. /**
  2502. * Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
  2503. *
  2504. * @param renderingGroupId The rendering group id corresponding to its index
  2505. * @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
  2506. */
  2507. Scene.prototype.setRenderingAutoClearDepthStencil = function (renderingGroupId, autoClearDepthStencil) {
  2508. this._renderingManager.setRenderingAutoClearDepthStencil(renderingGroupId, autoClearDepthStencil);
  2509. };
  2510. // Statics
  2511. Scene._FOGMODE_NONE = 0;
  2512. Scene._FOGMODE_EXP = 1;
  2513. Scene._FOGMODE_EXP2 = 2;
  2514. Scene._FOGMODE_LINEAR = 3;
  2515. Scene.MinDeltaTime = 1.0;
  2516. Scene.MaxDeltaTime = 1000.0;
  2517. return Scene;
  2518. }());
  2519. BABYLON.Scene = Scene;
  2520. })(BABYLON || (BABYLON = {}));