viewerLabs.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import { PBREnvironment, EnvironmentDeserializer } from "./environmentSerializer";
  2. import { Scene } from "babylonjs/scene";
  3. import { Vector3, Quaternion, Axis, Matrix, Tmp } from "babylonjs/Maths/math";
  4. import { SphericalPolynomial } from "babylonjs/Maths/sphericalPolynomial";
  5. import { ShadowLight } from "babylonjs/Lights/shadowLight";
  6. import { TextureUtils } from "./texture";
  7. /**
  8. * The ViewerLabs class will hold functions that are not (!) backwards compatible.
  9. * The APIs in all labs-related classes and configuration might change.
  10. * Once stable, lab features will be moved to the publis API and configuration object.
  11. */
  12. export class ViewerLabs {
  13. constructor(private _scene: Scene) { }
  14. public assetsRootURL: string;
  15. public environment: PBREnvironment = {
  16. //irradiance
  17. irradiancePolynomialCoefficients: {
  18. x: new Vector3(0, 0, 0),
  19. y: new Vector3(0, 0, 0),
  20. z: new Vector3(0, 0, 0),
  21. xx: new Vector3(0, 0, 0),
  22. yy: new Vector3(0, 0, 0),
  23. zz: new Vector3(0, 0, 0),
  24. yz: new Vector3(0, 0, 0),
  25. zx: new Vector3(0, 0, 0),
  26. xy: new Vector3(0, 0, 0)
  27. },
  28. textureIntensityScale: 1.0
  29. };
  30. /**
  31. * Loads an environment map from a given URL
  32. * @param url URL of environment map
  33. * @param onSuccess Callback fired after environment successfully applied to the scene
  34. * @param onProgress Callback fired at progress events while loading the environment map
  35. * @param onError Callback fired when the load fails
  36. */
  37. public loadEnvironment(url: string, onSuccess?: (env: PBREnvironment) => void, onProgress?: (bytesLoaded: number, bytesTotal: number) => void, onError?: (e: any) => void): void;
  38. /**
  39. * Loads an environment map from a given URL
  40. * @param buffer ArrayBuffer containing environment map
  41. * @param onSuccess Callback fired after environment successfully applied to the scene
  42. * @param onProgress Callback fired at progress events while loading the environment map
  43. * @param onError Callback fired when the load fails
  44. */
  45. public loadEnvironment(buffer: ArrayBuffer, onSuccess?: (env: PBREnvironment) => void, onProgress?: (bytesLoaded: number, bytesTotal: number) => void, onError?: (e: any) => void): void;
  46. /**
  47. * Sets the environment to an already loaded environment
  48. * @param env PBREnvironment instance
  49. * @param onSuccess Callback fired after environment successfully applied to the scene
  50. * @param onProgress Callback fired at progress events while loading the environment map
  51. * @param onError Callback fired when the load fails
  52. */
  53. public loadEnvironment(env: PBREnvironment, onSuccess?: (env: PBREnvironment) => void, onProgress?: (bytesLoaded: number, bytesTotal: number) => void, onError?: (e: any) => void): void;
  54. public loadEnvironment(data: string | ArrayBuffer | PBREnvironment, onSuccess?: (env: PBREnvironment) => void, onProgress?: (bytesLoaded: number, bytesTotal: number) => void, onError?: (e: any) => void): void {
  55. //@! todo: should loadEnvironment cancel any currently loading environments?
  56. if (data instanceof ArrayBuffer) {
  57. this.environment = EnvironmentDeserializer.Parse(data);
  58. if (onSuccess) { onSuccess(this.environment); }
  59. } else if (typeof data === 'string') {
  60. let url = this.getAssetUrl(data);
  61. this._scene._loadFile(
  62. url,
  63. (arrayBuffer: ArrayBuffer) => {
  64. this.environment = EnvironmentDeserializer.Parse(arrayBuffer);
  65. if (onSuccess) { onSuccess(this.environment); }
  66. },
  67. (progressEvent) => { if (onProgress) { onProgress(progressEvent.loaded, progressEvent.total); } },
  68. false,
  69. true,
  70. (r, e) => {
  71. if (onError) {
  72. onError(e);
  73. }
  74. }
  75. );
  76. } else {
  77. //data assumed to be PBREnvironment object
  78. this.environment = data;
  79. if (onSuccess) { onSuccess(data); }
  80. }
  81. }
  82. /**
  83. * Applies an `EnvironmentMapConfiguration` to the scene
  84. * @param environmentMapConfiguration Environment map configuration to apply
  85. */
  86. public applyEnvironmentMapConfiguration(rotationY?: number) {
  87. if (!this.environment) { return; }
  88. //set orientation
  89. let rotatquatRotationionY = Quaternion.RotationAxis(Axis.Y, rotationY || 0);
  90. // Add env texture to the scene.
  91. if (this.environment.specularTexture) {
  92. // IE crashes when disposing the old texture and setting a new one
  93. if (!this._scene.environmentTexture) {
  94. this._scene.environmentTexture = TextureUtils.GetBabylonCubeTexture(this._scene, this.environment.specularTexture, false, true);
  95. }
  96. if (this._scene.environmentTexture) {
  97. this._scene.environmentTexture.level = this.environment.textureIntensityScale;
  98. this._scene.environmentTexture.invertZ = true;
  99. this._scene.environmentTexture.lodLevelInAlpha = true;
  100. var poly = this._scene.environmentTexture.sphericalPolynomial || new SphericalPolynomial();
  101. poly.x = this.environment.irradiancePolynomialCoefficients.x;
  102. poly.y = this.environment.irradiancePolynomialCoefficients.y;
  103. poly.z = this.environment.irradiancePolynomialCoefficients.z;
  104. poly.xx = this.environment.irradiancePolynomialCoefficients.xx;
  105. poly.xy = this.environment.irradiancePolynomialCoefficients.xy;
  106. poly.yy = this.environment.irradiancePolynomialCoefficients.yy;
  107. poly.yz = this.environment.irradiancePolynomialCoefficients.yz;
  108. poly.zx = this.environment.irradiancePolynomialCoefficients.zx;
  109. poly.zz = this.environment.irradiancePolynomialCoefficients.zz;
  110. this._scene.environmentTexture.sphericalPolynomial = poly;
  111. //set orientation
  112. Matrix.FromQuaternionToRef(rotatquatRotationionY, this._scene.environmentTexture.getReflectionTextureMatrix());
  113. }
  114. }
  115. }
  116. /**
  117. * Get an environment asset url by using the configuration if the path is not absolute.
  118. * @param url Asset url
  119. * @returns The Asset url using the `environmentAssetsRootURL` if the url is not an absolute path.
  120. */
  121. public getAssetUrl(url: string): string {
  122. let returnUrl = url;
  123. if (url && url.toLowerCase().indexOf("//") === -1) {
  124. if (!this.assetsRootURL) {
  125. // Tools.Warn("Please, specify the root url of your assets before loading the configuration (labs.environmentAssetsRootURL) or disable the background through the viewer options.");
  126. return url;
  127. }
  128. returnUrl = this.assetsRootURL + returnUrl;
  129. }
  130. return returnUrl;
  131. }
  132. public rotateShadowLight(shadowLight: ShadowLight, amount: number, point = Vector3.Zero(), axis = Axis.Y, target = Vector3.Zero()) {
  133. axis.normalize();
  134. point.subtractToRef(shadowLight.position, Tmp.Vector3[0]);
  135. Matrix.TranslationToRef(Tmp.Vector3[0].x, Tmp.Vector3[0].y, Tmp.Vector3[0].z, Tmp.Matrix[0]);
  136. Tmp.Matrix[0].invertToRef(Tmp.Matrix[2]);
  137. Matrix.RotationAxisToRef(axis, amount, Tmp.Matrix[1]);
  138. Tmp.Matrix[2].multiplyToRef(Tmp.Matrix[1], Tmp.Matrix[2]);
  139. Tmp.Matrix[2].multiplyToRef(Tmp.Matrix[0], Tmp.Matrix[2]);
  140. Tmp.Matrix[2].decompose(Tmp.Vector3[0], Tmp.Quaternion[0], Tmp.Vector3[1]);
  141. shadowLight.position.addInPlace(Tmp.Vector3[1]);
  142. shadowLight.setDirectionToTarget(target);
  143. }
  144. }