当前位置:   article > 正文

【开发日志】2022.09.09 ZENO viewportwidge---raycast---sphere&AABB Box_sphere raycast

sphere raycast

RAYCAST

vdoc.pub_game-physics-cookbook.pdf

76a428ddde414a77a460da0a856d5d94.png


Linetest  Sphere

0d9b430d2c464f428a45c474769c67bb.png

 b57450e9f367471aa82ef4a965a31990.png

6f7e7bcee00d4df995d6aaeacc98f2d5.png  

  1. bool Raycast(const Sphere& sphere, const Ray& ray, RaycastResult* outResult) {
  2. ResetRaycastResult(outResult);
  3. vec3 e = sphere.position - ray.origin;
  4. float rSq = sphere.radius * sphere.radius;
  5. float eSq = MagnitudeSq(e);
  6. float a = Dot(e, ray.direction); // ray.direction is assumed to be normalized
  7. float bSq = /*sqrtf(*/eSq - (a * a)/*)*/;
  8. float f = sqrt(fabsf((rSq)- /*(b * b)*/bSq));
  9. // Assume normal intersection!
  10. float t = a - f;
  11. // No collision has happened
  12. if (rSq - (eSq - a * a) < 0.0f) {
  13. return false;
  14. }
  15. // Ray starts inside the sphere
  16. else if (eSq < rSq) {
  17. // Just reverse direction
  18. t = a + f;
  19. }
  20. if (outResult != 0) {
  21. outResult->t = t;
  22. outResult->hit = true;
  23. outResult->point = ray.origin + ray.direction * t;
  24. outResult->normal = Normalized(outResult->point - sphere.position);
  25. }
  26. return true;
  27. }
  1. bool Linetest(const Sphere& sphere, const Line& line) {
  2. Point closest = ClosestPoint(line, sphere.position);
  3. float distSq = MagnitudeSq(sphere.position - closest);
  4. return distSq <= (sphere.radius * sphere.radius);
  5. }

ZENO

  1. static std::optional<float> ray_sphere_intersect(
  2. zeno::vec3f const &ray_pos,
  3. zeno::vec3f const &ray_dir,
  4. zeno::vec3f const &sphere_center,
  5. float sphere_radius
  6. ) {
  7. auto &p = ray_pos;
  8. auto &d = ray_dir;
  9. auto &c = sphere_center;
  10. auto &r = sphere_radius;
  11. float t = zeno::dot(c - p, d);
  12. if (t < 0) {
  13. return std::nullopt;
  14. }
  15. zeno::vec3f dist = t * d + p - c;
  16. float l = zeno::length(dist);
  17. if (l > r) {
  18. return std::nullopt;
  19. }
  20. float t_diff = std::sqrt(r * r - l * l);
  21. float final_t = t - t_diff;
  22. return final_t;
  23. }
  1. if (zeno::objectGetFocusCenterRadius(ptr, center, radius)) {
  2. if (auto ret = ray_sphere_intersect(ro, rd, center, radius)) {
  3. float t = *ret;
  4. if (t < min_t) {
  5. min_t = t;
  6. name = key;
  7. }
  8. }
  9. }
objectGetFocusCenterRadius()在ObjectGeometryInfo.cpp 里,见后文 

98cda641a5ca47a090c6b9986ba65762.png

ff1143c3e14e414fbc926737040eb7b3.png

  1. bool Raycast(const AABB& aabb, const Ray& ray, RaycastResult* outResult) {
  2. ResetRaycastResult(outResult);
  3. vec3 min = GetMin(aabb);
  4. vec3 max = GetMax(aabb);
  5. // Any component of direction could be 0!
  6. // Address this by using a small number, close to
  7. // 0 in case any of directions components are 0
  8. float t1 = (min.x - ray.origin.x) / (CMP(ray.direction.x, 0.0f) ? 0.00001f : ray.direction.x);
  9. float t2 = (max.x - ray.origin.x) / (CMP(ray.direction.x, 0.0f) ? 0.00001f : ray.direction.x);
  10. float t3 = (min.y - ray.origin.y) / (CMP(ray.direction.y, 0.0f) ? 0.00001f : ray.direction.y);
  11. float t4 = (max.y - ray.origin.y) / (CMP(ray.direction.y, 0.0f) ? 0.00001f : ray.direction.y);
  12. float t5 = (min.z - ray.origin.z) / (CMP(ray.direction.z, 0.0f) ? 0.00001f : ray.direction.z);
  13. float t6 = (max.z - ray.origin.z) / (CMP(ray.direction.z, 0.0f) ? 0.00001f : ray.direction.z);
  14. float tmin = fmaxf(fmaxf(fminf(t1, t2), fminf(t3, t4)), fminf(t5, t6));
  15. float tmax = fminf(fminf(fmaxf(t1, t2), fmaxf(t3, t4)), fmaxf(t5, t6));
  16. // if tmax < 0, ray is intersecting AABB
  17. // but entire AABB is behing it's origin
  18. if (tmax < 0) {
  19. return false;
  20. }
  21. // if tmin > tmax, ray doesn't intersect AABB
  22. if (tmin > tmax) {
  23. return false;
  24. }
  25. float t_result = tmin;
  26. // If tmin is < 0, tmax is closer
  27. if (tmin < 0.0f) {
  28. t_result = tmax;
  29. }
  30. if (outResult != 0) {
  31. outResult->t = t_result;
  32. outResult->hit = true;
  33. outResult->point = ray.origin + ray.direction * t_result;
  34. vec3 normals[] = {
  35. vec3(-1, 0, 0),
  36. vec3(1, 0, 0),
  37. vec3(0, -1, 0),
  38. vec3(0, 1, 0),
  39. vec3(0, 0, -1),
  40. vec3(0, 0, 1)
  41. };
  42. float t[] = { t1, t2, t3, t4, t5, t6 };
  43. for (int i = 0; i < 6; ++i) {
  44. if (CMP(t_result, t[i])) {
  45. outResult->normal = normals[i];
  46. }
  47. }
  48. }
  49. return true;
  50. }
  1. bool Linetest(const AABB& aabb, const Line& line) {
  2. Ray ray;
  3. ray.origin = line.start;
  4. ray.direction = Normalized(line.end - line.start);
  5. RaycastResult raycast;
  6. if (!Raycast(aabb, ray, &raycast)) {
  7. return false;
  8. }
  9. float t = raycast.t;
  10. return t >= 0 && t * t <= LengthSq(line);
  11. }

ZENO 

  1. static std::optional<float> ray_box_intersect(
  2. zeno::vec3f const &bmin,
  3. zeno::vec3f const &bmax,
  4. zeno::vec3f const &ray_pos,
  5. zeno::vec3f const &ray_dir
  6. ) {
  7. //objectGetBoundingBox(IObject *ptr, vec3f &bmin, vec3f &bmax);
  8. auto &min = bmin;
  9. auto &max = bmax;
  10. auto &p = ray_pos;
  11. auto &d = ray_dir;
  12. //auto &t = t;
  13. float t1 = (min[0] - p[0]) / (CMP(d[0], 0.0f) ? 0.00001f : d[0]);
  14. float t2 = (max[0] - p[0]) / (CMP(d[0], 0.0f) ? 0.00001f : d[0]);
  15. float t3 = (min[1] - p[1]) / (CMP(d[1], 0.0f) ? 0.00001f : d[1]);
  16. float t4 = (max[1] - p[1]) / (CMP(d[1], 0.0f) ? 0.00001f : d[1]);
  17. float t5 = (min[2] - p[2]) / (CMP(d[2], 0.0f) ? 0.00001f : d[2]);
  18. float t6 = (max[2] - p[2]) / (CMP(d[2], 0.0f) ? 0.00001f : d[2]);
  19. float tmin = fmaxf(fmaxf(fminf(t1, t2), fminf(t3, t4)), fminf(t5, t6));
  20. float tmax = fminf(fminf(fmaxf(t1, t2), fmaxf(t3, t4)), fmaxf(t5, t6));
  21. // if tmax < 0, ray is intersecting AABB
  22. // but entire AABB is behing it's origin
  23. if (tmax < 0) {
  24. return std::nullopt;
  25. }
  26. // if tmin > tmax, ray doesn't intersect AABB
  27. if (tmin > tmax) {
  28. return std::nullopt;
  29. }
  30. float t_result = tmin;
  31. // If tmin is < 0, tmax is closer
  32. if (tmin < 0.0f) {
  33. t_result = tmax;
  34. }
  35. //zeno::vec3f final_t = p + d * t_result;
  36. return t_result;
  37. }
  1. zeno::vec3f bmin,bmax;
  2. if (zeno::objectGetBoundingBox(ptr,bmin,bmax) ){
  3. if (auto ret = ray_box_intersect(bmin, bmax, ro, rd)) {
  4. float t = *ret;
  5. if (t < min_t) {
  6. min_t = t;
  7. name = key;
  8. }
  9. }
  10. }
  11. }

