Open Source Tomb Raider Engine
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.

Selector.cpp 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*!
  2. * \file src/Selector.cpp
  3. * \brief Selector Window
  4. *
  5. * http://antongerdelan.net/opengl/raycasting.html
  6. *
  7. * \author xythobuz
  8. */
  9. #include "imgui/imgui.h"
  10. #include "global.h"
  11. #include "Camera.h"
  12. #include "Log.h"
  13. #include "World.h"
  14. #include "system/Window.h"
  15. #include "Selector.h"
  16. #include <glm/gtx/intersect.hpp>
  17. bool Selector::visible = false;
  18. WorldObjects Selector::lastClickedObject = WorldObjectCount;
  19. // geometryObject, roomSpriteObject, roomModelObject, spriteObject, meshObject, modelObject, entityObject
  20. std::array<bool, WorldObjectCount> Selector::clickOnObject = {{ false, true, true, false, false, false, false }};
  21. glm::i32vec2 Selector::rayScreen(-1, -1);
  22. glm::vec3 Selector::rayWorld, Selector::lastIntersectPos, Selector::lastIntersectNorm;
  23. unsigned long Selector::lastIndexA, Selector::lastIndexB;
  24. void Selector::handleMouseClick(unsigned int x, unsigned int y, KeyboardButton button,
  25. bool released) {
  26. if ((button == leftmouseKey) && (!released)) {
  27. // Calculate click ray
  28. rayScreen = glm::vec2(x, y);
  29. glm::vec2 normalized = glm::vec2((2.0f * rayScreen.x) / Window::getSize().x - 1.0f,
  30. 1.0f - (2.0f * rayScreen.y) / Window::getSize().y);
  31. glm::vec4 rayClip(normalized.x, normalized.y, -1.0f, 1.0f);
  32. glm::vec4 rayEye(glm::inverse(Camera::getProjectionMatrix()) * rayClip);
  33. rayEye = glm::vec4(rayEye.x, rayEye.y, -1.0f, 0.0f);
  34. rayWorld = glm::vec3(glm::inverse(Camera::getViewMatrix()) * rayEye);
  35. rayWorld = glm::normalize(rayWorld);
  36. // Check for any intersections with object bounding spheres
  37. bool foundSomething = false;
  38. float depth = -1.0f;
  39. if (clickOnObject[roomModelObject] || clickOnObject[roomSpriteObject]) {
  40. for (unsigned long i = 0; i < World::sizeRoom(); i++) {
  41. Room& r = World::getRoom(i);
  42. glm::vec3 pos, norm;
  43. if (clickOnObject[roomModelObject]) {
  44. for (unsigned long j = 0; j < r.sizeModels(); j++) {
  45. StaticModel& sm = r.getModel(j);
  46. if (glm::intersectRaySphere(Camera::getPosition(), rayWorld, sm.getCenter(), sm.getRadius(),
  47. pos, norm)) {
  48. float newDepth = glm::abs(glm::distance(sm.getCenter(), Camera::getPosition()));
  49. if ((newDepth < depth) || (depth < 0.0f)) {
  50. depth = newDepth;
  51. lastIndexA = i;
  52. lastIndexB = j;
  53. lastIntersectPos = pos;
  54. lastIntersectNorm = norm;
  55. lastClickedObject = roomModelObject;
  56. foundSomething = true;
  57. }
  58. }
  59. }
  60. }
  61. if (clickOnObject[roomSpriteObject]) {
  62. for (unsigned long j = 0; j < r.sizeSprites(); j++) {
  63. RoomSprite& rs = r.getSprite(j);
  64. if (glm::intersectRaySphere(Camera::getPosition(), rayWorld, rs.getCenter(), rs.getRadius(), pos,
  65. norm)) {
  66. float newDepth = glm::abs(glm::distance(rs.getCenter(), Camera::getPosition()));
  67. if ((newDepth < depth) || (depth < 0.0f)) {
  68. depth = newDepth;
  69. lastIndexA = i;
  70. lastIndexB = j;
  71. lastIntersectPos = pos;
  72. lastIntersectNorm = norm;
  73. lastClickedObject = roomSpriteObject;
  74. foundSomething = true;
  75. }
  76. }
  77. }
  78. }
  79. }
  80. }
  81. if (!foundSomething) {
  82. lastClickedObject = WorldObjectCount;
  83. }
  84. }
  85. }
  86. void Selector::displaySelection() {
  87. if (lastClickedObject == roomModelObject) {
  88. World::getRoom(lastIndexA).getModel(lastIndexB).displayBoundingSphere(
  89. Camera::getProjectionMatrix() * Camera::getViewMatrix(), glm::vec3(1.0f, 0.0f, 0.0f));
  90. } else if (lastClickedObject == roomSpriteObject) {
  91. World::getRoom(lastIndexA).getSprite(lastIndexB).displayBoundingSphere(
  92. Camera::getProjectionMatrix() * Camera::getViewMatrix(), glm::vec3(1.0f, 0.0f, 0.0f));
  93. } else {
  94. lastClickedObject = WorldObjectCount;
  95. }
  96. }
  97. void Selector::display() {
  98. if (!visible)
  99. return;
  100. if (!ImGui::Begin("Object Selector", &visible, ImVec2(500, 200))) {
  101. ImGui::End();
  102. return;
  103. }
  104. ImGui::Checkbox("RoomModels", &clickOnObject[roomModelObject]);
  105. ImGui::SameLine();
  106. ImGui::Checkbox("RoomSprites", &clickOnObject[roomSpriteObject]);
  107. ImGui::SameLine();
  108. if (ImGui::Button("Hide Selector")) {
  109. visible = false;
  110. }
  111. ImGui::Separator();
  112. ImGui::Text("Camera: (%.2f %.2f %.2f)", Camera::getPosition().x, Camera::getPosition().y,
  113. Camera::getPosition().z);
  114. ImGui::Text("Last click: (%d %d)", rayScreen.x, rayScreen.y);
  115. if ((rayScreen.x >= 0) && (rayScreen.y >= 0)) {
  116. ImGui::Text("Normalized Ray: (%.3f %.3f %.3f)", rayWorld.x, rayWorld.y, rayWorld.z);
  117. }
  118. if (lastClickedObject != WorldObjectCount) {
  119. ImGui::Text("Intersect Pos: (%.2f %.2f %.2f)", lastIntersectPos.x, lastIntersectPos.y,
  120. lastIntersectPos.z);
  121. ImGui::Text("Intersect Norm: (%.2f %.2f %.2f)", lastIntersectNorm.x, lastIntersectNorm.y,
  122. lastIntersectNorm.z);
  123. }
  124. if (lastClickedObject == roomModelObject) {
  125. ImGui::Text("Last Room: %lu", lastIndexA);
  126. ImGui::Text("Last RoomModel: %lu", lastIndexB);
  127. } else if (lastClickedObject == roomSpriteObject) {
  128. ImGui::Text("Last Room: %lu", lastIndexA);
  129. ImGui::Text("Last RoomSprite: %lu", lastIndexB);
  130. } else {
  131. lastClickedObject = WorldObjectCount;
  132. }
  133. ImGui::End();
  134. }