babylon.targetCamera.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. module BABYLON {
  2. export class TargetCamera extends Camera {
  3. public cameraDirection = new BABYLON.Vector3(0, 0, 0);
  4. public cameraRotation = new BABYLON.Vector2(0, 0);
  5. public rotation = new BABYLON.Vector3(0, 0, 0);
  6. public speed = 2.0;
  7. public noRotationConstraint = false;
  8. public lockedTarget = null;
  9. public _currentTarget = BABYLON.Vector3.Zero();
  10. public _viewMatrix = BABYLON.Matrix.Zero();
  11. public _camMatrix = BABYLON.Matrix.Zero();
  12. public _cameraTransformMatrix = BABYLON.Matrix.Zero();
  13. public _cameraRotationMatrix = BABYLON.Matrix.Zero();
  14. public _referencePoint = new BABYLON.Vector3(0, 0, 1);
  15. public _transformedReferencePoint = BABYLON.Vector3.Zero();
  16. public _lookAtTemp = BABYLON.Matrix.Zero();
  17. public _tempMatrix = BABYLON.Matrix.Zero();
  18. public _reset:() => void;
  19. public _waitingLockedTargetId:string;
  20. constructor(name:string, position:Vector3, scene:Scene) {
  21. super(name, position, scene);
  22. }
  23. public _getLockedTargetPosition():Vector3 {
  24. if (!this.lockedTarget) {
  25. return null;
  26. }
  27. return this.lockedTarget.position || this.lockedTarget;
  28. }
  29. // Cache
  30. public _initCache() {
  31. super._initCache();
  32. this._cache.lockedTarget = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
  33. this._cache.rotation = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
  34. }
  35. public _updateCache(ignoreParentClass?:boolean):void {
  36. if (!ignoreParentClass) {
  37. super._updateCache();
  38. }
  39. var lockedTargetPosition = this._getLockedTargetPosition();
  40. if (!lockedTargetPosition) {
  41. this._cache.lockedTarget = null;
  42. }
  43. else {
  44. if (!this._cache.lockedTarget) {
  45. this._cache.lockedTarget = lockedTargetPosition.clone();
  46. }
  47. else {
  48. this._cache.lockedTarget.copyFrom(lockedTargetPosition);
  49. }
  50. }
  51. this._cache.rotation.copyFrom(this.rotation);
  52. }
  53. // Synchronized
  54. public _isSynchronizedViewMatrix():boolean {
  55. if (!super._isSynchronizedViewMatrix()) {
  56. return false;
  57. }
  58. var lockedTargetPosition = this._getLockedTargetPosition();
  59. return (this._cache.lockedTarget ? this._cache.lockedTarget.equals(lockedTargetPosition) : !lockedTargetPosition)
  60. && this._cache.rotation.equals(this.rotation);
  61. }
  62. // Methods
  63. public _computeLocalCameraSpeed():number {
  64. return this.speed * ((BABYLON.Tools.GetDeltaTime() / (BABYLON.Tools.GetFps() * 10.0)));
  65. }
  66. // Target
  67. public setTarget(target:Vector3):void {
  68. this.upVector.normalize();
  69. BABYLON.Matrix.LookAtLHToRef(this.position, target, this.upVector, this._camMatrix);
  70. this._camMatrix.invert();
  71. this.rotation.x = Math.atan(this._camMatrix.m[6] / this._camMatrix.m[10]);
  72. var vDir = target.subtract(this.position);
  73. if (vDir.x >= 0.0) {
  74. this.rotation.y = (-Math.atan(vDir.z / vDir.x) + Math.PI / 2.0);
  75. } else {
  76. this.rotation.y = (-Math.atan(vDir.z / vDir.x) - Math.PI / 2.0);
  77. }
  78. this.rotation.z = -Math.acos(BABYLON.Vector3.Dot(new BABYLON.Vector3(0, 1.0, 0), this.upVector));
  79. if (isNaN(this.rotation.x)) {
  80. this.rotation.x = 0;
  81. }
  82. if (isNaN(this.rotation.y)) {
  83. this.rotation.y = 0;
  84. }
  85. if (isNaN(this.rotation.z)) {
  86. this.rotation.z = 0;
  87. }
  88. }
  89. public getTarget():Vector3 {
  90. return this._currentTarget;
  91. }
  92. public _decideIfNeedsToMove():boolean {
  93. return Math.abs(this.cameraDirection.x) > 0 || Math.abs(this.cameraDirection.y) > 0 || Math.abs(this.cameraDirection.z) > 0;
  94. }
  95. public _updatePosition():void{
  96. this.position.addInPlace(this.cameraDirection);
  97. }
  98. public _update():void {
  99. var needToMove = this._decideIfNeedsToMove();
  100. var needToRotate = Math.abs(this.cameraRotation.x) > 0 || Math.abs(this.cameraRotation.y) > 0;
  101. // Move
  102. if (needToMove) {
  103. this._updatePosition();
  104. }
  105. // Rotate
  106. if (needToRotate) {
  107. this.rotation.x += this.cameraRotation.x;
  108. this.rotation.y += this.cameraRotation.y;
  109. if (!this.noRotationConstraint) {
  110. var limit = (Math.PI / 2) * 0.95;
  111. if (this.rotation.x > limit)
  112. this.rotation.x = limit;
  113. if (this.rotation.x < -limit)
  114. this.rotation.x = -limit;
  115. }
  116. }
  117. // Inertia
  118. if (needToMove) {
  119. if (Math.abs(this.cameraDirection.x) < BABYLON.Engine.Epsilon) {
  120. this.cameraDirection.x = 0;
  121. }
  122. if (Math.abs(this.cameraDirection.y) < BABYLON.Engine.Epsilon) {
  123. this.cameraDirection.y = 0;
  124. }
  125. if (Math.abs(this.cameraDirection.z) < BABYLON.Engine.Epsilon) {
  126. this.cameraDirection.z = 0;
  127. }
  128. this.cameraDirection.scaleInPlace(this.inertia);
  129. }
  130. if (needToRotate) {
  131. if (Math.abs(this.cameraRotation.x) < BABYLON.Engine.Epsilon) {
  132. this.cameraRotation.x = 0;
  133. }
  134. if (Math.abs(this.cameraRotation.y) < BABYLON.Engine.Epsilon) {
  135. this.cameraRotation.y = 0;
  136. }
  137. this.cameraRotation.scaleInPlace(this.inertia);
  138. }
  139. }
  140. public _getViewMatrix():Matrix {
  141. if (!this.lockedTarget) {
  142. // Compute
  143. if (this.upVector.x != 0 || this.upVector.y != 1.0 || this.upVector.z != 0) {
  144. BABYLON.Matrix.LookAtLHToRef(BABYLON.Vector3.Zero(), this._referencePoint, this.upVector, this._lookAtTemp);
  145. BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._cameraRotationMatrix);
  146. this._lookAtTemp.multiplyToRef(this._cameraRotationMatrix, this._tempMatrix);
  147. this._lookAtTemp.invert();
  148. this._tempMatrix.multiplyToRef(this._lookAtTemp, this._cameraRotationMatrix);
  149. } else {
  150. BABYLON.Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._cameraRotationMatrix);
  151. }
  152. BABYLON.Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
  153. // Computing target and final matrix
  154. this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
  155. } else {
  156. this._currentTarget.copyFrom(this._getLockedTargetPosition());
  157. }
  158. BABYLON.Matrix.LookAtLHToRef(this.position, this._currentTarget, this.upVector, this._viewMatrix);
  159. return this._viewMatrix;
  160. }
  161. }
  162. }