#include "qscenerenderer.h" #include GLuint vertexbuffer; GLuint VertexArrayID; QSceneRenderer::QSceneRenderer(QWidget* parent): QOpenGLWidget(parent) { setFocusPolicy(Qt::FocusPolicy::StrongFocus); installEventFilter(this); QImage img = QImage("/home/bart/project/tiletest/images/heightmap.jpg").convertToFormat(QImage::Format_RGB32); m_zoom = 4; m_point = new Matrix2D(img.width(),img.height()); m_numPoints05= img.width()/MAP_WIDTH/1.5/2; for (int y = 0; yrow(y); for (int x = 0; xoperator ()(x,y).height = abs((x*10%200)-100); }*/ tiles=new Matrix2D(MAP_WIDTH,MAP_HEIGHT); } Tile * QSceneRenderer::getTile(int x, int y) { return &tiles->operator ()(x,y); } void QSceneRenderer::mousePressEvent(QMouseEvent *event) { lastPos = event->pos(); } void QSceneRenderer::mouseMoveEvent(QMouseEvent *event) { /*int dx = event->x() - lastPos.x(); int dy = event->y() - lastPos.y(); if (event->buttons() & Qt::LeftButton) { zRot += 8 * dx; } else if (event->buttons() & Qt::RightButton) { zRot -= 8 * dx; } lastPos = event->pos(); update();*/ } void QSceneRenderer::keyPressEvent(QKeyEvent *e) { if (e->key()== Qt::Key_A) { cameraPosition.setX(cameraPosition.x()+ 0.1f*cos(PI*(zRot+90)/180.0f)); cameraPosition.setY(cameraPosition.y()+ 0.1f*sin(PI*(zRot+90)/180.0f)); } else if (e->key()== Qt::Key_D) { cameraPosition.setX(cameraPosition.x()+ 0.1f*cos(PI*(zRot-90)/180.0f)); cameraPosition.setY(cameraPosition.y()+ 0.1f*sin(PI*(zRot-90)/180.0f)); } if (e->key()== Qt::Key_W) { cameraPosition.setX(cameraPosition.x()+ 0.1f*cos(PI*(zRot+0)/180.0f)); cameraPosition.setY(cameraPosition.y()+ 0.1f*sin(PI*(zRot+0)/180.0f)); } else if (e->key()== Qt::Key_S) { cameraPosition.setX(cameraPosition.x()+ 0.1f*cos(PI*(zRot+180)/180.0f)); cameraPosition.setY(cameraPosition.y()+ 0.1f*sin(PI*(zRot+180)/180.0f)); } else if (e->key()== Qt::Key_E) { zRot --; if (zRot<0.0) zRot+=360.0; } else if (e->key()== Qt::Key_Q) { zRot ++; if (zRot>=360.0) zRot-=360.0; } update(); } void QSceneRenderer::wheelEvent(QWheelEvent *e) { m_zoom -= e->delta()/100.0; if (m_zoom<2) m_zoom =2; if (m_zoom>10)m_zoom =10; update(); } void QSceneRenderer::initializeGL() { glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); } void QSceneRenderer::resizeGL(int width, int height) { Projection= QMatrix4x4(); Projection.perspective(45, (float) width / (float)height,0.1f,100.0f); } void QSceneRenderer::paintGL() { glEnable(GL_DEPTH_TEST); QMatrix4x4 cameraTransformation; QMatrix4x4 vMatrix; cameraTransformation.rotate(zRot, 0, 0, 1); cameraUpDirection = cameraTransformation * QVector3D(0, 0, 1); cameraPosition.setZ(m_zoom); QVector3D lookat = QVector3D(cameraPosition.x()+ m_zoom*m_zoom/5.0f*cos(PI*zRot/180.0f) , cameraPosition.y()+ m_zoom*m_zoom/5.0f*sin(PI*zRot/180.0f) ,0); vMatrix.lookAt(cameraPosition, lookat, cameraUpDirection); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Bounding box of the visible area in world coordinates float minWorldX = std::min(cameraPosition.x(), lookat.x()); float maxWorldX = std::max(cameraPosition.x(), lookat.x()); float minWorldY = std::min(cameraPosition.y(), lookat.y()); float maxWorldY = std::max(cameraPosition.y(), lookat.y()); float margin = m_zoom * 2.5f + 8.0f; minWorldX -= margin; maxWorldX += margin; minWorldY -= margin; maxWorldY += margin; float tileStepX = LOD_0_SIZE * 0.75f; float tileStepY = LOD_0_SIZE_Y * 2.0f; int minTileX = std::max(0, (int)floor(minWorldX / tileStepX)); int maxTileX = std::min(MAP_WIDTH - 1, (int)ceil(maxWorldX / tileStepX)); int minTileY = std::max(0, (int)floor(minWorldY / tileStepY)); int maxTileY = std::min(MAP_HEIGHT - 1, (int)ceil(maxWorldY / tileStepY)); // Expand margin by 1 for neighbor normal calculations int initMinX = std::max(0, minTileX - 1); int initMaxX = std::min(MAP_WIDTH - 1, maxTileX + 1); int initMinY = std::max(0, minTileY - 1); int initMaxY = std::min(MAP_HEIGHT - 1, maxTileY + 1); // 1. Lazy initialize visible tiles and direct neighbors for (int y = initMinY; y <= initMaxY; ++y) { for (int x = initMinX; x <= initMaxX; ++x) { tiles->operator()(x, y).ensureInitialized(this, x, y); } } // 2. Ensure normals are built for visible tiles for (int y = minTileY; y <= maxTileY; ++y) { for (int x = minTileX; x <= maxTileX; ++x) { tiles->operator()(x, y).ensureNormalsBuilt(); } } // 3. Render only visible tiles for (int y = minTileY; y <= maxTileY; ++y) { for (int x = minTileX; x <= maxTileX; ++x) { tiles->operator()(x, y).paint(Projection, cameraPosition, cameraUpDirection, vMatrix, zRot); } } }