Minimap.js 5.0 KB

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