paysages: Wanderer LOD + yaw.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@243 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-01-27 17:21:57 +00:00 committed by ThunderK
parent c57adf47f2
commit d484e0271a
5 changed files with 108 additions and 41 deletions

1
TODO
View file

@ -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.

View file

@ -11,6 +11,8 @@ DialogWanderer::DialogWanderer(QWidget* parent, CameraDefinition* camera):
setLayout(new QVBoxLayout());
layout()->addWidget(new WidgetWanderer(this, camera));
resize(700, 530);
}
DialogWanderer::~DialogWanderer()

View file

@ -2,6 +2,7 @@
#include <QGLWidget>
#include <QKeyEvent>
#include <math.h>
#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);
}

View file

@ -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));

View file

@ -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);