paysages : WIP on several parts.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@515 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2013-02-03 21:18:32 +00:00 committed by ThunderK
parent 324a01dca1
commit 22ed375111
17 changed files with 150 additions and 45 deletions

5
TODO
View file

@ -12,9 +12,7 @@ Technology Preview 2 :
=> Restore water filtering => Restore water filtering
=> Restore cloud lighting => Restore cloud lighting
=> Restore and improve skydome lighting => Restore and improve skydome lighting
- Apply Preetham's model usage - Hide Preetham's model.
=> Convert to HDR rendering.
=> Apply model's aerial perspective.
- Find a proper model for night sky (maybe Shirley). - Find a proper model for night sky (maybe Shirley).
- Improve textures (current model is greatly incorrect). - Improve textures (current model is greatly incorrect).
=> Separate models (basic texture and covering texture). => Separate models (basic texture and covering texture).
@ -29,6 +27,7 @@ Technology Preview 2 :
Technlogy Preview 3 : Technlogy Preview 3 :
- Fully move layer management from BaseForm to BaseFormLayer. - Fully move layer management from BaseForm to BaseFormLayer.
- Start vegetation system. - Start vegetation system.
- Add tone-mapping and exposure control to final image.
- Allow render saving in HDR compatible format. - Allow render saving in HDR compatible format.
- Add clouds to explorer with 3d textures. - Add clouds to explorer with 3d textures.
- Add fresnel effect to specular lighting. - Add fresnel effect to specular lighting.

View file

