Reference Source

src/plugins/NavCubePlugin/CubeTextureCanvas.js

  1. import {math} from "../../viewer/scene/math/math.js";
  2.  
  3. /**
  4. * @private
  5. */
  6. function CubeTextureCanvas(viewer, navCubeScene, cfg = {}) {
  7.  
  8. const cubeColor = "lightgrey";
  9. const cubeHighlightColor = cfg.hoverColor || "rgba(0,0,0,0.4)";
  10. const textColor = cfg.textColor || "black";
  11.  
  12. const height = 500;
  13. const width = height + (height / 3);
  14. const scale = width / 24;
  15.  
  16. const facesZUp = [
  17. {boundary: [6, 6, 6, 6], color: cfg.frontColor || cfg.color || "#55FF55"},
  18. {boundary: [18, 6, 6, 6], color: cfg.backColor || cfg.color || "#55FF55"},
  19. {boundary: [12, 6, 6, 6], color: cfg.rightColor || cfg.color || "#FF5555"},
  20. {boundary: [0, 6, 6, 6], color: cfg.leftColor || cfg.color || "#FF5555"},
  21. {boundary: [6, 0, 6, 6], color: cfg.topColor || cfg.color || "#7777FF"},
  22. {boundary: [6, 12, 6, 6], color: cfg.bottomColor || cfg.color || "#7777FF"}
  23. ];
  24.  
  25. const areasZUp = [
  26. {label: "NavCube.front", boundaries: [[7, 7, 4, 4]], dir: [0, 1, 0], up: [0, 0, 1]},
  27. {label: "NavCube.back", boundaries: [[19, 7, 4, 4]], dir: [0, -1, 0], up: [0, 0, 1]},
  28. {label: "NavCube.right", boundaries: [[13, 7, 4, 4]], dir: [-1, 0, 0], up: [0, 0, 1]},
  29. {label: "NavCube.left", boundaries: [[1, 7, 4, 4]], dir: [1, 0, 0], up: [0, 0, 1]},
  30. {label: "NavCube.top", boundaries: [[7, 1, 4, 4]], dir: [0, 0, -1], up: [0, 1, 0]},
  31. {label: "NavCube.bottom", boundaries: [[7, 13, 4, 4]], dir: [0, 0, 1], up: [0, -1, 0]},
  32. {boundaries: [[7, 5, 4, 2]], dir: [0, 1, -1], up: [0, 1, 1]},
  33. {boundaries: [[1, 6, 4, 1], [6, 1, 1, 4]], dir: [1, 0, -1], up: [1, 0, 1]},
  34. {boundaries: [[7, 0, 4, 1], [19, 6, 4, 1]], dir: [0, -1, -1], up: [0, -1, 1]},
  35. {boundaries: [[13, 6, 4, 1], [11, 1, 1, 4]], dir: [-1, 0, -1], up: [-1, 0, 1]},
  36. {boundaries: [[7, 11, 4, 2]], dir: [0, 1, 1], up: [0, -1, 1]},
  37. {boundaries: [[1, 11, 4, 1], [6, 13, 1, 4]], dir: [1, 0, 1], up: [-1, 0, 1]},
  38. {boundaries: [[7, 17, 4, 1], [19, 11, 4, 1]], dir: [0, -1, 1], up: [0, 1, 1]},
  39. {boundaries: [[13, 11, 4, 1], [11, 13, 1, 4]], dir: [-1, 0, 1], up: [1, 0, 1]},
  40. {boundaries: [[5, 7, 2, 4]], dir: [1, 1, 0], up: [0, 0, 1]},
  41. {boundaries: [[11, 7, 2, 4]], dir: [-1, 1, 0], up: [0, 0, 1]},
  42. {boundaries: [[17, 7, 2, 4]], dir: [-1, -1, 0], up: [0, 0, 1]},
  43. {boundaries: [[0, 7, 1, 4], [23, 7, 1, 4]], dir: [1, -1, 0], up: [0, 0, 1]},
  44. {boundaries: [[5, 11, 2, 2]], dir: [1, 1, 1], up: [-1, -1, 1]},
  45. {boundaries: [[23, 11, 1, 1], [6, 17, 1, 1], [0, 11, 1, 1]], dir: [1, -1, 1], up: [-1, 1, 1]},
  46. {boundaries: [[5, 5, 2, 2]], dir: [1, 1, -1], up: [1, 1, 1]},
  47. {boundaries: [[11, 17, 1, 1], [17, 11, 2, 1]], dir: [-1, -1, 1], up: [1, 1, 1]},
  48. {boundaries: [[17, 6, 2, 1], [11, 0, 1, 1]], dir: [-1, -1, -1], up: [-1, -1, 1]},
  49. {boundaries: [[11, 11, 2, 2]], dir: [-1, 1, 1], up: [1, -1, 1]},
  50. {boundaries: [[0, 6, 1, 1], [6, 0, 1, 1], [23, 6, 1, 1]], dir: [1, -1, -1], up: [1, -1, 1]},
  51. {boundaries: [[11, 5, 2, 2]], dir: [-1, 1, -1], up: [-1, 1, 1]}
  52. ];
  53.  
  54. const facesYUp = [
  55. {boundary: [6, 6, 6, 6], color: cfg.frontColor || cfg.color || "#55FF55"},
  56. {boundary: [18, 6, 6, 6], color: cfg.backColor || cfg.color || "#55FF55"},
  57. {boundary: [12, 6, 6, 6], color: cfg.rightColor || cfg.color || "#FF5555"},
  58. {boundary: [0, 6, 6, 6], color: cfg.leftColor || cfg.color || "#FF5555"},
  59. {boundary: [6, 0, 6, 6], color: cfg.topColor || cfg.color || "#7777FF"},
  60. {boundary: [6, 12, 6, 6], color: cfg.bottomColor || cfg.color || "#7777FF"}
  61. ];
  62.  
  63. const areasYUp = [
  64.  
  65. // Faces
  66.  
  67. {yUp: "", label: "NavCube.front", boundaries: [[7, 7, 4, 4]], dir: [0, 0, -1], up: [0, 1, 0]},
  68. {label: "NavCube.back", boundaries: [[19, 7, 4, 4]], dir: [0, 0, 1], up: [0, 1, 0]},
  69. {label: "NavCube.right", boundaries: [[13, 7, 4, 4]], dir: [-1, 0, 0], up: [0, 1, 0]},
  70. {label: "NavCube.left", boundaries: [[1, 7, 4, 4]], dir: [1, 0, 0], up: [0, 1, 0]},
  71. {label: "NavCube.top", boundaries: [[7, 1, 4, 4]], dir: [0, -1, 0], up: [0, 0, -1]},
  72. {label: "NavCube.bottom", boundaries: [[7, 13, 4, 4]], dir: [0, 1, 0], up: [0, 0, 1]},
  73. {boundaries: [[7, 5, 4, 2]], dir: [0, -0.7071, -0.7071], up: [0, 0.7071, -0.7071]}, // Top-front edge
  74. {boundaries: [[1, 6, 4, 1], [6, 1, 1, 4]], dir: [1, -1, 0], up: [1, 1, 0]}, // Top-left edge
  75. {boundaries: [[7, 0, 4, 1], [19, 6, 4, 1]], dir: [0, -0.7071, 0.7071], up: [0, 0.7071, 0.7071]}, // Top-back edge
  76. {boundaries: [[13, 6, 4, 1], [11, 1, 1, 4]], dir: [-1, -1, 0], up: [-1, 1, 0]}, // Top-right edge
  77. {boundaries: [[7, 11, 4, 2]], dir: [0, 1, -1], up: [0, 1, 1]}, // Bottom-front edge
  78. {boundaries: [[1, 11, 4, 1], [6, 13, 1, 4]], dir: [1, 1, 0], up: [-1, 1, 0]}, // Bottom-left edge
  79. {boundaries: [[7, 17, 4, 1], [19, 11, 4, 1]], dir: [0, 1, 1], up: [0, 1, -1]}, // Bottom-back edge
  80. {boundaries: [[13, 11, 4, 1], [11, 13, 1, 4]], dir: [-1, 1, 0], up: [1, 1, 0]}, // Bottom-right edge
  81. {boundaries: [[5, 7, 2, 4]], dir: [1, 0, -1], up: [0, 1, 0]},// Front-left edge
  82. {boundaries: [[11, 7, 2, 4]], dir: [-1, 0, -1], up: [0, 1, 0]}, // Front-right edge
  83. {boundaries: [[17, 7, 2, 4]], dir: [-1, 0, 1], up: [0, 1, 0]},// Back-right edge
  84. {boundaries: [[0, 7, 1, 4], [23, 7, 1, 4]], dir: [1, 0, 1], up: [0, 1, 0]},// Back-left edge
  85. {boundaries: [[5, 11, 2, 2]], "dir": [0.5, 0.7071, -0.5], "up": [-0.5, 0.7071, 0.5]}, // Bottom-left-front corner
  86. {boundaries: [[23, 11, 1, 1], [6, 17, 1, 1], [0, 11, 1, 1]],"dir": [0.5, 0.7071, 0.5],"up": [-0.5, 0.7071, -0.5]},// Bottom-back-left corner
  87. {boundaries: [[5, 5, 2, 2]], "dir": [0.5, -0.7071, -0.5], "up": [0.5, 0.7071, -0.5]}, // Left-front-top corner
  88. {boundaries: [[11, 17, 1, 1], [17, 11, 2, 1]], "dir": [-0.5, 0.7071, 0.5], "up": [0.5, 0.7071, -0.5]}, // Bottom-back-right corner
  89. {boundaries: [[17, 6, 2, 1], [11, 0, 1, 1]], "dir": [-0.5, -0.7071, 0.5], "up": [-0.5, 0.7071, 0.5]}, // Top-back-right corner
  90. {boundaries: [[11, 11, 2, 2]], "dir": [-0.5, 0.7071, -0.5], "up": [0.5, 0.7071, 0.5]}, // Bottom-front-right corner
  91. {boundaries: [[0, 6, 1, 1], [6, 0, 1, 1], [23, 6, 1, 1]], "dir": [0.5, -0.7071, 0.5], "up": [0.5, 0.7071, 0.5]},// Top-back-left corner
  92. {boundaries: [[11, 5, 2, 2]], "dir": [-0.5, -0.7071, -0.5], "up": [-0.5, 0.7071, -0.5]}// Top-front-right corner
  93. ];
  94.  
  95. for (let i = 0, len = areasZUp.length; i < len; i++) {
  96. math.normalizeVec3(areasZUp[i].dir, areasZUp[i].dir);
  97. math.normalizeVec3(areasZUp[i].up, areasZUp[i].up);
  98. }
  99.  
  100. for (let i = 0, len = areasYUp.length; i < len; i++) {
  101. math.normalizeVec3(areasYUp[i].dir, areasYUp[i].dir);
  102. math.normalizeVec3(areasYUp[i].up, areasYUp[i].up);
  103. }
  104.  
  105. var faces = facesYUp;
  106. var areas = areasYUp;
  107.  
  108. this._textureCanvas = document.createElement('canvas');
  109. this._textureCanvas.width = width;
  110. this._textureCanvas.height = height;
  111. this._textureCanvas.style.width = width + "px";
  112. this._textureCanvas.style.height = height + "px";
  113. this._textureCanvas.style.padding = "0";
  114. this._textureCanvas.style.margin = "0";
  115. this._textureCanvas.style.top = "0";
  116. this._textureCanvas.style.background = cubeColor;
  117. this._textureCanvas.style.position = "absolute";
  118. this._textureCanvas.style.opacity = "1.0";
  119. this._textureCanvas.style.visibility = "hidden";
  120. this._textureCanvas.style["z-index"] = 2000000;
  121.  
  122. const body = document.getElementsByTagName("body")[0];
  123. body.appendChild(this._textureCanvas);
  124.  
  125. const context = this._textureCanvas.getContext("2d");
  126.  
  127. let zUp = false;
  128.  
  129. function paint() {
  130.  
  131. for (let i = 0, len = facesZUp.length; i < len; i++) {
  132. const face = facesZUp[i];
  133. const boundary = face.boundary;
  134. const xmin = Math.round(boundary[0] * scale);
  135. const ymin = Math.round(boundary[1] * scale);
  136. const width = Math.round(boundary[2] * scale);
  137. const height = Math.round(boundary[3] * scale);
  138. context.fillStyle = face.color;
  139. context.fillRect(xmin, ymin, width, height);
  140. }
  141.  
  142. for (let i = 0, len = areas.length; i < len; i++) {
  143. let xmin;
  144. let ymin;
  145. let width;
  146. let height;
  147. const area = areas[i];
  148.  
  149. const boundaries = area.boundaries;
  150. for (var j = 0, lenj = boundaries.length; j < lenj; j++) {
  151. const boundary = boundaries[j];
  152. xmin = Math.round(boundary[0] * scale);
  153. ymin = Math.round(boundary[1] * scale);
  154. width = Math.round(boundary[2] * scale);
  155. height = Math.round(boundary[3] * scale);
  156. if (area.highlighted) {
  157. context.fillStyle = area.highlighted ? cubeHighlightColor : (area.color || cubeColor);
  158. context.fillRect(xmin, ymin, width, height);
  159. }
  160. }
  161. if (area.label) {
  162. context.fillStyle = textColor;
  163. context.font = '60px sans-serif';
  164. context.textAlign = "center";
  165. var xcenter = xmin + (width * 0.5);
  166. var ycenter = ymin + (height * 0.7);
  167. context.fillText(translateLabel(area.label), xcenter, ycenter, 80);
  168. }
  169. }
  170.  
  171. navCubeScene.glRedraw();
  172. }
  173.  
  174. const translateLabel = (function () {
  175.  
  176. const swizzleYUp = {
  177. "NavCube.front": "NavCube.front",
  178. "NavCube.back": "NavCube.back",
  179. "NavCube.right": "NavCube.right",
  180. "NavCube.left": "NavCube.left",
  181. "NavCube.top": "NavCube.top",
  182. "NavCube.bottom": "NavCube.bottom"
  183. };
  184.  
  185. const swizzleZUp = {
  186. "NavCube.front": "NavCube.front",
  187. "NavCube.back": "NavCube.back",
  188. "NavCube.right": "NavCube.right",
  189. "NavCube.left": "NavCube.left",
  190. "NavCube.top": "NavCube.top",
  191. "NavCube.bottom": "NavCube.bottom"
  192. };
  193.  
  194. const defaultLabels = {
  195. "NavCube.front": "FRONT",
  196. "NavCube.back": "BACK",
  197. "NavCube.right": "RIGHT",
  198. "NavCube.left": "LEFT",
  199. "NavCube.top": "TOP",
  200. "NavCube.bottom": "BOTTOM"
  201. };
  202.  
  203. return function (key) {
  204. const swizzle = zUp ? swizzleZUp : swizzleYUp;
  205. const swizzledKey = swizzle ? swizzle[key] : null;
  206. if (swizzledKey) {
  207. return viewer.localeService.translate(swizzledKey) || defaultLabels[swizzledKey] || swizzledKey;
  208. }
  209. return key;
  210. };
  211. })();
  212.  
  213. this.setZUp = function () {
  214. zUp = true;
  215. faces = facesZUp;
  216. areas = areasZUp;
  217. this.clear();
  218. };
  219.  
  220. this.setYUp = function () {
  221. zUp = false;
  222. faces = facesYUp;
  223. areas = areasYUp;
  224. this.clear();
  225. };
  226.  
  227. this.clear = function () {
  228. context.fillStyle = cubeColor;
  229. context.fillRect(0, 0, width, height);
  230. for (var i = 0, len = areas.length; i < len; i++) {
  231. const area = areas[i];
  232. area.highlighted = false;
  233. }
  234. paint();
  235. };
  236.  
  237. this.getArea = function (uv) {
  238. const s = uv[0] * width;
  239. const t = height - (uv[1] * height); // Correct for our texture Y-flipping
  240. for (var i = 0, len = areas.length; i < len; i++) {
  241. const area = areas[i];
  242. const boundaries = area.boundaries;
  243. for (var j = 0, lenj = boundaries.length; j < lenj; j++) {
  244. const boundary = boundaries[j];
  245. if (s >= (boundary[0] * scale) && s <= ((boundary[0] + boundary[2]) * scale) && t >= (boundary[1] * scale) && t <= ((boundary[1] + boundary[3]) * scale)) {
  246. return i;
  247. }
  248. }
  249. }
  250. return -1;
  251. };
  252.  
  253. this.setAreaHighlighted = function (areaId, highlighted) {
  254. var area = areas[areaId];
  255. if (!area) {
  256. throw "Area not found: " + areaId;
  257. }
  258. area.highlighted = !!highlighted;
  259. paint();
  260. };
  261.  
  262. this.getAreaDir = function (areaId) {
  263. var area = areas[areaId];
  264. if (!area) {
  265. throw "Unknown area: " + areaId;
  266. }
  267. return area.dir;
  268. };
  269.  
  270. this.getAreaUp = function (areaId) {
  271. var area = areas[areaId];
  272. if (!area) {
  273. throw "Unknown area: " + areaId;
  274. }
  275. return area.up;
  276. };
  277.  
  278. this.getImage = function () {
  279. return this._textureCanvas;
  280. };
  281.  
  282. this.destroy = function () {
  283. if (this._textureCanvas) {
  284. this._textureCanvas.parentNode.removeChild(this._textureCanvas);
  285. this._textureCanvas = null;
  286. }
  287. };
  288. }
  289.  
  290. export {CubeTextureCanvas};