You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
4.1 KiB

  1. import { mat4, vec3, vec4 } from "gl-matrix";
  2. import { Corner, GAT, Tile } from "../format/gat";
  3. import { createProgram, createShader, ShaderType } from "../util/render";
  4. /* @ts-ignore */
  5. import fragmentSource from "./gat.frag";
  6. /* @ts-ignore */
  7. import vertexSource from "./gat.vert";
  8. const UP = vec3.fromValues(0, 1, 0);
  9. export const renderGAT = (gl: WebGLRenderingContext, gat: GAT) => {
  10. console.log("gat", gat);
  11. gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  12. gl.clearColor(0, 0, 0, 1);
  13. gl.clear(gl.COLOR_BUFFER_BIT);
  14. const fragmentShader = createShader(gl, ShaderType.FRAGMENT, fragmentSource);
  15. const vertexShader = createShader(gl, ShaderType.VERTEX, vertexSource);
  16. const program = createProgram(gl, vertexShader, fragmentShader);
  17. gl.useProgram(program);
  18. gl.enable(gl.DEPTH_TEST);
  19. const maxAltitude = getMaxAltitude(gat);
  20. console.log("altitude", maxAltitude);
  21. const camera = vec3.fromValues(
  22. gat.width / 2,
  23. maxAltitude + 10,
  24. gat.height / 2
  25. );
  26. console.log("camera", camera);
  27. const centerX = Math.floor(gat.width / 2);
  28. const centerZ = Math.floor(gat.height / 2);
  29. const centerTile = gat.tiles[gat.width * centerZ + centerX];
  30. const center = vec3.fromValues(centerX, avgTileHeight(centerTile), centerZ);
  31. console.log("center", center);
  32. const model = mat4.create();
  33. mat4.identity(model);
  34. mat4.translate(model, model, vec3.fromValues(-centerX, 0, -centerZ));
  35. const view = mat4.create();
  36. mat4.lookAt(view, camera, center, UP);
  37. const perspective = mat4.create();
  38. const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
  39. mat4.perspective(perspective, Math.PI / 4, aspect, 0.5, 2000);
  40. const matrix = mat4.create();
  41. mat4.multiply(matrix, view, model);
  42. mat4.multiply(matrix, perspective, matrix);
  43. const matrixLoc = gl.getUniformLocation(program, "u_matrix");
  44. gl.uniformMatrix4fv(matrixLoc, false, matrix);
  45. console.log("model", model);
  46. console.log("view", view);
  47. console.log("projection", perspective);
  48. console.log("matrix", matrix);
  49. const vertices: number[] = [];
  50. gat.tiles.forEach((tile, i) => {
  51. const x = i % gat.width;
  52. const z = Math.floor(i / gat.width);
  53. const topLeft = [x, tile.altitude[Corner.TOP_LEFT], z];
  54. const topRight = [x + 1, tile.altitude[Corner.TOP_RIGHT], z];
  55. const bottomLeft = [x, tile.altitude[Corner.BOTTOM_LEFT], z + 1];
  56. const bottomRight = [x + 1, tile.altitude[Corner.BOTTOM_RIGHT], z + 1];
  57. vertices.push(
  58. ...topLeft,
  59. ...bottomLeft,
  60. ...topRight,
  61. ...topRight,
  62. ...bottomLeft,
  63. ...bottomRight
  64. );
  65. });
  66. let failCount = 0;
  67. for (let i = 0; i < vertices.length / 3; ++i) {
  68. const vec = vec3.fromValues(vertices[i], vertices[i + 1], vertices[i + 2]);
  69. const result = checkPixelCoord(vec, matrix);
  70. if (result) {
  71. if (failCount < 10) {
  72. console.log(vec);
  73. console.log(result);
  74. }
  75. failCount++;
  76. }
  77. }
  78. console.log("failCount", failCount);
  79. console.log("totalCount", vertices.length / 3);
  80. const positionLoc = gl.getAttribLocation(program, "a_position");
  81. const vertexBuffer = gl.createBuffer();
  82. gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  83. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
  84. gl.enableVertexAttribArray(positionLoc);
  85. gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  86. gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);
  87. gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 3);
  88. };
  89. const checkPixelCoord = (x: vec3, mat: mat4): vec4 | null => {
  90. const vec = vec4.fromValues(x[0], x[1], x[2], 1);
  91. vec4.transformMat4(vec, vec, mat);
  92. for (let i = 0; i < vec.length; ++i) {
  93. if (Math.abs(vec[i]) >= 1) {
  94. return vec;
  95. }
  96. }
  97. return null;
  98. };
  99. const getMaxAltitude = (gat: GAT): number =>
  100. gat.tiles.reduce(
  101. (max, tile) =>
  102. Object.values(tile.altitude).reduce(
  103. (max1, altitude) => Math.max(max1, altitude),
  104. max
  105. ),
  106. 0
  107. );
  108. const avgTileHeight = (tile: Tile): number => {
  109. const heights = [...Object.values(tile.altitude)];
  110. const s = heights.reduce((x, y) => x + y, 0);
  111. return s / heights.length;
  112. };