Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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. }