paysages : Big terrain refactoring for future sculpt mode (WIP).
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@475 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
de719c62dd
commit
5f22647b1c
44 changed files with 884 additions and 1389 deletions
|
@ -8,7 +8,6 @@
|
|||
#include "inputnoise.h"
|
||||
#include "inputcurve.h"
|
||||
#include "inputmaterial.h"
|
||||
#include "inputheightmap.h"
|
||||
#include "inputenum.h"
|
||||
#include "inputlayers.h"
|
||||
|
||||
|
@ -445,11 +444,6 @@ BaseInput* BaseForm::addInputMaterial(QString label, SurfaceMaterial* material)
|
|||
return addInput(new InputMaterial(_form, label, material));
|
||||
}
|
||||
|
||||
BaseInput* BaseForm::addInputHeightMap(QString label, HeightMap* heightmap, TerrainCanvas* canvas)
|
||||
{
|
||||
return addInput(new InputHeightMap(_form, label, heightmap, canvas));
|
||||
}
|
||||
|
||||
BaseInput* BaseForm::addInputEnum(QString label, int* value, const QStringList& values)
|
||||
{
|
||||
return addInput(new InputEnum(_form, label, value, values));
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "../lib_paysages/layers.h"
|
||||
#include "../lib_paysages/heightmap.h"
|
||||
#include "../lib_paysages/pack.h"
|
||||
#include "../lib_paysages/terraincanvas.h"
|
||||
|
||||
class BaseForm:public QWidget
|
||||
{
|
||||
|
@ -61,7 +60,6 @@ protected:
|
|||
BaseInput* addInputNoise(QString label, NoiseGenerator* value);
|
||||
BaseInput* addInputCurve(QString label, Curve* value, double xmin, double xmax, double ymin, double ymax, QString xlabel, QString ylabel);
|
||||
BaseInput* addInputMaterial(QString label, SurfaceMaterial* material);
|
||||
BaseInput* addInputHeightMap(QString label, HeightMap* heightmap, TerrainCanvas* canvas);
|
||||
BaseInput* addInputEnum(QString label, int* value, const QStringList& values);
|
||||
BaseInput* addInputLayers(QString label, Layers* value, FormLayerBuilder form_builder);
|
||||
|
||||
|
|
|
@ -9,12 +9,11 @@
|
|||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
#include <math.h>
|
||||
#include "../lib_paysages/terrain.h"
|
||||
#include "../lib_paysages/scenery.h"
|
||||
#include "widgetheightmap.h"
|
||||
|
||||
/**************** Dialog form ****************/
|
||||
DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap, TerrainCanvas* canvas) : DialogWithPreview(parent)
|
||||
DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap, void* canvas) : DialogWithPreview(parent)
|
||||
{
|
||||
QWidget* mainarea;
|
||||
QWidget* buttons;
|
||||
|
@ -27,7 +26,6 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap, TerrainC
|
|||
QPushButton* button;
|
||||
QComboBox* combobox;
|
||||
|
||||
_canvas = canvas;
|
||||
_value_original = heightmap;
|
||||
_value_modified = heightmapCreate();
|
||||
heightmapCopy(_value_original, &_value_modified);
|
||||
|
@ -138,7 +136,7 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap, TerrainC
|
|||
setWindowTitle(tr("Paysages 3D - Height map painting"));
|
||||
}
|
||||
|
||||
bool DialogHeightMap::editHeightMap(QWidget* parent, HeightMap* heightmap, TerrainCanvas* canvas)
|
||||
bool DialogHeightMap::editHeightMap(QWidget* parent, HeightMap* heightmap, void* canvas)
|
||||
{
|
||||
int result;
|
||||
|
||||
|
@ -206,7 +204,7 @@ void DialogHeightMap::loadFromFile()
|
|||
|
||||
void DialogHeightMap::resetToTerrain()
|
||||
{
|
||||
if (_canvas)
|
||||
/*if (_canvas)
|
||||
{
|
||||
TerrainDefinition terrain;
|
||||
|
||||
|
@ -218,7 +216,7 @@ void DialogHeightMap::resetToTerrain()
|
|||
terrainDeleteDefinition(&terrain);
|
||||
|
||||
_3dview->revert();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void DialogHeightMap::changeResolution()
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
#include "tools.h"
|
||||
#include "widgetheightmap.h"
|
||||
#include "../lib_paysages/heightmap.h"
|
||||
#include "../lib_paysages/terraincanvas.h"
|
||||
|
||||
class DialogHeightMap : public DialogWithPreview
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DialogHeightMap(QWidget* parent, HeightMap* heightmap, TerrainCanvas* canvas);
|
||||
static bool editHeightMap(QWidget* parent, HeightMap* heightmap, TerrainCanvas* canvas);
|
||||
explicit DialogHeightMap(QWidget* parent, HeightMap* heightmap, void* canvas);
|
||||
static bool editHeightMap(QWidget* parent, HeightMap* heightmap, void* canvas);
|
||||
|
||||
public slots:
|
||||
virtual void accept();
|
||||
|
@ -35,7 +34,6 @@ private:
|
|||
HeightMap _value_modified;
|
||||
WidgetHeightMap* _3dview;
|
||||
QLabel* _resolution_label;
|
||||
TerrainCanvas* _canvas;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -49,7 +49,7 @@ bool ExplorerChunkTerrain::onMaintainEvent()
|
|||
{
|
||||
if (_tessellation_current_size == 0 || i % old_tessellation_inc != 0 || j % old_tessellation_inc != 0)
|
||||
{
|
||||
double height = renderer->getTerrainHeight(renderer, _startx + _tessellation_step * (double)i, _startz + _tessellation_step * (double)j);
|
||||
double height = renderer->terrain->getHeight(renderer, _startx + _tessellation_step * (double)i, _startz + _tessellation_step * (double)j);
|
||||
_tessellation[j * (_tessellation_max_size + 1) + i] = height;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,18 +16,17 @@ public:
|
|||
{
|
||||
_renderer = rendererCreate();
|
||||
_renderer.applyTextures = _applyTextures;
|
||||
_renderer.getTerrainHeight = _getTerrainHeight;
|
||||
_renderer.alterLight = _alterLight;
|
||||
_renderer.getLightStatus = _getLightStatus;
|
||||
_renderer.camera_location.x = 0.0;
|
||||
_renderer.camera_location.y = 50.0;
|
||||
_renderer.camera_location.z = 0.0;
|
||||
|
||||
_terrain = terrainCreateDefinition();
|
||||
_textures = texturesCreateDefinition();
|
||||
_lighting = lightingCreateDefinition();
|
||||
_water = waterCreateDefinition();
|
||||
|
||||
_atmosphere = (AtmosphereDefinition*)AtmosphereDefinitionClass.create();
|
||||
_terrain = (TerrainDefinition*)TerrainDefinitionClass.create();
|
||||
|
||||
_renderer.customData[0] = &_terrain;
|
||||
_renderer.customData[1] = &_textures;
|
||||
|
@ -44,7 +43,7 @@ protected:
|
|||
{
|
||||
Vector3 down = {0.0, -1.0, 0.0};
|
||||
Vector3 location;
|
||||
double height = terrainGetHeight(&_terrain, x, y);
|
||||
double height = _renderer.terrain->getHeight(&_renderer, x, y);
|
||||
|
||||
if (height < _water.height)
|
||||
{
|
||||
|
@ -55,12 +54,14 @@ protected:
|
|||
}
|
||||
else
|
||||
{
|
||||
return colorToQColor(terrainGetColor(&_terrain, &_renderer, x, y, scaling));
|
||||
location.x = x;
|
||||
location.y = height;
|
||||
location.z = y;
|
||||
return colorToQColor(_renderer.terrain->getFinalColor(&_renderer, location, scaling));
|
||||
}
|
||||
}
|
||||
void updateData()
|
||||
{
|
||||
sceneryGetTerrain(&_terrain);
|
||||
sceneryGetLighting(&_lighting);
|
||||
sceneryGetTextures(&_textures);
|
||||
sceneryGetWater(&_water);
|
||||
|
@ -68,30 +69,23 @@ protected:
|
|||
sceneryGetAtmosphere(_atmosphere);
|
||||
AtmosphereRendererClass.bind(_renderer.atmosphere, _atmosphere);
|
||||
_renderer.atmosphere->applyAerialPerspective = _applyAerialPerspective;
|
||||
|
||||
sceneryGetTerrain(_terrain);
|
||||
TerrainRendererClass.bind(_renderer.terrain, _terrain);
|
||||
}
|
||||
private:
|
||||
Renderer _renderer;
|
||||
TerrainDefinition _terrain;
|
||||
TerrainDefinition* _terrain;
|
||||
WaterDefinition _water;
|
||||
TexturesDefinition _textures;
|
||||
LightingDefinition _lighting;
|
||||
AtmosphereDefinition* _atmosphere;
|
||||
|
||||
static double _getTerrainHeight(Renderer* renderer, double x, double z)
|
||||
{
|
||||
return terrainGetHeight((TerrainDefinition*)(renderer->customData[0]), x, z);
|
||||
}
|
||||
|
||||
static Color _applyTextures(Renderer* renderer, Vector3 location, double precision)
|
||||
{
|
||||
return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location.x, location.z, precision);
|
||||
}
|
||||
|
||||
static void _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||
{
|
||||
light->color = terrainLightFilter((TerrainDefinition*)(renderer->customData[0]), renderer, light->color, location, v3Scale(light->direction, -1000.0), v3Scale(light->direction, -1.0));
|
||||
}
|
||||
|
||||
static void _getLightStatus(Renderer* renderer, LightStatus* status, Vector3 location)
|
||||
{
|
||||
lightingGetStatus((LightingDefinition*)renderer->customData[2], renderer, location, status);
|
||||
|
|
|
@ -3,14 +3,12 @@
|
|||
#include <math.h>
|
||||
#include <QColor>
|
||||
#include <QSlider>
|
||||
#include "formterraincanvas.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "../lib_paysages/terrain.h"
|
||||
#include "../lib_paysages/scenery.h"
|
||||
#include "../lib_paysages/euclid.h"
|
||||
|
||||
static TerrainDefinition _definition;
|
||||
static TerrainDefinition* _definition;
|
||||
|
||||
/**************** Previews ****************/
|
||||
class PreviewTerrainHeight:public BasePreview
|
||||
|
@ -18,7 +16,7 @@ class PreviewTerrainHeight:public BasePreview
|
|||
public:
|
||||
PreviewTerrainHeight(QWidget* parent):BasePreview(parent)
|
||||
{
|
||||
_preview_definition = terrainCreateDefinition();
|
||||
_renderer = rendererCreate();
|
||||
|
||||
addOsd(QString("geolocation"));
|
||||
|
||||
|
@ -28,17 +26,18 @@ public:
|
|||
protected:
|
||||
QColor getColor(double x, double y)
|
||||
{
|
||||
double height;
|
||||
double height = 0.0;
|
||||
|
||||
height = terrainGetHeightNormalized(&_preview_definition, x, y);
|
||||
// TODO
|
||||
//height = terrainGetHeightNormalized(&_preview_definition, x, y);
|
||||
return QColor((int)(255.0 * height), (int)(255.0 * height), (int)(255.0 * height));
|
||||
}
|
||||
void updateData()
|
||||
{
|
||||
terrainCopyDefinition(&_definition, &_preview_definition);
|
||||
TerrainRendererClass.bind(_renderer.terrain, _definition);
|
||||
}
|
||||
private:
|
||||
TerrainDefinition _preview_definition;
|
||||
Renderer _renderer;
|
||||
};
|
||||
|
||||
class PreviewTerrainColor:public BasePreview
|
||||
|
@ -52,8 +51,6 @@ public:
|
|||
_renderer = rendererCreate();
|
||||
_renderer.render_quality = 3;
|
||||
_renderer.applyTextures = _applyTextures;
|
||||
_renderer.getTerrainHeight = _getTerrainHeight;
|
||||
_renderer.alterLight = _alterLight;
|
||||
_renderer.getLightStatus = _getLightStatus;
|
||||
_renderer.camera_location.x = 0.0;
|
||||
_renderer.camera_location.y = 50.0;
|
||||
|
@ -83,7 +80,6 @@ public:
|
|||
lightingAddLight(&_lighting, light);
|
||||
lightingValidateDefinition(&_lighting);
|
||||
|
||||
_terrain = terrainCreateDefinition();
|
||||
_textures = texturesCreateDefinition();
|
||||
texture = (TextureLayerDefinition*)layersGetLayer(_textures.layers, layersAddLayer(_textures.layers, NULL));
|
||||
texture->material.base = COLOR_WHITE;
|
||||
|
@ -92,7 +88,6 @@ public:
|
|||
texture->bump_height = 0.0;
|
||||
texturesLayerValidateDefinition(texture);
|
||||
|
||||
_renderer.customData[0] = &_terrain;
|
||||
_renderer.customData[1] = &_textures;
|
||||
_renderer.customData[2] = &_lighting;
|
||||
|
||||
|
@ -104,34 +99,29 @@ public:
|
|||
protected:
|
||||
QColor getColor(double x, double y)
|
||||
{
|
||||
return colorToQColor(terrainGetColor(&_terrain, &_renderer, x, y, scaling));
|
||||
Vector3 point;
|
||||
|
||||
point.x = x;
|
||||
point.y = _renderer.terrain->getHeight(&_renderer, x, y);
|
||||
point.z = y;
|
||||
|
||||
return colorToQColor(_renderer.terrain->getFinalColor(&_renderer, point, scaling));
|
||||
}
|
||||
void updateData()
|
||||
{
|
||||
terrainCopyDefinition(&_definition, &_terrain);
|
||||
TerrainRendererClass.bind(_renderer.terrain, _definition);
|
||||
//sceneryGetTextures(&_textures);
|
||||
}
|
||||
private:
|
||||
Renderer _renderer;
|
||||
TerrainDefinition _terrain;
|
||||
TexturesDefinition _textures;
|
||||
LightingDefinition _lighting;
|
||||
|
||||
static double _getTerrainHeight(Renderer* renderer, double x, double z)
|
||||
{
|
||||
return terrainGetHeight((TerrainDefinition*)(renderer->customData[0]), x, z);
|
||||
}
|
||||
|
||||
static Color _applyTextures(Renderer* renderer, Vector3 location, double precision)
|
||||
{
|
||||
return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location.x, location.z, precision);
|
||||
}
|
||||
|
||||
static void _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||
{
|
||||
light->color = terrainLightFilter((TerrainDefinition*)(renderer->customData[0]), renderer, light->color, location, v3Scale(light->direction, -1000.0), v3Scale(light->direction, -1.0));
|
||||
}
|
||||
|
||||
static void _getLightStatus(Renderer* renderer, LightStatus* status, Vector3 location)
|
||||
{
|
||||
lightingGetStatus((LightingDefinition*)renderer->customData[2], renderer, location, status);
|
||||
|
@ -140,44 +130,38 @@ private:
|
|||
};
|
||||
|
||||
/**************** Form ****************/
|
||||
static BaseFormLayer* _formBuilderCanvas(DialogLayers* parent, Layers* layers)
|
||||
{
|
||||
return new FormTerrainCanvas(parent, layers);
|
||||
}
|
||||
|
||||
FormTerrain::FormTerrain(QWidget *parent):
|
||||
BaseForm(parent)
|
||||
{
|
||||
_definition = terrainCreateDefinition();
|
||||
_definition = (TerrainDefinition*)TerrainDefinitionClass.create();
|
||||
|
||||
previewHeight = new PreviewTerrainHeight(this);
|
||||
previewColor = new PreviewTerrainColor(this);
|
||||
addPreview(previewHeight, tr("Height preview (normalized)"));
|
||||
addPreview(previewColor, tr("Lighted preview (no texture)"));
|
||||
|
||||
addInputNoise(tr("Noise"), _definition.height_noise);
|
||||
addInputDouble(tr("Height"), &_definition.height_factor, 0.0, 20.0, 0.1, 1.0);
|
||||
addInputDouble(tr("Scaling"), &_definition.scaling, 20.0, 200.0, 1.0, 10.0);
|
||||
addInputDouble(tr("Shadow smoothing"), &_definition.shadow_smoothing, 0.0, 0.3, 0.003, 0.03);
|
||||
addInputLayers(tr("Canvases"), _definition.canvases, _formBuilderCanvas);
|
||||
//addInputNoise(tr("Noise"), _definition.height_noise);
|
||||
addInputDouble(tr("Height"), &_definition->height, 0.0, 20.0, 0.1, 1.0);
|
||||
addInputDouble(tr("Scaling"), &_definition->scaling, 20.0, 200.0, 1.0, 10.0);
|
||||
addInputDouble(tr("Shadow smoothing"), &_definition->shadow_smoothing, 0.0, 0.3, 0.003, 0.03);
|
||||
|
||||
revertConfig();
|
||||
}
|
||||
|
||||
void FormTerrain::revertConfig()
|
||||
{
|
||||
sceneryGetTerrain(&_definition);
|
||||
sceneryGetTerrain(_definition);
|
||||
BaseForm::revertConfig();
|
||||
}
|
||||
|
||||
void FormTerrain::applyConfig()
|
||||
{
|
||||
scenerySetTerrain(&_definition);
|
||||
scenerySetTerrain(_definition);
|
||||
BaseForm::applyConfig();
|
||||
}
|
||||
|
||||
void FormTerrain::configChangeEvent()
|
||||
{
|
||||
terrainValidateDefinition(&_definition);
|
||||
TerrainDefinitionClass.validate(_definition);
|
||||
BaseForm::configChangeEvent();
|
||||
}
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
#include "formterraincanvas.h"
|
||||
|
||||
/**************** Form ****************/
|
||||
class PreviewTerrainCanvasHeight:public BasePreview
|
||||
{
|
||||
public:
|
||||
PreviewTerrainCanvasHeight(QWidget* parent, TerrainCanvas* canvas):BasePreview(parent)
|
||||
{
|
||||
_base_canvas = canvas;
|
||||
_preview_canvas = terrainCanvasCreate();
|
||||
|
||||
//addOsd(QString("geolocation"));
|
||||
|
||||
configScaling(1.0, 1.0, 1.0, 1.0);
|
||||
//configScrolling(-1000.0, 1000.0, 0.0, -1000.0, 1000.0, 0.0);
|
||||
}
|
||||
|
||||
~PreviewTerrainCanvasHeight()
|
||||
{
|
||||
terrainCanvasDelete(_preview_canvas);
|
||||
}
|
||||
protected:
|
||||
QColor getColor(double x, double y)
|
||||
{
|
||||
Color col, mask;
|
||||
double height;
|
||||
|
||||
if (_max - _min < 0.000001)
|
||||
{
|
||||
return Qt::black;
|
||||
}
|
||||
else
|
||||
{
|
||||
height = heightmapGetValue(&_preview_canvas->height_map, x + 0.5, y + 0.5);
|
||||
col.r = col.g = col.b = (height - _min) / (_max - _min);
|
||||
col.a = 1.0;
|
||||
|
||||
mask.r = 0.3;
|
||||
mask.g = 0.0;
|
||||
mask.b = 0.0;
|
||||
mask.a = 1.0 - terrainCanvasGetMaskValue(_preview_canvas, x + 0.5, y + 0.5);
|
||||
colorMask(&col, &mask);
|
||||
|
||||
return colorToQColor(col);
|
||||
}
|
||||
}
|
||||
void updateData()
|
||||
{
|
||||
terrainCanvasCopy(_base_canvas, _preview_canvas);
|
||||
heightmapGetLimits(&_preview_canvas->height_map, &_min, &_max);
|
||||
}
|
||||
private:
|
||||
TerrainCanvas* _base_canvas;
|
||||
TerrainCanvas* _preview_canvas;
|
||||
double _max, _min;
|
||||
};
|
||||
|
||||
/**************** Form ****************/
|
||||
FormTerrainCanvas::FormTerrainCanvas(QWidget *parent, Layers* layers):
|
||||
BaseFormLayer(parent, layers)
|
||||
{
|
||||
_definition = terrainCanvasCreate();
|
||||
|
||||
// TODO Area
|
||||
//addInputDouble(tr("Apply at height"), &_definition->offset_y, -20.0, 20.0, 0.1, 1.0);
|
||||
addInputHeightMap(tr("Height map"), &_definition->height_map, _definition);
|
||||
//addInputDouble(tr("Canvas height"), &_definition->height_factor, 0.0, 20.0, 0.1, 1.0);
|
||||
addInputNoise(tr("Detail noise"), _definition->detail_noise);
|
||||
addInputDouble(tr("Detail noise height"), &_definition->detail_height_factor, 0.0, 20.0, 0.1, 1.0);
|
||||
addInputDouble(tr("Detail noise scaling"), &_definition->detail_scaling, 0.0, 20.0, 0.1, 1.0);
|
||||
addInputEnum(tr("Mask shape"), &_definition->mask.mode, QStringList(tr("Square")) << tr("Circle"));
|
||||
addInputDouble(tr("Mask smoothing"), &_definition->mask.smoothing, 0.0, 1.0, 0.01, 0.1);
|
||||
|
||||
_previewHeight = new PreviewTerrainCanvasHeight(this, _definition);
|
||||
addPreview(_previewHeight, tr("Height preview (normalized)"));
|
||||
|
||||
revertConfig();
|
||||
}
|
||||
|
||||
FormTerrainCanvas::~FormTerrainCanvas()
|
||||
{
|
||||
terrainCanvasDelete(_definition);
|
||||
}
|
||||
|
||||
void FormTerrainCanvas::layerReadCurrentFrom(void* layer_definition)
|
||||
{
|
||||
terrainCanvasCopy((TerrainCanvas*)layer_definition, _definition);
|
||||
}
|
||||
|
||||
void FormTerrainCanvas::layerWriteCurrentTo(void* layer_definition)
|
||||
{
|
||||
terrainCanvasCopy(_definition, (TerrainCanvas*)layer_definition);
|
||||
}
|
||||
|
||||
void FormTerrainCanvas::afterLayerAdded(void* layer_definition)
|
||||
{
|
||||
terrainCanvasRevertToTerrain((TerrainCanvas*)layer_definition);
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef _PAYSAGES_QT_FORMTERRAINCANVAS_H_
|
||||
#define _PAYSAGES_QT_FORMTERRAINCANVAS_H_
|
||||
|
||||
#include <QWidget>
|
||||
#include "basepreview.h"
|
||||
#include "baseformlayer.h"
|
||||
#include "../lib_paysages/terraincanvas.h"
|
||||
|
||||
class FormTerrainCanvas : public BaseFormLayer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FormTerrainCanvas(QWidget* parent, Layers* layers);
|
||||
~FormTerrainCanvas();
|
||||
|
||||
protected:
|
||||
virtual void layerReadCurrentFrom(void* layer_definition);
|
||||
virtual void layerWriteCurrentTo(void* layer_definition);
|
||||
virtual void afterLayerAdded(void* layer_definition);
|
||||
|
||||
private:
|
||||
TerrainCanvas* _definition;
|
||||
BasePreview* _previewHeight;
|
||||
BasePreview* _previewColor;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -17,12 +17,10 @@ class PreviewTexturesCoverage:public BasePreview
|
|||
public:
|
||||
PreviewTexturesCoverage(QWidget* parent, TextureLayerDefinition* layer):BasePreview(parent)
|
||||
{
|
||||
_terrain = terrainCreateDefinition();
|
||||
_terrain = (TerrainDefinition*)TerrainDefinitionClass.create();
|
||||
|
||||
_renderer = rendererCreate();
|
||||
_renderer.render_quality = 3;
|
||||
_renderer.getTerrainHeight = _getTerrainHeight;
|
||||
_renderer.customData[0] = &_terrain;
|
||||
|
||||
_original_layer = layer;
|
||||
_preview_layer = texturesLayerCreateDefinition();
|
||||
|
@ -42,27 +40,24 @@ protected:
|
|||
Vector3 location;
|
||||
double coverage;
|
||||
location.x = x;
|
||||
location.y = terrainGetHeight(&_terrain, x, y);
|
||||
location.y = _renderer.terrain->getHeight(&_renderer, x, y);
|
||||
location.z = y;
|
||||
coverage = texturesGetLayerCoverage(_preview_layer, &_renderer, location, this->scaling);
|
||||
return QColor::fromRgbF(coverage, coverage, coverage, 1.0);
|
||||
}
|
||||
void updateData()
|
||||
{
|
||||
sceneryGetTerrain(&_terrain);
|
||||
sceneryGetTerrain(_terrain);
|
||||
TerrainRendererClass.bind(_renderer.terrain, _terrain);
|
||||
|
||||
texturesLayerCopyDefinition(_original_layer, _preview_layer);
|
||||
}
|
||||
|
||||
private:
|
||||
static double _getTerrainHeight(Renderer* renderer, double x, double z)
|
||||
{
|
||||
return terrainGetHeight((TerrainDefinition*)(renderer->customData[0]), x, z);
|
||||
}
|
||||
|
||||
Renderer _renderer;
|
||||
TextureLayerDefinition* _original_layer;
|
||||
TextureLayerDefinition* _preview_layer;
|
||||
TerrainDefinition _terrain;
|
||||
TerrainDefinition* _terrain;
|
||||
};
|
||||
|
||||
class PreviewTexturesColor:public BasePreview
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "../lib_paysages/lighting.h"
|
||||
#include "../lib_paysages/renderer.h"
|
||||
#include "../lib_paysages/scenery.h"
|
||||
#include "../lib_paysages/terrain.h"
|
||||
#include "../lib_paysages/water.h"
|
||||
#include "tools.h"
|
||||
|
||||
|
@ -21,15 +20,15 @@ class PreviewWaterCoverage:public BasePreview
|
|||
public:
|
||||
PreviewWaterCoverage(QWidget* parent):BasePreview(parent)
|
||||
{
|
||||
_water = waterCreateDefinition();
|
||||
_terrain = terrainCreateDefinition();
|
||||
/*_water = waterCreateDefinition();
|
||||
_terrain = terrainCreateDefinition();*/
|
||||
|
||||
addOsd(QString("geolocation"));
|
||||
|
||||
configScaling(0.5, 200.0, 3.0, 50.0);
|
||||
configScrolling(-1000.0, 1000.0, 0.0, -1000.0, 1000.0, 0.0);
|
||||
}
|
||||
protected:
|
||||
/*protected:
|
||||
QColor getColor(double x, double y)
|
||||
{
|
||||
double height;
|
||||
|
@ -49,7 +48,7 @@ protected:
|
|||
{
|
||||
waterCopyDefinition(&_definition, &_water);
|
||||
sceneryGetTerrain(&_terrain);
|
||||
}
|
||||
}*/
|
||||
private:
|
||||
WaterDefinition _water;
|
||||
TerrainDefinition _terrain;
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
#include "inputheightmap.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QPainter>
|
||||
#include "dialogheightmap.h"
|
||||
|
||||
class SmallPreviewHeightMap:public QWidget
|
||||
{
|
||||
public:
|
||||
SmallPreviewHeightMap(QWidget* parent, HeightMap* value) : QWidget(parent)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
|
||||
void paintEvent(QPaintEvent* event)
|
||||
{
|
||||
double min, max, value, fx, fy;
|
||||
int ivalue;
|
||||
QPainter painter(this);
|
||||
|
||||
heightmapGetLimits(_value, &min, &max);
|
||||
if (max - min < 0.000001)
|
||||
{
|
||||
painter.fillRect(rect(), Qt::black);
|
||||
return;
|
||||
}
|
||||
|
||||
fx = 1.0 / (double)(width() - 1);
|
||||
fy = 1.0 / (double)(height() - 1);
|
||||
for (int x = 0; x < width(); x++)
|
||||
{
|
||||
for (int y = 0; y < height(); y++)
|
||||
{
|
||||
value = heightmapGetRawValue(_value, fx * x, fy * y);
|
||||
ivalue = (int)(255.0 * (value - min) / (max - min));
|
||||
if (ivalue > 255 || ivalue < 0)
|
||||
{
|
||||
ivalue = 128;
|
||||
}
|
||||
painter.setPen(QColor(ivalue, ivalue, ivalue));
|
||||
painter.drawPoint(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
HeightMap* _value;
|
||||
};
|
||||
|
||||
InputHeightMap::InputHeightMap(QWidget* form, QString label, HeightMap* value, TerrainCanvas* canvas) : BaseInput(form, label)
|
||||
{
|
||||
_value = value;
|
||||
_canvas = canvas;
|
||||
|
||||
_preview = new SmallPreviewHeightMap(form, value);
|
||||
_preview->setMinimumSize(100, 100);
|
||||
|
||||
_control = new QPushButton(tr("Paint"), form);
|
||||
_control->setMaximumWidth(150);
|
||||
|
||||
connect((QPushButton*)_control, SIGNAL(clicked()), this, SLOT(editHeightMap()));
|
||||
}
|
||||
|
||||
void InputHeightMap::updatePreview()
|
||||
{
|
||||
_preview->update();
|
||||
|
||||
BaseInput::updatePreview();
|
||||
}
|
||||
|
||||
void InputHeightMap::applyValue()
|
||||
{
|
||||
BaseInput::applyValue();
|
||||
}
|
||||
|
||||
void InputHeightMap::revert()
|
||||
{
|
||||
BaseInput::revert();
|
||||
}
|
||||
|
||||
void InputHeightMap::editHeightMap()
|
||||
{
|
||||
if (DialogHeightMap::editHeightMap(_control, _value, _canvas))
|
||||
{
|
||||
applyValue();
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
#ifndef _PAYSAGES_QT_INPUTHEIGHTMAP_H_
|
||||
#define _PAYSAGES_QT_INPUTHEIGHTMAP_H_
|
||||
|
||||
#include <QWidget>
|
||||
#include "baseinput.h"
|
||||
|
||||
#include "../lib_paysages/heightmap.h"
|
||||
#include "../lib_paysages/terraincanvas.h"
|
||||
|
||||
class InputHeightMap:public BaseInput
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InputHeightMap(QWidget* form, QString label, HeightMap* value, TerrainCanvas* canvas);
|
||||
|
||||
public slots:
|
||||
virtual void updatePreview();
|
||||
virtual void applyValue();
|
||||
virtual void revert();
|
||||
|
||||
private slots:
|
||||
void editHeightMap();
|
||||
|
||||
private:
|
||||
HeightMap* _value;
|
||||
TerrainCanvas* _canvas;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -48,21 +48,11 @@ private:
|
|||
|
||||
static QVector<ChunkMaintenanceThread*> _threads;
|
||||
|
||||
static double _getTerrainHeight(Renderer* renderer, double x, double z)
|
||||
{
|
||||
return terrainGetHeight((TerrainDefinition*)(renderer->customData[0]), x, z);
|
||||
}
|
||||
|
||||
static Color _applyTextures(Renderer* renderer, Vector3 location, double precision)
|
||||
{
|
||||
return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location.x, location.z, precision);
|
||||
}
|
||||
|
||||
static void _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||
{
|
||||
light->color = terrainLightFilter((TerrainDefinition*)(renderer->customData[0]), renderer, light->color, location, v3Scale(light->direction, -1000.0), v3Scale(light->direction, -1.0));
|
||||
}
|
||||
|
||||
static void _getLightStatus(Renderer* renderer, LightStatus* status, Vector3 location)
|
||||
{
|
||||
lightingGetStatus((LightingDefinition*)renderer->customData[2], renderer, location, status);
|
||||
|
@ -79,8 +69,6 @@ WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera):
|
|||
|
||||
_water = waterCreateDefinition();
|
||||
sceneryGetWater(&_water);
|
||||
_terrain = terrainCreateDefinition();
|
||||
sceneryGetTerrain(&_terrain);
|
||||
_textures = texturesCreateDefinition();
|
||||
sceneryGetTextures(&_textures);
|
||||
_lighting = lightingCreateDefinition();
|
||||
|
@ -88,13 +76,10 @@ WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera):
|
|||
|
||||
_renderer = sceneryCreateStandardRenderer();
|
||||
_renderer.render_quality = 3;
|
||||
_renderer.customData[0] = &_terrain;
|
||||
_renderer.customData[1] = &_textures;
|
||||
_renderer.customData[2] = &_lighting;
|
||||
_renderer.customData[3] = &_water;
|
||||
_renderer.applyTextures = _applyTextures;
|
||||
_renderer.getTerrainHeight = _getTerrainHeight;
|
||||
_renderer.alterLight = _alterLight;
|
||||
_renderer.getLightStatus = _getLightStatus;
|
||||
|
||||
_updated = false;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include "../lib_paysages/camera.h"
|
||||
#include "../lib_paysages/water.h"
|
||||
#include "../lib_paysages/renderer.h"
|
||||
#include "../lib_paysages/terrain.h"
|
||||
#include "../lib_paysages/textures.h"
|
||||
#include "../lib_paysages/lighting.h"
|
||||
|
||||
|
@ -50,7 +49,6 @@ private:
|
|||
QMutex _lock_chunks;
|
||||
|
||||
WaterDefinition _water;
|
||||
TerrainDefinition _terrain;
|
||||
TexturesDefinition _textures;
|
||||
LightingDefinition _lighting;
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
BUILDMODE = debug
|
||||
BUILDPATH = ../build/${BUILDMODE}
|
||||
OBJPATH = ./obj/${BUILDMODE}
|
||||
SOURCES = $(wildcard *.c atmosphere/*.c)
|
||||
SOURCES = $(wildcard *.c atmosphere/*.c terrain/*.c)
|
||||
OBJECTS = ${SOURCES:%.c=${OBJPATH}/%.o}
|
||||
HEADERS = $(wildcard shared/*.h atmosphere/*.h *.h)
|
||||
HEADERS = $(wildcard *.h atmosphere/*.h terrain/*.h shared/*.h)
|
||||
RESULT = ${BUILDPATH}/libpaysages.so
|
||||
LIBS = glib-2.0 gthread-2.0 IL ILU
|
||||
CC_FLAGS = -Wall -fPIC -DHAVE_GLIB=1
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "../lighting.h"
|
||||
#include "../system.h"
|
||||
|
||||
#define SPHERE_SIZE 1000.0
|
||||
#define MAX_SKYDOME_LIGHTS 100
|
||||
|
||||
typedef struct
|
||||
|
@ -342,73 +341,3 @@ StandardRenderer AtmosphereRendererClass = {
|
|||
(FuncObjectDelete)_deleteRenderer,
|
||||
(FuncObjectBind)_bindRenderer
|
||||
};
|
||||
|
||||
/******************** Utilities ********************/
|
||||
static Color _postProcessFragment(Renderer* renderer, Vector3 location, void* data)
|
||||
{
|
||||
Vector3 direction;
|
||||
Color result;
|
||||
|
||||
UNUSED(data);
|
||||
|
||||
direction = v3Sub(location, renderer->camera_location);
|
||||
|
||||
/* TODO Don't compute result->color if it's fully covered by clouds */
|
||||
result = renderer->atmosphere->getSkyColor(renderer, v3Normalize(direction));
|
||||
result = renderer->applyClouds(renderer, result, renderer->camera_location, v3Add(renderer->camera_location, v3Scale(direction, 10.0)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void atmosphereRenderSkydome(Renderer* renderer)
|
||||
{
|
||||
int res_i, res_j;
|
||||
int i, j;
|
||||
double step_i, step_j;
|
||||
double current_i, current_j;
|
||||
Vector3 vertex1, vertex2, vertex3, vertex4;
|
||||
Vector3 direction;
|
||||
|
||||
res_i = renderer->render_quality * 40;
|
||||
res_j = renderer->render_quality * 20;
|
||||
step_i = M_PI * 2.0 / (double)res_i;
|
||||
step_j = M_PI / (double)res_j;
|
||||
|
||||
for (j = 0; j < res_j; j++)
|
||||
{
|
||||
if (!renderer->addRenderProgress(renderer, 0.0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
current_j = (double)(j - res_j / 2) * step_j;
|
||||
|
||||
for (i = 0; i < res_i; i++)
|
||||
{
|
||||
current_i = (double)i * step_i;
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j);
|
||||
vertex1 = v3Add(renderer->camera_location, direction);
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j);
|
||||
vertex2 = v3Add(renderer->camera_location, direction);
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j + step_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j + step_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j + step_j);
|
||||
vertex3 = v3Add(renderer->camera_location, direction);
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j + step_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j + step_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j + step_j);
|
||||
vertex4 = v3Add(renderer->camera_location, direction);
|
||||
|
||||
/* TODO Triangles at poles */
|
||||
renderer->pushQuad(renderer, vertex1, vertex4, vertex3, vertex2, _postProcessFragment, NULL);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "../renderer.h"
|
||||
#include "../lighting.h"
|
||||
#include "../terrain.h"
|
||||
|
||||
/*
|
||||
* Atmosphere previews.
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef _PAYSAGES_ATMOSPHERE_PRIVATE_H_
|
||||
#define _PAYSAGES_ATMOSPHERE_PRIVATE_H_
|
||||
|
||||
#define SPHERE_SIZE 1000.0
|
||||
|
||||
Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position);
|
||||
|
||||
Color preethamGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position);
|
||||
|
|
|
@ -11,31 +11,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*** TO EXTRACT ***/
|
||||
typedef void* (*FuncObjectCreate)();
|
||||
typedef void (*FuncObjectDelete)(void* object);
|
||||
typedef void (*FuncObjectCopy)(void* source, void* destination);
|
||||
typedef void (*FuncObjectValidate)(void* object);
|
||||
typedef void (*FuncObjectSave)(PackStream* stream, void* object);
|
||||
typedef void (*FuncObjectLoad)(PackStream* stream, void* object);
|
||||
typedef void (*FuncObjectBind)(void* base, void* sub);
|
||||
|
||||
typedef struct {
|
||||
FuncObjectCreate create;
|
||||
FuncObjectDelete destroy;
|
||||
FuncObjectCopy copy;
|
||||
FuncObjectValidate validate;
|
||||
FuncObjectSave save;
|
||||
FuncObjectLoad load;
|
||||
} StandardDefinition;
|
||||
|
||||
typedef struct {
|
||||
FuncObjectCreate create;
|
||||
FuncObjectDelete destroy;
|
||||
FuncObjectBind bind;
|
||||
} StandardRenderer;
|
||||
/*** TO EXTRACT ***/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ATMOSPHERE_MODEL_PREETHAM = 0,
|
||||
|
|
76
lib_paysages/atmosphere/raster.c
Normal file
76
lib_paysages/atmosphere/raster.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
#include "public.h"
|
||||
#include "private.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "../tools.h"
|
||||
#include "../renderer.h"
|
||||
|
||||
static Color _postProcessFragment(Renderer* renderer, Vector3 location, void* data)
|
||||
{
|
||||
Vector3 direction;
|
||||
Color result;
|
||||
|
||||
UNUSED(data);
|
||||
|
||||
direction = v3Sub(location, renderer->camera_location);
|
||||
|
||||
/* TODO Don't compute result->color if it's fully covered by clouds */
|
||||
result = renderer->atmosphere->getSkyColor(renderer, v3Normalize(direction));
|
||||
result = renderer->applyClouds(renderer, result, renderer->camera_location, v3Add(renderer->camera_location, v3Scale(direction, 10.0)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void atmosphereRenderSkydome(Renderer* renderer)
|
||||
{
|
||||
int res_i, res_j;
|
||||
int i, j;
|
||||
double step_i, step_j;
|
||||
double current_i, current_j;
|
||||
Vector3 vertex1, vertex2, vertex3, vertex4;
|
||||
Vector3 direction;
|
||||
|
||||
res_i = renderer->render_quality * 40;
|
||||
res_j = renderer->render_quality * 20;
|
||||
step_i = M_PI * 2.0 / (double)res_i;
|
||||
step_j = M_PI / (double)res_j;
|
||||
|
||||
for (j = 0; j < res_j; j++)
|
||||
{
|
||||
if (!renderer->addRenderProgress(renderer, 0.0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
current_j = (double)(j - res_j / 2) * step_j;
|
||||
|
||||
for (i = 0; i < res_i; i++)
|
||||
{
|
||||
current_i = (double)i * step_i;
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j);
|
||||
vertex1 = v3Add(renderer->camera_location, direction);
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j);
|
||||
vertex2 = v3Add(renderer->camera_location, direction);
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j + step_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j + step_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j + step_j);
|
||||
vertex3 = v3Add(renderer->camera_location, direction);
|
||||
|
||||
direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j + step_j);
|
||||
direction.y = SPHERE_SIZE * sin(current_j + step_j);
|
||||
direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j + step_j);
|
||||
vertex4 = v3Add(renderer->camera_location, direction);
|
||||
|
||||
/* TODO Triangles at poles */
|
||||
renderer->pushQuad(renderer, vertex1, vertex4, vertex3, vertex2, _postProcessFragment, NULL);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,7 +10,6 @@
|
|||
#include "lighting.h"
|
||||
#include "modifiers.h"
|
||||
#include "render.h"
|
||||
#include "terrain.h"
|
||||
#include "textures.h"
|
||||
#include "scenery.h"
|
||||
#include "system.h"
|
||||
|
@ -66,17 +65,6 @@ void autoGenRealisticLandscape(int seed)
|
|||
scenerySetWater(&water);
|
||||
waterDeleteDefinition(&water);
|
||||
|
||||
/* Terrain */
|
||||
terrain = terrainCreateDefinition();
|
||||
noiseClearLevels(terrain.height_noise);
|
||||
noiseAddLevelsSimple(terrain.height_noise, 10, 1.0, 1.0);
|
||||
noiseSetFunctionParams(terrain.height_noise, NOISE_FUNCTION_SIMPLEX, -0.2);
|
||||
terrain.height_factor = 12.0 / noiseGetMaxValue(terrain.height_noise);
|
||||
terrain.scaling = 80.0;
|
||||
terrain.shadow_smoothing = 0.03;
|
||||
scenerySetTerrain(&terrain);
|
||||
terrainDeleteDefinition(&terrain);
|
||||
|
||||
/* Textures */
|
||||
textures = texturesCreateDefinition();
|
||||
layer = layersAddLayer(textures.layers, NULL);
|
||||
|
|
|
@ -63,7 +63,7 @@ void cameraCopyDefinition(CameraDefinition* source, CameraDefinition* destinatio
|
|||
void cameraValidateDefinition(CameraDefinition* definition, int check_above)
|
||||
{
|
||||
WaterDefinition water;
|
||||
TerrainDefinition terrain;
|
||||
Renderer renderer;
|
||||
double water_height, terrain_height, diff;
|
||||
Vector3 move;
|
||||
Matrix4 rotation;
|
||||
|
@ -75,10 +75,9 @@ void cameraValidateDefinition(CameraDefinition* definition, int check_above)
|
|||
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);
|
||||
renderer = sceneryCreateStandardRenderer();
|
||||
terrain_height = renderer.terrain->getHeight(&renderer, definition->location.x, definition->location.z) + 0.5;
|
||||
rendererDelete(&renderer);
|
||||
|
||||
if (definition->location.y < water_height || definition->location.y < terrain_height)
|
||||
{
|
||||
|
|
|
@ -178,7 +178,7 @@ void heightmapRevertToTerrain(HeightMap* heightmap, TerrainDefinition* terrain,
|
|||
dx = (double)x / (double)(rx - 1);
|
||||
dz = (double)z / (double)(rz - 1);
|
||||
geoareaFromLocal(area, dx, dz, &dx, &dz);
|
||||
heightmap->data[z * rx + x] = terrainGetHeight(terrain, dx, dz);
|
||||
// heightmap->data[z * rx + x] = terrainGetHeight(terrain, dx, dz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "pack.h"
|
||||
#include "noise.h"
|
||||
#include "geoarea.h"
|
||||
#include "terrain.h"
|
||||
#include "terrain/public.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "euclid.h"
|
||||
#include "renderer.h"
|
||||
#include "scenery.h"
|
||||
#include "terrain.h"
|
||||
#include "tools.h"
|
||||
#include "water.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define _PAYSAGES_LIGHTING_H_
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "renderer.h"
|
||||
#include "pack.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -32,6 +31,8 @@ struct LightStatus
|
|||
LightDefinition lights[LIGHTING_MAX_LIGHTS * 2];
|
||||
};
|
||||
|
||||
typedef LightDefinition (*FuncLightingAlterLight)(Renderer* renderer, LightDefinition* light, Vector3 at);
|
||||
|
||||
void lightingInit();
|
||||
void lightingQuit();
|
||||
void lightingSave(PackStream* stream, LightingDefinition* definition);
|
||||
|
|
|
@ -73,11 +73,6 @@ static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector
|
|||
return _RAYCASTING_NULL;
|
||||
}
|
||||
|
||||
static double _getTerrainHeight(Renderer* renderer, double x, double z)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static HeightInfo _getWaterHeightInfo(Renderer* renderer)
|
||||
{
|
||||
return _WATER_HEIGHT_INFO;
|
||||
|
@ -118,7 +113,6 @@ Renderer rendererCreate()
|
|||
result.pushQuad = _pushQuad;
|
||||
|
||||
result.rayWalking = _rayWalking;
|
||||
result.getTerrainHeight = _getTerrainHeight;
|
||||
result.getWaterHeightInfo = _getWaterHeightInfo;
|
||||
result.applyTextures = _applyTextures;
|
||||
result.applyClouds = _applyClouds;
|
||||
|
@ -128,6 +122,7 @@ Renderer rendererCreate()
|
|||
result.applyLightStatus = _applyLightStatus;
|
||||
|
||||
result.atmosphere = AtmosphereRendererClass.create();
|
||||
result.terrain = TerrainRendererClass.create();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -135,6 +130,8 @@ Renderer rendererCreate()
|
|||
void rendererDelete(Renderer* renderer)
|
||||
{
|
||||
AtmosphereRendererClass.destroy(renderer->atmosphere);
|
||||
TerrainRendererClass.destroy(renderer->terrain);
|
||||
|
||||
renderDeleteArea(renderer->render_area);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "shared/types.h"
|
||||
#include "atmosphere/public.h"
|
||||
#include "terrain/public.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -31,7 +32,6 @@ struct Renderer
|
|||
|
||||
/* Scenery related */
|
||||
RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds);
|
||||
double (*getTerrainHeight)(Renderer* renderer, double x, double z);
|
||||
HeightInfo (*getWaterHeightInfo)(Renderer* renderer);
|
||||
Color (*applyTextures)(Renderer* renderer, Vector3 location, double precision);
|
||||
Color (*applyClouds)(Renderer* renderer, Color base, Vector3 start, Vector3 end);
|
||||
|
@ -43,6 +43,7 @@ struct Renderer
|
|||
|
||||
/* Autonomous sub-renderers */
|
||||
AtmosphereRenderer* atmosphere;
|
||||
TerrainRenderer* terrain;
|
||||
|
||||
/* Custom data */
|
||||
void* customData[10];
|
||||
|
|
|
@ -10,7 +10,7 @@ static AtmosphereDefinition* _atmosphere;
|
|||
static CameraDefinition _camera;
|
||||
static CloudsDefinition _clouds;
|
||||
static LightingDefinition _lighting;
|
||||
static TerrainDefinition _terrain;
|
||||
static TerrainDefinition* _terrain;
|
||||
static TexturesDefinition _textures;
|
||||
static WaterDefinition _water;
|
||||
|
||||
|
@ -27,7 +27,7 @@ void sceneryInit()
|
|||
_camera = cameraCreateDefinition();
|
||||
_clouds = cloudsCreateDefinition();
|
||||
_lighting = lightingCreateDefinition();
|
||||
_terrain = terrainCreateDefinition();
|
||||
_terrain = TerrainDefinitionClass.create();
|
||||
_textures = texturesCreateDefinition();
|
||||
_water = waterCreateDefinition();
|
||||
|
||||
|
@ -41,7 +41,7 @@ void sceneryQuit()
|
|||
cameraDeleteDefinition(&_camera);
|
||||
cloudsDeleteDefinition(&_clouds);
|
||||
lightingDeleteDefinition(&_lighting);
|
||||
terrainDeleteDefinition(&_terrain);
|
||||
TerrainDefinitionClass.destroy(_terrain);
|
||||
texturesDeleteDefinition(&_textures);
|
||||
waterDeleteDefinition(&_water);
|
||||
|
||||
|
@ -63,7 +63,7 @@ void scenerySave(PackStream* stream)
|
|||
cameraSave(stream, &_camera);
|
||||
cloudsSave(stream, &_clouds);
|
||||
lightingSave(stream, &_lighting);
|
||||
terrainSave(stream, &_terrain);
|
||||
TerrainDefinitionClass.save(stream, _terrain);
|
||||
texturesSave(stream, &_textures);
|
||||
waterSave(stream, &_water);
|
||||
|
||||
|
@ -82,14 +82,13 @@ void sceneryLoad(PackStream* stream)
|
|||
cameraLoad(stream, &_camera);
|
||||
cloudsLoad(stream, &_clouds);
|
||||
lightingLoad(stream, &_lighting);
|
||||
terrainLoad(stream, &_terrain);
|
||||
TerrainDefinitionClass.load(stream, _terrain);
|
||||
texturesLoad(stream, &_textures);
|
||||
waterLoad(stream, &_water);
|
||||
|
||||
cameraValidateDefinition(&_camera, 0);
|
||||
cloudsValidateDefinition(&_clouds);
|
||||
lightingValidateDefinition(&_lighting);
|
||||
terrainValidateDefinition(&_terrain);
|
||||
texturesValidateDefinition(&_textures);
|
||||
waterValidateDefinition(&_water);
|
||||
|
||||
|
@ -102,7 +101,6 @@ void sceneryLoad(PackStream* stream)
|
|||
void scenerySetAtmosphere(AtmosphereDefinition* atmosphere)
|
||||
{
|
||||
AtmosphereDefinitionClass.copy(atmosphere, _atmosphere);
|
||||
AtmosphereDefinitionClass.validate(_atmosphere);
|
||||
}
|
||||
|
||||
void sceneryGetAtmosphere(AtmosphereDefinition* atmosphere)
|
||||
|
@ -145,15 +143,14 @@ void sceneryGetLighting(LightingDefinition* lighting)
|
|||
|
||||
void scenerySetTerrain(TerrainDefinition* terrain)
|
||||
{
|
||||
terrainCopyDefinition(terrain, &_terrain);
|
||||
terrainValidateDefinition(&_terrain);
|
||||
TerrainDefinitionClass.copy(terrain, _terrain);
|
||||
|
||||
cameraValidateDefinition(&_camera, 1);
|
||||
}
|
||||
|
||||
void sceneryGetTerrain(TerrainDefinition* terrain)
|
||||
{
|
||||
terrainCopyDefinition(&_terrain, terrain);
|
||||
TerrainDefinitionClass.copy(_terrain, terrain);
|
||||
}
|
||||
|
||||
void scenerySetTextures(TexturesDefinition* textures)
|
||||
|
@ -182,7 +179,7 @@ void sceneryGetWater(WaterDefinition* water)
|
|||
|
||||
void sceneryRenderFirstPass(Renderer* renderer)
|
||||
{
|
||||
terrainRender(&_terrain, renderer);
|
||||
terrainRenderSurface(renderer);
|
||||
waterRender(&_water, renderer);
|
||||
atmosphereRenderSkydome(renderer);
|
||||
}
|
||||
|
@ -208,7 +205,7 @@ static void _alterLight(Renderer* renderer, LightDefinition* light, Vector3 loca
|
|||
}
|
||||
if (light->masked)
|
||||
{
|
||||
light->color = terrainLightFilter(&_terrain, renderer, light->color, location, light_location, direction_to_light);
|
||||
*light = renderer->terrain->alterLight(renderer, light, location);
|
||||
light->color = cloudsFilterLight(&_clouds, renderer, light->color, location, light_location, direction_to_light);
|
||||
}
|
||||
}
|
||||
|
@ -228,22 +225,19 @@ static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector
|
|||
RayCastingResult result;
|
||||
Color sky_color;
|
||||
|
||||
if (!terrainProjectRay(&_terrain, renderer, location, direction, &result.hit_location, &result.hit_color))
|
||||
result = renderer->terrain->castRay(renderer, location, direction);
|
||||
if (!result.hit)
|
||||
{
|
||||
sky_color = renderer->atmosphere->getSkyColor(renderer, direction);
|
||||
|
||||
result.hit = 1;
|
||||
result.hit_location = v3Add(location, v3Scale(direction, 1000.0));
|
||||
result.hit_color = renderer->applyClouds(renderer, sky_color, location, result.hit_location);
|
||||
}
|
||||
|
||||
result.hit = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
static double _getTerrainHeight(Renderer* renderer, double x, double z)
|
||||
{
|
||||
return terrainGetHeight(&_terrain, x, z);
|
||||
}
|
||||
|
||||
static HeightInfo _getWaterHeightInfo(Renderer* renderer)
|
||||
{
|
||||
return waterGetHeightInfo(&_water);
|
||||
|
@ -293,7 +287,6 @@ Renderer sceneryCreateStandardRenderer()
|
|||
result.getLightStatus = _getLightStatus;
|
||||
result.applyLightStatus = _applyLightStatus;
|
||||
result.rayWalking = _rayWalking;
|
||||
result.getTerrainHeight = _getTerrainHeight;
|
||||
result.getWaterHeightInfo = _getWaterHeightInfo;
|
||||
result.applyTextures = _applyTextures;
|
||||
result.applyClouds = _applyClouds;
|
||||
|
@ -302,6 +295,7 @@ Renderer sceneryCreateStandardRenderer()
|
|||
result.getPrecision = _getPrecision;
|
||||
|
||||
AtmosphereRendererClass.bind(result.atmosphere, _atmosphere);
|
||||
TerrainRendererClass.bind(result.terrain, _terrain);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
*/
|
||||
|
||||
#include "atmosphere/public.h"
|
||||
#include "terrain/public.h"
|
||||
#include "camera.h"
|
||||
#include "clouds.h"
|
||||
#include "lighting.h"
|
||||
#include "terrain.h"
|
||||
#include "textures.h"
|
||||
#include "water.h"
|
||||
#include "pack.h"
|
||||
|
|
|
@ -51,7 +51,7 @@ typedef struct
|
|||
Color hit_color;
|
||||
Vector3 hit_location;
|
||||
} RayCastingResult;
|
||||
typedef RayCastingResult (*RayCastingFunction)(Vector3 start, Vector3 direction);
|
||||
typedef RayCastingResult (*FuncGeneralCastRay)(Renderer* renderer, Vector3 start, Vector3 direction);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -83,6 +83,29 @@ typedef struct
|
|||
Matrix4 unproject;
|
||||
} CameraDefinition;
|
||||
|
||||
typedef void* (*FuncObjectCreate)();
|
||||
typedef void (*FuncObjectDelete)(void* object);
|
||||
typedef void (*FuncObjectCopy)(void* source, void* destination);
|
||||
typedef void (*FuncObjectValidate)(void* object);
|
||||
typedef void (*FuncObjectSave)(PackStream* stream, void* object);
|
||||
typedef void (*FuncObjectLoad)(PackStream* stream, void* object);
|
||||
typedef void (*FuncObjectBind)(void* base, void* sub);
|
||||
|
||||
typedef struct {
|
||||
FuncObjectCreate create;
|
||||
FuncObjectDelete destroy;
|
||||
FuncObjectCopy copy;
|
||||
FuncObjectValidate validate;
|
||||
FuncObjectSave save;
|
||||
FuncObjectLoad load;
|
||||
} StandardDefinition;
|
||||
|
||||
typedef struct {
|
||||
FuncObjectCreate create;
|
||||
FuncObjectDelete destroy;
|
||||
FuncObjectBind bind;
|
||||
} StandardRenderer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,390 +0,0 @@
|
|||
#include "terrain.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "euclid.h"
|
||||
#include "render.h"
|
||||
#include "textures.h"
|
||||
#include "water.h"
|
||||
#include "tools.h"
|
||||
#include "layers.h"
|
||||
#include "terraincanvas.h"
|
||||
|
||||
void terrainSave(PackStream* stream, TerrainDefinition* definition)
|
||||
{
|
||||
noiseSaveGenerator(stream, definition->height_noise);
|
||||
packWriteDouble(stream, &definition->height_factor);
|
||||
packWriteDouble(stream, &definition->scaling);
|
||||
layersSave(stream, definition->canvases);
|
||||
packWriteDouble(stream, &definition->shadow_smoothing);
|
||||
}
|
||||
|
||||
void terrainLoad(PackStream* stream, TerrainDefinition* definition)
|
||||
{
|
||||
noiseLoadGenerator(stream, definition->height_noise);
|
||||
packReadDouble(stream, &definition->height_factor);
|
||||
packReadDouble(stream, &definition->scaling);
|
||||
layersLoad(stream, definition->canvases);
|
||||
packReadDouble(stream, &definition->shadow_smoothing);
|
||||
|
||||
terrainValidateDefinition(definition);
|
||||
}
|
||||
|
||||
TerrainDefinition terrainCreateDefinition()
|
||||
{
|
||||
TerrainDefinition definition;
|
||||
|
||||
definition.height_noise = noiseCreateGenerator();
|
||||
definition.height_factor = 0.0;
|
||||
definition.scaling = 1.0;
|
||||
definition.canvases = layersCreate(terrainCanvasGetLayerType(), 50);
|
||||
definition.shadow_smoothing = 0.0;
|
||||
|
||||
terrainValidateDefinition(&definition);
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
void terrainDeleteDefinition(TerrainDefinition* definition)
|
||||
{
|
||||
noiseDeleteGenerator(definition->height_noise);
|
||||
layersDelete(definition->canvases);
|
||||
}
|
||||
|
||||
void terrainCopyDefinition(TerrainDefinition* source, TerrainDefinition* destination)
|
||||
{
|
||||
noiseCopy(source->height_noise, destination->height_noise);
|
||||
destination->height_factor = source->height_factor;
|
||||
destination->scaling = source->scaling;
|
||||
layersCopy(source->canvases, destination->canvases);
|
||||
destination->shadow_smoothing = source->shadow_smoothing;
|
||||
|
||||
terrainValidateDefinition(destination);
|
||||
}
|
||||
|
||||
void terrainValidateDefinition(TerrainDefinition* definition)
|
||||
{
|
||||
int i, n;
|
||||
TerrainCanvas* canvas;
|
||||
double min, max;
|
||||
|
||||
noiseValidate(definition->height_noise);
|
||||
layersValidate(definition->canvases);
|
||||
|
||||
/* Get minimal and maximal height */
|
||||
definition->_min_height = -noiseGetMaxValue(definition->height_noise) * definition->height_factor;
|
||||
definition->_max_height = noiseGetMaxValue(definition->height_noise) * definition->height_factor;
|
||||
|
||||
n = layersCount(definition->canvases);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
canvas = layersGetLayer(definition->canvases, i);
|
||||
terrainCanvasGetLimits(canvas, &min, &max);
|
||||
if (min < definition->_min_height)
|
||||
{
|
||||
definition->_min_height = min;
|
||||
}
|
||||
if (max > definition->_max_height)
|
||||
{
|
||||
definition->_max_height = max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline double _getHeight(TerrainDefinition* definition, double x, double z)
|
||||
{
|
||||
TerrainCanvas* canvas;
|
||||
Vector3 location;
|
||||
int i, n;
|
||||
|
||||
location.x = x;
|
||||
location.y = noiseGet2DTotal(definition->height_noise, x / definition->scaling, z / definition->scaling) * definition->height_factor;
|
||||
location.z = z;
|
||||
|
||||
n = layersCount(definition->canvases);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
canvas = layersGetLayer(definition->canvases, i);
|
||||
location = terrainCanvasApply(canvas, location);
|
||||
}
|
||||
|
||||
/* TODO Apply modifiers */
|
||||
|
||||
return location.y;
|
||||
}
|
||||
|
||||
static inline double _getHeightDetail(TerrainDefinition* definition, double x, double z, double detail)
|
||||
{
|
||||
TerrainCanvas* canvas;
|
||||
Vector3 location;
|
||||
int i, n;
|
||||
|
||||
location.x = x;
|
||||
location.y = noiseGet2DDetail(definition->height_noise, x / definition->scaling, z / definition->scaling, detail / definition->height_factor) * definition->height_factor;
|
||||
location.z = z;
|
||||
|
||||
n = layersCount(definition->canvases);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
canvas = layersGetLayer(definition->canvases, i);
|
||||
location = terrainCanvasApply(canvas, location);
|
||||
}
|
||||
|
||||
/* TODO Apply modifiers */
|
||||
|
||||
return location.y;
|
||||
}
|
||||
|
||||
static inline Vector3 _getPoint(TerrainDefinition* definition, double x, double z)
|
||||
{
|
||||
Vector3 result;
|
||||
|
||||
result.x = x;
|
||||
result.y = _getHeight(definition, x, z);
|
||||
result.z = z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Color terrainLightFilter(TerrainDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light)
|
||||
{
|
||||
Vector3 inc_vector;
|
||||
double inc_value, inc_base, inc_factor, height, diff, light_factor, smoothing, length;
|
||||
|
||||
direction_to_light = v3Normalize(direction_to_light);
|
||||
if ((fabs(direction_to_light.x) < 0.0001 && fabs(direction_to_light.z) < 0.0001) || definition->height_factor < 0.001)
|
||||
{
|
||||
return light;
|
||||
}
|
||||
else if (direction_to_light.y < 0.05)
|
||||
{
|
||||
return COLOR_BLACK;
|
||||
}
|
||||
else if (direction_to_light.y < 0.0000)
|
||||
{
|
||||
light.r *= (0.05 + direction_to_light.y) / 0.05;
|
||||
light.g *= (0.05 + direction_to_light.y) / 0.05;
|
||||
light.b *= (0.05 + direction_to_light.y) / 0.05;
|
||||
}
|
||||
|
||||
inc_factor = (double)renderer->render_quality;
|
||||
inc_base = definition->height_factor / definition->scaling;
|
||||
inc_value = inc_base / inc_factor;
|
||||
smoothing = definition->shadow_smoothing;
|
||||
|
||||
light_factor = 1.0;
|
||||
length = 0.0;
|
||||
diff = 0.0;
|
||||
do
|
||||
{
|
||||
inc_vector = v3Scale(direction_to_light, inc_value);
|
||||
length += v3Norm(inc_vector);
|
||||
location = v3Add(location, inc_vector);
|
||||
height = _getHeightDetail(definition, location.x, location.z, diff / inc_factor);
|
||||
diff = location.y - height;
|
||||
if (diff < 0.0)
|
||||
{
|
||||
if (length * smoothing > 0.000001)
|
||||
{
|
||||
light_factor += diff * v3Norm(inc_vector) / (length * smoothing);
|
||||
}
|
||||
else
|
||||
{
|
||||
light_factor = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (diff < inc_base / inc_factor)
|
||||
{
|
||||
inc_value = inc_base / inc_factor;
|
||||
}
|
||||
else if (diff > inc_base)
|
||||
{
|
||||
inc_value = inc_base;
|
||||
}
|
||||
else
|
||||
{
|
||||
inc_value = diff;
|
||||
}
|
||||
} while (light_factor > 0.0 && length < (10.0 * inc_factor) && location.y <= definition->_max_height);
|
||||
|
||||
if (light_factor <= 0.0)
|
||||
{
|
||||
return COLOR_BLACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
light.r *= light_factor;
|
||||
light.g *= light_factor;
|
||||
light.b *= light_factor;
|
||||
|
||||
return light;
|
||||
}
|
||||
}
|
||||
|
||||
static Color _getColor(TerrainDefinition* definition, Renderer* renderer, Vector3 point, double precision)
|
||||
{
|
||||
Color color;
|
||||
|
||||
color = renderer->applyTextures(renderer, point, precision);
|
||||
color = renderer->atmosphere->applyAerialPerspective(renderer, point, color);
|
||||
color = renderer->applyClouds(renderer, color, renderer->camera_location, point);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
int terrainProjectRay(TerrainDefinition* definition, Renderer* renderer, Vector3 start, Vector3 direction, Vector3* hit_point, Color* hit_color)
|
||||
{
|
||||
Vector3 inc_vector;
|
||||
double inc_value, inc_base, inc_factor, height, diff, lastdiff, length;
|
||||
|
||||
direction = v3Normalize(direction);
|
||||
inc_factor = (double)renderer->render_quality;
|
||||
inc_base = 1.0;
|
||||
inc_value = inc_base / inc_factor;
|
||||
lastdiff = start.y - _getHeight(definition, start.x, start.z);
|
||||
|
||||
length = 0.0;
|
||||
do
|
||||
{
|
||||
inc_vector = v3Scale(direction, inc_value);
|
||||
length += v3Norm(inc_vector);
|
||||
start = v3Add(start, inc_vector);
|
||||
height = _getHeight(definition, start.x, start.z);
|
||||
diff = start.y - height;
|
||||
if (diff < 0.0)
|
||||
{
|
||||
if (fabs(diff - lastdiff) > 0.00001)
|
||||
{
|
||||
start = v3Add(start, v3Scale(inc_vector, -diff / (diff - lastdiff)));
|
||||
start.y = _getHeight(definition, start.x, start.z);
|
||||
}
|
||||
else
|
||||
{
|
||||
start.y = height;
|
||||
}
|
||||
*hit_point = start;
|
||||
*hit_color = _getColor(definition, renderer, start, renderer->getPrecision(renderer, start));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (diff < inc_base / inc_factor)
|
||||
{
|
||||
inc_value = inc_base / inc_factor;
|
||||
}
|
||||
else if (diff > inc_base)
|
||||
{
|
||||
inc_value = inc_base;
|
||||
}
|
||||
else
|
||||
{
|
||||
inc_value = diff;
|
||||
}
|
||||
lastdiff = diff;
|
||||
} while (length < 50.0 && start.y <= definition->_max_height);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Color _postProcessFragment(Renderer* renderer, Vector3 point, void* data)
|
||||
{
|
||||
double precision;
|
||||
TerrainDefinition* definition;
|
||||
|
||||
definition = (TerrainDefinition*)data;
|
||||
|
||||
point = _getPoint(definition, point.x, point.z);
|
||||
|
||||
precision = renderer->getPrecision(renderer, point);
|
||||
return _getColor(definition, renderer, point, precision);
|
||||
}
|
||||
|
||||
static void _renderQuad(TerrainDefinition* definition, Renderer* renderer, double x, double z, double size, double water_height)
|
||||
{
|
||||
Vector3 v1, v2, v3, v4;
|
||||
|
||||
v1 = _getPoint(definition, x, z);
|
||||
v2 = _getPoint(definition, x, z + size);
|
||||
v3 = _getPoint(definition, x + size, z + size);
|
||||
v4 = _getPoint(definition, x + size, z);
|
||||
|
||||
if (v1.y > water_height || v2.y > water_height || v3.y > water_height || v4.y > water_height)
|
||||
{
|
||||
renderer->pushQuad(renderer, v1, v2, v3, v4, _postProcessFragment, definition);
|
||||
}
|
||||
}
|
||||
|
||||
double terrainGetHeight(TerrainDefinition* definition, double x, double z)
|
||||
{
|
||||
return _getHeight(definition, x, z);
|
||||
}
|
||||
|
||||
double terrainGetHeightNormalized(TerrainDefinition* definition, double x, double z)
|
||||
{
|
||||
if (definition->_max_height - definition->_min_height <= 0.0000001)
|
||||
{
|
||||
return 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (_getHeight(definition, x, z) - definition->_min_height) / (definition->_max_height - definition->_min_height);
|
||||
}
|
||||
}
|
||||
|
||||
Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double x, double z, double detail)
|
||||
{
|
||||
Vector3 point = _getPoint(definition, x, z);
|
||||
return _getColor(definition, renderer, point, detail);
|
||||
}
|
||||
|
||||
void terrainRender(TerrainDefinition* definition, Renderer* renderer)
|
||||
{
|
||||
int chunk_factor, chunk_count, i;
|
||||
double cx = renderer->camera_location.x;
|
||||
double cz = renderer->camera_location.z;
|
||||
double min_chunk_size, visible_chunk_size;
|
||||
double radius_int, radius_ext, chunk_size;
|
||||
double water_height;
|
||||
|
||||
min_chunk_size = 0.1 / (double)renderer->render_quality;
|
||||
visible_chunk_size = 0.05 / (double)renderer->render_quality;
|
||||
|
||||
chunk_factor = 1;
|
||||
chunk_count = 2;
|
||||
radius_int = 0.0;
|
||||
radius_ext = min_chunk_size;
|
||||
chunk_size = min_chunk_size;
|
||||
|
||||
water_height = renderer->getWaterHeightInfo(renderer).max_height;
|
||||
|
||||
while (radius_ext < 1000.0)
|
||||
{
|
||||
if (!renderer->addRenderProgress(renderer, 0.0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < chunk_count - 1; i++)
|
||||
{
|
||||
_renderQuad(definition, renderer, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size, water_height);
|
||||
_renderQuad(definition, renderer, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size, water_height);
|
||||
_renderQuad(definition, renderer, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size, water_height);
|
||||
_renderQuad(definition, renderer, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size, water_height);
|
||||
}
|
||||
|
||||
if (chunk_count % 64 == 0 && chunk_size / radius_int < visible_chunk_size)
|
||||
{
|
||||
chunk_count /= 2;
|
||||
chunk_factor *= 2;
|
||||
/* TODO Fill in gaps with triangles */
|
||||
}
|
||||
chunk_count += 2;
|
||||
chunk_size = min_chunk_size * chunk_factor;
|
||||
radius_int = radius_ext;
|
||||
radius_ext += chunk_size;
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
#ifndef _PAYSAGES_TERRAIN_H_
|
||||
#define _PAYSAGES_TERRAIN_H_
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "modifiers.h"
|
||||
#include "noise.h"
|
||||
#include "lighting.h"
|
||||
#include "pack.h"
|
||||
#include "layers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TERRAIN_MAX_MODIFIERS 50
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NoiseGenerator* height_noise;
|
||||
double height_factor;
|
||||
double scaling;
|
||||
Layers* canvases;
|
||||
double shadow_smoothing;
|
||||
|
||||
double _min_height;
|
||||
double _max_height;
|
||||
} TerrainDefinition;
|
||||
|
||||
void terrainSave(PackStream* stream, TerrainDefinition* definition);
|
||||
void terrainLoad(PackStream* stream, TerrainDefinition* definition);
|
||||
|
||||
TerrainDefinition terrainCreateDefinition();
|
||||
void terrainDeleteDefinition(TerrainDefinition* definition);
|
||||
void terrainCopyDefinition(TerrainDefinition* source, TerrainDefinition* destination);
|
||||
void terrainValidateDefinition(TerrainDefinition* definition);
|
||||
|
||||
Color terrainLightFilter(TerrainDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
|
||||
int terrainProjectRay(TerrainDefinition* definition, Renderer* renderer, Vector3 start, Vector3 direction, Vector3* hit_point, Color* hit_color);
|
||||
double terrainGetHeight(TerrainDefinition* definition, double x, double z);
|
||||
double terrainGetHeightNormalized(TerrainDefinition* definition, double x, double z);
|
||||
Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double x, double z, double detail);
|
||||
void terrainRender(TerrainDefinition* definition, Renderer* renderer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
300
lib_paysages/terrain/main.c
Normal file
300
lib_paysages/terrain/main.c
Normal file
|
@ -0,0 +1,300 @@
|
|||
#include "public.h"
|
||||
#include "private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "../tools.h"
|
||||
#include "../lighting.h"
|
||||
#include "../renderer.h"
|
||||
|
||||
/******************** Definition ********************/
|
||||
static void _validateDefinition(TerrainDefinition* definition)
|
||||
{
|
||||
noiseValidate(definition->_height_noise);
|
||||
|
||||
/* Get minimal and maximal height */
|
||||
definition->_min_height = -noiseGetMaxValue(definition->_height_noise) * definition->height;
|
||||
definition->_max_height = noiseGetMaxValue(definition->_height_noise) * definition->height;
|
||||
}
|
||||
|
||||
static TerrainDefinition* _createDefinition()
|
||||
{
|
||||
TerrainDefinition* definition = malloc(sizeof(TerrainDefinition));
|
||||
|
||||
definition->height = 0.0;
|
||||
definition->scaling = 1.0;
|
||||
definition->shadow_smoothing = 0.0;
|
||||
definition->_height_noise = noiseCreateGenerator();
|
||||
|
||||
terrainAutoPreset(definition, TERRAIN_PRESET_STANDARD);
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
static void _deleteDefinition(TerrainDefinition* definition)
|
||||
{
|
||||
noiseDeleteGenerator(definition->_height_noise);
|
||||
free(definition);
|
||||
}
|
||||
|
||||
static void _copyDefinition(TerrainDefinition* source, TerrainDefinition* destination)
|
||||
{
|
||||
destination->height = source->height;
|
||||
destination->scaling = source->scaling;
|
||||
destination->shadow_smoothing = source->shadow_smoothing;
|
||||
|
||||
_validateDefinition(destination);
|
||||
}
|
||||
|
||||
static void _saveDefinition(PackStream* stream, TerrainDefinition* definition)
|
||||
{
|
||||
packWriteDouble(stream, &definition->height);
|
||||
packWriteDouble(stream, &definition->scaling);
|
||||
packWriteDouble(stream, &definition->shadow_smoothing);
|
||||
}
|
||||
|
||||
static void _loadDefinition(PackStream* stream, TerrainDefinition* definition)
|
||||
{
|
||||
packReadDouble(stream, &definition->height);
|
||||
packReadDouble(stream, &definition->scaling);
|
||||
packReadDouble(stream, &definition->shadow_smoothing);
|
||||
|
||||
_validateDefinition(definition);
|
||||
}
|
||||
|
||||
StandardDefinition TerrainDefinitionClass = {
|
||||
(FuncObjectCreate)_createDefinition,
|
||||
(FuncObjectDelete)_deleteDefinition,
|
||||
(FuncObjectCopy)_copyDefinition,
|
||||
(FuncObjectValidate)_validateDefinition,
|
||||
(FuncObjectSave)_saveDefinition,
|
||||
(FuncObjectLoad)_loadDefinition
|
||||
};
|
||||
|
||||
/******************** Binding ********************/
|
||||
static double _fakeGetHeight(Renderer* renderer, double x, double z)
|
||||
{
|
||||
UNUSED(renderer);
|
||||
UNUSED(x);
|
||||
UNUSED(z);
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static double _getHeight(Renderer* renderer, double x, double z)
|
||||
{
|
||||
TerrainDefinition* definition = renderer->terrain->definition;
|
||||
return noiseGet2DTotal(definition->_height_noise, x / definition->scaling, z / definition->scaling) * definition->height;
|
||||
}
|
||||
|
||||
static Color _fakeGetFinalColor(Renderer* renderer, Vector3 location, double precision)
|
||||
{
|
||||
return COLOR_GREEN;
|
||||
}
|
||||
|
||||
static Color _getFinalColor(Renderer* renderer, Vector3 location, double precision)
|
||||
{
|
||||
Color color;
|
||||
|
||||
color = renderer->applyTextures(renderer, location, precision);
|
||||
|
||||
/* TODO Factorize this in scenery renderer */
|
||||
color = renderer->atmosphere->applyAerialPerspective(renderer, location, color);
|
||||
color = renderer->applyClouds(renderer, color, renderer->camera_location, location);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
RayCastingResult _fakeCastRay(Renderer* renderer, Vector3 start, Vector3 direction)
|
||||
{
|
||||
UNUSED(renderer);
|
||||
UNUSED(start);
|
||||
UNUSED(direction);
|
||||
|
||||
RayCastingResult result;
|
||||
result.hit = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
RayCastingResult _castRay(Renderer* renderer, Vector3 start, Vector3 direction)
|
||||
{
|
||||
RayCastingResult result;
|
||||
TerrainDefinition* definition = renderer->terrain->definition;
|
||||
Vector3 inc_vector;
|
||||
double inc_value, inc_base, inc_factor, height, diff, lastdiff, length;
|
||||
|
||||
direction = v3Normalize(direction);
|
||||
inc_factor = (double)renderer->render_quality;
|
||||
inc_base = 1.0;
|
||||
inc_value = inc_base / inc_factor;
|
||||
lastdiff = start.y - _getHeight(renderer, start.x, start.z);
|
||||
|
||||
length = 0.0;
|
||||
do
|
||||
{
|
||||
inc_vector = v3Scale(direction, inc_value);
|
||||
length += v3Norm(inc_vector);
|
||||
start = v3Add(start, inc_vector);
|
||||
height = _getHeight(renderer, start.x, start.z);
|
||||
diff = start.y - height;
|
||||
if (diff < 0.0)
|
||||
{
|
||||
if (fabs(diff - lastdiff) > 0.00001)
|
||||
{
|
||||
start = v3Add(start, v3Scale(inc_vector, -diff / (diff - lastdiff)));
|
||||
start.y = _getHeight(renderer, start.x, start.z);
|
||||
}
|
||||
else
|
||||
{
|
||||
start.y = height;
|
||||
}
|
||||
result.hit = 1;
|
||||
result.hit_location = start;
|
||||
result.hit_color = _getFinalColor(renderer, start, renderer->getPrecision(renderer, result.hit_location));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (diff < inc_base / inc_factor)
|
||||
{
|
||||
inc_value = inc_base / inc_factor;
|
||||
}
|
||||
else if (diff > inc_base)
|
||||
{
|
||||
inc_value = inc_base;
|
||||
}
|
||||
else
|
||||
{
|
||||
inc_value = diff;
|
||||
}
|
||||
lastdiff = diff;
|
||||
} while (length < 50.0 && start.y <= definition->_max_height);
|
||||
|
||||
result.hit = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
static LightDefinition _fakeAlterLight(Renderer* renderer, LightDefinition* light, Vector3 at)
|
||||
{
|
||||
UNUSED(renderer);
|
||||
UNUSED(at);
|
||||
|
||||
return *light;
|
||||
}
|
||||
|
||||
static LightDefinition _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||
{
|
||||
TerrainDefinition* definition = renderer->terrain->definition;
|
||||
LightDefinition result = *light;
|
||||
Vector3 inc_vector, direction_to_light;
|
||||
double inc_value, inc_base, inc_factor, height, diff, light_factor, smoothing, length;
|
||||
|
||||
direction_to_light = v3Scale(light->direction, -1.0);
|
||||
if ((fabs(direction_to_light.x) < 0.0001 && fabs(direction_to_light.z) < 0.0001) || definition->height < 0.001)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if (direction_to_light.y < 0.05)
|
||||
{
|
||||
result.color = COLOR_BLACK;
|
||||
return result;
|
||||
}
|
||||
else if (direction_to_light.y < 0.0000)
|
||||
{
|
||||
result.color.r *= (0.05 + direction_to_light.y) / 0.05;
|
||||
result.color.g *= (0.05 + direction_to_light.y) / 0.05;
|
||||
result.color.b *= (0.05 + direction_to_light.y) / 0.05;
|
||||
}
|
||||
|
||||
inc_factor = (double)renderer->render_quality;
|
||||
inc_base = definition->height / definition->scaling;
|
||||
inc_value = inc_base / inc_factor;
|
||||
smoothing = definition->shadow_smoothing;
|
||||
|
||||
light_factor = 1.0;
|
||||
length = 0.0;
|
||||
diff = 0.0;
|
||||
do
|
||||
{
|
||||
inc_vector = v3Scale(direction_to_light, inc_value);
|
||||
length += v3Norm(inc_vector);
|
||||
location = v3Add(location, inc_vector);
|
||||
height = _getHeight(renderer, location.x, location.z);
|
||||
diff = location.y - height;
|
||||
if (diff < 0.0)
|
||||
{
|
||||
if (length * smoothing > 0.000001)
|
||||
{
|
||||
light_factor += diff * v3Norm(inc_vector) / (length * smoothing);
|
||||
}
|
||||
else
|
||||
{
|
||||
light_factor = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (diff < inc_base / inc_factor)
|
||||
{
|
||||
inc_value = inc_base / inc_factor;
|
||||
}
|
||||
else if (diff > inc_base)
|
||||
{
|
||||
inc_value = inc_base;
|
||||
}
|
||||
else
|
||||
{
|
||||
inc_value = diff;
|
||||
}
|
||||
} while (light_factor > 0.0 && length < (10.0 * inc_factor) && location.y <= definition->_max_height);
|
||||
|
||||
if (light_factor <= 0.0)
|
||||
{
|
||||
result.color = COLOR_BLACK;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.color.r *= light_factor;
|
||||
result.color.g *= light_factor;
|
||||
result.color.b *= light_factor;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/******************** Renderer ********************/
|
||||
static TerrainRenderer* _createRenderer()
|
||||
{
|
||||
TerrainRenderer* result;
|
||||
|
||||
result = malloc(sizeof(TerrainRenderer));
|
||||
result->definition = TerrainDefinitionClass.create();
|
||||
|
||||
result->castRay = _fakeCastRay;
|
||||
result->alterLight = _fakeAlterLight;
|
||||
result->getHeight = _fakeGetHeight;
|
||||
result->getFinalColor = _fakeGetFinalColor;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void _deleteRenderer(TerrainRenderer* renderer)
|
||||
{
|
||||
TerrainDefinitionClass.destroy(renderer->definition);
|
||||
free(renderer);
|
||||
}
|
||||
|
||||
static void _bindRenderer(TerrainRenderer* renderer, TerrainDefinition* definition)
|
||||
{
|
||||
TerrainDefinitionClass.copy(definition, renderer->definition);
|
||||
|
||||
renderer->castRay = _castRay;
|
||||
renderer->alterLight = _alterLight;
|
||||
renderer->getHeight = _getHeight;
|
||||
renderer->getFinalColor = _getFinalColor;
|
||||
}
|
||||
|
||||
StandardRenderer TerrainRendererClass = {
|
||||
(FuncObjectCreate)_createRenderer,
|
||||
(FuncObjectDelete)_deleteRenderer,
|
||||
(FuncObjectBind)_bindRenderer
|
||||
};
|
25
lib_paysages/terrain/presets.c
Normal file
25
lib_paysages/terrain/presets.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "public.h"
|
||||
#include "private.h"
|
||||
|
||||
/*
|
||||
* Terrain presets.
|
||||
*/
|
||||
|
||||
void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset)
|
||||
{
|
||||
switch (preset)
|
||||
{
|
||||
case TERRAIN_PRESET_STANDARD:
|
||||
noiseClearLevels(definition->_height_noise);
|
||||
noiseAddLevelsSimple(definition->_height_noise, 10, 1.0, 1.0);
|
||||
noiseSetFunctionParams(definition->_height_noise, NOISE_FUNCTION_SIMPLEX, -0.2);
|
||||
definition->height = 12.0 / noiseGetMaxValue(definition->_height_noise);
|
||||
definition->scaling = 80.0;
|
||||
definition->shadow_smoothing = 0.03;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
TerrainDefinitionClass.validate(definition);
|
||||
}
|
4
lib_paysages/terrain/private.h
Normal file
4
lib_paysages/terrain/private.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#ifndef _PAYSAGES_TERRAIN_PRIVATE_H_
|
||||
#define _PAYSAGES_TERRAIN_PRIVATE_H_
|
||||
|
||||
#endif
|
56
lib_paysages/terrain/public.h
Normal file
56
lib_paysages/terrain/public.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef _PAYSAGES_TERRAIN_PUBLIC_H_
|
||||
#define _PAYSAGES_TERRAIN_PUBLIC_H_
|
||||
|
||||
#include "../shared/types.h"
|
||||
#include "../noise.h"
|
||||
#include "../lighting.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TERRAIN_PRESET_STANDARD
|
||||
} TerrainPreset;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double height;
|
||||
double scaling;
|
||||
double shadow_smoothing;
|
||||
|
||||
double _detail;
|
||||
NoiseGenerator* _height_noise;
|
||||
double _min_height;
|
||||
double _max_height;
|
||||
} TerrainDefinition;
|
||||
|
||||
typedef double (*FuncTerrainGetHeight)(Renderer* renderer, double x, double z);
|
||||
typedef Color (*FuncTerrainGetFinalColor)(Renderer* renderer, Vector3 location, double precision);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TerrainDefinition* definition;
|
||||
|
||||
FuncGeneralCastRay castRay;
|
||||
FuncLightingAlterLight alterLight;
|
||||
FuncTerrainGetHeight getHeight;
|
||||
FuncTerrainGetFinalColor getFinalColor;
|
||||
|
||||
void* _internal_data;
|
||||
} TerrainRenderer;
|
||||
|
||||
extern StandardDefinition TerrainDefinitionClass;
|
||||
extern StandardRenderer TerrainRendererClass;
|
||||
|
||||
void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset);
|
||||
void terrainRenderSurface(Renderer* renderer);
|
||||
/*Renderer terrainCreatePreviewRenderer();
|
||||
Color terrainGetPreview(Renderer* renderer, double x, double y);*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
94
lib_paysages/terrain/raster.c
Normal file
94
lib_paysages/terrain/raster.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
#include "public.h"
|
||||
#include "private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "../renderer.h"
|
||||
|
||||
/*
|
||||
* Terrain rasterization.
|
||||
*/
|
||||
|
||||
static inline Vector3 _getPoint(TerrainDefinition* definition, Renderer* renderer, double x, double z)
|
||||
{
|
||||
Vector3 result;
|
||||
|
||||
result.x = x;
|
||||
result.y = renderer->terrain->getHeight(renderer, x, z);
|
||||
result.z = z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static Color _postProcessFragment(Renderer* renderer, Vector3 point, void* data)
|
||||
{
|
||||
double precision;
|
||||
|
||||
point = _getPoint(renderer->terrain->definition, renderer, point.x, point.z);
|
||||
|
||||
precision = renderer->getPrecision(renderer, point);
|
||||
return renderer->terrain->getFinalColor(renderer, point, precision);
|
||||
}
|
||||
|
||||
static void _renderQuad(TerrainDefinition* definition, Renderer* renderer, double x, double z, double size, double water_height)
|
||||
{
|
||||
Vector3 v1, v2, v3, v4;
|
||||
|
||||
v1 = _getPoint(definition, renderer, x, z);
|
||||
v2 = _getPoint(definition, renderer, x, z + size);
|
||||
v3 = _getPoint(definition, renderer, x + size, z + size);
|
||||
v4 = _getPoint(definition, renderer, x + size, z);
|
||||
|
||||
if (v1.y > water_height || v2.y > water_height || v3.y > water_height || v4.y > water_height)
|
||||
{
|
||||
renderer->pushQuad(renderer, v1, v2, v3, v4, _postProcessFragment, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void terrainRenderSurface(Renderer* renderer)
|
||||
{
|
||||
int chunk_factor, chunk_count, i;
|
||||
double cx = renderer->camera_location.x;
|
||||
double cz = renderer->camera_location.z;
|
||||
double min_chunk_size, visible_chunk_size;
|
||||
double radius_int, radius_ext, chunk_size;
|
||||
double water_height;
|
||||
TerrainDefinition* definition = renderer->terrain->definition;
|
||||
|
||||
min_chunk_size = 0.1 / (double)renderer->render_quality;
|
||||
visible_chunk_size = 0.05 / (double)renderer->render_quality;
|
||||
|
||||
chunk_factor = 1;
|
||||
chunk_count = 2;
|
||||
radius_int = 0.0;
|
||||
radius_ext = min_chunk_size;
|
||||
chunk_size = min_chunk_size;
|
||||
|
||||
water_height = renderer->getWaterHeightInfo(renderer).max_height;
|
||||
|
||||
while (radius_ext < 1000.0)
|
||||
{
|
||||
if (!renderer->addRenderProgress(renderer, 0.0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < chunk_count - 1; i++)
|
||||
{
|
||||
_renderQuad(definition, renderer, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size, water_height);
|
||||
_renderQuad(definition, renderer, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size, water_height);
|
||||
_renderQuad(definition, renderer, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size, water_height);
|
||||
_renderQuad(definition, renderer, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size, water_height);
|
||||
}
|
||||
|
||||
if (chunk_count % 64 == 0 && chunk_size / radius_int < visible_chunk_size)
|
||||
{
|
||||
chunk_count /= 2;
|
||||
chunk_factor *= 2;
|
||||
/* TODO Fill in gaps with triangles */
|
||||
}
|
||||
chunk_count += 2;
|
||||
chunk_size = min_chunk_size * chunk_factor;
|
||||
radius_int = radius_ext;
|
||||
radius_ext += chunk_size;
|
||||
}
|
||||
}
|
|
@ -1,175 +0,0 @@
|
|||
#include "terraincanvas.h"
|
||||
#include "scenery.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
TerrainCanvas* terrainCanvasCreate()
|
||||
{
|
||||
TerrainCanvas* result = malloc(sizeof(TerrainCanvas));
|
||||
|
||||
result->area = geoareaCreate();
|
||||
result->offset_y = 0.0;
|
||||
result->height_map = heightmapCreate();
|
||||
heightmapChangeResolution(&result->height_map, 256, 256);
|
||||
result->height_factor = 1.0;
|
||||
result->detail_noise = noiseCreateGenerator();
|
||||
noiseAddLevelsSimple(result->detail_noise, 5, 1.0, 1.0);
|
||||
result->detail_height_factor = 0.2;
|
||||
result->detail_scaling = 0.4;
|
||||
result->mask.mode = INTEGRATIONMASK_MODE_CIRCLE;
|
||||
result->mask.smoothing = 0.1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void terrainCanvasDelete(TerrainCanvas* canvas)
|
||||
{
|
||||
heightmapDelete(&canvas->height_map);
|
||||
noiseDeleteGenerator(canvas->detail_noise);
|
||||
free(canvas);
|
||||
}
|
||||
|
||||
void terrainCanvasCopy(TerrainCanvas* source, TerrainCanvas* destination)
|
||||
{
|
||||
geoareaCopy(&source->area, &destination->area);
|
||||
destination->offset_y = source->offset_y;
|
||||
destination->height_factor = source->height_factor;
|
||||
heightmapCopy(&source->height_map, &destination->height_map);
|
||||
noiseCopy(source->detail_noise, destination->detail_noise);
|
||||
destination->detail_height_factor = source->detail_height_factor;
|
||||
destination->detail_scaling = source->detail_scaling;
|
||||
destination->mask = source->mask;
|
||||
}
|
||||
|
||||
void terrainCanvasValidate(TerrainCanvas* canvas)
|
||||
{
|
||||
if (canvas->detail_scaling < 0.00001)
|
||||
{
|
||||
canvas->detail_scaling = 0.00001;
|
||||
}
|
||||
geoareaValidate(&canvas->area);
|
||||
heightmapValidate(&canvas->height_map);
|
||||
noiseValidate(canvas->detail_noise);
|
||||
}
|
||||
|
||||
LayerType terrainCanvasGetLayerType()
|
||||
{
|
||||
LayerType result;
|
||||
|
||||
result.callback_create = (LayerCallbackCreate)terrainCanvasCreate;
|
||||
result.callback_delete = (LayerCallbackDelete)terrainCanvasDelete;
|
||||
result.callback_copy = (LayerCallbackCopy)terrainCanvasCopy;
|
||||
result.callback_validate = (LayerCallbackValidate)terrainCanvasValidate;
|
||||
result.callback_save = (LayerCallbackSave)terrainCanvasSave;
|
||||
result.callback_load = (LayerCallbackLoad)terrainCanvasLoad;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void terrainCanvasSave(PackStream* stream, TerrainCanvas* canvas)
|
||||
{
|
||||
geoareaSave(stream, &canvas->area);
|
||||
packWriteDouble(stream, &canvas->offset_y);
|
||||
heightmapSave(stream, &canvas->height_map);
|
||||
packWriteDouble(stream, &canvas->height_factor);
|
||||
noiseSaveGenerator(stream, canvas->detail_noise);
|
||||
packWriteDouble(stream, &canvas->detail_height_factor);
|
||||
packWriteDouble(stream, &canvas->detail_scaling);
|
||||
packWriteInt(stream, &canvas->mask.mode);
|
||||
packWriteDouble(stream, &canvas->mask.smoothing);
|
||||
}
|
||||
|
||||
void terrainCanvasLoad(PackStream* stream, TerrainCanvas* canvas)
|
||||
{
|
||||
geoareaLoad(stream, &canvas->area);
|
||||
packReadDouble(stream, &canvas->offset_y);
|
||||
heightmapLoad(stream, &canvas->height_map);
|
||||
packReadDouble(stream, &canvas->height_factor);
|
||||
noiseLoadGenerator(stream, canvas->detail_noise);
|
||||
packReadDouble(stream, &canvas->detail_height_factor);
|
||||
packReadDouble(stream, &canvas->detail_scaling);
|
||||
packReadInt(stream, &canvas->mask.mode);
|
||||
packReadDouble(stream, &canvas->mask.smoothing);
|
||||
}
|
||||
|
||||
void terrainCanvasGetLimits(TerrainCanvas* canvas, double* ymin, double* ymax)
|
||||
{
|
||||
double noise_max = noiseGetMaxValue(canvas->detail_noise) * canvas->detail_height_factor;
|
||||
heightmapGetLimits(&canvas->height_map, ymin, ymax);
|
||||
*ymin -= noise_max;
|
||||
*ymax += noise_max;
|
||||
}
|
||||
|
||||
void terrainCanvasRevertToTerrain(TerrainCanvas* canvas)
|
||||
{
|
||||
TerrainDefinition terrain;
|
||||
|
||||
terrain = terrainCreateDefinition();
|
||||
sceneryGetTerrain(&terrain);
|
||||
|
||||
heightmapRevertToTerrain(&canvas->height_map, &terrain, &canvas->area);
|
||||
|
||||
terrainDeleteDefinition(&terrain);
|
||||
}
|
||||
|
||||
Vector3 terrainCanvasApply(TerrainCanvas* canvas, Vector3 location)
|
||||
{
|
||||
if (location.x >= canvas->area.location_x &&
|
||||
location.z >= canvas->area.location_z &&
|
||||
location.x <= canvas->area.location_x + canvas->area.size_x &&
|
||||
location.z <= canvas->area.location_z + canvas->area.size_z)
|
||||
{
|
||||
double inside_x, inside_z;
|
||||
double height;
|
||||
|
||||
/* Get height map displacement */
|
||||
geoareaToLocal(&canvas->area, location.x, location.z, &inside_x, &inside_z);
|
||||
height = heightmapGetValue(&canvas->height_map, inside_x, inside_z);
|
||||
|
||||
/* Apply factor */
|
||||
height = height * canvas->height_factor + canvas->offset_y;
|
||||
|
||||
/* Apply detail noise */
|
||||
height += noiseGet2DTotal(canvas->detail_noise, location.x / canvas->detail_scaling, location.z / canvas->detail_scaling) * canvas->detail_height_factor;
|
||||
|
||||
/* Apply integration mask */
|
||||
double influence = terrainCanvasGetMaskValue(canvas, inside_x, inside_z);
|
||||
location.y = influence * height + (1.0 - influence) * location.y;
|
||||
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
double terrainCanvasGetMaskValue(TerrainCanvas* canvas, double local_x, double local_z)
|
||||
{
|
||||
double distance;
|
||||
|
||||
local_x = (local_x - 0.5) * 2.0;
|
||||
local_z = (local_z - 0.5) * 2.0;
|
||||
|
||||
if (canvas->mask.mode == INTEGRATIONMASK_MODE_SQUARE)
|
||||
{
|
||||
local_x = fabs(local_x);
|
||||
local_z = fabs(local_z);
|
||||
distance = local_x > local_z ? local_x : local_z;
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = sqrt(local_x * local_x + local_z * local_z);
|
||||
}
|
||||
|
||||
if (distance <= 1.0 - canvas->mask.smoothing)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
else if (distance <= 1.0)
|
||||
{
|
||||
return (1.0 - distance) / canvas->mask.smoothing;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
#ifndef _PAYSAGES_TERRAINCANVAS_H_
|
||||
#define _PAYSAGES_TERRAINCANVAS_H_
|
||||
|
||||
/* Terrain edition by painting over an area */
|
||||
|
||||
#include "pack.h"
|
||||
#include "noise.h"
|
||||
#include "terrain.h"
|
||||
#include "layers.h"
|
||||
#include "heightmap.h"
|
||||
#include "geoarea.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int mode;
|
||||
double smoothing;
|
||||
} IntegrationMask;
|
||||
|
||||
#define INTEGRATIONMASK_MODE_SQUARE 0
|
||||
#define INTEGRATIONMASK_MODE_CIRCLE 1
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GeoArea area;
|
||||
double offset_y;
|
||||
HeightMap height_map;
|
||||
double height_factor;
|
||||
NoiseGenerator* detail_noise;
|
||||
double detail_height_factor;
|
||||
double detail_scaling;
|
||||
IntegrationMask mask;
|
||||
} TerrainCanvas;
|
||||
|
||||
TerrainCanvas* terrainCanvasCreate();
|
||||
void terrainCanvasDelete(TerrainCanvas* canvas);
|
||||
void terrainCanvasCopy(TerrainCanvas* source, TerrainCanvas* destination);
|
||||
void terrainCanvasValidate(TerrainCanvas* canvas);
|
||||
LayerType terrainCanvasGetLayerType();
|
||||
|
||||
void terrainCanvasSave(PackStream* stream, TerrainCanvas* canvas);
|
||||
void terrainCanvasLoad(PackStream* stream, TerrainCanvas* canvas);
|
||||
|
||||
void terrainCanvasGetLimits(TerrainCanvas* canvas, double* ymin, double* ymax);
|
||||
void terrainCanvasRevertToTerrain(TerrainCanvas* canvas);
|
||||
Vector3 terrainCanvasApply(TerrainCanvas* canvas, Vector3 location);
|
||||
double terrainCanvasGetMaskValue(TerrainCanvas* canvas, double local_x, double local_z);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -6,10 +6,11 @@
|
|||
#include <assert.h>
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "terrain/public.h"
|
||||
#include "color.h"
|
||||
#include "euclid.h"
|
||||
#include "lighting.h"
|
||||
#include "terrain.h"
|
||||
#include "renderer.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define TEXTURES_MAX_LAYERS 50
|
||||
|
@ -177,25 +178,25 @@ static inline TextureResult _getTerrainResult(Renderer* renderer, double x, doub
|
|||
|
||||
center.x = x;
|
||||
center.z = z;
|
||||
center.y = renderer->getTerrainHeight(renderer, center.x, center.z);
|
||||
center.y = renderer->terrain->getHeight(renderer, center.x, center.z);
|
||||
|
||||
east.x = x + detail;
|
||||
east.z = z;
|
||||
east.y = renderer->getTerrainHeight(renderer, east.x, east.z);
|
||||
east.y = renderer->terrain->getHeight(renderer, east.x, east.z);
|
||||
|
||||
south.x = x;
|
||||
south.z = z + detail;
|
||||
south.y = renderer->getTerrainHeight(renderer, south.x, south.z);
|
||||
south.y = renderer->terrain->getHeight(renderer, south.x, south.z);
|
||||
|
||||
if (renderer->render_quality > 5)
|
||||
{
|
||||
west.x = x - detail;
|
||||
west.z = z;
|
||||
west.y = renderer->getTerrainHeight(renderer, west.x, west.z);
|
||||
west.y = renderer->terrain->getHeight(renderer, west.x, west.z);
|
||||
|
||||
north.x = x;
|
||||
north.z = z - detail;
|
||||
north.y = renderer->getTerrainHeight(renderer, north.x, north.z);
|
||||
north.y = renderer->terrain->getHeight(renderer, north.x, north.z);
|
||||
|
||||
result.normal = _getNormal4(center, north, east, south, west);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include "color.h"
|
||||
#include "euclid.h"
|
||||
#include "render.h"
|
||||
#include "terrain.h"
|
||||
#include "lighting.h"
|
||||
#include "tools.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue