babylon.camera.ts 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. module BABYLON {
  2. export class Camera extends Node {
  3. public inputs: CameraInputsManager<Camera>;
  4. // Statics
  5. private static _PERSPECTIVE_CAMERA = 0;
  6. private static _ORTHOGRAPHIC_CAMERA = 1;
  7. private static _FOVMODE_VERTICAL_FIXED = 0;
  8. private static _FOVMODE_HORIZONTAL_FIXED = 1;
  9. private static _RIG_MODE_NONE = 0;
  10. private static _RIG_MODE_STEREOSCOPIC_ANAGLYPH = 10;
  11. private static _RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL = 11;
  12. private static _RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED = 12;
  13. private static _RIG_MODE_STEREOSCOPIC_OVERUNDER = 13;
  14. private static _RIG_MODE_VR = 20;
  15. public static get PERSPECTIVE_CAMERA(): number {
  16. return Camera._PERSPECTIVE_CAMERA;
  17. }
  18. public static get ORTHOGRAPHIC_CAMERA(): number {
  19. return Camera._ORTHOGRAPHIC_CAMERA;
  20. }
  21. public static get FOVMODE_VERTICAL_FIXED(): number {
  22. return Camera._FOVMODE_VERTICAL_FIXED;
  23. }
  24. public static get FOVMODE_HORIZONTAL_FIXED(): number {
  25. return Camera._FOVMODE_HORIZONTAL_FIXED;
  26. }
  27. public static get RIG_MODE_NONE(): number {
  28. return Camera._RIG_MODE_NONE;
  29. }
  30. public static get RIG_MODE_STEREOSCOPIC_ANAGLYPH(): number {
  31. return Camera._RIG_MODE_STEREOSCOPIC_ANAGLYPH;
  32. }
  33. public static get RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL(): number {
  34. return Camera._RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL;
  35. }
  36. public static get RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED(): number {
  37. return Camera._RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED;
  38. }
  39. public static get RIG_MODE_STEREOSCOPIC_OVERUNDER(): number {
  40. return Camera._RIG_MODE_STEREOSCOPIC_OVERUNDER;
  41. }
  42. public static get RIG_MODE_VR(): number {
  43. return Camera._RIG_MODE_VR;
  44. }
  45. public static ForceAttachControlToAlwaysPreventDefault = false;
  46. // Members
  47. @serializeAsVector3()
  48. public position: Vector3;
  49. @serializeAsVector3()
  50. public upVector = Vector3.Up();
  51. @serialize()
  52. public orthoLeft = null;
  53. @serialize()
  54. public orthoRight = null;
  55. @serialize()
  56. public orthoBottom = null;
  57. @serialize()
  58. public orthoTop = null;
  59. @serialize()
  60. public fov = 0.8;
  61. @serialize()
  62. public minZ = 1.0;
  63. @serialize()
  64. public maxZ = 10000.0;
  65. @serialize()
  66. public inertia = 0.9;
  67. @serialize()
  68. public mode = Camera.PERSPECTIVE_CAMERA;
  69. public isIntermediate = false;
  70. public viewport = new Viewport(0, 0, 1.0, 1.0);
  71. @serialize()
  72. public layerMask: number = 0x0FFFFFFF;
  73. @serialize()
  74. public fovMode: number = Camera.FOVMODE_VERTICAL_FIXED;
  75. // Camera rig members
  76. @serialize()
  77. public cameraRigMode = Camera.RIG_MODE_NONE;
  78. @serialize()
  79. public interaxialDistance: number
  80. @serialize()
  81. public isStereoscopicSideBySide: boolean
  82. public _cameraRigParams: any;
  83. public _rigCameras = new Array<Camera>();
  84. public _rigPostProcess: PostProcess;
  85. // Cache
  86. private _computedViewMatrix = Matrix.Identity();
  87. public _projectionMatrix = new Matrix();
  88. private _worldMatrix: Matrix;
  89. public _postProcesses = new Array<PostProcess>();
  90. private _transformMatrix = Matrix.Zero();
  91. public _activeMeshes = new SmartArray<Mesh>(256);
  92. private _globalPosition = Vector3.Zero();
  93. private _frustumPlanes: Plane[];
  94. private _refreshFrustumPlanes = true;
  95. constructor(name: string, position: Vector3, scene: Scene) {
  96. super(name, scene);
  97. scene.addCamera(this);
  98. if (!scene.activeCamera) {
  99. scene.activeCamera = this;
  100. }
  101. this.position = position;
  102. }
  103. /**
  104. * @param {boolean} fullDetails - support for multiple levels of logging within scene loading
  105. */
  106. public toString(fullDetails?: boolean): string {
  107. var ret = "Name: " + this.name;
  108. ret += ", type: " + this.getTypeName();
  109. if (this.animations) {
  110. for (var i = 0; i < this.animations.length; i++) {
  111. ret += ", animation[0]: " + this.animations[i].toString(fullDetails);
  112. }
  113. }
  114. if (fullDetails) {
  115. }
  116. return ret;
  117. }
  118. public get globalPosition(): Vector3 {
  119. return this._globalPosition;
  120. }
  121. public getActiveMeshes(): SmartArray<Mesh> {
  122. return this._activeMeshes;
  123. }
  124. public isActiveMesh(mesh: Mesh): boolean {
  125. return (this._activeMeshes.indexOf(mesh) !== -1);
  126. }
  127. //Cache
  128. public _initCache() {
  129. super._initCache();
  130. this._cache.position = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
  131. this._cache.upVector = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
  132. this._cache.mode = undefined;
  133. this._cache.minZ = undefined;
  134. this._cache.maxZ = undefined;
  135. this._cache.fov = undefined;
  136. this._cache.aspectRatio = undefined;
  137. this._cache.orthoLeft = undefined;
  138. this._cache.orthoRight = undefined;
  139. this._cache.orthoBottom = undefined;
  140. this._cache.orthoTop = undefined;
  141. this._cache.renderWidth = undefined;
  142. this._cache.renderHeight = undefined;
  143. }
  144. public _updateCache(ignoreParentClass?: boolean): void {
  145. if (!ignoreParentClass) {
  146. super._updateCache();
  147. }
  148. var engine = this.getEngine();
  149. this._cache.position.copyFrom(this.position);
  150. this._cache.upVector.copyFrom(this.upVector);
  151. this._cache.mode = this.mode;
  152. this._cache.minZ = this.minZ;
  153. this._cache.maxZ = this.maxZ;
  154. this._cache.fov = this.fov;
  155. this._cache.aspectRatio = engine.getAspectRatio(this);
  156. this._cache.orthoLeft = this.orthoLeft;
  157. this._cache.orthoRight = this.orthoRight;
  158. this._cache.orthoBottom = this.orthoBottom;
  159. this._cache.orthoTop = this.orthoTop;
  160. this._cache.renderWidth = engine.getRenderWidth();
  161. this._cache.renderHeight = engine.getRenderHeight();
  162. }
  163. public _updateFromScene(): void {
  164. this.updateCache();
  165. this.update();
  166. }
  167. // Synchronized
  168. public _isSynchronized(): boolean {
  169. return this._isSynchronizedViewMatrix() && this._isSynchronizedProjectionMatrix();
  170. }
  171. public _isSynchronizedViewMatrix(): boolean {
  172. if (!super._isSynchronized())
  173. return false;
  174. return this._cache.position.equals(this.position)
  175. && this._cache.upVector.equals(this.upVector)
  176. && this.isSynchronizedWithParent();
  177. }
  178. public _isSynchronizedProjectionMatrix(): boolean {
  179. var check = this._cache.mode === this.mode
  180. && this._cache.minZ === this.minZ
  181. && this._cache.maxZ === this.maxZ;
  182. if (!check) {
  183. return false;
  184. }
  185. var engine = this.getEngine();
  186. if (this.mode === Camera.PERSPECTIVE_CAMERA) {
  187. check = this._cache.fov === this.fov
  188. && this._cache.aspectRatio === engine.getAspectRatio(this);
  189. }
  190. else {
  191. check = this._cache.orthoLeft === this.orthoLeft
  192. && this._cache.orthoRight === this.orthoRight
  193. && this._cache.orthoBottom === this.orthoBottom
  194. && this._cache.orthoTop === this.orthoTop
  195. && this._cache.renderWidth === engine.getRenderWidth()
  196. && this._cache.renderHeight === engine.getRenderHeight();
  197. }
  198. return check;
  199. }
  200. // Controls
  201. public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
  202. }
  203. public detachControl(element: HTMLElement): void {
  204. }
  205. public update(): void {
  206. if (this.cameraRigMode !== Camera.RIG_MODE_NONE) {
  207. this._updateRigCameras();
  208. }
  209. this._checkInputs();
  210. }
  211. public _checkInputs(): void {
  212. }
  213. private _cascadePostProcessesToRigCams(): void {
  214. // invalidate framebuffer
  215. if (this._postProcesses.length > 0) {
  216. this._postProcesses[0].markTextureDirty();
  217. }
  218. // glue the rigPostProcess to the end of the user postprocesses & assign to each sub-camera
  219. for (var i = 0, len = this._rigCameras.length; i < len; i++) {
  220. var cam = this._rigCameras[i];
  221. var rigPostProcess = cam._rigPostProcess;
  222. // for VR rig, there does not have to be a post process
  223. if (rigPostProcess) {
  224. var isPass = rigPostProcess instanceof PassPostProcess;
  225. if (isPass) {
  226. // any rig which has a PassPostProcess for rig[0], cannot be isIntermediate when there are also user postProcesses
  227. cam.isIntermediate = this._postProcesses.length === 0;
  228. }
  229. cam._postProcesses = this._postProcesses.slice(0).concat(rigPostProcess);
  230. rigPostProcess.markTextureDirty();
  231. } else {
  232. cam._postProcesses = this._postProcesses.slice(0);
  233. }
  234. }
  235. }
  236. public attachPostProcess(postProcess: PostProcess, insertAt: number = null): number {
  237. if (!postProcess.isReusable() && this._postProcesses.indexOf(postProcess) > -1) {
  238. Tools.Error("You're trying to reuse a post process not defined as reusable.");
  239. return 0;
  240. }
  241. if (insertAt == null || insertAt < 0) {
  242. this._postProcesses.push(postProcess);
  243. } else {
  244. this._postProcesses.splice(insertAt, 0, postProcess);
  245. }
  246. this._cascadePostProcessesToRigCams(); // also ensures framebuffer invalidated
  247. return this._postProcesses.indexOf(postProcess);
  248. }
  249. public detachPostProcess(postProcess: PostProcess, atIndices: any = null): number[] {
  250. var result = [];
  251. var i: number;
  252. var index: number;
  253. if (!atIndices) {
  254. var idx = this._postProcesses.indexOf(postProcess);
  255. if (idx !== -1) {
  256. this._postProcesses.splice(idx, 1);
  257. }
  258. } else {
  259. atIndices = (atIndices instanceof Array) ? atIndices : [atIndices];
  260. // iterate descending, so can just splice as we go
  261. for (i = atIndices.length - 1; i >= 0; i--) {
  262. if (this._postProcesses[atIndices[i]] !== postProcess) {
  263. result.push(i);
  264. continue;
  265. }
  266. this._postProcesses.splice(index, 1);
  267. }
  268. }
  269. this._cascadePostProcessesToRigCams(); // also ensures framebuffer invalidated
  270. return result;
  271. }
  272. public getWorldMatrix(): Matrix {
  273. if (!this._worldMatrix) {
  274. this._worldMatrix = Matrix.Identity();
  275. }
  276. var viewMatrix = this.getViewMatrix();
  277. viewMatrix.invertToRef(this._worldMatrix);
  278. return this._worldMatrix;
  279. }
  280. public _getViewMatrix(): Matrix {
  281. return Matrix.Identity();
  282. }
  283. public getViewMatrix(force?: boolean): Matrix {
  284. this._computedViewMatrix = this._computeViewMatrix(force);
  285. if (!force && this._isSynchronizedViewMatrix()) {
  286. return this._computedViewMatrix;
  287. }
  288. this._refreshFrustumPlanes = true;
  289. if (!this.parent || !this.parent.getWorldMatrix) {
  290. this._globalPosition.copyFrom(this.position);
  291. } else {
  292. if (!this._worldMatrix) {
  293. this._worldMatrix = Matrix.Identity();
  294. }
  295. this._computedViewMatrix.invertToRef(this._worldMatrix);
  296. this._worldMatrix.multiplyToRef(this.parent.getWorldMatrix(), this._computedViewMatrix);
  297. this._globalPosition.copyFromFloats(this._computedViewMatrix.m[12], this._computedViewMatrix.m[13], this._computedViewMatrix.m[14]);
  298. this._computedViewMatrix.invert();
  299. this._markSyncedWithParent();
  300. }
  301. this._currentRenderId = this.getScene().getRenderId();
  302. return this._computedViewMatrix;
  303. }
  304. public _computeViewMatrix(force?: boolean): Matrix {
  305. if (!force && this._isSynchronizedViewMatrix()) {
  306. return this._computedViewMatrix;
  307. }
  308. this._computedViewMatrix = this._getViewMatrix();
  309. this._currentRenderId = this.getScene().getRenderId();
  310. return this._computedViewMatrix;
  311. }
  312. public getProjectionMatrix(force?: boolean): Matrix {
  313. if (!force && this._isSynchronizedProjectionMatrix()) {
  314. return this._projectionMatrix;
  315. }
  316. this._refreshFrustumPlanes = true;
  317. var engine = this.getEngine();
  318. if (this.mode === Camera.PERSPECTIVE_CAMERA) {
  319. if (this.minZ <= 0) {
  320. this.minZ = 0.1;
  321. }
  322. Matrix.PerspectiveFovLHToRef(this.fov, engine.getAspectRatio(this), this.minZ, this.maxZ, this._projectionMatrix, this.fovMode === Camera.FOVMODE_VERTICAL_FIXED);
  323. return this._projectionMatrix;
  324. }
  325. var halfWidth = engine.getRenderWidth() / 2.0;
  326. var halfHeight = engine.getRenderHeight() / 2.0;
  327. Matrix.OrthoOffCenterLHToRef(this.orthoLeft || -halfWidth, this.orthoRight || halfWidth, this.orthoBottom || -halfHeight, this.orthoTop || halfHeight, this.minZ, this.maxZ, this._projectionMatrix);
  328. return this._projectionMatrix;
  329. }
  330. public getTranformationMatrix(): Matrix {
  331. this._computedViewMatrix.multiplyToRef(this._projectionMatrix, this._transformMatrix);
  332. return this._transformMatrix;
  333. }
  334. private updateFrustumPlanes(): void {
  335. if (!this._refreshFrustumPlanes) {
  336. return;
  337. }
  338. this.getTranformationMatrix();
  339. if (!this._frustumPlanes) {
  340. this._frustumPlanes = Frustum.GetPlanes(this._transformMatrix);
  341. } else {
  342. Frustum.GetPlanesToRef(this._transformMatrix, this._frustumPlanes);
  343. }
  344. this._refreshFrustumPlanes = false;
  345. }
  346. public isInFrustum(target: ICullable): boolean {
  347. this.updateFrustumPlanes();
  348. return target.isInFrustum(this._frustumPlanes);
  349. }
  350. public isCompletelyInFrustum(target: ICullable): boolean {
  351. this.updateFrustumPlanes();
  352. return target.isCompletelyInFrustum(this._frustumPlanes);
  353. }
  354. public dispose(): void {
  355. // Animations
  356. this.getScene().stopAnimation(this);
  357. // Remove from scene
  358. this.getScene().removeCamera(this);
  359. while (this._rigCameras.length > 0) {
  360. this._rigCameras.pop().dispose();
  361. }
  362. // Postprocesses
  363. for (var i = 0; i < this._postProcesses.length; ++i) {
  364. this._postProcesses[i].dispose(this);
  365. }
  366. super.dispose();
  367. }
  368. // ---- Camera rigs section ----
  369. public setCameraRigMode(mode: number, rigParams: any): void {
  370. while (this._rigCameras.length > 0) {
  371. this._rigCameras.pop().dispose();
  372. }
  373. this.cameraRigMode = mode;
  374. this._cameraRigParams = {};
  375. //we have to implement stereo camera calcultating left and right viewpoints from interaxialDistance and target,
  376. //not from a given angle as it is now, but until that complete code rewriting provisional stereoHalfAngle value is introduced
  377. this._cameraRigParams.interaxialDistance = rigParams.interaxialDistance || 0.0637;
  378. this._cameraRigParams.stereoHalfAngle = BABYLON.Tools.ToRadians(this._cameraRigParams.interaxialDistance / 0.0637);
  379. // create the rig cameras, unless none
  380. if (this.cameraRigMode !== Camera.RIG_MODE_NONE) {
  381. this._rigCameras.push(this.createRigCamera(this.name + "_L", 0));
  382. this._rigCameras.push(this.createRigCamera(this.name + "_R", 1));
  383. }
  384. switch (this.cameraRigMode) {
  385. case Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH:
  386. this._rigCameras[0]._rigPostProcess = new PassPostProcess(this.name + "_passthru", 1.0, this._rigCameras[0]);
  387. this._rigCameras[1]._rigPostProcess = new AnaglyphPostProcess(this.name + "_anaglyph", 1.0, this._rigCameras);
  388. break;
  389. case Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL:
  390. case Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED:
  391. case Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER:
  392. var isStereoscopicHoriz = this.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL || this.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED;
  393. this._rigCameras[0]._rigPostProcess = new PassPostProcess(this.name + "_passthru", 1.0, this._rigCameras[0]);
  394. this._rigCameras[1]._rigPostProcess = new StereoscopicInterlacePostProcess(this.name + "_stereoInterlace", this._rigCameras, isStereoscopicHoriz);
  395. break;
  396. case Camera.RIG_MODE_VR:
  397. var metrics = rigParams.vrCameraMetrics || VRCameraMetrics.GetDefault();
  398. this._rigCameras[0]._cameraRigParams.vrMetrics = metrics;
  399. this._rigCameras[0].viewport = new Viewport(0, 0, 0.5, 1.0);
  400. this._rigCameras[0]._cameraRigParams.vrWorkMatrix = new Matrix();
  401. this._rigCameras[0]._cameraRigParams.vrHMatrix = metrics.leftHMatrix;
  402. this._rigCameras[0]._cameraRigParams.vrPreViewMatrix = metrics.leftPreViewMatrix;
  403. this._rigCameras[0].getProjectionMatrix = this._rigCameras[0]._getVRProjectionMatrix;
  404. this._rigCameras[1]._cameraRigParams.vrMetrics = metrics;
  405. this._rigCameras[1].viewport = new Viewport(0.5, 0, 0.5, 1.0);
  406. this._rigCameras[1]._cameraRigParams.vrWorkMatrix = new Matrix();
  407. this._rigCameras[1]._cameraRigParams.vrHMatrix = metrics.rightHMatrix;
  408. this._rigCameras[1]._cameraRigParams.vrPreViewMatrix = metrics.rightPreViewMatrix;
  409. this._rigCameras[1].getProjectionMatrix = this._rigCameras[1]._getVRProjectionMatrix;
  410. if (metrics.compensateDistortion) {
  411. this._rigCameras[0]._rigPostProcess = new VRDistortionCorrectionPostProcess("VR_Distort_Compensation_Left", this._rigCameras[0], false, metrics);
  412. this._rigCameras[1]._rigPostProcess = new VRDistortionCorrectionPostProcess("VR_Distort_Compensation_Right", this._rigCameras[1], true, metrics);
  413. }
  414. break;
  415. }
  416. this._cascadePostProcessesToRigCams();
  417. this.
  418. update();
  419. }
  420. private _getVRProjectionMatrix(): Matrix {
  421. Matrix.PerspectiveFovLHToRef(this._cameraRigParams.vrMetrics.aspectRatioFov, this._cameraRigParams.vrMetrics.aspectRatio, this.minZ, this.maxZ, this._cameraRigParams.vrWorkMatrix);
  422. this._cameraRigParams.vrWorkMatrix.multiplyToRef(this._cameraRigParams.vrHMatrix, this._projectionMatrix);
  423. return this._projectionMatrix;
  424. }
  425. public setCameraRigParameter(name: string, value: any) {
  426. if (!this._cameraRigParams) {
  427. this._cameraRigParams = {};
  428. }
  429. this._cameraRigParams[name] = value;
  430. //provisionnally:
  431. if (name === "interaxialDistance") {
  432. this._cameraRigParams.stereoHalfAngle = Tools.ToRadians(value / 0.0637);
  433. }
  434. }
  435. /**
  436. * needs to be overridden by children so sub has required properties to be copied
  437. */
  438. public createRigCamera(name: string, cameraIndex: number): Camera {
  439. return null;
  440. }
  441. /**
  442. * May need to be overridden by children
  443. */
  444. public _updateRigCameras() {
  445. for (var i = 0; i < this._rigCameras.length; i++) {
  446. this._rigCameras[i].minZ = this.minZ;
  447. this._rigCameras[i].maxZ = this.maxZ;
  448. this._rigCameras[i].fov = this.fov;
  449. }
  450. // only update viewport when ANAGLYPH
  451. if (this.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH) {
  452. this._rigCameras[0].viewport = this._rigCameras[1].viewport = this.viewport;
  453. }
  454. }
  455. public _setupInputs() {
  456. }
  457. public serialize(): any {
  458. var serializationObject = SerializationHelper.Serialize(this);
  459. // Type
  460. serializationObject.type = this.getTypeName();
  461. // Parent
  462. if (this.parent) {
  463. serializationObject.parentId = this.parent.id;
  464. }
  465. if (this.inputs) {
  466. this.inputs.serialize(serializationObject);
  467. }
  468. // Animations
  469. Animation.AppendSerializedAnimations(this, serializationObject);
  470. serializationObject.ranges = this.serializeAnimationRanges();
  471. return serializationObject;
  472. }
  473. public getTypeName(): string {
  474. return "Camera";
  475. }
  476. public clone(name: string): Camera {
  477. return SerializationHelper.Clone(Camera.GetConstructorFromName(this.getTypeName(), name, this.getScene(), this.interaxialDistance, this.isStereoscopicSideBySide), this);
  478. }
  479. static GetConstructorFromName(type: string, name: string, scene: Scene, interaxial_distance: number = 0, isStereoscopicSideBySide: boolean = true): () => Camera {
  480. switch (type) {
  481. case "ArcRotateCamera":
  482. return () => new ArcRotateCamera(name, 0, 0, 1.0, Vector3.Zero(), scene);
  483. case "DeviceOrientationCamera":
  484. return () => new DeviceOrientationCamera(name, Vector3.Zero(), scene);
  485. case "FollowCamera":
  486. return () => new FollowCamera(name, Vector3.Zero(), scene);
  487. case "ArcFollowCamera":
  488. return () => new ArcFollowCamera(name, 0, 0, 1.0, null, scene);
  489. case "GamepadCamera":
  490. return () => new GamepadCamera(name, Vector3.Zero(), scene);
  491. case "TouchCamera":
  492. return () => new TouchCamera(name, Vector3.Zero(), scene);
  493. case "VirtualJoysticksCamera":
  494. return () => new VirtualJoysticksCamera(name, Vector3.Zero(), scene);
  495. case "WebVRFreeCamera":
  496. return () => new WebVRFreeCamera(name, Vector3.Zero(), scene);
  497. case "VRDeviceOrientationFreeCamera":
  498. return () => new VRDeviceOrientationFreeCamera(name, Vector3.Zero(), scene);
  499. case "AnaglyphArcRotateCamera":
  500. return () => new AnaglyphArcRotateCamera(name, 0, 0, 1.0, Vector3.Zero(), interaxial_distance, scene);
  501. case "AnaglyphFreeCamera":
  502. return () => new AnaglyphFreeCamera(name, Vector3.Zero(), interaxial_distance, scene);
  503. case "AnaglyphGamepadCamera":
  504. return () => new AnaglyphGamepadCamera(name, Vector3.Zero(), interaxial_distance, scene);
  505. case "AnaglyphUniversalCamera":
  506. return () => new AnaglyphUniversalCamera(name, Vector3.Zero(), interaxial_distance, scene);
  507. case "StereoscopicArcRotateCamera":
  508. return () => new StereoscopicArcRotateCamera(name, 0, 0, 1.0, Vector3.Zero(), interaxial_distance, isStereoscopicSideBySide, scene);
  509. case "StereoscopicFreeCamera":
  510. return () => new StereoscopicFreeCamera(name, Vector3.Zero(), interaxial_distance, isStereoscopicSideBySide, scene);
  511. case "StereoscopicGamepadCamera":
  512. return () => new StereoscopicGamepadCamera(name, Vector3.Zero(), interaxial_distance, isStereoscopicSideBySide, scene);
  513. case "StereoscopicUniversalCamera":
  514. return () => new StereoscopicUniversalCamera(name, Vector3.Zero(), interaxial_distance, isStereoscopicSideBySide, scene);
  515. case "FreeCamera": // Forcing Universal here
  516. return () => new UniversalCamera(name, Vector3.Zero(), scene);
  517. default: // Universal Camera is the default value
  518. return () => new UniversalCamera(name, Vector3.Zero(), scene);
  519. }
  520. }
  521. public static Parse(parsedCamera: any, scene: Scene): Camera {
  522. var type = parsedCamera.type;
  523. var construct = Camera.GetConstructorFromName(type, parsedCamera.name, scene, parsedCamera.interaxial_distance, parsedCamera.isStereoscopicSideBySide);
  524. var camera = SerializationHelper.Parse(construct, parsedCamera, scene);
  525. // Parent
  526. if (parsedCamera.parentId) {
  527. camera._waitingParentId = parsedCamera.parentId;
  528. }
  529. //If camera has an input manager, let it parse inputs settings
  530. if (camera.inputs) {
  531. camera.inputs.parse(parsedCamera);
  532. camera._setupInputs();
  533. }
  534. // Target
  535. if (parsedCamera.target) {
  536. if ((<any>camera).setTarget) {
  537. (<any>camera).setTarget(Vector3.FromArray(parsedCamera.target));
  538. }
  539. }
  540. // Apply 3d rig, when found
  541. if (parsedCamera.cameraRigMode) {
  542. var rigParams = (parsedCamera.interaxial_distance) ? { interaxialDistance: parsedCamera.interaxial_distance } : {};
  543. camera.setCameraRigMode(parsedCamera.cameraRigMode, rigParams);
  544. }
  545. // Animations
  546. if (parsedCamera.animations) {
  547. for (var animationIndex = 0; animationIndex < parsedCamera.animations.length; animationIndex++) {
  548. var parsedAnimation = parsedCamera.animations[animationIndex];
  549. camera.animations.push(Animation.Parse(parsedAnimation));
  550. }
  551. Node.ParseAnimationRanges(camera, parsedCamera, scene);
  552. }
  553. if (parsedCamera.autoAnimate) {
  554. scene.beginAnimation(camera, parsedCamera.autoAnimateFrom, parsedCamera.autoAnimateTo, parsedCamera.autoAnimateLoop, parsedCamera.autoAnimateSpeed || 1.0);
  555. }
  556. return camera;
  557. }
  558. }
  559. }