From 22ed37511127b9f111879b94da6f73af137c05e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 3 Feb 2013 21:18:32 +0000 Subject: [PATCH] paysages : WIP on several parts. git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@515 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- TODO | 5 ++- gui_qt/dialogheightmap.cpp | 10 ++++++ gui_qt/dialogheightmap.h | 2 ++ gui_qt/formrender.cpp | 2 +- gui_qt/formterrain.cpp | 5 ++- gui_qt/widgetheightmap.cpp | 36 +++++++++++++++++++ gui_qt/widgetheightmap.h | 6 ++++ lib_paysages/atmosphere/bruneton.c | 2 +- lib_paysages/atmosphere/main.c | 45 ++++++++++++------------ lib_paysages/clouds/preview.c | 2 +- lib_paysages/clouds/tools.c | 2 ++ lib_paysages/renderer.c | 10 +++++- lib_paysages/renderer.h | 1 + lib_paysages/terrain/main.c | 5 +-- lib_paysages/terrain/painting.c | 55 +++++++++++++++++++++++++----- lib_paysages/terrain/public.h | 4 +++ lib_paysages/water.c | 3 +- 17 files changed, 150 insertions(+), 45 deletions(-) diff --git a/TODO b/TODO index da1b1c1..e5547c4 100644 --- a/TODO +++ b/TODO @@ -12,9 +12,7 @@ Technology Preview 2 : => Restore water filtering => Restore cloud lighting => Restore and improve skydome lighting -- Apply Preetham's model usage - => Convert to HDR rendering. - => Apply model's aerial perspective. +- Hide Preetham's model. - Find a proper model for night sky (maybe Shirley). - Improve textures (current model is greatly incorrect). => Separate models (basic texture and covering texture). @@ -29,6 +27,7 @@ Technology Preview 2 : Technlogy Preview 3 : - Fully move layer management from BaseForm to BaseFormLayer. - Start vegetation system. +- Add tone-mapping and exposure control to final image. - Allow render saving in HDR compatible format. - Add clouds to explorer with 3d textures. - Add fresnel effect to specular lighting. diff --git a/gui_qt/dialogheightmap.cpp b/gui_qt/dialogheightmap.cpp index 33367bc..7cba8e7 100644 --- a/gui_qt/dialogheightmap.cpp +++ b/gui_qt/dialogheightmap.cpp @@ -55,6 +55,8 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, TerrainDefinition* terrain) : // Viewer layout (3d display + sliders) _3dview = new WidgetHeightMap(viewer, _value_modified); viewer_layout->addWidget(_3dview, 0, 0); + connect(_3dview, SIGNAL(heightmapChanged()), this, SLOT(heightmapChanged())); + slider = new QSlider(Qt::Horizontal, viewer); slider->setRange(0, 1000); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(angleHChanged(int))); @@ -65,6 +67,9 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, TerrainDefinition* terrain) : viewer_layout->addWidget(slider, 0, 1); // Panel layout + _info_memory = new QLabel(panel); + panel->layout()->addWidget(_info_memory); + /*button = new QPushButton(tr("Load from picture file"), panel); connect(button, SIGNAL(clicked()), this, SLOT(loadFromFile())); panel->layout()->addWidget(button);*/ @@ -175,6 +180,11 @@ void DialogHeightMap::brushStrengthChanged(int value) _3dview->setBrushStrength((double)value / 2000.0); } +void DialogHeightMap::heightmapChanged() +{ + _info_memory->setText(tr("Memory used: %1").arg(_3dview->getMemoryStats())); +} + /*void DialogHeightMap::loadFromFile() { QString filepath = QFileDialog::getOpenFileName(this, tr("Paysages 3D - Choose a picture to load"), QString(), tr("Images (*.jpg *.jpeg *.bmp *.png)")); diff --git a/gui_qt/dialogheightmap.h b/gui_qt/dialogheightmap.h index 66f1d5a..1d4f030 100644 --- a/gui_qt/dialogheightmap.h +++ b/gui_qt/dialogheightmap.h @@ -24,11 +24,13 @@ private slots: void brushSizeChanged(int value); void brushSmoothingChanged(int value); void brushStrengthChanged(int value); + void heightmapChanged(); //void loadFromFile(); private: TerrainDefinition* _value_original; TerrainDefinition* _value_modified; + QLabel* _info_memory; WidgetHeightMap* _3dview; }; diff --git a/gui_qt/formrender.cpp b/gui_qt/formrender.cpp index fff21bb..aab4235 100644 --- a/gui_qt/formrender.cpp +++ b/gui_qt/formrender.cpp @@ -80,7 +80,7 @@ private: return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location.x, location.z, precision); } - static Vector3 _getCameraLocation(Renderer* renderer, Vector3 location) + static Vector3 _getCameraLocation(Renderer*, Vector3 location) { return v3Add(location, v3Scale(VECTOR_UP, 50.0)); } diff --git a/gui_qt/formterrain.cpp b/gui_qt/formterrain.cpp index 593695c..51b7d19 100644 --- a/gui_qt/formterrain.cpp +++ b/gui_qt/formterrain.cpp @@ -76,5 +76,8 @@ void FormTerrain::configChangeEvent() void FormTerrain::startPainting() { - DialogHeightMap::editHeightMap(this, _definition); + if (DialogHeightMap::editHeightMap(this, _definition)) + { + configChangeEvent(); + } } diff --git a/gui_qt/widgetheightmap.cpp b/gui_qt/widgetheightmap.cpp index f0487ad..b50a53b 100644 --- a/gui_qt/widgetheightmap.cpp +++ b/gui_qt/widgetheightmap.cpp @@ -17,6 +17,8 @@ WidgetHeightMap::WidgetHeightMap(QWidget *parent, TerrainDefinition* terrain): setCursor(Qt::CrossCursor); startTimer(100); + _memory_stats = terrainGetMemoryStats(terrain); + _terrain = terrain; _renderer = rendererCreate(); TerrainRendererClass.bind(_renderer, _terrain); @@ -98,6 +100,36 @@ void WidgetHeightMap::setBrushStrength(double strength) updateGL(); } +QString WidgetHeightMap::getMemoryStats() +{ + qint64 memused = _memory_stats; + if (memused >= 1024) + { + memused /= 1024; + if (memused >= 1024) + { + memused /= 1024; + if (memused >= 1024) + { + memused /= 1024; + return tr("%1 GB").arg(memused); + } + else + { + return tr("%1 MB").arg(memused); + } + } + else + { + return tr("%1 kB").arg(memused); + } + } + else + { + return tr("%1 B").arg(memused); + } +} + void WidgetHeightMap::revert() { _dirty = true; @@ -121,6 +153,7 @@ void WidgetHeightMap::mousePressEvent(QMouseEvent* event) void WidgetHeightMap::mouseReleaseEvent(QMouseEvent*) { _last_brush_action = 0; + terrainEndBrushStroke(_terrain->height_map); } void WidgetHeightMap::mouseMoveEvent(QMouseEvent* event) @@ -244,6 +277,7 @@ void WidgetHeightMap::paintGL() if (_dirty) { updateVertexInfo(); + emit heightmapChanged(); _dirty = false; } @@ -359,6 +393,8 @@ void WidgetHeightMap::updateVertexInfo() _vertices = new _VertexInfo[rx * rz]; delete[] old_vertices; + _memory_stats = terrainGetMemoryStats(_terrain); + // Update positions for (int x = 0; x < rx; x++) { diff --git a/gui_qt/widgetheightmap.h b/gui_qt/widgetheightmap.h index 9fd312e..17a50ed 100644 --- a/gui_qt/widgetheightmap.h +++ b/gui_qt/widgetheightmap.h @@ -33,9 +33,14 @@ public: void setBrushSmoothing(double smoothing); void setBrushStrength(double smoothing); + QString getMemoryStats(); + public slots: void revert(); +signals: + void heightmapChanged(); + protected: void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); @@ -56,6 +61,7 @@ private: _VertexInfo* _vertices; bool _dirty; + qint64 _memory_stats; double _average_frame_time; diff --git a/lib_paysages/atmosphere/bruneton.c b/lib_paysages/atmosphere/bruneton.c index 3b0b5e2..1d614ed 100644 --- a/lib_paysages/atmosphere/bruneton.c +++ b/lib_paysages/atmosphere/bruneton.c @@ -26,7 +26,7 @@ static const double exposure = 0.4; static const double ISun = 100.0; static const double AVERAGE_GROUND_REFLECTANCE = 0.1; -#if 1 +#if 0 #define RES_MU 128 #define RES_MU_S 32 #define RES_R 32 diff --git a/lib_paysages/atmosphere/main.c b/lib_paysages/atmosphere/main.c index 4ae1c2b..bbb3dd6 100644 --- a/lib_paysages/atmosphere/main.c +++ b/lib_paysages/atmosphere/main.c @@ -144,33 +144,32 @@ static Color _getSkyColor(Renderer* renderer, Vector3 direction) } /* Get sun shape */ - double sun_radius = definition->sun_radius * SUN_RADIUS_SCALED; - Vector3 hit1, hit2; - int hits = euclidRayIntersectSphere(camera_location, direction, sun_position, sun_radius, &hit1, &hit2); - if (hits > 1) + if (v3Dot(sun_direction, direction) >= 0) { - double dist = v3Norm(v3Sub(hit2, hit1)) / sun_radius; /* distance between intersection points (relative to radius) */ - - sun_color = definition->sun_color; - sun_color.r *= 100.0; - sun_color.g *= 100.0; - sun_color.b *= 100.0; - - if (dist > 0.05) + double sun_radius = definition->sun_radius * SUN_RADIUS_SCALED * 5.0; /* FIXME Why should we multiply by 5 ? */ + Vector3 hit1, hit2; + int hits = euclidRayIntersectSphere(camera_location, direction, sun_position, sun_radius, &hit1, &hit2); + if (hits > 1) { - return sun_color; - } - else - { - sun_color.a = 1.0 - dist / 0.05; - colorMask(&sky_color, &sun_color); - return sky_color; + double dist = v3Norm(v3Sub(hit2, hit1)) / sun_radius; /* distance between intersection points (relative to radius) */ + + sun_color = definition->sun_color; + sun_color.r *= 100.0; + sun_color.g *= 100.0; + sun_color.b *= 100.0; + + if (dist > 0.05) + { + return sun_color; + } + else + { + sun_color.a = 1.0 - dist / 0.05; + colorMask(&sky_color, &sun_color); + } } } - else - { - return sky_color; - } + return sky_color; } static Vector3 _getSunDirection(Renderer* renderer) diff --git a/lib_paysages/clouds/preview.c b/lib_paysages/clouds/preview.c index 6d5381a..df39f87 100644 --- a/lib_paysages/clouds/preview.c +++ b/lib_paysages/clouds/preview.c @@ -36,7 +36,7 @@ Color cloudsGetPreviewCoverage(Renderer* renderer, double x, double y, double sc eye.y = scaling; eye.z = -10.0 * scaling; look.x = x * 0.01 / scaling; - look.y = -y * 0.01 / scaling - 0.3; + look.y = -(y * 0.01 - 0.3) / scaling; look.z = 1.0; look = v3Normalize(look); diff --git a/lib_paysages/clouds/tools.c b/lib_paysages/clouds/tools.c index 4e65514..5eadc6b 100644 --- a/lib_paysages/clouds/tools.c +++ b/lib_paysages/clouds/tools.c @@ -289,6 +289,8 @@ Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* col.a = inside_length / definition->transparencydepth; } + col = renderer->atmosphere->applyAerialPerspective(renderer, start, col); + colorMask(&base, &col); return base; diff --git a/lib_paysages/renderer.c b/lib_paysages/renderer.c index 4ee006c..c3ea4d2 100644 --- a/lib_paysages/renderer.c +++ b/lib_paysages/renderer.c @@ -89,7 +89,7 @@ static Color _applyTextures(Renderer* renderer, Vector3 location, double precisi return COLOR_TRANSPARENT; } -Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material) +static Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material) { LightStatus* light = lightingCreateStatus(renderer->lighting, location, renderer->getCameraLocation(renderer, location)); renderer->atmosphere->getLightingStatus(renderer, light, normal, 0); @@ -98,6 +98,13 @@ Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 norm return result; } +static Color _applyMediumTraversal(Renderer* renderer, Vector3 location, Color color) +{ + color = renderer->atmosphere->applyAerialPerspective(renderer, location, color); + color = renderer->clouds->getColor(renderer, color, renderer->getCameraLocation(renderer, location), location); + return color; +} + Renderer* rendererCreate() { Renderer* result = malloc(sizeof(Renderer)); @@ -128,6 +135,7 @@ Renderer* rendererCreate() result->applyTextures = _applyTextures; result->applyLightingToSurface = _applyLightingToSurface; + result->applyMediumTraversal = _applyMediumTraversal; result->lighting = lightingManagerCreate(); diff --git a/lib_paysages/renderer.h b/lib_paysages/renderer.h index edbd834..b523b57 100644 --- a/lib_paysages/renderer.h +++ b/lib_paysages/renderer.h @@ -35,6 +35,7 @@ struct Renderer /* Shortcuts */ Color (*applyLightingToSurface)(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material); + Color (*applyMediumTraversal)(Renderer* renderer, Vector3 location, Color color); /* Scenery related */ RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds); diff --git a/lib_paysages/terrain/main.c b/lib_paysages/terrain/main.c index 15c7547..a859bce 100644 --- a/lib_paysages/terrain/main.c +++ b/lib_paysages/terrain/main.c @@ -121,10 +121,7 @@ static Color _getFinalColor(Renderer* renderer, Vector3 location, double precisi Color color; color = renderer->applyTextures(renderer, location, precision); - - /* TODO Factorize this in scenery renderer */ - color = renderer->atmosphere->applyAerialPerspective(renderer, location, color); - color = renderer->clouds->getColor(renderer, color, renderer->getCameraLocation(renderer, location), location); + color = renderer->applyMediumTraversal(renderer, location, color); return color; } diff --git a/lib_paysages/terrain/painting.c b/lib_paysages/terrain/painting.c index 41df548..ed31f71 100644 --- a/lib_paysages/terrain/painting.c +++ b/lib_paysages/terrain/painting.c @@ -74,14 +74,16 @@ void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destinatio for (i = 0; i < destination->fixed_count; i++) { - TerrainHeightMapChunk* chunk = destination->fixed_data + i; + TerrainHeightMapChunk* chunk_source = source->fixed_data + i; + TerrainHeightMapChunk* chunk_destination = destination->fixed_data + i; + size_t mapsize = sizeof(double) * chunk_source->rect.xsize * chunk_source->rect.zsize; - chunk->rect = chunk->rect; - if (chunk->rect.xsize * chunk->rect.zsize > 0) + chunk_destination->rect = chunk_source->rect; + if (chunk_source->rect.xsize * chunk_source->rect.zsize > 0) { - chunk->data = realloc(chunk->data, sizeof(double) * chunk->rect.xsize * chunk->rect.zsize); + chunk_destination->data = realloc(chunk_destination->data, mapsize); + memcpy(chunk_destination->data, chunk_source->data, mapsize); } - memcpy(chunk->data, chunk->data, sizeof(double) * chunk->rect.xsize * chunk->rect.zsize); } destination->floating_used = 0; @@ -219,9 +221,9 @@ static void _prepareBrushStroke(TerrainHeightMap* heightmap, TerrainBrush* brush heightmap->floating_data.rect.zsize += gz1 + gz2; _resetRect(heightmap, 0, new_width - 1, 0, gz1 - 1); - _resetRect(heightmap, 0, new_width - 1, new_height - gz2 + 1, new_height - 1); - _resetRect(heightmap, 0, gx1 - 1, gz1, new_height - gz2); - _resetRect(heightmap, new_width - gx2 + 1, new_width - 1, gz1, new_height - gz2); + _resetRect(heightmap, 0, new_width - 1, new_height - gz2, new_height - 1); + _resetRect(heightmap, 0, gx1 - 1, gz1, new_height - 1 - gz2); + _resetRect(heightmap, new_width - gx2, new_width - 1, gz1, new_height - 1 - gz2); } } else @@ -244,6 +246,24 @@ static void _prepareBrushStroke(TerrainHeightMap* heightmap, TerrainBrush* brush } } +size_t terrainGetMemoryStats(TerrainDefinition* definition) +{ + TerrainHeightMap* heightmap = definition->height_map; + size_t result = 0; + int i; + + if (heightmap->floating_used) + { + result += sizeof(double) * heightmap->floating_data.rect.xsize * heightmap->floating_data.rect.zsize; + } + for (i = 0; i < heightmap->fixed_count; i++) + { + result += sizeof(double) * heightmap->fixed_data[i].rect.xsize * heightmap->fixed_data[i].rect.zsize; + } + + return result; +} + void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value) { _prepareBrushStroke(heightmap, brush); @@ -263,6 +283,25 @@ void terrainBrushReset(TerrainHeightMap* heightmap, TerrainBrush* brush, double { } +void terrainEndBrushStroke(TerrainHeightMap* heightmap) +{ + /* Commit floating data to fixed */ + if (heightmap->floating_used) + { + /* TODO Find overlapping data and merge with them */ + + size_t mapsize = sizeof(double) * heightmap->floating_data.rect.xsize * heightmap->floating_data.rect.zsize; + heightmap->fixed_data = realloc(heightmap->fixed_data, sizeof(TerrainHeightMapChunk) * (heightmap->fixed_count + 1)); + heightmap->fixed_data[heightmap->fixed_count].rect = heightmap->floating_data.rect; + heightmap->fixed_data[heightmap->fixed_count].data = malloc(mapsize); + memcpy(heightmap->fixed_data[heightmap->fixed_count].data, heightmap->floating_data.data, mapsize); + + heightmap->fixed_count++; + heightmap->floating_used = 0; + heightmap->floating_data.data = realloc(heightmap->floating_data.data, sizeof(double)); + } +} + #if 0 static void _loadFromFilePixel(HeightMap* heightmap, int x, int y, Color col) { diff --git a/lib_paysages/terrain/public.h b/lib_paysages/terrain/public.h index 9b36ad4..6ca3158 100644 --- a/lib_paysages/terrain/public.h +++ b/lib_paysages/terrain/public.h @@ -1,6 +1,7 @@ #ifndef _PAYSAGES_TERRAIN_PUBLIC_H_ #define _PAYSAGES_TERRAIN_PUBLIC_H_ +#include #include "../shared/types.h" #include "../tools/color.h" #include "../tools/euclid.h" @@ -51,6 +52,7 @@ extern StandardRenderer TerrainRendererClass; void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset); void terrainRenderSurface(Renderer* renderer); double terrainGetGridHeight(TerrainDefinition* definition, int x, int z, int with_painting); +size_t terrainGetMemoryStats(TerrainDefinition* definition); Renderer* terrainCreatePreviewRenderer(); Color terrainGetPreviewColor(Renderer* renderer, double x, double z, double detail); @@ -64,10 +66,12 @@ typedef struct double total_radius; } TerrainBrush; +/* Heightmap manipulation */ void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value); void terrainBrushSmooth(TerrainHeightMap* heightmap, TerrainBrush* brush, double value); void terrainBrushAddNoise(TerrainHeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value); void terrainBrushReset(TerrainHeightMap* heightmap, TerrainBrush* brush, double value); +void terrainEndBrushStroke(TerrainHeightMap* heightmap); #ifdef __cplusplus } diff --git a/lib_paysages/water.c b/lib_paysages/water.c index 4401722..788ae54 100644 --- a/lib_paysages/water.c +++ b/lib_paysages/water.c @@ -355,8 +355,7 @@ WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, _applyFoam(definition, location, normal, detail, &material); color = renderer->applyLightingToSurface(renderer, location, normal, &material); - color = renderer->atmosphere->applyAerialPerspective(renderer, location, color); - color = renderer->clouds->getColor(renderer, color, renderer->getCameraLocation(renderer, location), location); + color = renderer->applyMediumTraversal(renderer, location, color); result.base = definition->material.base; result.final = color;