From e5365091aad57f20a91c7e112eea8a0a2dccc0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 29 Jan 2012 11:34:49 +0000 Subject: [PATCH] paysages: Camera support for roll (WIP). git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@248 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- TODO | 2 + gui_qt/formrender.cpp | 2 +- gui_qt/widgetwanderer.cpp | 3 + lib_paysages/camera.c | 164 ++++++++++++++++++++++++++++---------- lib_paysages/camera.h | 17 +++- lib_paysages/scenery.c | 28 +++---- 6 files changed, 155 insertions(+), 61 deletions(-) diff --git a/TODO b/TODO index a850556..cba5a72 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,5 @@ +- Clouds are lighted without filtering from ground (clouds lighted at night !) +- Camera should respect ratio aspect of render area. - All noises should use the same entropy pool (saved separately), and avoid reallocs. - Implement light multi-sampling (mainly for skydome). - All Save and Load methods should have same signature : void ...Save(FILE*, ...*). diff --git a/gui_qt/formrender.cpp b/gui_qt/formrender.cpp index 0e3f472..1fdc932 100644 --- a/gui_qt/formrender.cpp +++ b/gui_qt/formrender.cpp @@ -48,7 +48,7 @@ void FormRender::applyConfig() void FormRender::configChangeEvent() { - cameraValidateDefinition(&_camera); + cameraValidateDefinition(&_camera, 1); BaseForm::configChangeEvent(); } diff --git a/gui_qt/widgetwanderer.cpp b/gui_qt/widgetwanderer.cpp index e30e317..4a3186f 100644 --- a/gui_qt/widgetwanderer.cpp +++ b/gui_qt/widgetwanderer.cpp @@ -125,6 +125,7 @@ void WidgetWanderer::mouseMoveEvent(QMouseEvent* event) else if (event->buttons() & Qt::RightButton) { cameraRotateYaw(&_current_camera, (double)(event->x() - last_mouse_x) * factor * 0.1); + cameraRotatePitch(&_current_camera, (double)(event->y() - last_mouse_y) * factor * 0.1); updateGL(); event->accept(); } @@ -265,6 +266,8 @@ static void _renderTerrain(TerrainDefinition* terrain, CameraDefinition* camera, void WidgetWanderer::paintGL() { + cameraValidateDefinition(&_current_camera, 1); + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(_current_camera.location.x, _current_camera.location.y, _current_camera.location.z, _current_camera.target.x, _current_camera.target.y, _current_camera.target.z, _current_camera.up.x, _current_camera.up.y, _current_camera.up.z); diff --git a/lib_paysages/camera.c b/lib_paysages/camera.c index 3d1f0c5..f8e1b72 100644 --- a/lib_paysages/camera.c +++ b/lib_paysages/camera.c @@ -8,6 +8,7 @@ #include "shared/globals.h" #include "shared/constants.h" #include "shared/functions.h" +#include "scenery.h" void cameraInit() { @@ -16,29 +17,33 @@ void cameraInit() void cameraSave(FILE* f, CameraDefinition* camera) { v3Save(camera->location, f); - v3Save(camera->target, f); + toolsSaveDouble(f, camera->yaw); + toolsSaveDouble(f, camera->pitch); + toolsSaveDouble(f, camera->roll); } void cameraLoad(FILE* f, CameraDefinition* camera) { camera->location = v3Load(f); - camera->target = v3Load(f); + camera->yaw = toolsLoadDouble(f); + camera->pitch = toolsLoadDouble(f); + camera->roll = toolsLoadDouble(f); - cameraValidateDefinition(camera); + cameraValidateDefinition(camera, 0); } CameraDefinition cameraCreateDefinition() { CameraDefinition definition; - definition.location.x = -1.0; + definition.location.x = 0.0; definition.location.y = 0.0; definition.location.z = 0.0; - definition.target.x = 0.0; - definition.target.y = 0.0; - definition.target.z = 0.0; + definition.yaw = 0.0; + definition.pitch = 0.0; + definition.roll = 0.0; - cameraValidateDefinition(&definition); + cameraValidateDefinition(&definition, 0); return definition; } @@ -50,16 +55,66 @@ void cameraDeleteDefinition(CameraDefinition* definition) void cameraCopyDefinition(CameraDefinition* source, CameraDefinition* destination) { *destination = *source; + + cameraValidateDefinition(destination, 0); } -void cameraValidateDefinition(CameraDefinition* definition) +void cameraValidateDefinition(CameraDefinition* definition, int check_above) { - /* TODO Recompute up vector */ + WaterDefinition water; + TerrainDefinition terrain; + double water_height, terrain_height, diff; + Vector3 move; + Matrix4 rotation; + + if (check_above) + { + water = waterCreateDefinition(); + sceneryGetWater(&water); + water_height = water.height + 0.5; + waterDeleteDefinition(&water); + + terrain = terrainCreateDefinition(); + sceneryGetTerrain(&terrain); + terrain_height = terrainGetHeight(&terrain, definition->location.x, definition->location.z) + 0.5; + terrainDeleteDefinition(&terrain); + + if (definition->location.y < water_height || definition->location.y < terrain_height) + { + if (water_height > terrain_height) + { + diff = water_height - definition->location.y; + } + else + { + diff = terrain_height - definition->location.y; + } + + move.x = move.z = 0.0; + move.y = diff; + definition->location = v3Add(definition->location, move); + } + } + + definition->forward.x = 1.0; + definition->forward.y = 0.0; + definition->forward.z = 0.0; + definition->right.x = 0.0; + definition->right.y = 0.0; + definition->right.z = 1.0; definition->up.x = 0.0; definition->up.y = 1.0; definition->up.z = 0.0; + + rotation = m4NewRotateEuler(definition->yaw, definition->pitch, definition->roll); + + definition->forward = m4MultPoint(rotation, definition->forward); + definition->right = m4MultPoint(rotation, definition->right); + definition->up = m4MultPoint(rotation, definition->up); + + definition->target = v3Add(definition->location, definition->forward); - definition->project = m4Mult(m4NewPerspective(1.57, 1.333333, 1.0, 1000.0), m4NewLookAt(VECTOR_ZERO, v3Sub(definition->target, definition->location), definition->up)); + definition->project = m4Mult(m4NewPerspective(1.57, 1.333333, 1.0, 1000.0), m4NewLookAt(VECTOR_ZERO, definition->forward, definition->up)); definition->unproject = m4Inverse(definition->project); } @@ -69,68 +124,91 @@ void cameraSetLocation(CameraDefinition* camera, double x, double y, double z) camera->location.y = y; camera->location.z = z; - cameraValidateDefinition(camera); + cameraValidateDefinition(camera, 0); } void cameraSetTarget(CameraDefinition* camera, double x, double y, double z) { - camera->target.x = x; - camera->target.y = y; - camera->target.z = z; + Vector3 forward, target; + + target.x = x; + target.y = y; + target.z = z; + + forward = v3Sub(target, camera->location); + if (v3Norm(forward) < 0.0000001) + { + return; + } + forward = v3Normalize(forward); + + if (fabs(forward.x) < 0.0000001 && fabs(forward.z) < 0.0000001) + { + /* Forward vector is vertical */ + if (forward.y > 0.0) + { + camera->pitch = M_PI_2; + } + else if (forward.y > 0.0) + { + camera->pitch = -M_PI_2; + } + } + else + { + /* TODO Guess angles */ + } - cameraValidateDefinition(camera); + cameraValidateDefinition(camera, 0); } -void cameraSetAngle(CameraDefinition* camera, double angle) +void cameraSetRoll(CameraDefinition* camera, double angle) { - /* TODO */ + camera->roll = angle; + + cameraValidateDefinition(camera, 0); } void cameraStrafeForward(CameraDefinition* camera, double value) { - Vector3 move; + camera->location = v3Add(camera->location, v3Scale(camera->forward, value)); - move = v3Scale(v3Normalize(v3Sub(camera->target, camera->location)), value); - camera->location = v3Add(camera->location, move); - camera->target = v3Add(camera->target, move); - - cameraValidateDefinition(camera); + cameraValidateDefinition(camera, 0); } void cameraStrafeRight(CameraDefinition* camera, double value) { - Vector3 move; + camera->location = v3Add(camera->location, v3Scale(camera->right, value)); - move = v3Scale(v3Normalize(v3Cross(v3Sub(camera->target, camera->location), camera->up)), value); - camera->location = v3Add(camera->location, move); - camera->target = v3Add(camera->target, move); - - cameraValidateDefinition(camera); + cameraValidateDefinition(camera, 0); } void cameraStrafeUp(CameraDefinition* camera, double value) { - Vector3 move; + camera->location = v3Add(camera->location, v3Scale(camera->up, value)); - move = v3Scale(v3Normalize(camera->up), value); - camera->location = v3Add(camera->location, move); - camera->target = v3Add(camera->target, move); - - cameraValidateDefinition(camera); + cameraValidateDefinition(camera, 0); } void cameraRotateYaw(CameraDefinition* camera, double value) { - Matrix4 m; - Vector3 v; + camera->yaw += value; - v = v3Sub(camera->target, camera->location); - m = m4NewRotateAxis(value, camera->up); - v = m4MultPoint(m, v); + cameraValidateDefinition(camera, 0); +} - camera->target = v3Add(camera->location, v); +void cameraRotatePitch(CameraDefinition* camera, double value) +{ + camera->pitch += value; - cameraValidateDefinition(camera); + cameraValidateDefinition(camera, 0); +} + +void cameraRotateRoll(CameraDefinition* camera, double value) +{ + camera->roll += value; + + cameraValidateDefinition(camera, 0); } Vector3 cameraProject(CameraDefinition* camera, Vector3 point) diff --git a/lib_paysages/camera.h b/lib_paysages/camera.h index e393e4b..b236fa7 100644 --- a/lib_paysages/camera.h +++ b/lib_paysages/camera.h @@ -8,11 +8,22 @@ extern "C" { #endif +/* Definition of a 3D scene camera. + * + * Don't modify this structure directly, use the provided functions. + */ typedef struct { Vector3 location; + double yaw; + double pitch; + double roll; + Vector3 target; + Vector3 forward; + Vector3 right; Vector3 up; + Matrix4 project; Matrix4 unproject; } CameraDefinition; @@ -24,16 +35,18 @@ void cameraLoad(FILE* f, CameraDefinition* camera); CameraDefinition cameraCreateDefinition(); void cameraDeleteDefinition(CameraDefinition* definition); void cameraCopyDefinition(CameraDefinition* source, CameraDefinition* destination); -void cameraValidateDefinition(CameraDefinition* definition); +void cameraValidateDefinition(CameraDefinition* definition, int check_above); void cameraSetLocation(CameraDefinition* camera, double x, double y, double z); void cameraSetTarget(CameraDefinition* camera, double x, double y, double z); -void cameraSetAngle(CameraDefinition* camera, double angle); +void cameraSetRoll(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); +void cameraRotatePitch(CameraDefinition* camera, double value); +void cameraRotateRoll(CameraDefinition* camera, double value); Vector3 cameraProject(CameraDefinition* camera, Vector3 point); Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point); diff --git a/lib_paysages/scenery.c b/lib_paysages/scenery.c index c010109..5e36ed4 100644 --- a/lib_paysages/scenery.c +++ b/lib_paysages/scenery.c @@ -58,27 +58,21 @@ void sceneryLoadFromFile(char* filepath) /* TODO Use intermediary definitions ? */ atmosphereLoad(f, &_atmosphere); - atmosphereValidateDefinition(&_atmosphere); - cameraLoad(f, &_camera); - cameraValidateDefinition(&_camera); - cloudsLoad(f, &_clouds); - cloudsValidateDefinition(&_clouds); - lightingLoad(f, &_lighting); - lightingValidateDefinition(&_lighting); - skyLoad(f, &_sky); - skyValidateDefinition(&_sky); - terrainLoad(f, &_terrain); - terrainValidateDefinition(&_terrain); - texturesLoad(f, &_textures); - texturesValidateDefinition(&_textures); - waterLoad(f, &_water); + + atmosphereValidateDefinition(&_atmosphere); + cameraValidateDefinition(&_camera, 0); + cloudsValidateDefinition(&_clouds); + lightingValidateDefinition(&_lighting); + skyValidateDefinition(&_sky); + terrainValidateDefinition(&_terrain); + texturesValidateDefinition(&_textures); waterValidateDefinition(&_water); fclose(f); @@ -98,7 +92,7 @@ void sceneryGetAtmosphere(AtmosphereDefinition* atmosphere) void scenerySetCamera(CameraDefinition* camera) { cameraCopyDefinition(camera, &_camera); - cameraValidateDefinition(&_camera); + cameraValidateDefinition(&_camera, 1); } void sceneryGetCamera(CameraDefinition* camera) @@ -146,6 +140,8 @@ void scenerySetTerrain(TerrainDefinition* terrain) { terrainCopyDefinition(terrain, &_terrain); terrainValidateDefinition(&_terrain); + + cameraValidateDefinition(&_camera, 1); } void sceneryGetTerrain(TerrainDefinition* terrain) @@ -168,6 +164,8 @@ void scenerySetWater(WaterDefinition* water) { waterCopyDefinition(water, &_water); waterValidateDefinition(&_water); + + cameraValidateDefinition(&_camera, 1); } void sceneryGetWater(WaterDefinition* water)