paysages : WIP.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@559 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2013-04-27 21:40:31 +00:00 committed by ThunderK
parent 9a4cf159ee
commit 48ce97e4cb
8 changed files with 224 additions and 59 deletions

View file

@ -6,6 +6,7 @@
#include <math.h>
#include <GL/glu.h>
#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;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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