From d484e0271a80e2f6f7f10920960007e5dbc0088d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Fri, 27 Jan 2012 17:21:57 +0000 Subject: [PATCH] paysages: Wanderer LOD + yaw. git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@243 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- TODO | 1 + gui_qt/dialogwanderer.cpp | 2 + gui_qt/widgetwanderer.cpp | 131 ++++++++++++++++++++++++++------------ lib_paysages/camera.c | 14 ++++ lib_paysages/camera.h | 1 + 5 files changed, 108 insertions(+), 41 deletions(-) diff --git a/TODO b/TODO index edb3192..a850556 100644 --- a/TODO +++ b/TODO @@ -3,3 +3,4 @@ - All Save and Load methods should have same signature : void ...Save(FILE*, ...*). - Remove all global variables (render_quality, render_width...), it should all be set in Renderer. - Implement scaling and scrolling on previews. +- Water and terrain LOD moves with the camera, fix it like in the wanderer. diff --git a/gui_qt/dialogwanderer.cpp b/gui_qt/dialogwanderer.cpp index 34aabe6..1c8da18 100644 --- a/gui_qt/dialogwanderer.cpp +++ b/gui_qt/dialogwanderer.cpp @@ -11,6 +11,8 @@ DialogWanderer::DialogWanderer(QWidget* parent, CameraDefinition* camera): setLayout(new QVBoxLayout()); layout()->addWidget(new WidgetWanderer(this, camera)); + + resize(700, 530); } DialogWanderer::~DialogWanderer() diff --git a/gui_qt/widgetwanderer.cpp b/gui_qt/widgetwanderer.cpp index 87748d5..1902f73 100644 --- a/gui_qt/widgetwanderer.cpp +++ b/gui_qt/widgetwanderer.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "../lib_paysages/scenery.h" WidgetWanderer::WidgetWanderer(QWidget *parent, CameraDefinition* camera): @@ -38,6 +39,7 @@ void WidgetWanderer::keyPressEvent(QKeyEvent* event) { factor = 1.0; } + factor *= 3.0; if (event->key() == Qt::Key_Up) { @@ -108,6 +110,12 @@ void WidgetWanderer::mouseMoveEvent(QMouseEvent* event) updateGL(); event->accept(); } + else if (event->buttons() & Qt::RightButton) + { + cameraRotateYaw(&camera, (double)(event->x() - last_mouse_x) * factor * 0.1); + updateGL(); + event->accept(); + } else { event->ignore(); @@ -133,7 +141,7 @@ void WidgetWanderer::wheelEvent(QWheelEvent* event) { factor = 0.1; } - factor *= 0.1; + factor *= 0.03; if (event->orientation() == Qt::Vertical) { @@ -147,6 +155,21 @@ void WidgetWanderer::wheelEvent(QWheelEvent* event) void WidgetWanderer::initializeGL() { glClearColor(0.4, 0.7, 0.8, 0.0); + + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE); + + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); + + glDepthFunc(GL_LEQUAL); + glDepthMask(true); + glEnable(GL_DEPTH_TEST); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_LINE_SMOOTH); + glLineWidth(1.0); } void WidgetWanderer::resizeGL(int w, int h) @@ -160,31 +183,82 @@ void WidgetWanderer::resizeGL(int w, int h) glFrustum(-2.5, 2.5, -2.5 * ratio, 2.5 * ratio, 2.0, 1000.0); } -static inline void _pushTerrainVertex(TerrainDefinition* terrain, double x, double z) +static inline void _renderTerrainQuad(TerrainDefinition* terrain, double x, double z, double size) { - glVertex3f(x, terrainGetHeight(terrain, x, z), z); + double y1, y2, y3, y4; + + y1 = terrainGetHeight(terrain, x, z); + y2 = terrainGetHeight(terrain, x, z + size); + y3 = terrainGetHeight(terrain, x + size, z + size); + y4 = terrainGetHeight(terrain, x + size, z); + + glColor3f(0.0, 0.5, 0.0); + glBegin(GL_QUADS); + glVertex3f(x, y1, z); + glVertex3f(x, y2, z + size); + glVertex3f(x + size, y3, z + size); + glVertex3f(x + size, y4, z); + glEnd(); + + glColor3f(0.0, 1.0, 0.0); + glBegin(GL_LINE_LOOP); + glVertex3f(x, y1, z); + glVertex3f(x, y2, z + size); + glVertex3f(x + size, y3, z + size); + glVertex3f(x + size, y4, z); + glEnd(); +} + +static void _renderTerrain(TerrainDefinition* terrain, CameraDefinition* camera, int quality) +{ + int chunk_factor, chunk_count, i; + double min_chunk_size, visible_chunk_size; + double radius_int, radius_ext, chunk_size; + double cx, cz; + + min_chunk_size = 1.0 / (double)quality; + visible_chunk_size = 1.0 / (double)quality; + + cx = camera->location.x - fmod(camera->location.x, min_chunk_size * 16.0); + cz = camera->location.z - fmod(camera->location.z, min_chunk_size * 16.0); + + chunk_factor = 1; + chunk_count = 2; + radius_int = 0.0; + radius_ext = min_chunk_size; + chunk_size = min_chunk_size; + + while (radius_ext < 100.0) + { + for (i = 0; i < chunk_count - 1; i++) + { + _renderTerrainQuad(terrain, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size); + _renderTerrainQuad(terrain, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size); + _renderTerrainQuad(terrain, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size); + _renderTerrainQuad(terrain, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size); + } + + if (chunk_count % 32 == 0 && chunk_size / radius_int < visible_chunk_size) + { + chunk_count /= 2; + chunk_factor *= 2; + /* TODO Fill in gaps with triangles */ + } + chunk_count += 2; + chunk_size = min_chunk_size * chunk_factor; + radius_int = radius_ext; + radius_ext += chunk_size; + } } void WidgetWanderer::paintGL() { - double x, z, step; - glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(camera.location.x, camera.location.y, camera.location.z, camera.target.x, camera.target.y, camera.target.z, camera.up.x, camera.up.y, camera.up.z); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glFrontFace(GL_CCW); - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); - - glDepthFunc(GL_LEQUAL); - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - - glLineWidth(1.0); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor3f(0.0, 0.0, 1.0); glBegin(GL_QUADS); @@ -194,30 +268,5 @@ void WidgetWanderer::paintGL() glVertex3f(500.0, water.height, -500.0); glEnd(); - step = 2.0; - for (x = -50.0; x < 50.0; x += step) - { - for (z = -50.0; z < 50.0; z += step) - { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glColor3f(0.0, 0.5, 0.0); - glBegin(GL_QUADS); - _pushTerrainVertex(&terrain, x, z); - _pushTerrainVertex(&terrain, x, z + step); - _pushTerrainVertex(&terrain, x + step, z + step); - _pushTerrainVertex(&terrain, x + step, z); - glEnd(); - - glEnable(GL_LINE_SMOOTH); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glColor3f(0.0, 1.0, 0.0); - glBegin(GL_QUADS); - _pushTerrainVertex(&terrain, x, z); - _pushTerrainVertex(&terrain, x, z + step); - _pushTerrainVertex(&terrain, x + step, z + step); - _pushTerrainVertex(&terrain, x + step, z); - glEnd(); - glDisable(GL_LINE_SMOOTH); - } - } + _renderTerrain(&terrain, &camera, 3); } diff --git a/lib_paysages/camera.c b/lib_paysages/camera.c index 7cf6d93..3d1f0c5 100644 --- a/lib_paysages/camera.c +++ b/lib_paysages/camera.c @@ -119,6 +119,20 @@ void cameraStrafeUp(CameraDefinition* camera, double value) cameraValidateDefinition(camera); } +void cameraRotateYaw(CameraDefinition* camera, double value) +{ + Matrix4 m; + Vector3 v; + + v = v3Sub(camera->target, camera->location); + m = m4NewRotateAxis(value, camera->up); + v = m4MultPoint(m, v); + + camera->target = v3Add(camera->location, v); + + cameraValidateDefinition(camera); +} + Vector3 cameraProject(CameraDefinition* camera, Vector3 point) { point = m4Transform(camera->project, v3Sub(point, camera->location)); diff --git a/lib_paysages/camera.h b/lib_paysages/camera.h index eb7fb9c..e393e4b 100644 --- a/lib_paysages/camera.h +++ b/lib_paysages/camera.h @@ -33,6 +33,7 @@ void cameraSetAngle(CameraDefinition* camera, double angle); void cameraStrafeForward(CameraDefinition* camera, double value); void cameraStrafeRight(CameraDefinition* camera, double value); void cameraStrafeUp(CameraDefinition* camera, double value); +void cameraRotateYaw(CameraDefinition* camera, double value); Vector3 cameraProject(CameraDefinition* camera, Vector3 point); Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point);