From 6198236db338e73ce55898c9696bec5e1d8cb9cc Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Mon, 9 Feb 2026 15:57:03 -0700 Subject: [PATCH] feat: Add top-right viewport view cube with axis and face labels Co-authored-by: aider (gemini/gemini-2.5-pro) --- src/ViewportWidget.cpp | 127 +++++++++++++++++++++++++++++++++++++++++ src/ViewportWidget.h | 2 + 2 files changed, 129 insertions(+) diff --git a/src/ViewportWidget.cpp b/src/ViewportWidget.cpp index 37128a9..4c8ae18 100644 --- a/src/ViewportWidget.cpp +++ b/src/ViewportWidget.cpp @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include ViewportWidget::ViewportWidget(QWidget *parent) : QOpenGLWidget(parent) @@ -17,6 +20,8 @@ void ViewportWidget::initializeGL() void ViewportWidget::paintGL() { + // Main scene rendering + glViewport(0, 0, width(), height()); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); QMatrix4x4 model; @@ -33,6 +38,63 @@ void ViewportWidget::paintGL() glLoadMatrixf(model.constData()); drawCube(); + + // View cube rendering in top right + int viewCubeSize = 150; + glViewport(width() - viewCubeSize, height() - viewCubeSize, viewCubeSize, viewCubeSize); + glClear(GL_DEPTH_BUFFER_BIT); + + QMatrix4x4 viewCubeProjection; + viewCubeProjection.ortho(-2, 2, -2, 2, -10, 10); + + QMatrix4x4 viewCubeModel; + viewCubeModel.rotate(xRot / 16.0f, 1, 0, 0); + viewCubeModel.rotate(yRot / 16.0f, 0, 1, 0); + + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(viewCubeProjection.constData()); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(viewCubeModel.constData()); + + drawViewCube(); + drawAxes(); + + glViewport(0, 0, width(), height()); + + // Text rendering with QPainter + QPainter painter(this); + painter.setPen(Qt::white); + painter.setFont(QFont("Arial", 10)); + + struct Face { + QString name; + QVector3D center; + QVector3D normal; + }; + QVector faces = { + {"FRONT", {0, 0, 1.0}, {0, 0, 1}}, + {"BACK", {0, 0, -1.0}, {0, 0, -1}}, + {"TOP", {0, 1.0, 0}, {0, 1, 0}}, + {"BOTTOM",{0, -1.0, 0}, {0, -1, 0}}, + {"RIGHT", {1.0, 0, 0}, {1, 0, 0}}, + {"LEFT", {-1.0, 0, 0}, {-1, 0, 0}} + }; + + for (const auto& face : faces) { + QVector3D transformedNormal = viewCubeModel.mapVector(face.normal); + // Use a small epsilon for floating point comparison + if (transformedNormal.z() > 0.1) { // Simple back-face culling + QRect viewportRect(width() - viewCubeSize, 0, viewCubeSize, viewCubeSize); + QVector3D pos2D = face.center.project(viewCubeModel, viewCubeProjection, viewportRect); + + QFontMetrics metrics(painter.font()); + int textWidth = metrics.horizontalAdvance(face.name); + int textHeight = metrics.height(); + QRect textRect(pos2D.x() - textWidth / 2, pos2D.y() - textHeight / 2, textWidth, textHeight); + painter.drawText(textRect, Qt::AlignCenter, face.name); + } + } } void ViewportWidget::resizeGL(int w, int h) @@ -75,6 +137,71 @@ void ViewportWidget::wheelEvent(QWheelEvent *event) update(); } +void ViewportWidget::drawViewCube() +{ + float size = 0.75; + glBegin(GL_QUADS); + // All faces are light gray + glColor3f(0.8, 0.8, 0.8); + + // Front face + glVertex3f(-size, -size, size); + glVertex3f(size, -size, size); + glVertex3f(size, size, size); + glVertex3f(-size, size, size); + + // Back face + glVertex3f(-size, -size, -size); + glVertex3f(-size, size, -size); + glVertex3f(size, size, -size); + glVertex3f(size, -size, -size); + + // Top face + glVertex3f(-size, size, -size); + glVertex3f(-size, size, size); + glVertex3f(size, size, size); + glVertex3f(size, size, -size); + + // Bottom face + glVertex3f(-size, -size, -size); + glVertex3f(size, -size, -size); + glVertex3f(size, -size, size); + glVertex3f(-size, -size, size); + + // Right face + glVertex3f(size, -size, -size); + glVertex3f(size, size, -size); + glVertex3f(size, size, size); + glVertex3f(size, -size, size); + + // Left face + glVertex3f(-size, -size, -size); + glVertex3f(-size, -size, size); + glVertex3f(-size, size, size); + glVertex3f(-size, size, -size); + glEnd(); +} + +void ViewportWidget::drawAxes() +{ + glLineWidth(2.0f); + glBegin(GL_LINES); + // X-axis (red) + glColor3f(1.0, 0.0, 0.0); + glVertex3f(0.0, 0.0, 0.0); + glVertex3f(1.5, 0.0, 0.0); + // Y-axis (green) + glColor3f(0.0, 1.0, 0.0); + glVertex3f(0.0, 0.0, 0.0); + glVertex3f(0.0, 1.5, 0.0); + // Z-axis (blue) + glColor3f(0.0, 0.0, 1.0); + glVertex3f(0.0, 0.0, 0.0); + glVertex3f(0.0, 0.0, 1.5); + glEnd(); + glLineWidth(1.0f); +} + void ViewportWidget::drawCube() { glBegin(GL_QUADS); diff --git a/src/ViewportWidget.h b/src/ViewportWidget.h index d9e4771..4301f59 100644 --- a/src/ViewportWidget.h +++ b/src/ViewportWidget.h @@ -24,6 +24,8 @@ protected: private: void drawCube(); + void drawViewCube(); + void drawAxes(); QMatrix4x4 projection;