@ -55,6 +55,8 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, TerrainDefinition* terrain) :
// Viewer layout (3d display + sliders) // Viewer layout (3d display + sliders)
_3dview = new WidgetHeightMap(viewer, _value_modified); _3dview = new WidgetHeightMap(viewer, _value_modified);
viewer_layout->addWidget(_3dview, 0, 0); viewer_layout->addWidget(_3dview, 0, 0);
connect(_3dview, SIGNAL(heightmapChanged()), this, SLOT(heightmapChanged()));
slider = new QSlider(Qt::Horizontal, viewer); slider = new QSlider(Qt::Horizontal, viewer);
slider->setRange(0, 1000); slider->setRange(0, 1000);
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(angleHChanged(int))); 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); viewer_layout->addWidget(slider, 0, 1);
// Panel layout // Panel layout
_info_memory = new QLabel(panel);
panel->layout()->addWidget(_info_memory);
/*button = new QPushButton(tr("Load from picture file"), panel); /*button = new QPushButton(tr("Load from picture file"), panel);
connect(button, SIGNAL(clicked()), this, SLOT(loadFromFile())); connect(button, SIGNAL(clicked()), this, SLOT(loadFromFile()));
panel->layout()->addWidget(button);*/ panel->layout()->addWidget(button);*/
@ -175,6 +180,11 @@ void DialogHeightMap::brushStrengthChanged(int value)
_3dview->setBrushStrength((double)value / 2000.0); _3dview->setBrushStrength((double)value / 2000.0);
} }
void DialogHeightMap::heightmapChanged()
{
_info_memory->setText(tr("Memory used: %1").arg(_3dview->getMemoryStats()));
}
/*void DialogHeightMap::loadFromFile() /*void DialogHeightMap::loadFromFile()
{ {
QString filepath = QFileDialog::getOpenFileName(this, tr("Paysages 3D - Choose a picture to load"), QString(), tr("Images (*.jpg *.jpeg *.bmp *.png)")); QString filepath = QFileDialog::getOpenFileName(this, tr("Paysages 3D - Choose a picture to load"), QString(), tr("Images (*.jpg *.jpeg *.bmp *.png)"));

View file

@ -24,11 +24,13 @@ private slots:
void brushSizeChanged(int value); void brushSizeChanged(int value);
void brushSmoothingChanged(int value); void brushSmoothingChanged(int value);
void brushStrengthChanged(int value); void brushStrengthChanged(int value);
void heightmapChanged();
//void loadFromFile(); //void loadFromFile();
private: private:
TerrainDefinition* _value_original; TerrainDefinition* _value_original;
TerrainDefinition* _value_modified; TerrainDefinition* _value_modified;
QLabel* _info_memory;
WidgetHeightMap* _3dview; WidgetHeightMap* _3dview;
}; };

View file

@ -80,7 +80,7 @@ private:
return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location.x, location.z, precision); 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)); return v3Add(location, v3Scale(VECTOR_UP, 50.0));
} }

View file

@ -76,5 +76,8 @@ void FormTerrain::configChangeEvent()
void FormTerrain::startPainting() void FormTerrain::startPainting()
{ {
DialogHeightMap::editHeightMap(this, _definition); if (DialogHeightMap::editHeightMap(this, _definition))
{
configChangeEvent();
}
} }

View file

@ -17,6 +17,8 @@ WidgetHeightMap::WidgetHeightMap(QWidget *parent, TerrainDefinition* terrain):
setCursor(Qt::CrossCursor); setCursor(Qt::CrossCursor);
startTimer(100); startTimer(100);
_memory_stats = terrainGetMemoryStats(terrain);
_terrain = terrain; _terrain = terrain;
_renderer = rendererCreate(); _renderer = rendererCreate();
TerrainRendererClass.bind(_renderer, _terrain); TerrainRendererClass.bind(_renderer, _terrain);
@ -98,6 +100,36 @@ void WidgetHeightMap::setBrushStrength(double strength)
updateGL(); 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() void WidgetHeightMap::revert()
{ {
_dirty = true; _dirty = true;
@ -121,6 +153,7 @@ void WidgetHeightMap::mousePressEvent(QMouseEvent* event)
void WidgetHeightMap::mouseReleaseEvent(QMouseEvent*) void WidgetHeightMap::mouseReleaseEvent(QMouseEvent*)
{ {
_last_brush_action = 0; _last_brush_action = 0;
terrainEndBrushStroke(_terrain->height_map);
} }
void WidgetHeightMap::mouseMoveEvent(QMouseEvent* event) void WidgetHeightMap::mouseMoveEvent(QMouseEvent* event)
@ -244,6 +277,7 @@ void WidgetHeightMap::paintGL()
if (_dirty) if (_dirty)
{ {
updateVertexInfo(); updateVertexInfo();
emit heightmapChanged();
_dirty = false; _dirty = false;
} }
@ -359,6 +393,8 @@ void WidgetHeightMap::updateVertexInfo()
_vertices = new _VertexInfo[rx * rz]; _vertices = new _VertexInfo[rx * rz];
delete[] old_vertices; delete[] old_vertices;
_memory_stats = terrainGetMemoryStats(_terrain);
// Update positions // Update positions
for (int x = 0; x < rx; x++) for (int x = 0; x < rx; x++)
{ {

View file

@ -33,9 +33,14 @@ public:
void setBrushSmoothing(double smoothing); void setBrushSmoothing(double smoothing);
void setBrushStrength(double smoothing); void setBrushStrength(double smoothing);
QString getMemoryStats();
public slots: public slots:
void revert(); void revert();
signals:
void heightmapChanged();
protected: protected:
void mousePressEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event);
@ -56,6 +61,7 @@ private:
_VertexInfo* _vertices; _VertexInfo* _vertices;
bool _dirty; bool _dirty;
qint64 _memory_stats;
double _average_frame_time; double _average_frame_time;

View file

@ -26,7 +26,7 @@ static const double exposure = 0.4;
static const double ISun = 100.0; static const double ISun = 100.0;
static const double AVERAGE_GROUND_REFLECTANCE = 0.1; static const double AVERAGE_GROUND_REFLECTANCE = 0.1;
#if 1 #if 0
#define RES_MU 128 #define RES_MU 128
#define RES_MU_S 32 #define RES_MU_S 32
#define RES_R 32 #define RES_R 32

View file

@ -144,33 +144,32 @@ static Color _getSkyColor(Renderer* renderer, Vector3 direction)
} }
/* Get sun shape */ /* Get sun shape */
double sun_radius = definition->sun_radius * SUN_RADIUS_SCALED; if (v3Dot(sun_direction, direction) >= 0)
Vector3 hit1, hit2;
int hits = euclidRayIntersectSphere(camera_location, direction, sun_position, sun_radius, &hit1, &hit2);
if (hits > 1)
{ {
double dist = v3Norm(v3Sub(hit2, hit1)) / sun_radius; /* distance between intersection points (relative to radius) */ double sun_radius = definition->sun_radius * SUN_RADIUS_SCALED * 5.0; /* FIXME Why should we multiply by 5 ? */
Vector3 hit1, hit2;
sun_color = definition->sun_color; int hits = euclidRayIntersectSphere(camera_location, direction, sun_position, sun_radius, &hit1, &hit2);
sun_color.r *= 100.0; if (hits > 1)
sun_color.g *= 100.0;
sun_color.b *= 100.0;
if (dist > 0.05)
{ {
return sun_color; double dist = v3Norm(v3Sub(hit2, hit1)) / sun_radius; /* distance between intersection points (relative to radius) */
}
else sun_color = definition->sun_color;
{ sun_color.r *= 100.0;
sun_color.a = 1.0 - dist / 0.05; sun_color.g *= 100.0;
colorMask(&sky_color, &sun_color); sun_color.b *= 100.0;
return sky_color;
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) static Vector3 _getSunDirection(Renderer* renderer)

View file

@ -36,7 +36,7 @@ Color cloudsGetPreviewCoverage(Renderer* renderer, double x, double y, double sc
eye.y = scaling; eye.y = scaling;
eye.z = -10.0 * scaling; eye.z = -10.0 * scaling;
look.x = x * 0.01 / 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.z = 1.0;
look = v3Normalize(look); look = v3Normalize(look);

View file

@ -289,6 +289,8 @@ Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer*
col.a = inside_length / definition->transparencydepth; col.a = inside_length / definition->transparencydepth;
} }
col = renderer->atmosphere->applyAerialPerspective(renderer, start, col);
colorMask(&base, &col); colorMask(&base, &col);
return base; return base;

View file

@ -89,7 +89,7 @@ static Color _applyTextures(Renderer* renderer, Vector3 location, double precisi
return COLOR_TRANSPARENT; 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)); LightStatus* light = lightingCreateStatus(renderer->lighting, location, renderer->getCameraLocation(renderer, location));
renderer->atmosphere->getLightingStatus(renderer, light, normal, 0); renderer->atmosphere->getLightingStatus(renderer, light, normal, 0);
@ -98,6 +98,13 @@ Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 norm
return result; 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* rendererCreate()
{ {
Renderer* result = malloc(sizeof(Renderer)); Renderer* result = malloc(sizeof(Renderer));
@ -128,6 +135,7 @@ Renderer* rendererCreate()
result->applyTextures = _applyTextures; result->applyTextures = _applyTextures;
result->applyLightingToSurface = _applyLightingToSurface; result->applyLightingToSurface = _applyLightingToSurface;
result->applyMediumTraversal = _applyMediumTraversal;
result->lighting = lightingManagerCreate(); result->lighting = lightingManagerCreate();

View file

@ -35,6 +35,7 @@ struct Renderer
/* Shortcuts */ /* Shortcuts */
Color (*applyLightingToSurface)(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material); Color (*applyLightingToSurface)(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material);
Color (*applyMediumTraversal)(Renderer* renderer, Vector3 location, Color color);
/* Scenery related */ /* Scenery related */
RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds); RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds);

View file

@ -121,10 +121,7 @@ static Color _getFinalColor(Renderer* renderer, Vector3 location, double precisi
Color color; Color color;
color = renderer->applyTextures(renderer, location, precision); color = renderer->applyTextures(renderer, location, precision);
color = renderer->applyMediumTraversal(renderer, location, color);
/* TODO Factorize this in scenery renderer */
color = renderer->atmosphere->applyAerialPerspective(renderer, location, color);
color = renderer->clouds->getColor(renderer, color, renderer->getCameraLocation(renderer, location), location);
return color; return color;
} }

