From b5a07b1b009e5bd145b853b9500b85063ac65927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Skowro=C5=84ski?= Date: Wed, 14 Jun 2023 15:48:52 +0200 Subject: [PATCH 1/5] Added extensions for 3Dconnexion integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patryk Skowroński --- avogadro/rendering/CMakeLists.txt | 9 ++ avogadro/rendering/camera.cpp | 6 +- avogadro/rendering/camera.h | 22 +++- avogadro/rendering/geometryvisitor.cpp | 14 +++ avogadro/rendering/geometryvisitor.h | 42 ++++++++ avogadro/rendering/glrenderer.cpp | 62 +++++++++++ avogadro/rendering/glrenderer.h | 12 ++- avogadro/rendering/scene.h | 32 +++++- avogadro/rendering/tdxextensions.cpp | 141 +++++++++++++++++++++++++ 9 files changed, 330 insertions(+), 10 deletions(-) create mode 100644 avogadro/rendering/tdxextensions.cpp diff --git a/avogadro/rendering/CMakeLists.txt b/avogadro/rendering/CMakeLists.txt index ef4368c507..02533642f0 100644 --- a/avogadro/rendering/CMakeLists.txt +++ b/avogadro/rendering/CMakeLists.txt @@ -1,5 +1,6 @@ find_package(OpenGL REQUIRED) find_package(GLEW REQUIRED) + if(WIN32 AND NOT BUILD_SHARED_LIBS) add_definitions(-DGLEW_STATIC) endif() @@ -94,6 +95,10 @@ target_sources(Rendering PRIVATE ambientocclusionspheregeometry.cpp ) +if(USE_3DCONNEXION AND (WIN32 OR APPLE)) + target_sources(Rendering PRIVATE tdxextensions.cpp) +endif() + set(shader_files "arrow_vs.glsl" "cylinders_fs.glsl" @@ -144,3 +149,7 @@ target_link_libraries(Rendering Avogadro::Core # Needed for an emum in residue.h that we should move, maybe others. GLEW::GLEW OpenGL::GL) + +if(USE_3DCONNEXION AND (WIN32 OR APPLE)) + target_compile_definitions(Rendering PUBLIC _3DCONNEXION) +endif() \ No newline at end of file diff --git a/avogadro/rendering/camera.cpp b/avogadro/rendering/camera.cpp index 7c5e1b9c97..6970e74760 100644 --- a/avogadro/rendering/camera.cpp +++ b/avogadro/rendering/camera.cpp @@ -23,7 +23,7 @@ Camera::Camera() Camera::Camera(const Camera& o) : m_width(o.m_width), m_height(o.m_height), m_projectionType(o.m_projectionType), - m_orthographicScale(o.m_orthographicScale), m_data(new EigenData(*o.m_data)) + m_orthographicScale(o.m_orthographicScale), m_data(new EigenData(*o.m_data)) {} Camera& Camera::operator=(const Camera& o) @@ -132,7 +132,7 @@ Vector3f Camera::unProject(const Vector2f& point, } void Camera::calculatePerspective(float fieldOfView, float aspectRatio, - float zNear, float zFar) + float zNear, float zFar) { m_data->projection.setIdentity(); float f = 1.0f / std::tan(fieldOfView * float(M_PI) / 360.0f); @@ -152,7 +152,7 @@ void Camera::calculatePerspective(float fieldOfView, float zNear, float zFar) } void Camera::calculateOrthographic(float left, float right, float bottom, - float top, float zNear, float zFar) + float top, float zNear, float zFar) { left *= m_orthographicScale; right *= m_orthographicScale; diff --git a/avogadro/rendering/camera.h b/avogadro/rendering/camera.h index 692d58aadc..d5072c8763 100644 --- a/avogadro/rendering/camera.h +++ b/avogadro/rendering/camera.h @@ -100,7 +100,7 @@ class AVOGADRORENDERING_EXPORT Camera * reference point (defaults to the origin if nothing is supplied). */ Vector3f unProject(const Vector2f& point, - const Vector3f& reference = Vector3f::Zero()) const; + const Vector3f& reference = Vector3f::Zero()) const; /** * Calculate the perspective projection matrix. @@ -110,7 +110,7 @@ class AVOGADRORENDERING_EXPORT Camera * @param zFar is the distance from the viewer to the far clipping plane. */ void calculatePerspective(float fieldOfView, float aspectRatio, float zNear, - float zFar); + float zFar); /** * Calculate the perspective projection matrix. Computes the aspect ratio @@ -120,7 +120,21 @@ class AVOGADRORENDERING_EXPORT Camera * @param zFar is the distance from the viewer to the far clipping plane. */ void calculatePerspective(float fieldOfView, float zNear, float zFar); - +#ifdef _3DCONNEXION + /** + * << API Extension for TDX >> + * Calculate the perspective projection matrix using frustum planes + * coordinates. + * @param left left vertical clipping plane. + * @param right right vertical clipping plane. + * @param bottom bottom horizontal clipping plane. + * @param top top horizontal clipping plane. + * @param zNear distance to the near clipping plane. + * @param zFar distance to the far clipping plane. + */ + void calculatePerspective(float left, float right, float bottom, float top, + float zNear, float zFar); +#endif /** * Calculate the orthographic projection matrix. * @param left left vertical clipping plane. @@ -131,7 +145,7 @@ class AVOGADRORENDERING_EXPORT Camera * @param zFar distance to the far clipping plane. */ void calculateOrthographic(float left, float right, float bottom, float top, - float zNear, float zFar); + float zNear, float zFar); /** * Set the dimensions of the viewport in pixels. diff --git a/avogadro/rendering/geometryvisitor.cpp b/avogadro/rendering/geometryvisitor.cpp index c5dedf209b..bf471f9b21 100644 --- a/avogadro/rendering/geometryvisitor.cpp +++ b/avogadro/rendering/geometryvisitor.cpp @@ -9,6 +9,9 @@ #include "curvegeometry.h" #include "linestripgeometry.h" #include "spheregeometry.h" +#ifdef _3DCONNEXION +#include "cylindergeometry.h" +#endif namespace Avogadro::Rendering { @@ -27,6 +30,9 @@ void GeometryVisitor::visit(Drawable&) void GeometryVisitor::visit(SphereGeometry& geometry) { +#ifdef _3DCONNEXION + m_sphereGeometries.push_back(geometry); +#endif const Core::Array& spheres = geometry.spheres(); if (!spheres.size()) return; @@ -47,6 +53,9 @@ void GeometryVisitor::visit(SphereGeometry& geometry) float distance = (it->center - tmpCenter).squaredNorm(); if (distance > tmpRadius) tmpRadius = distance; +#ifdef _3DCONNEXION + m_spheres.push_back(*it); +#endif } } tmpRadius = std::sqrt(tmpRadius); @@ -145,6 +154,11 @@ void GeometryVisitor::clear() m_dirty = false; m_centers.clear(); m_radii.clear(); +#ifdef _3DCONNEXION + m_spheres.clear(); + m_sphereGeometries.clear(); + m_cylinderGeometries.clear(); +#endif } Vector3f GeometryVisitor::center() diff --git a/avogadro/rendering/geometryvisitor.h b/avogadro/rendering/geometryvisitor.h index 41f9389701..5b15df449c 100644 --- a/avogadro/rendering/geometryvisitor.h +++ b/avogadro/rendering/geometryvisitor.h @@ -25,6 +25,12 @@ namespace Rendering { * notably the center and radius of the bounding sphere. */ +#ifdef _3DCONNEXION +struct SphereColor; +class SphereGeometry; +class CylinderGeometry; +#endif + class GeometryVisitor : public Visitor { public: @@ -41,7 +47,11 @@ class GeometryVisitor : public Visitor void visit(SphereGeometry&) override; void visit(AmbientOcclusionSphereGeometry&) override; void visit(CurveGeometry&) override; +#ifdef _3DCONNEXION + void visit(CylinderGeometry&) override; +#else void visit(CylinderGeometry&) override { return; } +#endif void visit(MeshGeometry&) override { return; } void visit(TextLabel2D&) override { return; } void visit(TextLabel3D&) override { return; } @@ -61,7 +71,34 @@ class GeometryVisitor : public Visitor * Get the radius of the scene. */ float radius(); +#ifdef _3DCONNEXION + /** + * <> + * Calculates the bounding box of the molecule. + * @param minX [out] minimum X coordinate of the box diagonal + * @param minY [out] minimum Y coordinate of the box diagonal + * @param minZ [out] minimum Z coordinate of the box diagonal + * @param maxX [out] maximum X coordinate of the box diagonal + * @param maxY [out] maximum Y coordinate of the box diagonal + * @param maxZ [out] maximum Z coordinate of the box diagonal + * @param flags [in] flags informing which atoms will be included + * in the bounding box. + */ + void boundingBox(double& minX, double& minY, double& minZ, double& maxX, + double& maxY, double& maxZ, + const std::vector& flags) const; + /** + * <> + * Hit-tests underlying geometry. + * @param rayOrigin Origin of the ray. + * @param rayDirection Normalized direction of the ray. + * @return Distance to the intersection point lying on the passed ray. + * If returned value is less than zero, then there is no intersection. + */ + float hit(const Vector3f& rayOrigin, const Vector3f& rayDirection, + const float rayLength); +#endif private: /** * Get the average of the accumulated spherical centers and minimal radius. @@ -74,6 +111,11 @@ class GeometryVisitor : public Visitor std::vector m_centers; std::vector m_radii; +#ifdef _3DCONNEXION + std::vector m_spheres; + std::vector m_sphereGeometries; + std::vector m_cylinderGeometries; +#endif }; } // End namespace Rendering diff --git a/avogadro/rendering/glrenderer.cpp b/avogadro/rendering/glrenderer.cpp index 310bcfcae2..8e94b1cb7b 100644 --- a/avogadro/rendering/glrenderer.cpp +++ b/avogadro/rendering/glrenderer.cpp @@ -27,8 +27,25 @@ using Core::Array; GLRenderer::GLRenderer() : m_valid(false), m_textRenderStrategy(nullptr), m_center(Vector3f::Zero()), m_radius(20.0) +#ifdef _3DCONNEXION + , + m_drawIcon(false), m_iconData(nullptr), m_iconWidth(0u), m_iconHeight(0u), + m_iconPosition(Eigen::Vector3f::Zero()) +#endif { m_overlayCamera.setIdentity(); +#ifdef _3DCONNEXION + float aspectRatio = static_cast(m_camera.width()) / + static_cast(m_camera.height()); + float distance = m_camera.distance(m_center); + float offset = distance + m_radius; + m_perspectiveFrustum = { + -aspectRatio, aspectRatio, -1.0f, 1.0f, 2.0f, offset + }; + m_orthographicFrustum = { + -5.0f * aspectRatio, 5.0f * aspectRatio, -5.0f, 5.0f, -offset, offset + }; +#endif } GLRenderer::~GLRenderer() @@ -117,6 +134,24 @@ void GLRenderer::render() visitor.setCamera(m_overlayCamera); glDisable(GL_DEPTH_TEST); m_scene.rootNode().accept(visitor); + +#ifdef _3DCONNEXION + if (m_drawIcon && (m_iconData != nullptr)) { + glPushMatrix(); + Eigen::Vector4f pivotPosition = + m_camera.projection().matrix() * m_camera.modelView().matrix() * + Eigen::Vector4f(m_iconPosition.x(), m_iconPosition.y(), + m_iconPosition.z(), 1.0); + pivotPosition /= pivotPosition.w(); + glRasterPos3d(pivotPosition.x(), pivotPosition.y(), pivotPosition.z()); + glPixelZoom(1.0f, -1.0f); + glBitmap(0.0f, 0.0f, 0.0f, 0.0f, -static_cast(m_iconWidth >> 1), + static_cast(m_iconHeight >> 1), NULL); + glDrawPixels(m_iconWidth, m_iconHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, + m_iconData); + glPopMatrix(); + } +#endif } void GLRenderer::resetCamera() @@ -169,16 +204,43 @@ void GLRenderer::setTextRenderStrategy(TextRenderStrategy* tren) void GLRenderer::applyProjection() { float distance = m_camera.distance(m_center); +#ifdef _3DCONNEXION + float aspectRatio = static_cast(m_camera.width()) / + static_cast(m_camera.height()); +#endif if (m_camera.projectionType() == Perspective) { +#ifdef _3DCONNEXION + m_perspectiveFrustum[0] = m_perspectiveFrustum[2] * aspectRatio; + m_perspectiveFrustum[1] = m_perspectiveFrustum[3] * aspectRatio; + m_perspectiveFrustum[5] = distance + m_radius; + m_camera.calculatePerspective( + m_perspectiveFrustum[0], m_perspectiveFrustum[1], m_perspectiveFrustum[2], + m_perspectiveFrustum[3], m_perspectiveFrustum[4], + m_perspectiveFrustum[5]); +#else m_camera.calculatePerspective(40.0f, std::max(2.0f, distance - m_radius), distance + m_radius); +#endif } else { // Renders the orthographic projection of the molecule +#ifdef _3DCONNEXION + m_orthographicFrustum[0] = m_orthographicFrustum[2] * aspectRatio; + m_orthographicFrustum[1] = m_orthographicFrustum[3] * aspectRatio; + m_orthographicFrustum[5] = distance + m_radius; + m_orthographicFrustum[4] = -m_orthographicFrustum[5]; + m_camera.calculateOrthographic(m_orthographicFrustum[0], // L + m_orthographicFrustum[1], // R + m_orthographicFrustum[2], // B + m_orthographicFrustum[3], // T + m_orthographicFrustum[4], // N + m_orthographicFrustum[5]); // F +#else const double halfHeight = m_radius; const double halfWidth = halfHeight * m_camera.width() / m_camera.height(); m_camera.calculateOrthographic( -halfWidth, halfWidth, -halfHeight, halfHeight, std::max(2.0f, distance - m_radius), distance + m_radius); +#endif } m_overlayCamera.calculateOrthographic( 0.f, static_cast(m_overlayCamera.width()), 0.f, diff --git a/avogadro/rendering/glrenderer.h b/avogadro/rendering/glrenderer.h index 1acfcac6bb..34136bca17 100644 --- a/avogadro/rendering/glrenderer.h +++ b/avogadro/rendering/glrenderer.h @@ -104,6 +104,16 @@ class AVOGADRORENDERING_EXPORT GLRenderer void setTextRenderStrategy(TextRenderStrategy* tren); /** @} */ +#ifdef _3DCONNEXION + std::array m_perspectiveFrustum; // L, R, B, T, N, F (planes order) + std::array m_orthographicFrustum; // L, R, B, T, N, F (planes order) + bool m_drawIcon; + void* m_iconData; + uint32_t m_iconWidth; + uint32_t m_iconHeight; + Eigen::Vector3f m_iconPosition; +#endif + private: /** * Apply the projection matrix. @@ -136,7 +146,7 @@ class AVOGADRORENDERING_EXPORT GLRenderer Scene m_scene; TextRenderStrategy* m_textRenderStrategy; SolidPipeline m_solidPipeline; - + Vector3f m_center; float m_radius; }; diff --git a/avogadro/rendering/scene.h b/avogadro/rendering/scene.h index ddf0c331d9..aa72e7e722 100644 --- a/avogadro/rendering/scene.h +++ b/avogadro/rendering/scene.h @@ -130,11 +130,39 @@ class AVOGADRORENDERING_EXPORT Scene /** Clear the scene of all elements. */ void clear(); - +#ifdef _3DCONNEXION + /** + * <> + * Calculte and return bounding box of the scene objects. + * @param minX [out] minimum X coordinate of the box diagonal + * @param minY [out] minimum Y coordinate of the box diagonal + * @param minZ [out] minimum Z coordinate of the box diagonal + * @param maxX [out] maximum X coordinate of the box diagonal + * @param maxY [out] maximum Y coordinate of the box diagonal + * @param maxZ [out] maximum Z coordinate of the box diagonal + * @param flags [in] flags informing which atoms will be included + * in the bounding box + */ + void getBoundingBox(double& minX, double& minY, double& minZ, double& maxX, + double& maxY, double& maxZ, + const std::vector& flags); + + /** <> + * Return distance from ray origin to the ray with scene content instersection + * point. + * @param rayOrigin Origin of the ray. + * @param rayEnd End point of the ray. + * @param rayDirection Normalized direction of the ray. + * @return Distance to the intersection point lying on the passed ray. If + * returned value is less than zero, then there is no intersection. + */ + float getHitDistance(const Vector3f& rayOrigin, const Vector3f& rayDirection, + const float rayLength); +#endif private: GroupNode m_rootNode; Vector4ub m_backgroundColor; - + mutable bool m_dirty; mutable Vector3f m_center; mutable float m_radius; diff --git a/avogadro/rendering/tdxextensions.cpp b/avogadro/rendering/tdxextensions.cpp new file mode 100644 index 0000000000..f8568dafde --- /dev/null +++ b/avogadro/rendering/tdxextensions.cpp @@ -0,0 +1,141 @@ +/****************************************************************************** + This source file is part of the Avogadro project. + This source code is released under the 3-Clause BSD License, (see "LICENSE"). +******************************************************************************/ + +#include "camera.h" +#include "cylindergeometry.h" +#include "geometryvisitor.h" +#include "scene.h" +#include "spheregeometry.h" + +void Avogadro::Rendering::Camera::calculatePerspective(float left, float right, + float bottom, float top, + float zNear, float zFar) +{ + m_data->projection.setIdentity(); + + m_data->projection(0, 0) = (2.0f * zNear) / (right - left); + m_data->projection(1, 1) = (2.0f * zNear) / (top - bottom); + m_data->projection(0, 2) = (right + left) / (right - left); + m_data->projection(1, 2) = (top + bottom) / (top - bottom); + m_data->projection(2, 2) = -(zFar + zNear) / (zFar - zNear); + m_data->projection(3, 2) = -1.0f; + m_data->projection(2, 3) = -(2.0f * zFar * zNear) / (zFar - zNear); + m_data->projection(3, 3) = 0.0f; +} + +void Avogadro::Rendering::Scene::getBoundingBox(double& minX, double& minY, + double& minZ, double& maxX, + double& maxY, double& maxZ, + const std::vector& flags) +{ + GeometryVisitor visitor; + + m_rootNode.accept(visitor); + visitor.boundingBox(minX, minY, minZ, maxX, maxY, maxZ, flags); +} + +float Avogadro::Rendering::Scene::getHitDistance(const Vector3f& rayOrigin, + const Vector3f& rayDirection, + const float rayLength) +{ + GeometryVisitor visitor; + + m_rootNode.accept(visitor); + return visitor.hit(rayOrigin, rayDirection, rayLength); +} + +void Avogadro::Rendering::GeometryVisitor::visit(CylinderGeometry& geometry) +{ + m_cylinderGeometries.push_back(geometry); +} + +void Avogadro::Rendering::GeometryVisitor::boundingBox( + double& minX, double& minY, double& minZ, double& maxX, double& maxY, + double& maxZ, const std::vector& flags) const +{ + minX = std::numeric_limits::max(); + minY = minX; + minZ = minX; + maxX = -minX; + maxY = maxX; + maxZ = maxX; + + bool noSelection = true; + + for (uint32_t i = 0; i < flags.size(); i++) { + if (flags[i]) { + noSelection = false; + break; + } + } + + for (uint32_t i = 0; i < m_spheres.size(); i++) { + + if (flags.empty() || noSelection || flags[i]) { + + float radius = m_spheres[i].radius + 0.5f; + + double bufferMinX = m_spheres[i].center.x() - radius; + double bufferMinY = m_spheres[i].center.y() - radius; + double bufferMinZ = m_spheres[i].center.z() - radius; + double bufferMaxX = m_spheres[i].center.x() + radius; + double bufferMaxY = m_spheres[i].center.y() + radius; + double bufferMaxZ = m_spheres[i].center.z() + radius; + + if (bufferMinX < minX) + minX = bufferMinX; + + if (bufferMinY < minY) + minY = bufferMinY; + + if (bufferMinZ < minZ) + minZ = bufferMinZ; + + if (bufferMaxX > maxX) + maxX = bufferMaxX; + + if (bufferMaxY > maxY) + maxY = bufferMaxY; + + if (bufferMaxZ > maxZ) + maxZ = bufferMaxZ; + } + } +} + +float Avogadro::Rendering::GeometryVisitor::hit(const Vector3f& rayOrigin, + const Vector3f& rayDirection, + const float rayLength) +{ + auto minDistance = [rayOrigin, rayDirection, rayLength]( + const std::vector& drawables) -> float { + float result = std::numeric_limits::max(); + + for (auto& drawable : drawables) { + std::multimap hitsMap = + drawable->hits(rayOrigin, rayOrigin + rayLength * rayDirection, + rayDirection); + + for (auto& hit : hitsMap) { + if (hit.first < result) + result = hit.first; + } + } + return result; + }; + + std::vector pDrawables; + pDrawables.reserve(m_sphereGeometries.size() + m_cylinderGeometries.size()); + + for (auto& m_sphereGeometry : m_sphereGeometries) + pDrawables.push_back(&m_sphereGeometry); + + for (auto& m_cylinderGeometry : m_cylinderGeometries) + pDrawables.push_back(&m_cylinderGeometry); + + float result = minDistance(pDrawables); + + return result < std::numeric_limits::max() ? result : -1.0f; +} From d30019fdcb8bffa7a050df26a43817d2d418a65d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Skowro=C5=84ski?= Date: Wed, 5 Jul 2023 12:41:22 +0200 Subject: [PATCH 2/5] Changes after 1st PR review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patryk Skowroński --- avogadro/rendering/CMakeLists.txt | 4 - avogadro/rendering/camera.cpp | 20 +++- avogadro/rendering/camera.h | 10 +- avogadro/rendering/geometryvisitor.cpp | 63 ++++++++--- avogadro/rendering/geometryvisitor.h | 25 +---- avogadro/rendering/glrenderer.cpp | 30 +++--- avogadro/rendering/glrenderer.h | 8 +- avogadro/rendering/scene.cpp | 10 ++ avogadro/rendering/scene.h | 14 +-- avogadro/rendering/tdxextensions.cpp | 141 ------------------------- 10 files changed, 106 insertions(+), 219 deletions(-) delete mode 100644 avogadro/rendering/tdxextensions.cpp diff --git a/avogadro/rendering/CMakeLists.txt b/avogadro/rendering/CMakeLists.txt index 02533642f0..ddebfe8483 100644 --- a/avogadro/rendering/CMakeLists.txt +++ b/avogadro/rendering/CMakeLists.txt @@ -95,10 +95,6 @@ target_sources(Rendering PRIVATE ambientocclusionspheregeometry.cpp ) -if(USE_3DCONNEXION AND (WIN32 OR APPLE)) - target_sources(Rendering PRIVATE tdxextensions.cpp) -endif() - set(shader_files "arrow_vs.glsl" "cylinders_fs.glsl" diff --git a/avogadro/rendering/camera.cpp b/avogadro/rendering/camera.cpp index 6970e74760..528a238af0 100644 --- a/avogadro/rendering/camera.cpp +++ b/avogadro/rendering/camera.cpp @@ -132,7 +132,7 @@ Vector3f Camera::unProject(const Vector2f& point, } void Camera::calculatePerspective(float fieldOfView, float aspectRatio, - float zNear, float zFar) + float zNear, float zFar) { m_data->projection.setIdentity(); float f = 1.0f / std::tan(fieldOfView * float(M_PI) / 360.0f); @@ -152,7 +152,7 @@ void Camera::calculatePerspective(float fieldOfView, float zNear, float zFar) } void Camera::calculateOrthographic(float left, float right, float bottom, - float top, float zNear, float zFar) + float top, float zNear, float zFar) { left *= m_orthographicScale; right *= m_orthographicScale; @@ -184,4 +184,20 @@ void Camera::setModelView(const Eigen::Affine3f& transform) m_data->modelView = transform; } +void Camera::calculatePerspective(float left, float right, + float bottom, float top, + float zNear, float zFar) +{ + m_data->projection.setIdentity(); + + m_data->projection(0, 0) = (2.0f * zNear) / (right - left); + m_data->projection(1, 1) = (2.0f * zNear) / (top - bottom); + m_data->projection(0, 2) = (right + left) / (right - left); + m_data->projection(1, 2) = (top + bottom) / (top - bottom); + m_data->projection(2, 2) = -(zFar + zNear) / (zFar - zNear); + m_data->projection(3, 2) = -1.0f; + m_data->projection(2, 3) = -(2.0f * zFar * zNear) / (zFar - zNear); + m_data->projection(3, 3) = 0.0f; +} + } // namespace Avogadro diff --git a/avogadro/rendering/camera.h b/avogadro/rendering/camera.h index d5072c8763..2a584f5520 100644 --- a/avogadro/rendering/camera.h +++ b/avogadro/rendering/camera.h @@ -100,7 +100,7 @@ class AVOGADRORENDERING_EXPORT Camera * reference point (defaults to the origin if nothing is supplied). */ Vector3f unProject(const Vector2f& point, - const Vector3f& reference = Vector3f::Zero()) const; + const Vector3f& reference = Vector3f::Zero()) const; /** * Calculate the perspective projection matrix. @@ -110,7 +110,7 @@ class AVOGADRORENDERING_EXPORT Camera * @param zFar is the distance from the viewer to the far clipping plane. */ void calculatePerspective(float fieldOfView, float aspectRatio, float zNear, - float zFar); + float zFar); /** * Calculate the perspective projection matrix. Computes the aspect ratio @@ -120,7 +120,7 @@ class AVOGADRORENDERING_EXPORT Camera * @param zFar is the distance from the viewer to the far clipping plane. */ void calculatePerspective(float fieldOfView, float zNear, float zFar); -#ifdef _3DCONNEXION + /** * << API Extension for TDX >> * Calculate the perspective projection matrix using frustum planes @@ -134,7 +134,7 @@ class AVOGADRORENDERING_EXPORT Camera */ void calculatePerspective(float left, float right, float bottom, float top, float zNear, float zFar); -#endif + /** * Calculate the orthographic projection matrix. * @param left left vertical clipping plane. @@ -145,7 +145,7 @@ class AVOGADRORENDERING_EXPORT Camera * @param zFar distance to the far clipping plane. */ void calculateOrthographic(float left, float right, float bottom, float top, - float zNear, float zFar); + float zNear, float zFar); /** * Set the dimensions of the viewport in pixels. diff --git a/avogadro/rendering/geometryvisitor.cpp b/avogadro/rendering/geometryvisitor.cpp index bf471f9b21..d9c0a69686 100644 --- a/avogadro/rendering/geometryvisitor.cpp +++ b/avogadro/rendering/geometryvisitor.cpp @@ -9,9 +9,6 @@ #include "curvegeometry.h" #include "linestripgeometry.h" #include "spheregeometry.h" -#ifdef _3DCONNEXION -#include "cylindergeometry.h" -#endif namespace Avogadro::Rendering { @@ -30,9 +27,6 @@ void GeometryVisitor::visit(Drawable&) void GeometryVisitor::visit(SphereGeometry& geometry) { -#ifdef _3DCONNEXION - m_sphereGeometries.push_back(geometry); -#endif const Core::Array& spheres = geometry.spheres(); if (!spheres.size()) return; @@ -53,9 +47,7 @@ void GeometryVisitor::visit(SphereGeometry& geometry) float distance = (it->center - tmpCenter).squaredNorm(); if (distance > tmpRadius) tmpRadius = distance; -#ifdef _3DCONNEXION m_spheres.push_back(*it); -#endif } } tmpRadius = std::sqrt(tmpRadius); @@ -154,11 +146,7 @@ void GeometryVisitor::clear() m_dirty = false; m_centers.clear(); m_radii.clear(); -#ifdef _3DCONNEXION m_spheres.clear(); - m_sphereGeometries.clear(); - m_cylinderGeometries.clear(); -#endif } Vector3f GeometryVisitor::center() @@ -201,4 +189,55 @@ void GeometryVisitor::average() } } +void GeometryVisitor::boundingBox(double& minX, double& minY, double& minZ, + double& maxX, double& maxY, double& maxZ, + const std::vector& flags) const +{ + minX = std::numeric_limits::max(); + minY = minX; + minZ = minX; + maxX = -minX; + maxY = maxX; + maxZ = maxX; + + bool noSelection = true; + + for (uint32_t i = 0; i < flags.size(); i++) { + if (flags[i]) { + noSelection = false; + break; + } + } + + for (uint32_t i = 0; i < m_spheres.size(); i++) { + if (flags.empty() || noSelection || flags[i]) { + float radius = m_spheres[i].radius + 0.5f; + double bufferMinX = m_spheres[i].center.x() - radius; + double bufferMinY = m_spheres[i].center.y() - radius; + double bufferMinZ = m_spheres[i].center.z() - radius; + double bufferMaxX = m_spheres[i].center.x() + radius; + double bufferMaxY = m_spheres[i].center.y() + radius; + double bufferMaxZ = m_spheres[i].center.z() + radius; + + if (bufferMinX < minX) + minX = bufferMinX; + + if (bufferMinY < minY) + minY = bufferMinY; + + if (bufferMinZ < minZ) + minZ = bufferMinZ; + + if (bufferMaxX > maxX) + maxX = bufferMaxX; + + if (bufferMaxY > maxY) + maxY = bufferMaxY; + + if (bufferMaxZ > maxZ) + maxZ = bufferMaxZ; + } + } +} + } // End namespace Avogadro diff --git a/avogadro/rendering/geometryvisitor.h b/avogadro/rendering/geometryvisitor.h index 5b15df449c..c07730ae5a 100644 --- a/avogadro/rendering/geometryvisitor.h +++ b/avogadro/rendering/geometryvisitor.h @@ -25,11 +25,7 @@ namespace Rendering { * notably the center and radius of the bounding sphere. */ -#ifdef _3DCONNEXION struct SphereColor; -class SphereGeometry; -class CylinderGeometry; -#endif class GeometryVisitor : public Visitor { @@ -47,11 +43,7 @@ class GeometryVisitor : public Visitor void visit(SphereGeometry&) override; void visit(AmbientOcclusionSphereGeometry&) override; void visit(CurveGeometry&) override; -#ifdef _3DCONNEXION - void visit(CylinderGeometry&) override; -#else void visit(CylinderGeometry&) override { return; } -#endif void visit(MeshGeometry&) override { return; } void visit(TextLabel2D&) override { return; } void visit(TextLabel3D&) override { return; } @@ -71,7 +63,7 @@ class GeometryVisitor : public Visitor * Get the radius of the scene. */ float radius(); -#ifdef _3DCONNEXION + /** * <> * Calculates the bounding box of the molecule. @@ -88,17 +80,6 @@ class GeometryVisitor : public Visitor double& maxY, double& maxZ, const std::vector& flags) const; - /** - * <> - * Hit-tests underlying geometry. - * @param rayOrigin Origin of the ray. - * @param rayDirection Normalized direction of the ray. - * @return Distance to the intersection point lying on the passed ray. - * If returned value is less than zero, then there is no intersection. - */ - float hit(const Vector3f& rayOrigin, const Vector3f& rayDirection, - const float rayLength); -#endif private: /** * Get the average of the accumulated spherical centers and minimal radius. @@ -111,11 +92,7 @@ class GeometryVisitor : public Visitor std::vector m_centers; std::vector m_radii; -#ifdef _3DCONNEXION std::vector m_spheres; - std::vector m_sphereGeometries; - std::vector m_cylinderGeometries; -#endif }; } // End namespace Rendering diff --git a/avogadro/rendering/glrenderer.cpp b/avogadro/rendering/glrenderer.cpp index 8e94b1cb7b..e2a13f366e 100644 --- a/avogadro/rendering/glrenderer.cpp +++ b/avogadro/rendering/glrenderer.cpp @@ -34,7 +34,7 @@ GLRenderer::GLRenderer() #endif { m_overlayCamera.setIdentity(); -#ifdef _3DCONNEXION + float aspectRatio = static_cast(m_camera.width()) / static_cast(m_camera.height()); float distance = m_camera.distance(m_center); @@ -45,7 +45,7 @@ GLRenderer::GLRenderer() m_orthographicFrustum = { -5.0f * aspectRatio, 5.0f * aspectRatio, -5.0f, 5.0f, -offset, offset }; -#endif + } GLRenderer::~GLRenderer() @@ -204,12 +204,9 @@ void GLRenderer::setTextRenderStrategy(TextRenderStrategy* tren) void GLRenderer::applyProjection() { float distance = m_camera.distance(m_center); -#ifdef _3DCONNEXION float aspectRatio = static_cast(m_camera.width()) / static_cast(m_camera.height()); -#endif if (m_camera.projectionType() == Perspective) { -#ifdef _3DCONNEXION m_perspectiveFrustum[0] = m_perspectiveFrustum[2] * aspectRatio; m_perspectiveFrustum[1] = m_perspectiveFrustum[3] * aspectRatio; m_perspectiveFrustum[5] = distance + m_radius; @@ -217,13 +214,8 @@ void GLRenderer::applyProjection() m_perspectiveFrustum[0], m_perspectiveFrustum[1], m_perspectiveFrustum[2], m_perspectiveFrustum[3], m_perspectiveFrustum[4], m_perspectiveFrustum[5]); -#else - m_camera.calculatePerspective(40.0f, std::max(2.0f, distance - m_radius), - distance + m_radius); -#endif } else { // Renders the orthographic projection of the molecule -#ifdef _3DCONNEXION m_orthographicFrustum[0] = m_orthographicFrustum[2] * aspectRatio; m_orthographicFrustum[1] = m_orthographicFrustum[3] * aspectRatio; m_orthographicFrustum[5] = distance + m_radius; @@ -234,13 +226,6 @@ void GLRenderer::applyProjection() m_orthographicFrustum[3], // T m_orthographicFrustum[4], // N m_orthographicFrustum[5]); // F -#else - const double halfHeight = m_radius; - const double halfWidth = halfHeight * m_camera.width() / m_camera.height(); - m_camera.calculateOrthographic( - -halfWidth, halfWidth, -halfHeight, halfHeight, - std::max(2.0f, distance - m_radius), distance + m_radius); -#endif } m_overlayCamera.calculateOrthographic( 0.f, static_cast(m_overlayCamera.width()), 0.f, @@ -320,6 +305,17 @@ Array GLRenderer::hits(const GroupNode* group, return result; } +float GLRenderer::hit(const Vector3f& rayOrigin, + const Vector3f& rayEnd, + const Vector3f& rayDirection) const +{ + std::multimap results = + hits(&m_scene.rootNode(), rayOrigin, rayEnd, rayDirection); + if (results.size()) + return results.begin()->first; + return std::numeric_limits::max(); +} + Array GLRenderer::hits(int x1, int y1, int x2, int y2) const { // Figure out where the corners of our rectangle are. diff --git a/avogadro/rendering/glrenderer.h b/avogadro/rendering/glrenderer.h index 34136bca17..0e3a59e925 100644 --- a/avogadro/rendering/glrenderer.h +++ b/avogadro/rendering/glrenderer.h @@ -68,6 +68,12 @@ class AVOGADRORENDERING_EXPORT GLRenderer */ Identifier hit(int x, int y) const; + /** Return the depth of provided ray - geometry hit test. + */ + float hit(const Vector3f& rayOrigin, + const Vector3f& rayEnd, + const Vector3f& rayDirection) const; + /** Return the primitives in the rectangular area provided. */ Core::Array hits(int x1, int y1, int x2, int y2) const; @@ -104,9 +110,9 @@ class AVOGADRORENDERING_EXPORT GLRenderer void setTextRenderStrategy(TextRenderStrategy* tren); /** @} */ -#ifdef _3DCONNEXION std::array m_perspectiveFrustum; // L, R, B, T, N, F (planes order) std::array m_orthographicFrustum; // L, R, B, T, N, F (planes order) +#ifdef _3DCONNEXION bool m_drawIcon; void* m_iconData; uint32_t m_iconWidth; diff --git a/avogadro/rendering/scene.cpp b/avogadro/rendering/scene.cpp index edc3e1b1ce..1e6c158e1b 100644 --- a/avogadro/rendering/scene.cpp +++ b/avogadro/rendering/scene.cpp @@ -53,4 +53,14 @@ void Scene::clear() m_dirty = true; } +void Scene::getBoundingBox(double& minX, double& minY, double& minZ, + double& maxX, double& maxY, double& maxZ, + const std::vector& flags) +{ + GeometryVisitor visitor; + + m_rootNode.accept(visitor); + visitor.boundingBox(minX, minY, minZ, maxX, maxY, maxZ, flags); +} + } // End Avogadro namespace diff --git a/avogadro/rendering/scene.h b/avogadro/rendering/scene.h index aa72e7e722..e29c250b44 100644 --- a/avogadro/rendering/scene.h +++ b/avogadro/rendering/scene.h @@ -130,7 +130,7 @@ class AVOGADRORENDERING_EXPORT Scene /** Clear the scene of all elements. */ void clear(); -#ifdef _3DCONNEXION + /** * <> * Calculte and return bounding box of the scene objects. @@ -147,18 +147,6 @@ class AVOGADRORENDERING_EXPORT Scene double& maxY, double& maxZ, const std::vector& flags); - /** <> - * Return distance from ray origin to the ray with scene content instersection - * point. - * @param rayOrigin Origin of the ray. - * @param rayEnd End point of the ray. - * @param rayDirection Normalized direction of the ray. - * @return Distance to the intersection point lying on the passed ray. If - * returned value is less than zero, then there is no intersection. - */ - float getHitDistance(const Vector3f& rayOrigin, const Vector3f& rayDirection, - const float rayLength); -#endif private: GroupNode m_rootNode; Vector4ub m_backgroundColor; diff --git a/avogadro/rendering/tdxextensions.cpp b/avogadro/rendering/tdxextensions.cpp deleted file mode 100644 index f8568dafde..0000000000 --- a/avogadro/rendering/tdxextensions.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#include "camera.h" -#include "cylindergeometry.h" -#include "geometryvisitor.h" -#include "scene.h" -#include "spheregeometry.h" - -void Avogadro::Rendering::Camera::calculatePerspective(float left, float right, - float bottom, float top, - float zNear, float zFar) -{ - m_data->projection.setIdentity(); - - m_data->projection(0, 0) = (2.0f * zNear) / (right - left); - m_data->projection(1, 1) = (2.0f * zNear) / (top - bottom); - m_data->projection(0, 2) = (right + left) / (right - left); - m_data->projection(1, 2) = (top + bottom) / (top - bottom); - m_data->projection(2, 2) = -(zFar + zNear) / (zFar - zNear); - m_data->projection(3, 2) = -1.0f; - m_data->projection(2, 3) = -(2.0f * zFar * zNear) / (zFar - zNear); - m_data->projection(3, 3) = 0.0f; -} - -void Avogadro::Rendering::Scene::getBoundingBox(double& minX, double& minY, - double& minZ, double& maxX, - double& maxY, double& maxZ, - const std::vector& flags) -{ - GeometryVisitor visitor; - - m_rootNode.accept(visitor); - visitor.boundingBox(minX, minY, minZ, maxX, maxY, maxZ, flags); -} - -float Avogadro::Rendering::Scene::getHitDistance(const Vector3f& rayOrigin, - const Vector3f& rayDirection, - const float rayLength) -{ - GeometryVisitor visitor; - - m_rootNode.accept(visitor); - return visitor.hit(rayOrigin, rayDirection, rayLength); -} - -void Avogadro::Rendering::GeometryVisitor::visit(CylinderGeometry& geometry) -{ - m_cylinderGeometries.push_back(geometry); -} - -void Avogadro::Rendering::GeometryVisitor::boundingBox( - double& minX, double& minY, double& minZ, double& maxX, double& maxY, - double& maxZ, const std::vector& flags) const -{ - minX = std::numeric_limits::max(); - minY = minX; - minZ = minX; - maxX = -minX; - maxY = maxX; - maxZ = maxX; - - bool noSelection = true; - - for (uint32_t i = 0; i < flags.size(); i++) { - if (flags[i]) { - noSelection = false; - break; - } - } - - for (uint32_t i = 0; i < m_spheres.size(); i++) { - - if (flags.empty() || noSelection || flags[i]) { - - float radius = m_spheres[i].radius + 0.5f; - - double bufferMinX = m_spheres[i].center.x() - radius; - double bufferMinY = m_spheres[i].center.y() - radius; - double bufferMinZ = m_spheres[i].center.z() - radius; - double bufferMaxX = m_spheres[i].center.x() + radius; - double bufferMaxY = m_spheres[i].center.y() + radius; - double bufferMaxZ = m_spheres[i].center.z() + radius; - - if (bufferMinX < minX) - minX = bufferMinX; - - if (bufferMinY < minY) - minY = bufferMinY; - - if (bufferMinZ < minZ) - minZ = bufferMinZ; - - if (bufferMaxX > maxX) - maxX = bufferMaxX; - - if (bufferMaxY > maxY) - maxY = bufferMaxY; - - if (bufferMaxZ > maxZ) - maxZ = bufferMaxZ; - } - } -} - -float Avogadro::Rendering::GeometryVisitor::hit(const Vector3f& rayOrigin, - const Vector3f& rayDirection, - const float rayLength) -{ - auto minDistance = [rayOrigin, rayDirection, rayLength]( - const std::vector& drawables) -> float { - float result = std::numeric_limits::max(); - - for (auto& drawable : drawables) { - std::multimap hitsMap = - drawable->hits(rayOrigin, rayOrigin + rayLength * rayDirection, - rayDirection); - - for (auto& hit : hitsMap) { - if (hit.first < result) - result = hit.first; - } - } - return result; - }; - - std::vector pDrawables; - pDrawables.reserve(m_sphereGeometries.size() + m_cylinderGeometries.size()); - - for (auto& m_sphereGeometry : m_sphereGeometries) - pDrawables.push_back(&m_sphereGeometry); - - for (auto& m_cylinderGeometry : m_cylinderGeometries) - pDrawables.push_back(&m_cylinderGeometry); - - float result = minDistance(pDrawables); - - return result < std::numeric_limits::max() ? result : -1.0f; -} From 6009616856fc963ede57876a626f580ccf76d929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Skowro=C5=84ski?= Date: Mon, 31 Jul 2023 16:32:39 +0200 Subject: [PATCH 3/5] Bounding box calucation moved to Molecule. --- avogadro/core/molecule.cpp | 59 +++++++++++++++++++++-- avogadro/core/molecule.h | 18 +++++-- avogadro/rendering/camera.h | 1 - avogadro/rendering/geometryvisitor.cpp | 67 ++------------------------ avogadro/rendering/geometryvisitor.h | 19 -------- avogadro/rendering/scene.cpp | 12 +---- avogadro/rendering/scene.h | 18 +------ 7 files changed, 75 insertions(+), 119 deletions(-) diff --git a/avogadro/core/molecule.cpp b/avogadro/core/molecule.cpp index d4465c29d2..0effa4cf63 100644 --- a/avogadro/core/molecule.cpp +++ b/avogadro/core/molecule.cpp @@ -46,9 +46,9 @@ Molecule::Molecule(const Molecule& other) m_meshes(std::vector()), m_cubes(std::vector()), m_basisSet(other.m_basisSet ? other.m_basisSet->clone() : nullptr), m_unitCell(other.m_unitCell ? new UnitCell(*other.m_unitCell) : nullptr), - m_residues(other.m_residues), - m_hallNumber(other.m_hallNumber), m_graph(other.m_graph), - m_bondOrders(other.m_bondOrders), m_atomicNumbers(other.m_atomicNumbers), + m_residues(other.m_residues), m_hallNumber(other.m_hallNumber), + m_graph(other.m_graph), m_bondOrders(other.m_bondOrders), + m_atomicNumbers(other.m_atomicNumbers), m_layers(LayerManager::getMoleculeLayer(this)) { // Copy over any meshes @@ -88,8 +88,8 @@ Molecule::Molecule(Molecule&& other) noexcept m_selectedAtoms(std::move(other.m_selectedAtoms)), m_meshes(std::move(other.m_meshes)), m_cubes(std::move(other.m_cubes)), m_residues(other.m_residues), m_hallNumber(other.m_hallNumber), - m_graph(other.m_graph), - m_bondOrders(other.m_bondOrders), m_atomicNumbers(other.m_atomicNumbers), + m_graph(other.m_graph), m_bondOrders(other.m_bondOrders), + m_atomicNumbers(other.m_atomicNumbers), m_layers(LayerManager::getMoleculeLayer(this)) { m_basisSet = other.m_basisSet; @@ -1324,4 +1324,53 @@ std::list Molecule::getAtomsAtLayer(size_t layer) return result; } +void Molecule::boundingBox(Vector3& boxMin, Vector3& boxMax) const +{ + boxMin.setConstant(std::numeric_limits::max()); + boxMax.setConstant(-std::numeric_limits::max()); + + bool noSelection = true; + + for (uint32_t i = 0; i < m_selectedAtoms.size(); i++) { + if (m_selectedAtoms[i]) { + noSelection = false; + break; + } + } + + for (uint32_t i = 0; i < atomCount(); i++) { + if (noSelection || m_selectedAtoms[i]) { + double radius = 1.0; + + Vector3 boxMinBuffer; + Vector3 boxMaxBuffer; + + boxMinBuffer.x() = atom(i).position3d().x() - radius; + boxMinBuffer.y() = atom(i).position3d().y() - radius; + boxMinBuffer.z() = atom(i).position3d().z() - radius; + boxMaxBuffer.x() = atom(i).position3d().x() + radius; + boxMaxBuffer.y() = atom(i).position3d().y() + radius; + boxMaxBuffer.z() = atom(i).position3d().z() + radius; + + if (boxMinBuffer.x() < boxMin.x()) + boxMin.x() = boxMinBuffer.x(); + + if (boxMinBuffer.y() < boxMin.y()) + boxMin.y() = boxMinBuffer.y(); + + if (boxMinBuffer.z() < boxMin.z()) + boxMin.z() = boxMinBuffer.z(); + + if (boxMaxBuffer.x() > boxMax.x()) + boxMax.x() = boxMaxBuffer.x(); + + if (boxMaxBuffer.y() > boxMax.y()) + boxMax.y() = boxMaxBuffer.y(); + + if (boxMaxBuffer.z() > boxMax.z()) + boxMax.z() = boxMaxBuffer.z(); + } + } +} + } // namespace Avogadro::Core diff --git a/avogadro/core/molecule.h b/avogadro/core/molecule.h index c6a038a073..3a25818d80 100644 --- a/avogadro/core/molecule.h +++ b/avogadro/core/molecule.h @@ -526,9 +526,10 @@ class AVOGADROCORE_EXPORT Molecule /** * Perceives bonds in the molecule based on preset residue data. - * - * Use this if you have residue data available (e.g., reading PDB or MMTF files) - * Otherwise consider @sa perceiveBondsSimple and @sa perceiveBondOrders + * + * Use this if you have residue data available (e.g., reading PDB or MMTF + * files) Otherwise consider @sa perceiveBondsSimple and @sa + * perceiveBondOrders */ void perceiveBondsFromResidueData(); @@ -717,9 +718,18 @@ class AVOGADROCORE_EXPORT Molecule Layer& layer(); const Layer& layer() const; + /** + * Calculte and return bounding box of the whole molecule or selected atoms + * only. + * @param boxMin [out] the minimum corner (first end of the box diagonal) + * @param boxMax [out] the maximum corner (second end of the box diagonal) + */ + void boundingBox(Vector3& boxMin, Vector3& boxMax) const; + protected: VariantMap m_data; - std::map m_partialCharges; //!< Sets of atomic partial charges + std::map + m_partialCharges; //!< Sets of atomic partial charges CustomElementMap m_customElementMap; ElementMask m_elements; //!< Which elements this molecule contains (e.g., for //!< force fields) diff --git a/avogadro/rendering/camera.h b/avogadro/rendering/camera.h index 2a584f5520..2a77d34aec 100644 --- a/avogadro/rendering/camera.h +++ b/avogadro/rendering/camera.h @@ -122,7 +122,6 @@ class AVOGADRORENDERING_EXPORT Camera void calculatePerspective(float fieldOfView, float zNear, float zFar); /** - * << API Extension for TDX >> * Calculate the perspective projection matrix using frustum planes * coordinates. * @param left left vertical clipping plane. diff --git a/avogadro/rendering/geometryvisitor.cpp b/avogadro/rendering/geometryvisitor.cpp index d9c0a69686..b2c694aa06 100644 --- a/avogadro/rendering/geometryvisitor.cpp +++ b/avogadro/rendering/geometryvisitor.cpp @@ -17,13 +17,9 @@ GeometryVisitor::GeometryVisitor() { } -GeometryVisitor::~GeometryVisitor() -{ -} +GeometryVisitor::~GeometryVisitor() {} -void GeometryVisitor::visit(Drawable&) -{ -} +void GeometryVisitor::visit(Drawable&) {} void GeometryVisitor::visit(SphereGeometry& geometry) { @@ -47,7 +43,6 @@ void GeometryVisitor::visit(SphereGeometry& geometry) float distance = (it->center - tmpCenter).squaredNorm(); if (distance > tmpRadius) tmpRadius = distance; - m_spheres.push_back(*it); } } tmpRadius = std::sqrt(tmpRadius); @@ -123,13 +118,13 @@ void GeometryVisitor::visit(LineStripGeometry& lsg) m_dirty = true; Vector3f tmpCenter(Vector3f::Zero()); - for (const auto & vert : verts) { + for (const auto& vert : verts) { tmpCenter += vert.vertex; } tmpCenter /= static_cast(verts.size()); float tmpRadius(0.f); - for (const auto & vert : verts) { + for (const auto& vert : verts) { float distance = (vert.vertex - tmpCenter).squaredNorm(); if (distance > tmpRadius) tmpRadius = distance; @@ -146,7 +141,6 @@ void GeometryVisitor::clear() m_dirty = false; m_centers.clear(); m_radii.clear(); - m_spheres.clear(); } Vector3f GeometryVisitor::center() @@ -189,55 +183,4 @@ void GeometryVisitor::average() } } -void GeometryVisitor::boundingBox(double& minX, double& minY, double& minZ, - double& maxX, double& maxY, double& maxZ, - const std::vector& flags) const -{ - minX = std::numeric_limits::max(); - minY = minX; - minZ = minX; - maxX = -minX; - maxY = maxX; - maxZ = maxX; - - bool noSelection = true; - - for (uint32_t i = 0; i < flags.size(); i++) { - if (flags[i]) { - noSelection = false; - break; - } - } - - for (uint32_t i = 0; i < m_spheres.size(); i++) { - if (flags.empty() || noSelection || flags[i]) { - float radius = m_spheres[i].radius + 0.5f; - double bufferMinX = m_spheres[i].center.x() - radius; - double bufferMinY = m_spheres[i].center.y() - radius; - double bufferMinZ = m_spheres[i].center.z() - radius; - double bufferMaxX = m_spheres[i].center.x() + radius; - double bufferMaxY = m_spheres[i].center.y() + radius; - double bufferMaxZ = m_spheres[i].center.z() + radius; - - if (bufferMinX < minX) - minX = bufferMinX; - - if (bufferMinY < minY) - minY = bufferMinY; - - if (bufferMinZ < minZ) - minZ = bufferMinZ; - - if (bufferMaxX > maxX) - maxX = bufferMaxX; - - if (bufferMaxY > maxY) - maxY = bufferMaxY; - - if (bufferMaxZ > maxZ) - maxZ = bufferMaxZ; - } - } -} - -} // End namespace Avogadro +} // namespace Avogadro::Rendering diff --git a/avogadro/rendering/geometryvisitor.h b/avogadro/rendering/geometryvisitor.h index c07730ae5a..41f9389701 100644 --- a/avogadro/rendering/geometryvisitor.h +++ b/avogadro/rendering/geometryvisitor.h @@ -25,8 +25,6 @@ namespace Rendering { * notably the center and radius of the bounding sphere. */ -struct SphereColor; - class GeometryVisitor : public Visitor { public: @@ -64,22 +62,6 @@ class GeometryVisitor : public Visitor */ float radius(); - /** - * <> - * Calculates the bounding box of the molecule. - * @param minX [out] minimum X coordinate of the box diagonal - * @param minY [out] minimum Y coordinate of the box diagonal - * @param minZ [out] minimum Z coordinate of the box diagonal - * @param maxX [out] maximum X coordinate of the box diagonal - * @param maxY [out] maximum Y coordinate of the box diagonal - * @param maxZ [out] maximum Z coordinate of the box diagonal - * @param flags [in] flags informing which atoms will be included - * in the bounding box. - */ - void boundingBox(double& minX, double& minY, double& minZ, double& maxX, - double& maxY, double& maxZ, - const std::vector& flags) const; - private: /** * Get the average of the accumulated spherical centers and minimal radius. @@ -92,7 +74,6 @@ class GeometryVisitor : public Visitor std::vector m_centers; std::vector m_radii; - std::vector m_spheres; }; } // End namespace Rendering diff --git a/avogadro/rendering/scene.cpp b/avogadro/rendering/scene.cpp index 1e6c158e1b..76ad64b74f 100644 --- a/avogadro/rendering/scene.cpp +++ b/avogadro/rendering/scene.cpp @@ -53,14 +53,4 @@ void Scene::clear() m_dirty = true; } -void Scene::getBoundingBox(double& minX, double& minY, double& minZ, - double& maxX, double& maxY, double& maxZ, - const std::vector& flags) -{ - GeometryVisitor visitor; - - m_rootNode.accept(visitor); - visitor.boundingBox(minX, minY, minZ, maxX, maxY, maxZ, flags); -} - -} // End Avogadro namespace +} // namespace Avogadro::Rendering diff --git a/avogadro/rendering/scene.h b/avogadro/rendering/scene.h index e29c250b44..ddf0c331d9 100644 --- a/avogadro/rendering/scene.h +++ b/avogadro/rendering/scene.h @@ -131,26 +131,10 @@ class AVOGADRORENDERING_EXPORT Scene /** Clear the scene of all elements. */ void clear(); - /** - * <> - * Calculte and return bounding box of the scene objects. - * @param minX [out] minimum X coordinate of the box diagonal - * @param minY [out] minimum Y coordinate of the box diagonal - * @param minZ [out] minimum Z coordinate of the box diagonal - * @param maxX [out] maximum X coordinate of the box diagonal - * @param maxY [out] maximum Y coordinate of the box diagonal - * @param maxZ [out] maximum Z coordinate of the box diagonal - * @param flags [in] flags informing which atoms will be included - * in the bounding box - */ - void getBoundingBox(double& minX, double& minY, double& minZ, double& maxX, - double& maxY, double& maxZ, - const std::vector& flags); - private: GroupNode m_rootNode; Vector4ub m_backgroundColor; - + mutable bool m_dirty; mutable Vector3f m_center; mutable float m_radius; From 7461add111307661b79ba71effce9a0b1c721070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Skowro=C5=84ski?= Date: Tue, 1 Aug 2023 10:01:42 +0200 Subject: [PATCH 4/5] Fix formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patryk Skowroński --- avogadro/rendering/camera.cpp | 15 +++++++-------- avogadro/rendering/glrenderer.cpp | 5 ++--- avogadro/rendering/glrenderer.h | 5 ++--- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/avogadro/rendering/camera.cpp b/avogadro/rendering/camera.cpp index 528a238af0..4a5b388e52 100644 --- a/avogadro/rendering/camera.cpp +++ b/avogadro/rendering/camera.cpp @@ -23,7 +23,7 @@ Camera::Camera() Camera::Camera(const Camera& o) : m_width(o.m_width), m_height(o.m_height), m_projectionType(o.m_projectionType), - m_orthographicScale(o.m_orthographicScale), m_data(new EigenData(*o.m_data)) + m_orthographicScale(o.m_orthographicScale), m_data(new EigenData(*o.m_data)) {} Camera& Camera::operator=(const Camera& o) @@ -116,10 +116,10 @@ Vector3f Camera::unProject(const Vector3f& point) const m_data->projection.matrix() * m_data->modelView.matrix(); Vector4f result( 2.0f * point.x() / static_cast(m_width) - 1.0f, - 2.0f * (static_cast(m_height) - point.y()) / - static_cast(m_height) - - 1.0f, - 2.0f * point.z() - 1.0f, 1.0f); + 2.0f * (static_cast(m_height) - point.y()) / + static_cast(m_height) - + 1.0f, + 2.0f * point.z() - 1.0f, 1.0f); result = mvp.matrix().inverse() * result; return Vector3f(result.x() / result.w(), result.y() / result.w(), result.z() / result.w()); @@ -184,9 +184,8 @@ void Camera::setModelView(const Eigen::Affine3f& transform) m_data->modelView = transform; } -void Camera::calculatePerspective(float left, float right, - float bottom, float top, - float zNear, float zFar) +void Camera::calculatePerspective(float left, float right, float bottom, + float top, float zNear, float zFar) { m_data->projection.setIdentity(); diff --git a/avogadro/rendering/glrenderer.cpp b/avogadro/rendering/glrenderer.cpp index e2a13f366e..65d1e2767d 100644 --- a/avogadro/rendering/glrenderer.cpp +++ b/avogadro/rendering/glrenderer.cpp @@ -67,7 +67,7 @@ void GLRenderer::initialize() m_valid = false; return; } - + m_solidPipeline.initialize(); } @@ -305,8 +305,7 @@ Array GLRenderer::hits(const GroupNode* group, return result; } -float GLRenderer::hit(const Vector3f& rayOrigin, - const Vector3f& rayEnd, +float GLRenderer::hit(const Vector3f& rayOrigin, const Vector3f& rayEnd, const Vector3f& rayDirection) const { std::multimap results = diff --git a/avogadro/rendering/glrenderer.h b/avogadro/rendering/glrenderer.h index 0e3a59e925..86642a2ae3 100644 --- a/avogadro/rendering/glrenderer.h +++ b/avogadro/rendering/glrenderer.h @@ -70,8 +70,7 @@ class AVOGADRORENDERING_EXPORT GLRenderer /** Return the depth of provided ray - geometry hit test. */ - float hit(const Vector3f& rayOrigin, - const Vector3f& rayEnd, + float hit(const Vector3f& rayOrigin, const Vector3f& rayEnd, const Vector3f& rayDirection) const; /** Return the primitives in the rectangular area provided. */ @@ -152,7 +151,7 @@ class AVOGADRORENDERING_EXPORT GLRenderer Scene m_scene; TextRenderStrategy* m_textRenderStrategy; SolidPipeline m_solidPipeline; - + Vector3f m_center; float m_radius; }; From a914e8da04b4966172dac88ef7931a38584770e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Skowro=C5=84ski?= Date: Thu, 10 Aug 2023 13:59:54 +0200 Subject: [PATCH 5/5] Molecule::boundingBox refactor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patryk Skowroński --- avogadro/core/molecule.cpp | 46 +++++++++----------------------------- avogadro/core/molecule.h | 4 +++- 2 files changed, 14 insertions(+), 36 deletions(-) diff --git a/avogadro/core/molecule.cpp b/avogadro/core/molecule.cpp index 0effa4cf63..e2a4028407 100644 --- a/avogadro/core/molecule.cpp +++ b/avogadro/core/molecule.cpp @@ -1324,51 +1324,27 @@ std::list Molecule::getAtomsAtLayer(size_t layer) return result; } -void Molecule::boundingBox(Vector3& boxMin, Vector3& boxMax) const +void Molecule::boundingBox(Vector3& boxMin, Vector3& boxMax, + const double radius) const { boxMin.setConstant(std::numeric_limits::max()); boxMax.setConstant(-std::numeric_limits::max()); - bool noSelection = true; - - for (uint32_t i = 0; i < m_selectedAtoms.size(); i++) { - if (m_selectedAtoms[i]) { - noSelection = false; - break; - } - } + const bool noSelection = isSelectionEmpty(); for (uint32_t i = 0; i < atomCount(); i++) { if (noSelection || m_selectedAtoms[i]) { - double radius = 1.0; - - Vector3 boxMinBuffer; - Vector3 boxMaxBuffer; - - boxMinBuffer.x() = atom(i).position3d().x() - radius; - boxMinBuffer.y() = atom(i).position3d().y() - radius; - boxMinBuffer.z() = atom(i).position3d().z() - radius; - boxMaxBuffer.x() = atom(i).position3d().x() + radius; - boxMaxBuffer.y() = atom(i).position3d().y() + radius; - boxMaxBuffer.z() = atom(i).position3d().z() + radius; - - if (boxMinBuffer.x() < boxMin.x()) - boxMin.x() = boxMinBuffer.x(); - - if (boxMinBuffer.y() < boxMin.y()) - boxMin.y() = boxMinBuffer.y(); - - if (boxMinBuffer.z() < boxMin.z()) - boxMin.z() = boxMinBuffer.z(); - if (boxMaxBuffer.x() > boxMax.x()) - boxMax.x() = boxMaxBuffer.x(); + const Vector3 boxMinBuffer = atom(i).position3d().array() - radius; + const Vector3 boxMaxBuffer = atom(i).position3d().array() + radius; - if (boxMaxBuffer.y() > boxMax.y()) - boxMax.y() = boxMaxBuffer.y(); + boxMin.x() = std::min(boxMinBuffer.x(), boxMin.x()); + boxMin.y() = std::min(boxMinBuffer.y(), boxMin.y()); + boxMin.z() = std::min(boxMinBuffer.z(), boxMin.z()); - if (boxMaxBuffer.z() > boxMax.z()) - boxMax.z() = boxMaxBuffer.z(); + boxMax.x() = std::max(boxMaxBuffer.x(), boxMax.x()); + boxMax.y() = std::max(boxMaxBuffer.y(), boxMax.y()); + boxMax.z() = std::max(boxMaxBuffer.z(), boxMax.z()); } } } diff --git a/avogadro/core/molecule.h b/avogadro/core/molecule.h index 3a25818d80..f2b921ebea 100644 --- a/avogadro/core/molecule.h +++ b/avogadro/core/molecule.h @@ -723,8 +723,10 @@ class AVOGADROCORE_EXPORT Molecule * only. * @param boxMin [out] the minimum corner (first end of the box diagonal) * @param boxMax [out] the maximum corner (second end of the box diagonal) + * @param radius [in] radius of a single sphere */ - void boundingBox(Vector3& boxMin, Vector3& boxMax) const; + void boundingBox(Vector3& boxMin, Vector3& boxMax, + const double radius = 1.0) const; protected: VariantMap m_data;