Minimap.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /**
  2. * @author Yuan Yao https://github.com/LeonYuanYao
  3. *
  4. * A Minimap viewing tool for three.js
  5. *
  6. * @param {WebGLRenderer} renderer
  7. * @param {Scene} scene
  8. * @param {Camera} mainCamera
  9. * @param {Object} params
  10. */
  11. import {
  12. Camera,
  13. CameraHelper,
  14. CircleBufferGeometry,
  15. DoubleSide,
  16. FrontSide,
  17. Group,
  18. Mesh,
  19. MeshBasicMaterial,
  20. OrthographicCamera,
  21. PlaneBufferGeometry,
  22. Scene,
  23. Vector3,
  24. Vector4,
  25. WebGLRenderer
  26. } from "../../../build/three.module.js";
  27. var Minimap = function(renderer, scene, mainCamera, params) {
  28. this.renderer = renderer;
  29. this.scene = scene;
  30. this.object = mainCamera;
  31. this.viewRange = params.viewRange !== undefined ? params.viewRange : 1000;
  32. this.mapSize = params.mapSize !== undefined ? params.mapSize : 300;
  33. this.heightOffset = params.heightOffset !== undefined ? params.heightOffset : 10;
  34. var scope = this;
  35. var clientWidth, clientHeight;
  36. var updatePos, idcPos;
  37. var viewport = new Vector4();
  38. renderer.getCurrentViewport(viewport);
  39. var up = mainCamera.up.clone(), lookat = new Vector3(), lastLookat = new Vector3();
  40. getLookatVecProjected(mainCamera, lastLookat);
  41. var minimapGroup = new Group();
  42. var minimapCamera = new OrthographicCamera(
  43. - scope.viewRange / 2,
  44. scope.viewRange / 2,
  45. scope.viewRange / 2,
  46. - scope.viewRange / 2,
  47. 0.01,
  48. 10000
  49. );
  50. // set orthographic camera always look downward
  51. minimapCamera.lookAt(up.clone().negate());
  52. minimapGroup.add(minimapCamera);
  53. var mainCameraHelper = new CameraHelper(mainCamera);
  54. minimapGroup.add(mainCameraHelper);
  55. scene.add(minimapGroup);
  56. initBackplane(0x000000);
  57. initIndicator();
  58. Minimap.prototype.getCamera = function () {
  59. return minimapCamera;
  60. };
  61. Minimap.prototype.setMinimapVisibility = function (flag) {
  62. minimapCamera.backplane.visible = flag;
  63. minimapCamera.indicator.visible = flag;
  64. mainCameraHelper.visible = flag;
  65. };
  66. Minimap.prototype.renderMinimap = function (){
  67. setAutoClear(false);
  68. // render minimap
  69. scope.setMinimapVisibility(true);
  70. renderMinimap();
  71. // set the render state back to original
  72. scope.renderer.setViewport(0, 0, clientWidth, clientHeight);
  73. scope.renderer.setScissor(0, 0, clientWidth, clientHeight);
  74. scope.renderer.setScissorTest(true);
  75. setAutoClear(true);
  76. };
  77. /**
  78. * Private functions
  79. */
  80. function setAutoClear(flag) {
  81. scope.renderer.autoClear = flag;
  82. scope.renderer.autoClearColor = flag;
  83. scope.renderer.autoClearDepth = flag;
  84. }
  85. function renderMinimap() {
  86. updateMinimapCamera();
  87. scope.renderer.setViewport(0, 0, scope.mapSize, scope.mapSize);
  88. scope.renderer.render(scene, minimapCamera);
  89. }
  90. function initBackplane(color) {
  91. var width = Math.abs(minimapCamera.left - minimapCamera.right);
  92. var height = Math.abs(minimapCamera.top - minimapCamera.bottom);
  93. var plane = new Mesh(
  94. new PlaneBufferGeometry(width, height, 1),
  95. new MeshBasicMaterial({ color: color, side: FrontSide })
  96. );
  97. plane.quaternion.setFromAxisAngle(new Vector3(0, 0, 1), Math.PI / 2);
  98. minimapGroup.add(plane);
  99. minimapCamera.backplane = plane;
  100. }
  101. function initIndicator() {
  102. var dot = new Mesh(
  103. new CircleBufferGeometry(scope.mapSize / 45, 16, 0, 2 * Math.PI),
  104. new MeshBasicMaterial({ color: 0xffffff, side: DoubleSide })
  105. );
  106. dot.rotateX(Math.PI / 2);
  107. dot.visible = false;
  108. minimapGroup.add(dot);
  109. minimapCamera.indicator = dot;
  110. }
  111. function getLookatVecProjected(object, result) {
  112. object.getWorldDirection(result);
  113. result.projectOnPlane(up); // get the lookat vector projected on the orthographic camera
  114. }
  115. function updateMinimapCamera() {
  116. clientWidth = scope.renderer.domElement.clientWidth;
  117. clientHeight = scope.renderer.domElement.clientHeight;
  118. // update view frustum
  119. minimapCamera.left = - scope.viewRange / 2;
  120. minimapCamera.right = scope.viewRange / 2;
  121. minimapCamera.top = scope.viewRange / 2;
  122. minimapCamera.bottom = - scope.viewRange / 2;
  123. minimapCamera.updateProjectionMatrix();
  124. // update position
  125. updatePos = mainCamera.position.clone().add(up.clone().multiplyScalar(scope.heightOffset));
  126. minimapCamera.position.set(updatePos.x, updatePos.y, updatePos.z);
  127. minimapCamera.updateMatrixWorld();
  128. minimapCamera.backplane.position.set(minimapCamera.position.x, minimapCamera.position.y, minimapCamera.position.z - minimapCamera.far);
  129. minimapCamera.backplane.updateMatrixWorld();
  130. var idc = minimapCamera.indicator;
  131. idcPos = minimapCamera.position.clone().add(up.clone().negate().multiplyScalar(0.02));
  132. // idcPos = mainCamera.position.clone().add(up.clone().negate().multiplyScalar(0.02));
  133. idc.position.set(idcPos.x, idcPos.y, idcPos.z);
  134. idc.updateMatrixWorld();
  135. getLookatVecProjected(mainCamera, lastLookat); // store the last lookat vector
  136. }
  137. }
  138. export { Minimap };