From 48ce97e4cb7091740a545f7c58fc268ccc6208e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sat, 27 Apr 2013 21:40:31 +0000 Subject: [PATCH] paysages : WIP. git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@559 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- src/editing/widgetheightmap.cpp | 83 ++++++++++++++++++++-- src/editing/widgetheightmap.h | 6 ++ src/rendering/camera.c | 118 ++++++++++++++++++-------------- src/rendering/camera.h | 1 + src/rendering/tools/euclid.c | 14 +++- src/rendering/tools/euclid.h | 1 + src/testing/camera.c | 2 +- src/testing/euclid.c | 58 +++++++++++++++- 8 files changed, 224 insertions(+), 59 deletions(-) diff --git a/src/editing/widgetheightmap.cpp b/src/editing/widgetheightmap.cpp index a86c2f4..a5f4348 100644 --- a/src/editing/widgetheightmap.cpp +++ b/src/editing/widgetheightmap.cpp @@ -6,6 +6,7 @@ #include #include #include "tools.h" +#include "rendering/scenery.h" #define HEIGHTMAP_RESOLUTION 256 @@ -27,6 +28,13 @@ QGLWidget(parent) _dirty = true; + _water = true; + _wireframe = true; + WaterDefinition* water_definition = (WaterDefinition*) WaterDefinitionClass.create(); + sceneryGetWater(water_definition); + _water_height = water_definition->height; + WaterDefinitionClass.destroy(water_definition); + _average_frame_time = 0.0; _last_brush_action = 0; @@ -38,10 +46,12 @@ QGLWidget(parent) _current_camera = cameraCreateDefinition(); _top_camera = cameraCreateDefinition(); _temp_camera = cameraCreateDefinition(); + _zoom = 50.0; - Vector3 camera_location = {0.0, 80.0, 20.0}; + Vector3 camera_location = {0.0, 80.0, 10.0}; cameraSetLocation(_current_camera, camera_location); cameraSetTarget(_current_camera, VECTOR_ZERO); + cameraSetZoomToTarget(_top_camera, _zoom); cameraCopyDefinition(_current_camera, _top_camera); _brush_x = 0.0; @@ -132,6 +142,25 @@ void WidgetHeightMap::revert() updateGL(); } +void WidgetHeightMap::wheelEvent(QWheelEvent* event) +{ + if (event->orientation() == Qt::Vertical) + { + _zoom -= 0.05 * (double) event->delta(); + if (_zoom < 10.0) + { + _zoom = 10.0; + } + else if (_zoom > 70.0) + { + _zoom = 70.0; + } + + cameraSetZoomToTarget(_top_camera, _zoom); + } + event->accept(); +} + void WidgetHeightMap::mousePressEvent(QMouseEvent* event) { _last_mouse_x = event->x(); @@ -228,7 +257,7 @@ void WidgetHeightMap::timerEvent(QTimerEvent*) } // Move camera - if (cameraTransitionToAnother(_current_camera, _top_camera, 0.1)) + if (cameraTransitionToAnother(_current_camera, _top_camera, 0.8)) { updateGL(); } @@ -293,8 +322,8 @@ void WidgetHeightMap::initializeGL() //glCullFace(GL_BACK); glDisable(GL_CULL_FACE); - glDepthFunc(GL_LESS); - glDepthMask(true); + glDepthFunc(GL_LEQUAL); + glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -421,6 +450,52 @@ void WidgetHeightMap::paintGL() glEnd(); } + // Wireframe + if (_wireframe) + { + glDisable(GL_LIGHTING); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(0.8, 0.0, 0.0, 0.1); + for (int z = 0; z < rz; z++) + { + glBegin(GL_LINE_STRIP); + for (int x = 0; x < rx; x++) + { + _VertexInfo* vertex = _vertices + z * rx + x; + glVertex3f(vertex->point.x - tx, vertex->point.y, vertex->point.z - tz); + } + glEnd(); + } + for (int x = 0; x < rx; x++) + { + glBegin(GL_LINE_STRIP); + for (int z = 0; z < rz; z++) + { + _VertexInfo* vertex = _vertices + z * rx + x; + glVertex3f(vertex->point.x - tx, vertex->point.y, vertex->point.z - tz); + } + glEnd(); + } + glEnable(GL_LIGHTING); + glDisable(GL_BLEND); + } + + // Water + if (_water) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(0.2, 0.3, 0.7, 0.7); + glBegin(GL_QUADS); + glVertex3f(camera_target.x - 500.0, _water_height, camera_target.z - 500.0); + glVertex3f(camera_target.x - 500.0, _water_height, camera_target.z + 500.0); + glVertex3f(camera_target.x + 500.0, _water_height, camera_target.z + 500.0); + glVertex3f(camera_target.x + 500.0, _water_height, camera_target.z - 500.0); + glEnd(); + glDisable(GL_BLEND); + } + // Time stats frame_time = 0.001 * (double) start_time.msecsTo(QTime::currentTime()); _average_frame_time = _average_frame_time * 0.8 + frame_time * 0.2; diff --git a/src/editing/widgetheightmap.h b/src/editing/widgetheightmap.h index 7494cd2..fb1652b 100644 --- a/src/editing/widgetheightmap.h +++ b/src/editing/widgetheightmap.h @@ -46,6 +46,7 @@ protected: void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); + void wheelEvent(QWheelEvent* event); void timerEvent(QTimerEvent* event); @@ -64,6 +65,10 @@ private: bool _dirty; qint64 _memory_stats; + double _water_height; + bool _water; + bool _wireframe; + double _average_frame_time; int _last_brush_action; @@ -75,6 +80,7 @@ private: CameraDefinition* _top_camera; CameraDefinition* _temp_camera; CameraDefinition* _current_camera; + double _zoom; double _brush_x; double _brush_z; diff --git a/src/rendering/camera.c b/src/rendering/camera.c index b80d505..11d3c83 100644 --- a/src/rendering/camera.c +++ b/src/rendering/camera.c @@ -8,24 +8,21 @@ struct CameraDefinition { + /* Definition */ Vector3 location; - double yaw; - double pitch; + VectorSpherical direction; double roll; + /* Projection info */ + double width; + double height; + CameraPerspective perspective; + + /* Auto updated */ Vector3 target; Vector3 forward; Vector3 right; Vector3 up; - - double width; - double height; - CameraPerspective perspective; - double yfov; - double xratio; - double znear; - double zfar; - Matrix4 project; Matrix4 unproject; }; @@ -33,16 +30,18 @@ struct CameraDefinition void cameraSave(PackStream* stream, CameraDefinition* camera) { v3Save(stream, &camera->location); - packWriteDouble(stream, &camera->yaw); - packWriteDouble(stream, &camera->pitch); + packWriteDouble(stream, &camera->direction.r); + packWriteDouble(stream, &camera->direction.phi); + packWriteDouble(stream, &camera->direction.theta); packWriteDouble(stream, &camera->roll); } void cameraLoad(PackStream* stream, CameraDefinition* camera) { v3Load(stream, &camera->location); - packReadDouble(stream, &camera->yaw); - packReadDouble(stream, &camera->pitch); + packReadDouble(stream, &camera->direction.r); + packReadDouble(stream, &camera->direction.phi); + packReadDouble(stream, &camera->direction.theta); packReadDouble(stream, &camera->roll); cameraValidateDefinition(camera, 0); @@ -57,16 +56,17 @@ CameraDefinition* cameraCreateDefinition() definition->location.x = 0.0; definition->location.y = 0.0; definition->location.z = 0.0; - definition->yaw = 0.0; - definition->pitch = 0.0; + definition->direction.phi = 0.0; + definition->direction.theta = 0.0; + definition->direction.r = 1.0; definition->roll = 0.0; definition->width = 1.0; definition->height = 1.0; - definition->yfov = 1.57; - definition->xratio = 1.0; - definition->znear = 1.0; - definition->zfar = 1000.0; + definition->perspective.yfov = 1.57; + definition->perspective.xratio = 1.0; + definition->perspective.znear = 1.0; + definition->perspective.zfar = 1000.0; cameraValidateDefinition(definition, 0); @@ -131,15 +131,15 @@ void cameraValidateDefinition(CameraDefinition* definition, int check_above) definition->up.y = 1.0; definition->up.z = 0.0; - rotation = m4NewRotateEuler(definition->yaw, definition->pitch, definition->roll); + rotation = m4NewRotateEuler(definition->direction.phi, definition->direction.theta, 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->target = v3Add(definition->location, v3FromSpherical(definition->direction)); - definition->project = m4Mult(m4NewPerspective(definition->yfov, definition->xratio, definition->znear, definition->zfar), m4NewLookAt(definition->location, definition->target, definition->up)); + definition->project = m4Mult(m4NewPerspective(definition->perspective.yfov, definition->perspective.xratio, definition->perspective.znear, definition->perspective.zfar), m4NewLookAt(definition->location, definition->target, definition->up)); definition->unproject = m4Inverse(definition->project); } @@ -165,7 +165,7 @@ double cameraGetRoll(CameraDefinition* camera) Vector3 cameraGetDirection(CameraDefinition* camera) { - return camera->forward; + return v3FromSpherical(camera->direction); } Vector3 cameraGetDirectionNormalized(CameraDefinition* camera) @@ -175,6 +175,7 @@ Vector3 cameraGetDirectionNormalized(CameraDefinition* camera) VectorSpherical cameraGetDirectionSpherical(CameraDefinition* camera) { + return camera->direction; } CameraPerspective cameraGetPerspective(CameraDefinition* camera) @@ -204,27 +205,8 @@ void cameraSetTarget(CameraDefinition* camera, Vector3 target) { 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 - { - /* Guess angles */ - VectorSpherical spherical = v3ToSpherical(forward); - camera->yaw = spherical.phi; - camera->pitch = spherical.theta; - } + camera->direction = v3ToSpherical(forward); cameraValidateDefinition(camera, 0); } @@ -242,6 +224,14 @@ void cameraSetRoll(CameraDefinition* camera, double angle) cameraValidateDefinition(camera, 0); } +void cameraSetZoomToTarget(CameraDefinition* camera, double zoom) +{ + camera->direction.r = zoom; + camera->location = v3Add(camera->target, v3Scale(v3FromSpherical(camera->direction), -1.0)); + + cameraValidateDefinition(camera, 0); +} + void cameraStrafeForward(CameraDefinition* camera, double value) { camera->location = v3Add(camera->location, v3Scale(camera->forward, value)); @@ -265,14 +255,14 @@ void cameraStrafeUp(CameraDefinition* camera, double value) void cameraRotateYaw(CameraDefinition* camera, double value) { - camera->yaw += value; + camera->direction.phi += value; cameraValidateDefinition(camera, 0); } void cameraRotatePitch(CameraDefinition* camera, double value) { - camera->pitch += value; + camera->direction.theta += value; cameraValidateDefinition(camera, 0); } @@ -288,7 +278,7 @@ void cameraSetRenderSize(CameraDefinition* camera, int width, int height) { camera->width = (double)width; camera->height = (double)height; - camera->xratio = camera->width / camera->height; + camera->perspective.xratio = camera->width / camera->height; cameraValidateDefinition(camera, 0); } @@ -408,12 +398,36 @@ int cameraIsBoxInView(CameraDefinition* camera, Vector3 center, double xsize, do projected = cameraProject(camera, center); _updateBox(&projected, &xmin, &xmax, &ymin, &ymax, &zmax); - return xmin <= camera->width && xmax >= 0.0 && ymin <= camera->height && ymax >= 0.0 && zmax >= camera->znear; + return xmin <= camera->width && xmax >= 0.0 && ymin <= camera->height && ymax >= 0.0 && zmax >= camera->perspective.znear; } int cameraTransitionToAnother(CameraDefinition* current, CameraDefinition* wanted, double factor) { - current->location.z += factor; - cameraValidateDefinition(current, 0); - return 1; + double dx, dy, dz, dr, dphi, dtheta, droll; + + dx = wanted->location.x - current->location.x; + dy = wanted->location.y - current->location.y; + dz = wanted->location.z - current->location.z; + dr = wanted->direction.r - current->direction.r; + dphi = wanted->direction.phi - current->direction.phi; + dtheta = wanted->direction.theta - current->direction.theta; + droll = wanted->roll - current->roll; + + if (fabs(dx) < 0.000001 && fabs(dy) < 0.000001 && fabs(dz) < 0.000001 && fabs(dr) < 0.000001 && fabs(dphi) < 0.000001 && fabs(dtheta) < 0.000001 && fabs(droll) < 0.000001) + { + return 0; + } + else + { + current->location.x += dx * factor; + current->location.y += dy * factor; + current->location.z += dz * factor; + current->direction.r += dr * factor; + current->direction.phi += dphi * factor; + current->direction.theta += dtheta * factor; + current->roll += droll * factor; + + cameraValidateDefinition(current, 0); + return 1; + } } diff --git a/src/rendering/camera.h b/src/rendering/camera.h index be996fb..a77967c 100644 --- a/src/rendering/camera.h +++ b/src/rendering/camera.h @@ -41,6 +41,7 @@ void cameraSetLocationCoords(CameraDefinition* camera, double x, double y, doubl void cameraSetTarget(CameraDefinition* camera, Vector3 target); void cameraSetTargetCoords(CameraDefinition* camera, double x, double y, double z); void cameraSetRoll(CameraDefinition* camera, double angle); +void cameraSetZoomToTarget(CameraDefinition* camera, double zoom); void cameraStrafeForward(CameraDefinition* camera, double value); void cameraStrafeRight(CameraDefinition* camera, double value); diff --git a/src/rendering/tools/euclid.c b/src/rendering/tools/euclid.c index a7a0631..bc0af63 100644 --- a/src/rendering/tools/euclid.c +++ b/src/rendering/tools/euclid.c @@ -105,9 +105,21 @@ Vector3 v3Cross(Vector3 v1, Vector3 v2) VectorSpherical v3ToSpherical(Vector3 v) { VectorSpherical result; - result.phi = euclidGet2DAngle(v.x, v.z); + + result.phi = euclidGet2DAngle(v.x, -v.z); result.theta = euclidGet2DAngle(sqrt(v.x * v.x + v.z * v.z), v.y); + if (v.y < 0.0) + { + result.theta -= 2.0 * M_PI; + } result.r = v3Norm(v); + + return result; +} + +Vector3 v3FromSpherical(VectorSpherical v) +{ + Vector3 result = {v.r * cos(v.phi) * cos(v.theta), v.r * sin(v.theta), -v.r * sin(v.phi) * cos(v.theta)}; return result; } diff --git a/src/rendering/tools/euclid.h b/src/rendering/tools/euclid.h index dd45a39..b5bbd6f 100644 --- a/src/rendering/tools/euclid.h +++ b/src/rendering/tools/euclid.h @@ -89,6 +89,7 @@ Vector3 v3Normalize(Vector3 v); double v3Dot(Vector3 v1, Vector3 v2); Vector3 v3Cross(Vector3 v1, Vector3 v2); VectorSpherical v3ToSpherical(Vector3 v); +Vector3 v3FromSpherical(VectorSpherical v); void m4Save(PackStream* stream, Matrix4* m); void m4Load(PackStream* stream, Matrix4* m); diff --git a/src/testing/camera.c b/src/testing/camera.c index adb4e4c..8c8ada9 100644 --- a/src/testing/camera.c +++ b/src/testing/camera.c @@ -13,7 +13,7 @@ START_TEST(test_camera_definition) cameraSetTargetCoords(cam, 0.0, 0.0, 0.0); _checkVector(cameraGetLocation(cam), 0.0, 1.0, 1.0); - _checkVector(cameraGetTarget(cam), 0.0, 1.0, 1.0); + _checkVector(cameraGetTarget(cam), 0.0, 0.0, 0.0); cameraDeleteDefinition(cam); } diff --git a/src/testing/euclid.c b/src/testing/euclid.c index be224b6..7c6dcaa 100644 --- a/src/testing/euclid.c +++ b/src/testing/euclid.c @@ -66,10 +66,66 @@ START_TEST(test_vectors_spherical) VectorSpherical v2; /* Test conversion to spherical */ + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + v2 = v3ToSpherical(v1); + ck_assert_double_eq(v2.r, 0.0); + ck_assert_double_eq(v2.phi, 0.0); + ck_assert_double_eq(v2.theta, 0.0); + + v1.x = 1.0; + v1.y = 0.0; + v1.z = 0.0; + v2 = v3ToSpherical(v1); + ck_assert_double_eq(v2.r, 1.0); + ck_assert_double_eq(v2.phi, 0.0); + ck_assert_double_eq(v2.theta, 0.0); + + v1.x = -1.0; + v1.y = 0.0; + v1.z = 0.0; + v2 = v3ToSpherical(v1); + ck_assert_double_eq(v2.r, 1.0); + ck_assert_double_eq(v2.phi, M_PI); + ck_assert_double_eq(v2.theta, 0.0); + + v1.x = 0.0; + v1.y = 1.0; + v1.z = 0.0; + v2 = v3ToSpherical(v1); + ck_assert_double_eq(v2.r, 1.0); + ck_assert_double_eq(v2.phi, 0.0); + ck_assert_double_eq(v2.theta, M_PI_2); + + v1.x = 0.0; + v1.y = -1.0; + v1.z = 0.0; + v2 = v3ToSpherical(v1); + ck_assert_double_eq(v2.r, 1.0); + ck_assert_double_eq(v2.phi, 0.0); + ck_assert_double_eq(v2.theta, -M_PI_2); + + v1.x = 0.0; + v1.y = 0.0; + v1.z = 1.0; + v2 = v3ToSpherical(v1); + ck_assert_double_eq(v2.r, 1.0); + ck_assert_double_eq(v2.phi, 3.0 * M_PI_2); + ck_assert_double_eq(v2.theta, 0.0); + + v1.x = 0.0; + v1.y = 0.0; + v1.z = -1.0; + v2 = v3ToSpherical(v1); + ck_assert_double_eq(v2.r, 1.0); + ck_assert_double_eq(v2.phi, M_PI_2); + ck_assert_double_eq(v2.theta, 0.0); + v1.x = v1.y = v1.z = 0.5; v2 = v3ToSpherical(v1); ck_assert_double_eq(v2.r, sqrt(0.5 * 0.5 + 0.5 * 0.5 + 0.5 * 0.5)); - ck_assert_double_eq(v2.phi, M_PI_4); + ck_assert_double_eq(v2.phi, 7.0 * M_PI_4); ck_assert_double_eq(v2.theta, M_PI_2 - 0.955316618125); } END_TEST