View file

@ -74,14 +74,16 @@ void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destinatio
for (i = 0; i < destination->fixed_count; i++) 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; chunk_destination->rect = chunk_source->rect;
if (chunk->rect.xsize * chunk->rect.zsize > 0) 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; destination->floating_used = 0;
@ -219,9 +221,9 @@ static void _prepareBrushStroke(TerrainHeightMap* heightmap, TerrainBrush* brush
heightmap->floating_data.rect.zsize += gz1 + gz2; heightmap->floating_data.rect.zsize += gz1 + gz2;
_resetRect(heightmap, 0, new_width - 1, 0, gz1 - 1); _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, new_width - 1, new_height - gz2, new_height - 1);
_resetRect(heightmap, 0, gx1 - 1, gz1, new_height - gz2); _resetRect(heightmap, 0, gx1 - 1, gz1, new_height - 1 - gz2);
_resetRect(heightmap, new_width - gx2 + 1, new_width - 1, gz1, new_height - gz2); _resetRect(heightmap, new_width - gx2, new_width - 1, gz1, new_height - 1 - gz2);
} }
} }
else 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) void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value)
{ {
_prepareBrushStroke(heightmap, brush); _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 #if 0
static void _loadFromFilePixel(HeightMap* heightmap, int x, int y, Color col) static void _loadFromFilePixel(HeightMap* heightmap, int x, int y, Color col)
{ {

View file

@ -1,6 +1,7 @@
#ifndef _PAYSAGES_TERRAIN_PUBLIC_H_ #ifndef _PAYSAGES_TERRAIN_PUBLIC_H_
#define _PAYSAGES_TERRAIN_PUBLIC_H_ #define _PAYSAGES_TERRAIN_PUBLIC_H_
#include <stdlib.h>
#include "../shared/types.h" #include "../shared/types.h"
#include "../tools/color.h" #include "../tools/color.h"
#include "../tools/euclid.h" #include "../tools/euclid.h"
@ -51,6 +52,7 @@ extern StandardRenderer TerrainRendererClass;
void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset); void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset);
void terrainRenderSurface(Renderer* renderer); void terrainRenderSurface(Renderer* renderer);
double terrainGetGridHeight(TerrainDefinition* definition, int x, int z, int with_painting); double terrainGetGridHeight(TerrainDefinition* definition, int x, int z, int with_painting);
size_t terrainGetMemoryStats(TerrainDefinition* definition);
Renderer* terrainCreatePreviewRenderer(); Renderer* terrainCreatePreviewRenderer();
Color terrainGetPreviewColor(Renderer* renderer, double x, double z, double detail); Color terrainGetPreviewColor(Renderer* renderer, double x, double z, double detail);
@ -64,10 +66,12 @@ typedef struct
double total_radius; double total_radius;
} TerrainBrush; } TerrainBrush;
/* Heightmap manipulation */
void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value); void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value);
void terrainBrushSmooth(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 terrainBrushAddNoise(TerrainHeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value);
void terrainBrushReset(TerrainHeightMap* heightmap, TerrainBrush* brush, double value); void terrainBrushReset(TerrainHeightMap* heightmap, TerrainBrush* brush, double value);
void terrainEndBrushStroke(TerrainHeightMap* heightmap);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -355,8 +355,7 @@ WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer,
_applyFoam(definition, location, normal, detail, &material); _applyFoam(definition, location, normal, detail, &material);
color = renderer->applyLightingToSurface(renderer, location, normal, &material); color = renderer->applyLightingToSurface(renderer, location, normal, &material);
color = renderer->atmosphere->applyAerialPerspective(renderer, location, color); color = renderer->applyMediumTraversal(renderer, location, color);
color = renderer->clouds->getColor(renderer, color, renderer->getCameraLocation(renderer, location), location);
result.base = definition->material.base; result.base = definition->material.base;
result.final = color; result.final = color;