ObjectGeometryInfo.cpp 

/zeno/zeno/src/funcs

  1. #include <zeno/funcs/ObjectGeometryInfo.h>
  2. #include <zeno/types/PrimitiveObject.h>
  3. #include <zeno/funcs/PrimitiveTools.h>
  4. #include <zeno/types/UserData.h>
  5. namespace zeno {
  6. ZENO_API bool objectGetBoundingBox(IObject *ptr, vec3f &bmin, vec3f &bmax) {
  7. auto &ud = ptr->userData();
  8. if (ud.has("_bboxMin") && ud.has("_bboxMax")) {
  9. bmin = ud.getLiterial<vec3f>("_bboxMin");
  10. bmax = ud.getLiterial<vec3f>("_bboxMax");
  11. return true;
  12. } else {
  13. if (auto obj = dynamic_cast<PrimitiveObject *>(ptr)) {
  14. std::tie(bmin, bmax) = primBoundingBox(obj);
  15. ud.setLiterial("_bboxMin", bmin);
  16. ud.setLiterial("_bboxMax", bmax);
  17. return true;
  18. }
  19. else {
  20. return false;
  21. }
  22. }
  23. }
  24. ZENO_API bool objectGetFocusCenterRadius(IObject *ptr, vec3f &center, float &radius) {
  25. vec3f bmin, bmax;
  26. if (!objectGetBoundingBox(ptr, bmin, bmax))
  27. return false;
  28. auto delta = bmax - bmin;
  29. radius = std::max(std::max(delta[0], delta[1]), delta[2]) * 0.5f;
  30. center = (bmin + bmax) * 0.5f;
  31. return true;
  32. }
  33. }
  1. for (auto const &[key, ptr] : scene->objectsMan->pairs()) {
  2. zeno::vec3f center;
  3. float radius;
  4. zeno::vec3f ro(cam_pos[0], cam_pos[1], cam_pos[2]);
  5. zeno::vec3f rd(rdir[0], rdir[1], rdir[2]);
  6. if (zeno::objectGetFocusCenterRadius(ptr, center, radius)) {
  7. if (auto ret = ray_sphere_intersect(ro, rd, center, radius)) {
  8. float t = *ret;
  9. if (t < min_t) {
  10. min_t = t;
  11. name = key;
  12. }
  13. }
  14. }
  15. }


viewportwidget.cpp

