babylon.tools.panoramatocubemap.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /// <reference path="../../../dist/preview release/babylon.d.ts"/>
  2. module BABYLON.Internals {
  3. export interface CubeMapInfo {
  4. front: Float32Array;
  5. back: Float32Array;
  6. left: Float32Array;
  7. right: Float32Array;
  8. up: Float32Array;
  9. down: Float32Array;
  10. size: number;
  11. }
  12. export class PanoramaToCubeMapTools {
  13. private static FACE_FRONT = [
  14. new Vector3(-1.0, -1.0, -1.0),
  15. new Vector3(1.0, -1.0, -1.0),
  16. new Vector3(-1.0, 1.0, -1.0),
  17. new Vector3(1.0, 1.0, -1.0)
  18. ];
  19. private static FACE_BACK = [
  20. new Vector3(1.0, -1.0, 1.0),
  21. new Vector3(-1.0, -1.0, 1.0),
  22. new Vector3(1.0, 1.0, 1.0),
  23. new Vector3(-1.0, 1.0, 1.0)
  24. ];
  25. private static FACE_LEFT = [
  26. new Vector3(1.0, -1.0, -1.0),
  27. new Vector3(1.0, -1.0, 1.0),
  28. new Vector3(1.0, 1.0, -1.0),
  29. new Vector3(1.0, 1.0, 1.0)
  30. ];
  31. private static FACE_RIGHT = [
  32. new Vector3(-1.0, -1.0, 1.0),
  33. new Vector3(-1.0, -1.0, -1.0),
  34. new Vector3(-1.0, 1.0, 1.0),
  35. new Vector3(-1.0, 1.0, -1.0)
  36. ];
  37. private static FACE_UP = [
  38. new Vector3(-1.0, 1.0, -1.0),
  39. new Vector3(1.0, 1.0, -1.0),
  40. new Vector3(-1.0, 1.0, 1.0),
  41. new Vector3(1.0, 1.0, 1.0)
  42. ];
  43. private static FACE_DOWN = [
  44. new Vector3(-1.0, -1.0, 1.0),
  45. new Vector3(1.0, -1.0, 1.0),
  46. new Vector3(-1.0, -1.0, -1.0),
  47. new Vector3(1.0, -1.0, -1.0)
  48. ];
  49. public static ConvertPanoramaToCubemap(float32Array: Float32Array, inputWidth: number, inputHeight: number, size: number): CubeMapInfo {
  50. if (!float32Array) {
  51. throw "ConvertPanoramaToCubemap: input cannot be null";
  52. }
  53. if (float32Array.length != inputWidth * inputHeight * 3) {
  54. throw "ConvertPanoramaToCubemap: input size is wrong";
  55. }
  56. var textureFront = this.CreateCubemapTexture(size, this.FACE_FRONT, float32Array, inputWidth, inputHeight);
  57. var textureBack = this.CreateCubemapTexture(size, this.FACE_BACK, float32Array, inputWidth, inputHeight);
  58. var textureLeft = this.CreateCubemapTexture(size, this.FACE_LEFT, float32Array, inputWidth, inputHeight);
  59. var textureRight = this.CreateCubemapTexture(size, this.FACE_RIGHT, float32Array, inputWidth, inputHeight);
  60. var textureUp = this.CreateCubemapTexture(size, this.FACE_UP, float32Array, inputWidth, inputHeight);
  61. var textureDown = this.CreateCubemapTexture(size, this.FACE_DOWN, float32Array, inputWidth, inputHeight);
  62. return {
  63. front: textureFront,
  64. back: textureBack,
  65. left: textureLeft,
  66. right: textureRight,
  67. up: textureUp,
  68. down: textureDown,
  69. size: size
  70. };
  71. }
  72. private static CreateCubemapTexture(texSize: number, faceData: Vector3[], float32Array: Float32Array, inputWidth: number, inputHeight: number) {
  73. var buffer = new ArrayBuffer(texSize * texSize * 4 * 3);
  74. var textureArray = new Float32Array(buffer);
  75. var rotDX1 = faceData[1].subtract(faceData[0]).scale(1 / texSize);
  76. var rotDX2 = faceData[3].subtract(faceData[2]).scale(1 / texSize);
  77. var dy = 1 / texSize;
  78. var fy = 0;
  79. for (var y = 0; y < texSize; y++) {
  80. var xv1 = faceData[0];
  81. var xv2 = faceData[2];
  82. for (var x = 0; x < texSize; x++) {
  83. var v = xv2.subtract(xv1).scale(fy).add(xv1);
  84. v.normalize();
  85. var color = this.CalcProjectionSpherical(v, float32Array, inputWidth, inputHeight);
  86. // 3 channels per pixels
  87. textureArray[y * texSize * 3 + (x * 3) + 0] = color.r;
  88. textureArray[y * texSize * 3 + (x * 3) + 1] = color.g;
  89. textureArray[y * texSize * 3 + (x * 3) + 2] = color.b;
  90. xv1 = xv1.add(rotDX1);
  91. xv2 = xv2.add(rotDX2);
  92. }
  93. fy += dy;
  94. }
  95. return textureArray;
  96. }
  97. private static CalcProjectionSpherical(vDir: Vector3, float32Array: Float32Array, inputWidth: number, inputHeight: number): any {
  98. var theta = Math.atan2(vDir.z, vDir.x);
  99. var phi = Math.acos(vDir.y);
  100. while (theta < -Math.PI) theta += 2 * Math.PI;
  101. while (theta > Math.PI) theta -= 2 * Math.PI;
  102. var dx = theta / Math.PI;
  103. var dy = phi / Math.PI;
  104. // recenter.
  105. dx = dx * 0.5 + 0.5;
  106. var px = Math.round(dx * inputWidth);
  107. if (px < 0) px = 0;
  108. else if (px >= inputWidth) px = inputWidth - 1;
  109. var py = Math.round(dy * inputHeight);
  110. if (py < 0) py = 0;
  111. else if (py >= inputHeight) py = inputHeight - 1;
  112. var inputY = (inputHeight - py - 1);
  113. var r = float32Array[inputY * inputWidth * 3 + (px * 3) + 0];
  114. var g = float32Array[inputY * inputWidth * 3 + (px * 3) + 1];
  115. var b = float32Array[inputY * inputWidth * 3 + (px * 3) + 2];
  116. return {
  117. r: r,
  118. g: g,
  119. b: b
  120. };
  121. }
  122. }
  123. }