/zeno/ui/zenoedit/viewport

  1. #include <zenovis/RenderEngine.h>
  2. #include "viewportwidget.h"
  3. #include "zenovis.h"
  4. #include "camerakeyframe.h"
  5. #include "timeline/ztimeline.h"
  6. #include "graphsmanagment.h"
  7. #include "model/graphsmodel.h"
  8. #include "launch/corelaunch.h"
  9. #include "zenoapplication.h"
  10. #include "zenomainwindow.h"
  11. #include "dialog/zrecorddlg.h"
  12. #include "dialog/zrecprogressdlg.h"
  13. #include <zeno/utils/log.h>
  14. #include <zenovis/ObjectsManager.h>
  15. #include <zenovis/Scene.h>
  16. #include <zeno/funcs/ObjectGeometryInfo.h>
  17. #include <zeno/types/UserData.h>
  18. #include <viewport/zenovis.h>
  19. #include <util/log.h>
  20. #include <zenoui/style/zenostyle.h>
  21. //#include <zeno/utils/zeno_p.h>
  22. #include <nodesys/nodesmgr.h>
  23. #include <cmath>
  24. #include <algorithm>
  25. #include <optional>
  26. #include <zeno/core/Session.h>
  27. #include <zeno/extra/GlobalState.h>
  28. #include <zeno/extra/GlobalComm.h>
  29. #include <zenoui/util/uihelper.h>
  30. #include "recordvideomgr.h"
  31. #define CMP(x, y) \
  32. (fabsf(x - y) <= FLT_EPSILON * fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y))))
  33. static std::optional<float> ray_sphere_intersect(
  34. zeno::vec3f const &ray_pos,
  35. zeno::vec3f const &ray_dir,
  36. zeno::vec3f const &sphere_center,
  37. float sphere_radius
  38. ) {
  39. auto &p = ray_pos;
  40. auto &d = ray_dir;
  41. auto &c = sphere_center;
  42. auto &r = sphere_radius;
  43. float t = zeno::dot(c - p, d);
  44. if (t < 0) {
  45. return std::nullopt;
  46. }
  47. zeno::vec3f dist = t * d + p - c;
  48. float l = zeno::length(dist);
  49. if (l > r) {
  50. return std::nullopt;
  51. }
  52. float t_diff = std::sqrt(r * r - l * l);
  53. float final_t = t - t_diff;
  54. return final_t;
  55. }
  56. static std::optional<float> ray_box_intersect(
  57. zeno::vec3f const &bmin,
  58. zeno::vec3f const &bmax,
  59. zeno::vec3f const &ray_pos,
  60. zeno::vec3f const &ray_dir
  61. ) {
  62. //objectGetBoundingBox(IObject *ptr, vec3f &bmin, vec3f &bmax);
  63. auto &min = bmin;
  64. auto &max = bmax;
  65. auto &p = ray_pos;
  66. auto &d = ray_dir;
  67. //auto &t = t;
  68. float t1 = (min[0] - p[0]) / (CMP(d[0], 0.0f) ? 0.00001f : d[0]);
  69. float t2 = (max[0] - p[0]) / (CMP(d[0], 0.0f) ? 0.00001f : d[0]);
  70. float t3 = (min[1] - p[1]) / (CMP(d[1], 0.0f) ? 0.00001f : d[1]);
  71. float t4 = (max[1] - p[1]) / (CMP(d[1], 0.0f) ? 0.00001f : d[1]);
  72. float t5 = (min[2] - p[2]) / (CMP(d[2], 0.0f) ? 0.00001f : d[2]);
  73. float t6 = (max[2] - p[2]) / (CMP(d[2], 0.0f) ? 0.00001f : d[2]);
  74. float tmin = fmaxf(fmaxf(fminf(t1, t2), fminf(t3, t4)), fminf(t5, t6));
  75. float tmax = fminf(fminf(fmaxf(t1, t2), fmaxf(t3, t4)), fmaxf(t5, t6));
  76. // if tmax < 0, ray is intersecting AABB
  77. // but entire AABB is behing it's origin
  78. if (tmax < 0) {
  79. return std::nullopt;
  80. }
  81. // if tmin > tmax, ray doesn't intersect AABB
  82. if (tmin > tmax) {
  83. return std::nullopt;
  84. }
  85. float t_result = tmin;
  86. // If tmin is < 0, tmax is closer
  87. if (tmin < 0.0f) {
  88. t_result = tmax;
  89. }
  90. //zeno::vec3f final_t = p + d * t_result;
  91. return t_result;
  92. }
  93. static bool test_in_selected_bounding(
  94. QVector3D centerWS,
  95. QVector3D cam_posWS,
  96. QVector3D left_normWS,
  97. QVector3D right_normWS,
  98. QVector3D up_normWS,
  99. QVector3D down_normWS
  100. ) {
  101. QVector3D dir = centerWS - cam_posWS;
  102. dir.normalize();
  103. bool left_test = QVector3D::dotProduct(dir, left_normWS) > 0;
  104. bool right_test = QVector3D::dotProduct(dir, right_normWS) > 0;
  105. bool up_test = QVector3D::dotProduct(dir, up_normWS) > 0;
  106. bool down_test = QVector3D::dotProduct(dir, down_normWS) > 0;
  107. return left_test && right_test && up_test && down_test;
  108. }
  109. CameraControl::CameraControl(QWidget* parent)
  110. : m_mmb_pressed(false)
  111. , m_theta(0.)
  112. , m_phi(0.)
  113. , m_ortho_mode(false)
  114. , m_fov(45.)
  115. , m_radius(5.0)
  116. , m_res(1, 1)
  117. , m_aperture(0.1f)
  118. , m_focalPlaneDistance(2.0f)
  119. {
  120. transformer = std::make_unique<zeno::FakeTransformer>();
  121. updatePerspective();
  122. }
  123. void CameraControl::setRes(QVector2D res)
  124. {
  125. m_res = res;
  126. }
  127. void CameraControl::setAperture(float aperture){
  128. m_aperture = aperture;
  129. }
  130. void CameraControl::setDisPlane(float disPlane){
  131. m_focalPlaneDistance = disPlane;
  132. }
  133. void CameraControl::fakeMousePressEvent(QMouseEvent* event)
  134. {
  135. if (event->buttons() & Qt::MiddleButton) {
  136. m_lastPos = event->pos();
  137. }
  138. else if (event->buttons() & Qt::LeftButton) {
  139. m_boundRectStartPos = event->pos();
  140. m_lastMovePos = event->pos();
  141. // check if clicked a selected object
  142. auto scene = Zenovis::GetInstance().getSession()->get_scene();
  143. if (!scene->selected.empty() && mouseEnteredRing(event->x(), event->y())) {
  144. transformer->startTransform();
  145. }
  146. }
  147. }
  148. QVector2D CameraControl::qtCoordToGLCoord(int x, int y) {
  149. auto w = res()[0];
  150. auto h = res()[1];
  151. auto mx = x * 1.0f;
  152. auto my = y * 1.0f;
  153. mx = (2 * mx / w) - 1;
  154. my = 1 - (2 * my / h);
  155. return {mx, my};
  156. }
  157. bool CameraControl::mouseEnteredRing(int x, int y) {
  158. auto scene = Zenovis::GetInstance().getSession()->get_scene();
  159. auto world_coord = glm::vec4(transformer->getCenter(), 1.0);
  160. auto screen_coord = scene->camera->m_proj * scene->camera->m_view * world_coord;
  161. screen_coord /= screen_coord[3];
  162. auto cx = screen_coord[0];
  163. auto cy = screen_coord[1];
  164. auto mp = qtCoordToGLCoord(x, y);
  165. auto mx = mp.x();
  166. auto my = mp.y();
  167. auto ar = res()[0] / res()[1];
  168. auto dis = sqrt(((cx - mx) * ar) * ((cx - mx) * ar) + (cy - my) * (cy - my));
  169. // 0.1 is the bigger radius of ring
  170. return dis < 0.1;
  171. }
  172. void CameraControl::fakeMouseMoveEvent(QMouseEvent* event)
  173. {
  174. auto session = Zenovis::GetInstance().getSession();
  175. auto scene = session->get_scene();
  176. if (event->buttons() & Qt::MiddleButton) {
  177. float ratio = QApplication::desktop()->devicePixelRatio();
  178. float xpos = event->x(), ypos = event->y();
  179. float dx = xpos - m_lastPos.x(), dy = ypos - m_lastPos.y();
  180. dx *= ratio / m_res[0];
  181. dy *= ratio / m_res[1];
  182. bool shift_pressed = event->modifiers() & Qt::ShiftModifier;
  183. if (shift_pressed)
  184. {
  185. float cos_t = cos(m_theta);
  186. float sin_t = sin(m_theta);
  187. float cos_p = cos(m_phi);
  188. float sin_p = sin(m_phi);
  189. QVector3D back(cos_t * sin_p, sin_t, -cos_t * cos_p);
  190. QVector3D up(-sin_t * sin_p, cos_t, sin_t * cos_p);
  191. QVector3D right = QVector3D::crossProduct(up, back);
  192. up = QVector3D::crossProduct(back, right);
  193. right.normalize();
  194. up.normalize();
  195. QVector3D delta = right * dx + up * dy;
  196. m_center += delta * m_radius;
  197. }
  198. else
  199. {
  200. m_theta -= dy * M_PI;
  201. m_phi += dx * M_PI;
  202. }
  203. m_lastPos = QPointF(xpos, ypos);
  204. }
  205. else if (event->buttons() & Qt::LeftButton) {
  206. if (transformer->isTransforming()) {
  207. bool alt_pressed = event->modifiers() & Qt::AltModifier;
  208. bool ctrl_pressed = event->modifiers() & Qt::ControlModifier;
  209. glm::mat4 transform_matrix(1.0f);
  210. auto transform_center = transformer->getCenter();
  211. QVector3D center_qvec(transform_center[0], transform_center[1], transform_center[2]);
  212. zeno::vec3f center_zvec(transform_center[0], transform_center[1], transform_center[2]);
  213. std::set<std::unique_ptr<zenovis::IGraphicDraw>> interactingGraphics;
  214. QVector3D x_axis(1, 0, 0);
  215. QVector3D y_axis(0, 1, 0);
  216. QVector3D z_axis(0, 0, 1);
  217. QVariant start, end;
  218. QVector3D start_vec, end_vec;
  219. // get transform matrix
  220. if (ctrl_pressed && alt_pressed) {
  221. // rotate
  222. if (m_pressedKeys.contains(Qt::Key_Z)) {
  223. // rotate along x=center_qvec.x plane
  224. start = hitOnPlane((float)m_lastMovePos.x() / res().x(), (float)m_lastMovePos.y() / res().y(),
  225. x_axis, center_qvec);
  226. end = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  227. x_axis, center_qvec);
  228. if (start.isValid() && end.isValid()) {
  229. start_vec = start.value<QVector3D>() - center_qvec;
  230. end_vec = end.value<QVector3D>() - center_qvec;
  231. transformer->rotate(start_vec, end_vec, x_axis);
  232. interactingGraphics.insert(
  233. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {1, 0, 0}));
  234. }
  235. }
  236. else if (m_pressedKeys.contains(Qt::Key_X)) {
  237. // rotate along y=center_qvec.y plane
  238. start = hitOnPlane((float)m_lastMovePos.x() / res().x(), (float)m_lastMovePos.y() / res().y(),
  239. y_axis, center_qvec);
  240. end = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  241. y_axis, center_qvec);
  242. if (start.isValid() && end.isValid()) {
  243. start_vec = start.value<QVector3D>() - center_qvec;
  244. end_vec = end.value<QVector3D>() - center_qvec;
  245. transformer->rotate(start_vec, end_vec, y_axis);
  246. interactingGraphics.insert(
  247. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {0, 1, 0}));
  248. }
  249. }
  250. else if (m_pressedKeys.contains(Qt::Key_C)) {
  251. // rotate along z=center_qvec.z plane
  252. start = hitOnPlane((float)m_lastMovePos.x() / res().x(), (float)m_lastMovePos.y() / res().y(),
  253. z_axis, center_qvec);
  254. end = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  255. z_axis, center_qvec);
  256. if (start.isValid() && end.isValid()) {
  257. start_vec = start.value<QVector3D>() - center_qvec;
  258. end_vec = end.value<QVector3D>() - center_qvec;
  259. transformer->rotate(start_vec, end_vec, z_axis);
  260. interactingGraphics.insert(
  261. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {0, 0, 1}));
  262. }
  263. }
  264. }
  265. else if (alt_pressed) {
  266. // scale
  267. auto vp = scene->camera->m_proj * scene->camera->m_view;
  268. auto screen_center = vp * glm::vec4(transform_center, 1.0f);
  269. screen_center /= screen_center[3];
  270. QVector2D screen_center_2d(screen_center[0], screen_center[1]);
  271. QVector2D mouse_pos = qtCoordToGLCoord(event->x(), event->y());
  272. float scale_size = mouse_pos.distanceToPoint(screen_center_2d);
  273. if (m_pressedKeys.contains(Qt::Key_A)) {
  274. // scale along a plane
  275. if (m_pressedKeys.contains(Qt::Key_Z)) {
  276. // scale along x=center_qvec.x plane
  277. auto cur = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  278. y_axis, center_qvec);
  279. if (cur.isValid()) {
  280. transformer->scale(cur.value<QVector3D>() - center_qvec,{0, 1, 1}, scale_size);
  281. }
  282. interactingGraphics.insert(
  283. zenovis::makeGraphicInteractingAxis(scene, center_zvec,{0, 1, 1}));
  284. }
  285. else if (m_pressedKeys.contains(Qt::Key_X)) {
  286. // scale along y=center_qvec.y plane
  287. auto cur = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  288. y_axis, center_qvec);
  289. if (cur.isValid()) {
  290. transformer->scale(cur.value<QVector3D>() - center_qvec,{1, 0, 1}, scale_size);
  291. }
  292. interactingGraphics.insert(
  293. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {1, 0, 1}));
  294. }
  295. else if (m_pressedKeys.contains(Qt::Key_C)) {
  296. // scale along z=center_qvec.z plane
  297. auto cur = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  298. z_axis, center_qvec);
  299. if (cur.isValid()) {
  300. transformer->scale(cur.value<QVector3D>() - center_qvec,{1, 1, 0}, scale_size);
  301. }
  302. interactingGraphics.insert(
  303. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {1, 1, 0}));
  304. }
  305. }
  306. else {
  307. // scale along an axis
  308. if (m_pressedKeys.contains(Qt::Key_Z)) {
  309. // scale along x axis
  310. auto cur = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  311. y_axis, center_qvec);
  312. if (cur.isValid()) {
  313. transformer->scale(cur.value<QVector3D>() - center_qvec,{1, 0, 0}, scale_size);
  314. }
  315. interactingGraphics.insert(
  316. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {1, 0, 0}));
  317. }
  318. else if (m_pressedKeys.contains(Qt::Key_X)) {
  319. // scale along y=center_qvec.y plane
  320. auto cur = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  321. y_axis, center_qvec);
  322. if (cur.isValid()) {
  323. transformer->scale(cur.value<QVector3D>() - center_qvec,{0, 1, 0}, scale_size);
  324. }
  325. interactingGraphics.insert(
  326. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {0, 1, 0}));
  327. }
  328. else if (m_pressedKeys.contains(Qt::Key_C)) {
  329. auto cur = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  330. z_axis, center_qvec);
  331. if (cur.isValid()) {
  332. transformer->scale(cur.value<QVector3D>() - center_qvec,{0, 0, 1}, scale_size);
  333. }
  334. interactingGraphics.insert(
  335. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {0, 0, 1}));
  336. }
  337. }
  338. }
  339. else if (ctrl_pressed){
  340. // translate
  341. if (m_pressedKeys.contains(Qt::Key_A)) {
  342. // translate along a plane
  343. if (m_pressedKeys.contains(Qt::Key_Z)) {
  344. // translate along x=center_qvec.x plane
  345. start = hitOnPlane((float)m_lastMovePos.x() / res().x(), (float)m_lastMovePos.y() / res().y(),
  346. x_axis, center_qvec);
  347. end = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  348. x_axis, center_qvec);
  349. if (start.isValid() && end.isValid()) {
  350. transformer->translate(start.value<QVector3D>(),
  351. end.value<QVector3D>(), {0, 1, 1});
  352. }
  353. interactingGraphics.insert(
  354. zenovis::makeGraphicInteractingAxis(scene, center_zvec,{0, 1, 1}));
  355. }
  356. else if (m_pressedKeys.contains(Qt::Key_X)) {
  357. // translate along y=center_qvec.y plane
  358. start = hitOnPlane((float)m_lastMovePos.x() / res().x(), (float)m_lastMovePos.y() / res().y(),
  359. y_axis, center_qvec);
  360. end = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  361. y_axis, center_qvec);
  362. if (start.isValid() && end.isValid()) {
  363. transformer->translate(start.value<QVector3D>(),
  364. end.value<QVector3D>(), {1, 0, 1});
  365. }
  366. interactingGraphics.insert(
  367. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {1, 0, 1}));
  368. }
  369. else if (m_pressedKeys.contains(Qt::Key_C)) {
  370. // translate along z=center_qvec.z plane
  371. start = hitOnPlane((float)m_lastMovePos.x() / res().x(), (float)m_lastMovePos.y() / res().y(),
  372. z_axis, center_qvec);
  373. end = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  374. z_axis, center_qvec);
  375. if (start.isValid() && end.isValid()) {
  376. transformer->translate(start.value<QVector3D>(),
  377. end.value<QVector3D>(), {1, 1, 0});
  378. }
  379. interactingGraphics.insert(
  380. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {1, 1, 0}));
  381. }
  382. }
  383. else {
  384. // translate along an axis
  385. QVector3D translate_axis;
  386. if (m_pressedKeys.contains(Qt::Key_Z)) {
  387. // translate along x axis
  388. start = hitOnPlane((float)m_lastMovePos.x() / res().x(), (float)m_lastMovePos.y() / res().y(),
  389. y_axis, center_qvec);
  390. end = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  391. y_axis, center_qvec);
  392. if (start.isValid() && end.isValid()) {
  393. transformer->translate(start.value<QVector3D>(),end.value<QVector3D>(), x_axis);
  394. }
  395. interactingGraphics.insert(
  396. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {1, 0, 0}));
  397. }
  398. else if (m_pressedKeys.contains(Qt::Key_X)) {
  399. // translate along y=center_qvec.y plane
  400. start = hitOnPlane((float)m_lastMovePos.x() / res().x(), (float)m_lastMovePos.y() / res().y(),
  401. z_axis, center_qvec);
  402. end = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  403. z_axis, center_qvec);
  404. if (start.isValid() && end.isValid()) {
  405. transformer->translate(start.value<QVector3D>(),end.value<QVector3D>(), y_axis);
  406. }
  407. interactingGraphics.insert(
  408. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {0, 1, 0}));
  409. }
  410. else if (m_pressedKeys.contains(Qt::Key_C)) {
  411. // translate along z=center_qvec.z plane
  412. start = hitOnPlane((float)m_lastMovePos.x() / res().x(), (float)m_lastMovePos.y() / res().y(),
  413. y_axis, center_qvec);
  414. end = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  415. y_axis, center_qvec);
  416. if (start.isValid() && end.isValid()) {
  417. transformer->translate(start.value<QVector3D>(),end.value<QVector3D>(), z_axis);
  418. }
  419. interactingGraphics.insert(
  420. zenovis::makeGraphicInteractingAxis(scene, center_zvec, {0, 0, 1}));
  421. }
  422. }
  423. }
  424. else {
  425. // free translate (along sight plane)
  426. QVector3D camera_front(scene->camera->m_lodfront[0],
  427. scene->camera->m_lodfront[1],
  428. scene->camera->m_lodfront[2]);
  429. start = hitOnPlane((float)m_lastMovePos.x() / res().x(), (float)m_lastMovePos.y() / res().y(),
  430. camera_front, center_qvec);
  431. end = hitOnPlane((float)event->x() / res().x(), (float)event->y() / res().y(),
  432. camera_front, center_qvec);
  433. if (start.isValid() && end.isValid()) {
  434. transformer->translate(start.value<QVector3D>(),end.value<QVector3D>(), {1, 1, 1});
  435. }
  436. }
  437. session->set_interacting_graphics(interactingGraphics);
  438. m_lastMovePos = event->pos();
  439. zenoApp->getMainWindow()->updateViewport();
  440. }
  441. else {
  442. float min_x = std::min((float)m_boundRectStartPos.x(), (float)event->x()) / m_res.x();
  443. float max_x = std::max((float)m_boundRectStartPos.x(), (float)event->x()) / m_res.x();
  444. float min_y = std::min((float)m_boundRectStartPos.y(), (float)event->y()) / m_res.y();
  445. float max_y = std::max((float)m_boundRectStartPos.y(), (float)event->y()) / m_res.y();
  446. scene->select_box = zeno::vec4f(min_x, min_y, max_x, max_y);
  447. }
  448. }
  449. else {
  450. if (mouseEnteredRing(event->x(), event->y())) {
  451. Zenovis::GetInstance().getSession()->set_hovered_graphic("ring");
  452. }
  453. else {
  454. Zenovis::GetInstance().getSession()->set_hovered_graphic("");
  455. }
  456. }
  457. updatePerspective();
  458. }
  459. void CameraControl::updatePerspective()
  460. {
  461. float cx = m_center[0], cy = m_center[1], cz = m_center[2];
  462. Zenovis::GetInstance().updatePerspective(m_res, PerspectiveInfo(cx, cy, cz, m_theta, m_phi, m_radius, m_fov, m_ortho_mode, m_aperture, m_focalPlaneDistance));
  463. }
  464. void CameraControl::fakeWheelEvent(QWheelEvent* event)
  465. {
  466. int dy = event->angleDelta().y();
  467. float scale = (dy >= 0) ? 0.89 : 1 / 0.89;
  468. bool shift_pressed = (event->modifiers() & Qt::ShiftModifier) && !(event->modifiers() & Qt::ControlModifier);
  469. bool aperture_pressed = (event->modifiers() & Qt::ControlModifier) && !(event->modifiers() & Qt::ShiftModifier);
  470. bool focalPlaneDistance_pressed = (event->modifiers() & Qt::ControlModifier) && (event->modifiers() & Qt::ShiftModifier);
  471. float delta = dy > 0? 1: -1;
  472. if (shift_pressed){
  473. float temp = m_fov / scale;
  474. m_fov = temp < 170 ? temp : 170;
  475. }
  476. else if (aperture_pressed) {
  477. float temp = m_aperture += delta * 0.01;
  478. m_aperture = temp >= 0 ? temp : 0;
  479. }
  480. else if (focalPlaneDistance_pressed) {
  481. float temp = m_focalPlaneDistance + delta*0.05;
  482. m_focalPlaneDistance = temp >= 0.05 ? temp : 0.05;
  483. }
  484. else {
  485. m_radius *= scale;
  486. }
  487. updatePerspective();
  488. if(zenoApp->getMainWindow()->lightPanel != nullptr){
  489. zenoApp->getMainWindow()->lightPanel->camApertureEdit->setText(QString::number(m_aperture));
  490. zenoApp->getMainWindow()->lightPanel->camDisPlaneEdit->setText(QString::number(m_focalPlaneDistance));
  491. }
  492. }
  493. void CameraControl::setKeyFrame()
  494. {
  495. //todo
  496. }
  497. void CameraControl::focus(QVector3D center, float radius)
  498. {
  499. m_center = center;
  500. if (m_fov >= 1e-6)
  501. radius /= (m_fov / 45.0f);
  502. m_radius = radius;
  503. updatePerspective();
  504. }
  505. QVector3D CameraControl::realPos() const {
  506. float cos_t = std::cos(m_theta);
  507. float sin_t = std::sin(m_theta);
  508. float cos_p = std::cos(m_phi);
  509. float sin_p = std::sin(m_phi);
  510. QVector3D back(cos_t * sin_p, sin_t, -cos_t * cos_p);
  511. return m_center - back * m_radius;
  512. }
  513. // x, y from [0, 1]
  514. QVector3D CameraControl::screenToWorldRay(float x, float y) const {
  515. float cos_t = cos(m_theta);
  516. float sin_t = sin(m_theta);
  517. float cos_p = cos(m_phi);
  518. float sin_p = sin(m_phi);
  519. QVector3D back(cos_t * sin_p, sin_t, -cos_t * cos_p);
  520. QVector3D up(-sin_t * sin_p, cos_t, sin_t * cos_p);
  521. QVector3D right = QVector3D::crossProduct(up, back);
  522. up = QVector3D::crossProduct(back, right);
  523. right.normalize();
  524. up.normalize();
  525. QMatrix4x4 view;
  526. view.setToIdentity();
  527. view.lookAt(realPos(), m_center, up);
  528. x = (x - 0.5) * 2;
  529. y = (y - 0.5) * (-2);
  530. float v = std::tan(m_fov * M_PI / 180.f * 0.5f);
  531. float aspect = res().x() / res().y();
  532. auto dir = QVector3D(v * x * aspect, v * y, -1);
  533. dir = dir.normalized();
  534. dir = view.inverted().mapVector(dir);
  535. return dir;
  536. }
  537. QVariant CameraControl::hitOnFloor(float x, float y) const {
  538. auto dir = screenToWorldRay(x, y);
  539. auto pos = realPos();
  540. float t = (0 - pos.y()) / dir.y();
  541. if (t > 0) {
  542. auto p = pos + dir * t;
  543. return p;
  544. } else {
  545. return {};
  546. }
  547. }
  548. QVariant CameraControl::hitOnPlane(float x, float y, QVector3D n, QVector3D p) const {
  549. auto dir = screenToWorldRay(x, y);
  550. auto pos = realPos();
  551. float t = (n.x()*p.x() + n.y()*p.y() + n.z()*p.z() - n.x()*pos.x() - n.y()*pos.y() - n.z()*pos.z()) /
  552. (n.x()*dir.x() + n.y()*dir.y() + n.z()*dir.z());
  553. if (t > 0)
  554. return pos + dir * t;
  555. else
  556. return {};
  557. }
  558. void CameraControl::fakeMouseReleaseEvent(QMouseEvent *event) {
  559. if (event->button() == Qt::LeftButton) {
  560. //if (Zenovis::GetInstance().m_bAddPoint == true) {
  561. //float x = (float)event->x() / m_res.x();
  562. //float y = (float)event->y() / m_res.y();
  563. //auto rdir = screenToWorldRay(x, y);
  564. //auto pos = realPos();
  565. //float t = (0 - pos.y()) / rdir.y();
  566. //auto p = pos + rdir * t;
  567. //float cos_t = std::cos(m_theta);
  568. //float sin_t = std::sin(m_theta);
  569. //float cos_p = std::cos(m_phi);
  570. //float sin_p = std::sin(m_phi);
  571. //QVector3D back(cos_t * sin_p, sin_t, -cos_t * cos_p);
  572. //QVector3D up(-sin_t * sin_p, cos_t, sin_t * cos_p);
  573. //QVector3D right = QVector3D::crossProduct(up, back).normalized();
  574. //up = QVector3D::crossProduct(right, back).normalized();
  575. //QVector3D delta = right * x + up * y;
  576. //zeno::log_info("create point at x={} y={}", p[0], p[1]);
  577. createPointNode(QPointF(p[0], p[1]));
  578. //Zenovis::GetInstance().m_bAddPoint = false;
  579. //}
  580. auto scene = Zenovis::GetInstance().getSession()->get_scene();
  581. if (transformer->isTransforming()) {
  582. bool moved = false;
  583. if (m_boundRectStartPos != event->pos()) {
  584. // create/modify transform primitive node
  585. moved = true;
  586. }
  587. transformer->endTransform(moved);
  588. }
  589. else {
  590. auto cam_pos = realPos();
  591. scene->select_box = std::nullopt;
  592. bool shift_pressed = event->modifiers() & Qt::ShiftModifier;
  593. if (!shift_pressed) {
  594. scene->selected.clear();
  595. transformer->clear();
  596. }
  597. QPoint releasePos = event->pos();
  598. if (m_boundRectStartPos == releasePos) {
  599. float x = (float)event->x() / m_res.x();
  600. float y = (float)event->y() / m_res.y();
  601. auto rdir = screenToWorldRay(x, y);
  602. float min_t = std::numeric_limits<float>::max();
  603. std::string name("");
  604. for (auto const &[key, ptr] : scene->objectsMan->pairs()) {
  605. zeno::vec3f center;
  606. float radius;
  607. zeno::vec3f ro(cam_pos[0], cam_pos[1], cam_pos[2]);
  608. zeno::vec3f rd(rdir[0], rdir[1], rdir[2]);
  609. // if (zeno::objectGetFocusCenterRadius(ptr, center, radius)) {
  610. // if (auto ret = ray_sphere_intersect(ro, rd, center, radius)) {
  611. // float t = *ret;
  612. // if (t < min_t) {
  613. // min_t = t;
  614. // name = key;
  615. // }
  616. // }
  617. // }
  618. zeno::vec3f bmin,bmax;
  619. if (zeno::objectGetBoundingBox(ptr,bmin,bmax) ){
  620. if (auto ret = ray_box_intersect(bmin, bmax, ro, rd)) {
  621. float t = *ret;
  622. if (t < min_t) {
  623. min_t = t;
  624. name = key;
  625. }
  626. }
  627. }
  628. }
  629. if (!name.empty()) {
  630. if (scene->selected.count(name) > 0) {
  631. scene->selected.erase(name);
  632. transformer->removeObject(name);
  633. } else {
  634. scene->selected.insert(name);
  635. transformer->addObject(name);
  636. // printf("selected %s\n", name.c_str());
  637. }
  638. }
  639. } else {
  640. float min_x = std::min((float)m_boundRectStartPos.x(), (float)releasePos.x());
  641. float max_x = std::max((float)m_boundRectStartPos.x(), (float)releasePos.x());
  642. float min_y = std::min((float)m_boundRectStartPos.y(), (float)releasePos.y());
  643. float max_y = std::max((float)m_boundRectStartPos.y(), (float)releasePos.y());
  644. auto left_up = screenToWorldRay(min_x / m_res.x(), min_y / m_res.y());
  645. auto left_down = screenToWorldRay(min_x / m_res.x(), max_y / m_res.y());
  646. auto right_up = screenToWorldRay(max_x / m_res.x(), min_y / m_res.y());
  647. auto right_down = screenToWorldRay(max_x / m_res.x(), max_y / m_res.y());
  648. auto cam_posWS = realPos();
  649. auto left_normWS = QVector3D::crossProduct(left_down, left_up);
  650. auto right_normWS = QVector3D::crossProduct(right_up, right_down);
  651. auto up_normWS = QVector3D::crossProduct(left_up, right_up);
  652. auto down_normWS = QVector3D::crossProduct(right_down, left_down);
  653. std::vector<std::string> passed_prim;
  654. for (auto const &[key, ptr] : scene->objectsMan->pairs()) {
  655. zeno::vec3f c;
  656. float radius;
  657. if (zeno::objectGetFocusCenterRadius(ptr, c, radius)) {
  658. bool passed = test_in_selected_bounding(QVector3D(c[0], c[1], c[2]), cam_pos, left_normWS,
  659. right_normWS, up_normWS, down_normWS);
  660. if (passed) {
  661. passed_prim.push_back(key);
  662. transformer->addObject(key);
  663. }
  664. }
  665. }
  666. scene->selected.insert(passed_prim.begin(), passed_prim.end());
  667. }
  668. }
  669. if (!scene->selected.empty()) {
  670. auto center = transformer->getCenter();
  671. zeno::vec3f ring_center(center[0], center[1], center[2]);
  672. std::map<std::string, std::unique_ptr<zenovis::IGraphicInteractDraw>> interactGraphics;
  673. interactGraphics["ring"] = zenovis::makeGraphicRing(scene, ring_center);
  674. interactGraphics["axis"] = zenovis::makeGraphicInteractAxis(scene, ring_center);
  675. Zenovis::GetInstance().getSession()->set_interactive_graphics(interactGraphics);
  676. zenoApp->getMainWindow()->updateViewport();
  677. }
  678. ZenoMainWindow* mainWin = zenoApp->getMainWindow();
  679. mainWin->onPrimitiveSelected(scene->selected);
  680. }
  681. }
  682. void CameraControl::addPressedKey(int key) {
  683. m_pressedKeys += key;
  684. }
  685. void CameraControl::rmvPressedKey(int key) {
  686. m_pressedKeys -= key;
  687. }
  688. //void CameraControl::createPointNode(QPointF pnt) {
  689. //auto pModel = zenoApp->graphsManagment()->currentModel();
  690. //ZASSERT_EXIT(pModel);
  691. todo luzh: select specific subgraph to add node.
  692. //const QModelIndex &subgIdx = pModel->index("main");
  693. //NODE_DATA tmpNodeInfo = NodesMgr::createPointNode(pModel, subgIdx, "CreatePoint", {10, 10}, pnt);
  694. //STATUS_UPDATE_INFO info;
  695. //info.role = ROLE_OPTIONS;
  696. //info.newValue = OPT_VIEW;
  697. //pModel->updateNodeStatus(tmpNodeInfo[ROLE_OBJID].toString(), info, subgIdx, true);
  698. //}
  699. ViewportWidget::ViewportWidget(QWidget* parent)
  700. : QOpenGLWidget(parent)
  701. , m_camera(nullptr)
  702. , updateLightOnce(true)
  703. {
  704. QSurfaceFormat fmt;
  705. int nsamples = 16; // TODO: adjust in a zhouhang-panel
  706. fmt.setSamples(nsamples);
  707. fmt.setVersion(3, 2);
  708. fmt.setProfile(QSurfaceFormat::CoreProfile);
  709. setFormat(fmt);
  710. m_camera = std::make_shared<CameraControl>();
  711. Zenovis::GetInstance().m_camera_control = m_camera.get();
  712. }
  713. ViewportWidget::~ViewportWidget()
  714. {
  715. }
  716. namespace {
  717. struct OpenGLProcAddressHelper {
  718. inline static QOpenGLContext *ctx;
  719. static void *getProcAddress(const char *name) {
  720. return (void *)ctx->getProcAddress(name);
  721. }
  722. };
  723. }
  724. void ViewportWidget::initializeGL()
  725. {
  726. OpenGLProcAddressHelper::ctx = context();
  727. Zenovis::GetInstance().loadGLAPI((void *)OpenGLProcAddressHelper::getProcAddress);
  728. Zenovis::GetInstance().initializeGL();
  729. }
  730. void ViewportWidget::resizeGL(int nx, int ny)
  731. {
  732. float ratio = devicePixelRatioF();
  733. zeno::log_trace("nx={}, ny={}, dpr={}", nx, ny, ratio);
  734. m_camera->setRes(QVector2D(nx * ratio, ny * ratio));
  735. m_camera->updatePerspective();
  736. }
  737. QVector2D ViewportWidget::cameraRes() const
  738. {
  739. return m_camera->res();
  740. }
  741. void ViewportWidget::setCameraRes(const QVector2D& res)
  742. {
  743. m_camera->setRes(res);
  744. }
  745. void ViewportWidget::updatePerspective()
  746. {
  747. m_camera->updatePerspective();
  748. }
  749. void ViewportWidget::paintGL()
  750. {
  751. Zenovis::GetInstance().paintGL();
  752. if(updateLightOnce){
  753. auto scene = Zenovis::GetInstance().getSession()->get_scene();
  754. if(scene->objectsMan->lightObjects.size() > 0){
  755. zenoApp->getMainWindow()->updateLightList();
  756. updateLightOnce = false;
  757. }
  758. }
  759. if (!record_path.empty() /*&& f <= frame_end*/) //py has bug: frame_end not initialized.
  760. {
  761. int f = Zenovis::GetInstance().getCurrentFrameId();
  762. auto record_file = zeno::format("{}/{:06d}.png", record_path, f);
  763. checkRecord(record_file, record_res);
  764. }
  765. }
  766. void ViewportWidget::checkRecord(std::string a_record_file, QVector2D a_record_res)
  767. {
  768. if (!record_path.empty() /*&& f <= frame_end*/) //py has bug: frame_end not initialized.
  769. {
  770. QVector2D oldRes = m_camera->res();
  771. m_camera->setRes(a_record_res);
  772. m_camera->updatePerspective();
  773. auto extname = QFileInfo(QString::fromStdString(a_record_file)).suffix().toStdString();
  774. Zenovis::GetInstance().getSession()->do_screenshot(a_record_file, extname);
  775. m_camera->setRes(oldRes);
  776. m_camera->updatePerspective();
  777. //if f == self.frame_end:
  778. // self.parent_widget.record_video.finish_record()
  779. }
  780. }
  781. void ViewportWidget::mousePressEvent(QMouseEvent* event)
  782. {
  783. _base::mousePressEvent(event);
  784. m_camera->fakeMousePressEvent(event);
  785. update();
  786. }
  787. void ViewportWidget::mouseMoveEvent(QMouseEvent* event)
  788. {
  789. _base::mouseMoveEvent(event);
  790. m_camera->fakeMouseMoveEvent(event);
  791. update();
  792. }
  793. void ViewportWidget::wheelEvent(QWheelEvent* event)
  794. {
  795. _base::wheelEvent(event);
  796. m_camera->fakeWheelEvent(event);
  797. update();
  798. }
  799. void ViewportWidget::mouseReleaseEvent(QMouseEvent *event) {
  800. _base::mouseReleaseEvent(event);
  801. m_camera->fakeMouseReleaseEvent(event);
  802. update();
  803. }
  804. void ViewportWidget::addPressedKey(int key) {
  805. m_camera->addPressedKey(key);
  806. }
  807. void ViewportWidget::rmvPressedKey(int key) {
  808. m_camera->rmvPressedKey(key);
  809. }
  810. void ViewportWidget::updateCameraProp(float aperture, float disPlane) {
  811. m_camera->setAperture(aperture);
  812. m_camera->setDisPlane(disPlane);
  813. updatePerspective();
  814. }
  815. /*
  816. QDMDisplayMenu::QDMDisplayMenu()r("Show Grid")
  817. {
  818. setTitle(tr("Display"));
  819. QAction* pAction = new QAction(tr("Show Grid"), this);
  820. pAction->setCheckable(true);
  821. pAction->setChecked(true);
  822. addAction(pAction);
  823. pAction = new QAction(tr("Background Color"), this);
  824. addAction(pAction);
  825. addSeparator();
  826. pAction = new QAction(tr("Smooth Shading"), this);
  827. pAction->setCheckable(true);
  828. pAction->setChecked(false);
  829. addAction(pAction);
  830. pAction = new QAction(tr("Wireframe"), this);
  831. pAction->setCheckable(true);
  832. pAction->setChecked(false);
  833. addSeparator();
  834. pAction = new QAction(tr("Enable PBR"), this);
  835. pAction->setCheckable(true);
  836. pAction->setChecked(false);
  837. addAction(pAction);
  838. pAction = new QAction(tr("Enable GI"), this);
  839. pAction->setCheckable(true);
  840. pAction->setChecked(false);
  841. addAction(pAction);
  842. addSeparator();
  843. pAction = new QAction(tr("Camera Keyframe"), this);
  844. addAction(pAction);
  845. addSeparator();
  846. pAction = new QAction(tr("English / Chinese"), this);
  847. pAction->setCheckable(true);
  848. pAction->setChecked(true);
  849. addAction(pAction);
  850. }
  851. QDMRecordMenu::QDMRecordMenu()
  852. {
  853. setTitle(tr("Record"));
  854. QAction* pAction = new QAction(tr("Screenshot"), this);
  855. pAction->setShortcut(QKeySequence("F12"));
  856. addAction(pAction);
  857. pAction = new QAction(tr("Record Video"), this);
  858. pAction->setShortcut(QKeySequence(tr("Shift+F12")));
  859. addAction(pAction);
  860. }
  861. */
  862. DisplayWidget::DisplayWidget(ZenoMainWindow* pMainWin)
  863. : QWidget(pMainWin)
  864. , m_view(nullptr)
  865. , m_timeline(nullptr)
  866. , m_mainWin(pMainWin)
  867. , m_pTimer(nullptr)
  868. {
  869. QVBoxLayout* pLayout = new QVBoxLayout;
  870. pLayout->setContentsMargins(0, 0, 0, 0);
  871. pLayout->setSpacing(0);
  872. setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
  873. /*
  874. ZMenuBar* menuBar = new ZMenuBar;
  875. menuBar->setMaximumHeight(26);
  876. QDMDisplayMenu* menuDisplay = new QDMDisplayMenu;
  877. menuBar->addMenu(menuDisplay);
  878. QDMRecordMenu* recordDisplay = new QDMRecordMenu;
  879. menuBar->addMenu(recordDisplay);
  880. pLayout->addWidget(menuBar);
  881. */
  882. m_view = new ViewportWidget;
  883. // viewport interaction need to set mouse tracking true
  884. // but it will lead to a light panel edit bug
  885. // m_view->setMouseTracking(true);
  886. pLayout->addWidget(m_view);
  887. m_timeline = new ZTimeline;
  888. pLayout->addWidget(m_timeline);
  889. setLayout(pLayout);
  890. //RecordVideoDialog
  891. m_camera_keyframe = new CameraKeyframeWidget;
  892. Zenovis::GetInstance().m_camera_keyframe = m_camera_keyframe;
  893. connect(&Zenovis::GetInstance(), SIGNAL(frameUpdated(int)), m_timeline, SLOT(onTimelineUpdate(int)));
  894. connect(m_timeline, SIGNAL(playForward(bool)), this, SLOT(onPlayClicked(bool)));
  895. connect(m_timeline, SIGNAL(sliderValueChanged(int)), this, SLOT(onSliderValueChanged(int)));
  896. connect(m_timeline, SIGNAL(run()), this, SLOT(onRun()));
  897. connect(m_timeline, SIGNAL(alwaysChecked()), this, SLOT(onRun()));
  898. connect(m_timeline, SIGNAL(kill()), this, SLOT(onKill()));
  899. //connect(m_view, SIGNAL(sig_Draw()), this, SLOT(onRun()));
  900. auto graphs = zenoApp->graphsManagment();
  901. connect(&*graphs, SIGNAL(modelDataChanged()), this, SLOT(onModelDataChanged()));
  902. m_pTimer = new QTimer(this);
  903. connect(m_pTimer, SIGNAL(timeout()), this, SLOT(updateFrame()));
  904. }
  905. DisplayWidget::~DisplayWidget()
  906. {
  907. }
  908. void DisplayWidget::init()
  909. {
  910. //m_camera->installEventFilter(this);
  911. }
  912. TIMELINE_INFO DisplayWidget::timelineInfo()
  913. {
  914. TIMELINE_INFO info;
  915. info.bAlways = m_timeline->isAlways();
  916. info.beginFrame = m_timeline->fromTo().first;
  917. info.endFrame = m_timeline->fromTo().second;
  918. return info;
  919. }
  920. void DisplayWidget::setTimelineInfo(TIMELINE_INFO info)
  921. {
  922. m_timeline->setAlways(info.bAlways);
  923. m_timeline->setFromTo(info.beginFrame, info.endFrame);
  924. }
  925. ViewportWidget* DisplayWidget::getViewportWidget()
  926. {
  927. return m_view;
  928. }
  929. QSize DisplayWidget::sizeHint() const
  930. {
  931. return ZenoStyle::dpiScaledSize(QSize(12, 400));
  932. }
  933. void DisplayWidget::updateFrame(const QString &action) // cihou optix
  934. {
  935. if (m_mainWin && m_mainWin->inDlgEventLoop())
  936. return;
  937. if (action == "newFrame") {
  938. m_pTimer->stop();
  939. //zeno::log_warn("stop");
  940. return;
  941. } else if (action == "finishFrame") {
  942. if (isOptxRendering()) {
  943. m_pTimer->start(m_updateFeq);
  944. }
  945. } else if (!action.isEmpty()) {
  946. if (action == "optx") {
  947. m_pTimer->start(m_updateFeq);
  948. } else {
  949. m_pTimer->stop();
  950. }
  951. }
  952. m_view->update();
  953. }
  954. void DisplayWidget::onFinished()
  955. {
  956. int frameid_ui = m_timeline->value();
  957. if (frameid_ui != Zenovis::GetInstance().getCurrentFrameId())
  958. {
  959. Zenovis::GetInstance().setCurrentFrameId(frameid_ui);
  960. updateFrame();
  961. onPlayClicked(false);
  962. BlockSignalScope scope(m_timeline);
  963. m_timeline->setPlayButtonToggle(false);
  964. }
  965. }
  966. bool DisplayWidget::isOptxRendering() const
  967. {
  968. auto& inst = Zenovis::GetInstance();
  969. auto sess = inst.getSession();
  970. if (!sess)
  971. return false;
  972. auto scene = sess->get_scene();
  973. if (!scene)
  974. return false;
  975. return (scene->renderMan && scene->renderMan->getDefaultEngineName() == "optx");
  976. }
  977. void DisplayWidget::onModelDataChanged()
  978. {
  979. if (m_timeline->isAlways())
  980. {
  981. onRun();
  982. }
  983. }
  984. void DisplayWidget::onPlayClicked(bool bChecked)
  985. {
  986. if (bChecked)
  987. {
  988. m_pTimer->start(m_sliderFeq);
  989. }
  990. else
  991. {
  992. if (!isOptxRendering())
  993. m_pTimer->stop();
  994. }
  995. Zenovis::GetInstance().startPlay(bChecked);
  996. }
  997. void DisplayWidget::onSliderValueChanged(int frame)
  998. {
  999. m_mainWin->clearErrorMark();
  1000. if (m_timeline->isAlways())
  1001. {
  1002. auto pGraphsMgr = zenoApp->graphsManagment();
  1003. IGraphsModel* pModel = pGraphsMgr->currentModel();
  1004. if (!pModel)
  1005. return;
  1006. launchProgram(pModel, frame, frame);
  1007. }
  1008. else
  1009. {
  1010. Zenovis::GetInstance().setCurrentFrameId(frame);
  1011. updateFrame();
  1012. onPlayClicked(false);
  1013. BlockSignalScope scope(m_timeline);
  1014. m_timeline->setPlayButtonToggle(false);
  1015. }
  1016. }
  1017. void DisplayWidget::onRun()
  1018. {
  1019. m_mainWin->clearErrorMark();
  1020. Zenovis::GetInstance().getSession()->get_scene()->selected.clear();
  1021. QPair<int, int> fromTo = m_timeline->fromTo();
  1022. int beginFrame = fromTo.first;
  1023. int endFrame = fromTo.second;
  1024. if (endFrame >= beginFrame && beginFrame >= 0)
  1025. {
  1026. auto pGraphsMgr = zenoApp->graphsManagment();
  1027. IGraphsModel* pModel = pGraphsMgr->currentModel();
  1028. if (!pModel)
  1029. return;
  1030. launchProgram(pModel, beginFrame, endFrame);
  1031. }
  1032. else
  1033. {
  1034. }
  1035. m_view->updateLightOnce = true;
  1036. auto scene = Zenovis::GetInstance().getSession()->get_scene();
  1037. scene->objectsMan->lightObjects.clear();
  1038. }
  1039. void DisplayWidget::keyPressEvent(QKeyEvent* event) {
  1040. if (!event->isAutoRepeat())
  1041. m_view->addPressedKey(event->key());
  1042. }
  1043. void DisplayWidget::keyReleaseEvent(QKeyEvent* event) {
  1044. if (!event->isAutoRepeat())
  1045. m_view->rmvPressedKey(event->key());
  1046. }
  1047. void DisplayWidget::onRecord()
  1048. {
  1049. auto& inst = Zenovis::GetInstance();
  1050. auto& ptr = zeno::getSession().globalComm;
  1051. ZASSERT_EXIT(ptr);
  1052. if (ptr->maxPlayFrames() == 0) {
  1053. //run.
  1054. QMessageBox::information(nullptr, "Zeno", tr("Run the graph before recording"), QMessageBox::Ok);
  1055. return;
  1056. }
  1057. int frameLeft = ptr->beginFrameNumber;
  1058. int frameRight = ptr->endFrameNumber;
  1059. ZRecordVideoDlg dlg(frameLeft, frameRight, this);
  1060. if (QDialog::Accepted == dlg.exec())
  1061. {
  1062. int frameStart = 0, frameEnd = 0, fps = 0, bitrate = 0, width = 0, height = 0;
  1063. QString presets, path, filename;
  1064. dlg.getInfo(frameStart, frameEnd, fps, bitrate, presets, width, height, path, filename);
  1065. //validation.
  1066. VideoRecInfo recInfo;
  1067. recInfo.record_path = path;
  1068. recInfo.frameRange = { frameStart, frameEnd };
  1069. recInfo.res = { (float)width, (float)height };
  1070. recInfo.bitrate = bitrate;
  1071. recInfo.fps = fps;
  1072. recInfo.videoname = filename;
  1073. Zenovis::GetInstance().startPlay(true);
  1074. RecordVideoMgr recordMgr(m_view, recInfo, nullptr);
  1075. ZRecordProgressDlg dlgProc(recInfo);
  1076. connect(&recordMgr, SIGNAL(frameFinished(int)), &dlgProc, SLOT(onFrameFinished(int)));
  1077. connect(&recordMgr, SIGNAL(recordFinished()), &dlgProc, SLOT(onRecordFinished()));
  1078. connect(&recordMgr, SIGNAL(recordFailed(QString)), &dlgProc, SLOT(onRecordFailed(QString)));
  1079. if (QDialog::Accepted == dlgProc.exec())
  1080. {
  1081. }
  1082. else
  1083. {
  1084. recordMgr.cancelRecord();
  1085. }
  1086. }
  1087. }
  1088. void DisplayWidget::onKill()
  1089. {
  1090. killProgram();
  1091. }

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/520616
推荐阅读
相关标签
  

闽ICP备14008679号