diff --git a/gui_qt/dialognoise.cpp b/gui_qt/dialognoise.cpp index 4247f56..d0e89f8 100644 --- a/gui_qt/dialognoise.cpp +++ b/gui_qt/dialognoise.cpp @@ -21,7 +21,7 @@ public: _noise = noise; _level = -1; } - + void setLevel(int row) { _level = row; @@ -76,7 +76,7 @@ DialogNoise::DialogNoise(QWidget *parent, NoiseGenerator* value): QWidget* form; QWidget* buttons; QPushButton* button; - + _base = value; _current = noiseCreateGenerator(); @@ -85,7 +85,7 @@ DialogNoise::DialogNoise(QWidget *parent, NoiseGenerator* value): previews = new QWidget(this); previews->setLayout(new QVBoxLayout()); layout()->addWidget(previews); - + previewLevel = new PreviewLevel(previews, _current); previews->layout()->addWidget(new QLabel("Level preview")); previews->layout()->addWidget(previewLevel); @@ -98,16 +98,16 @@ DialogNoise::DialogNoise(QWidget *parent, NoiseGenerator* value): form = new QWidget(this); form->setLayout(new QVBoxLayout()); layout()->addWidget(form); - + form->layout()->addWidget(new QLabel("Noise components")); levels = new QListWidget(form); form->layout()->addWidget(levels); QObject::connect(levels, SIGNAL(currentRowChanged(int)), this, SLOT(levelChanged(int))); - + buttons = new QWidget(form); buttons->setLayout(new QHBoxLayout()); form->layout()->addWidget(buttons); - + button = new QPushButton("Add component", buttons); buttons->layout()->addWidget(button); QObject::connect(button, SIGNAL(clicked()), this, SLOT(addLevel())); @@ -139,11 +139,11 @@ DialogNoise::DialogNoise(QWidget *parent, NoiseGenerator* value): slider_scaling->setTickPosition(QSlider::TicksBelow); form->layout()->addWidget(slider_scaling); QObject::connect(slider_scaling, SIGNAL(valueChanged(int)), this, SLOT(scalingChanged(int))); - + buttons = new QWidget(form); buttons->setLayout(new QHBoxLayout()); form->layout()->addWidget(buttons); - + button = new QPushButton("Validate", buttons); buttons->layout()->addWidget(button); QObject::connect(button, SIGNAL(clicked()), this, SLOT(accept())); @@ -157,7 +157,7 @@ DialogNoise::DialogNoise(QWidget *parent, NoiseGenerator* value): QObject::connect(button, SIGNAL(clicked()), this, SLOT(reject())); setWindowTitle("Paysages 3D - Noise editor"); - + revert(); } @@ -165,7 +165,7 @@ DialogNoise::~DialogNoise() { delete previewLevel; delete previewTotal; - + noiseDeleteGenerator(_current); } @@ -202,14 +202,14 @@ void DialogNoise::revert() void DialogNoise::revertToCurrent() { int i, n; - + levels->clear(); n = noiseGetLevelCount(_current); for (i = 0; i < n; i++) { - levels->addItem("Level"); + levels->addItem(QString("Component %1").arg(i + 1)); } - + previewLevel->redraw(); previewTotal->redraw(); } @@ -217,20 +217,22 @@ void DialogNoise::revertToCurrent() void DialogNoise::addLevel() { NoiseLevel level; - + level.height = 0.1; level.scaling = 0.1; level.xoffset = 0.0; level.yoffset = 0.0; level.zoffset = 0.0; noiseAddLevel(_current, level); - + revertToCurrent(); } void DialogNoise::removeLevel() { - // TODO + noiseRemoveLevel(_current, _current_level); + + revertToCurrent(); } void DialogNoise::levelChanged(int row) @@ -239,7 +241,7 @@ void DialogNoise::levelChanged(int row) { _current_level = row; ((PreviewLevel*)previewLevel)->setLevel(row); - + slider_height->setValue(_current_level_params.height * 1000.0); slider_scaling->setValue(_current_level_params.scaling * 1000.0); } diff --git a/gui_qt/formterrain.cpp b/gui_qt/formterrain.cpp new file mode 100644 index 0000000..0f2c4bc --- /dev/null +++ b/gui_qt/formterrain.cpp @@ -0,0 +1,75 @@ +#include "formterrain.h" + +#include "tools.h" +#include +#include +#include + +#include "../lib_paysages/terrain.h" +#include "../lib_paysages/shared/functions.h" +#include "../lib_paysages/shared/constants.h" + +static TerrainDefinition _definition; + +/**************** Previews ****************/ +class PreviewTerrainHeight:public Preview +{ +public: + PreviewTerrainHeight(QWidget* parent): + Preview(parent) + { + } +protected: + QColor getColor(double x, double y) + { + double height; + + height = terrainGetHeightNormalized(x, y); + return QColor((int)(255.0 * height), (int)(255.0 * height), (int)(255.0 * height)); + } +}; + +class PreviewTerrainColor:public Preview +{ +public: + PreviewTerrainColor(QWidget* parent): + Preview(parent) + { + _environment.toggle_fog = 0; + } +protected: + QColor getColor(double x, double y) + { + return colorToQColor(terrainGetColorCustom(x, y, scaling, &_definition, NULL, &_environment)); + } +private: + TerrainEnvironment _environment; +}; + +/**************** Form ****************/ +FormTerrain::FormTerrain(QWidget *parent): + BaseForm(parent) +{ + _definition = terrainCreateDefinition(); + + previewHeight = new PreviewTerrainHeight(this); + previewColor = new PreviewTerrainColor(this); + addPreview(previewHeight, QString("Height preview")); + addPreview(previewColor, QString("Color preview")); + + addInputNoise("Height", _definition.height_noise); + + revertConfig(); +} + +void FormTerrain::revertConfig() +{ + terrainCopyDefinition(terrainGetDefinition(), &_definition); + BaseForm::revertConfig(); +} + +void FormTerrain::applyConfig() +{ + terrainSetDefinition(_definition); + BaseForm::applyConfig(); +} diff --git a/gui_qt/formterrain.h b/gui_qt/formterrain.h new file mode 100644 index 0000000..7bb292d --- /dev/null +++ b/gui_qt/formterrain.h @@ -0,0 +1,24 @@ +#ifndef _PAYSAGES_QT_FORMTERRAIN_H_ +#define _PAYSAGES_QT_FORMTERRAIN_H_ + +#include +#include "preview.h" +#include "baseform.h" + +class FormTerrain : public BaseForm +{ + Q_OBJECT + +public: + explicit FormTerrain(QWidget *parent = 0); + +public slots: + virtual void revertConfig(); + virtual void applyConfig(); + +private: + Preview* previewHeight; + Preview* previewColor; +}; + +#endif diff --git a/gui_qt/formwater.cpp b/gui_qt/formwater.cpp index 8de4169..5809cad 100644 --- a/gui_qt/formwater.cpp +++ b/gui_qt/formwater.cpp @@ -13,10 +13,10 @@ static WaterDefinition _definition; /**************** Previews ****************/ -class PreviewCoverage:public Preview +class PreviewWaterCoverage:public Preview { public: - PreviewCoverage(QWidget* parent): + PreviewWaterCoverage(QWidget* parent): Preview(parent) { } @@ -38,10 +38,10 @@ protected: } }; -class PreviewColor:public Preview +class PreviewWaterColor:public Preview { public: - PreviewColor(QWidget* parent): + PreviewWaterColor(QWidget* parent): Preview(parent) { } @@ -85,6 +85,7 @@ protected: environment.toggle_fog = 0; environment.toggle_shadows = 0; quality.force_detail = 0.0001; + quality.detail_boost = 1.0; result = waterGetColorCustom(location, look, &definition, &quality, &environment).final; return colorToQColor(result); @@ -100,6 +101,7 @@ private: if (direction.z < 0.0001) { result.hit_color = COLOR_WHITE; + result.hit_location = start; } else { @@ -114,8 +116,10 @@ private: { result.hit_color = COLOR_GREY; } + result.hit_location.x = x; + result.hit_location.y = y; + result.hit_location.z = 0.0; } - /* TODO hit_location */ return result; } @@ -127,8 +131,8 @@ FormWater::FormWater(QWidget *parent): { _definition = waterCreateDefinition(); - previewCoverage = new PreviewCoverage(this); - previewColor = new PreviewColor(this); + previewCoverage = new PreviewWaterCoverage(this); + previewColor = new PreviewWaterColor(this); addPreview(previewCoverage, QString("Coverage preview")); addPreview(previewColor, QString("Color preview")); diff --git a/gui_qt/mainwindow.cpp b/gui_qt/mainwindow.cpp index 0e31607..e007ff3 100644 --- a/gui_qt/mainwindow.cpp +++ b/gui_qt/mainwindow.cpp @@ -4,6 +4,7 @@ #include #include +#include "formterrain.h" #include "formwater.h" #include "formsky.h" #include "formrender.h" @@ -30,7 +31,7 @@ MainWindow::MainWindow(QWidget *parent) : QMenu* menu; tabs = new QTabWidget(this); - tabs->addTab(new BaseForm(tabs), "Temp"); + tabs->addTab(new FormTerrain(tabs), "Terrain"); tabs->addTab(new FormWater(tabs), "Water"); tabs->addTab(new FormSky(tabs), "Sky"); tabs->addTab(new FormRender(tabs), "Render"); diff --git a/gui_qt/paysages-qt.pro b/gui_qt/paysages-qt.pro index 27eac72..459b130 100644 --- a/gui_qt/paysages-qt.pro +++ b/gui_qt/paysages-qt.pro @@ -14,34 +14,36 @@ win32:LIBS += ../libpaysages.a -lDevIL -lILU -lILUT -lglib-2.0 -lgthread-2.0 # Input HEADERS += ../lib_paysages/shared/functions.h ../lib_paysages/shared/types.h \ - mainwindow.h \ - formwater.h \ - preview.h \ baseform.h \ - inputdouble.h \ baseinput.h \ - inputcolor.h \ - formrender.h \ - inputint.h \ - dialogrender.h \ dialognoise.h \ - inputcolorgradation.h \ + dialogrender.h \ + formrender.h \ formsky.h \ + formterrain.h \ + formwater.h \ + inputcolor.h \ + inputcolorgradation.h \ + inputdouble.h \ + inputint.h \ inputnoise.h \ + mainwindow.h \ + preview.h \ tools.h FORMS += SOURCES += \ - mainwindow.cpp \ - formwater.cpp \ - preview.cpp \ baseform.cpp \ - inputdouble.cpp \ baseinput.cpp \ - inputcolor.cpp \ - formrender.cpp \ - inputint.cpp \ - dialogrender.cpp \ dialognoise.cpp \ - inputcolorgradation.cpp \ + dialogrender.cpp \ + formrender.cpp \ formsky.cpp \ - inputnoise.cpp + formterrain.cpp \ + formwater.cpp \ + inputcolor.cpp \ + inputcolorgradation.cpp \ + inputdouble.cpp \ + inputint.cpp \ + inputnoise.cpp \ + mainwindow.cpp \ + preview.cpp diff --git a/gui_qt/preview.cpp b/gui_qt/preview.cpp index 602ca22..1cb9216 100644 --- a/gui_qt/preview.cpp +++ b/gui_qt/preview.cpp @@ -3,8 +3,6 @@ #include #include -static QVector _previews; - class PreviewDrawer:public QThread { public: @@ -48,15 +46,18 @@ Preview::Preview(QWidget* parent) : this->xoffset = 0.0; this->yoffset = 0.0; this->pixbuf = new QImage(this->size(), QImage::Format_ARGB32); + this->pixbuf->fill(0x00000000); this->alive = true; this->need_rerender = false; - this->need_render = false; + this->need_render = true; this->setMinimumSize(256, 256); this->setMaximumSize(256, 256); this->resize(256, 256); + QObject::connect(this, SIGNAL(contentChange()), this, SLOT(update())); + this->updater = new PreviewDrawer(this); this->updater->start(); } @@ -85,7 +86,7 @@ void Preview::doRender() } if (this->need_render) { - this->need_render = 0; + this->need_render = false; this->renderPixbuf(); } } @@ -94,7 +95,7 @@ void Preview::doRender() void Preview::redraw() { //lock->lock(); - need_rerender = 1; + need_rerender = true; //lock->unlock(); } @@ -110,12 +111,18 @@ void Preview::resizeEvent(QResizeEvent* event) QImage* image; this->lock->lock(); - image = this->pixbuf; - this->pixbuf = new QImage(this->size(), QImage::Format_ARGB32); - delete image; - this->lock->unlock(); - this->forceRender(); + image = this->pixbuf; + + this->pixbuf = new QImage(this->size(), QImage::Format_ARGB32); + + this->pixbuf->fill(0x00000000); + this->need_rerender = false; + this->need_render = true; + + delete image; + + this->lock->unlock(); } void Preview::paintEvent(QPaintEvent* event) @@ -128,8 +135,8 @@ void Preview::forceRender() { this->lock->lock(); this->pixbuf->fill(0x00000000); - this->need_rerender = 0; - this->need_render = 1; + this->need_rerender = false; + this->need_render = true; this->lock->unlock(); } @@ -164,14 +171,12 @@ void Preview::renderPixbuf() } if (done && (x == w - 1 || x % 10 == 0)) { - this->update(); + emit contentChange(); } - this->lock->unlock(); } } - //static void _scrollPixbuf(SmallPreview* preview, int dx, int dy) //{ // int xstart, ystart, xsize, ysize, y; diff --git a/gui_qt/preview.h b/gui_qt/preview.h index d694bac..8aafc1d 100644 --- a/gui_qt/preview.h +++ b/gui_qt/preview.h @@ -17,7 +17,7 @@ public: static void startUpdater(); void doRender(); void redraw(); - + void setScaling(double scaling); protected: @@ -50,8 +50,12 @@ protected: bool alive; bool need_rerender; bool need_render; + private: QThread* updater; + +signals: + void contentChange(); }; #endif diff --git a/lib_paysages/auto.c b/lib_paysages/auto.c index 4745c29..2e0de34 100644 --- a/lib_paysages/auto.c +++ b/lib_paysages/auto.c @@ -15,6 +15,7 @@ #include "modifiers.h" #include "terrain.h" #include "textures.h" +#include "lighting.h" #ifdef WIN32 #include @@ -47,47 +48,6 @@ void autoInit() #ifdef _SC_NPROCESSORS_ONLN _cpu_count = (int)sysconf(_SC_NPROCESSORS_ONLN); #endif - renderSetBackgroundColor(&COLOR_BLACK); - - terrainInit(); - waterInit(); - renderInit(); -} - -void autoSave(char* filepath) -{ - FILE* f = fopen(filepath, "wb"); - - texturesSave(f); - - cameraSave(f); - cloudsSave(f); - fogSave(f); - lightingSave(f); - renderSave(f); - skySave(f); - terrainSave(f); - waterSave(f); - - fclose(f); -} - -void autoLoad(char* filepath) -{ - FILE* f = fopen(filepath, "rb"); - - texturesLoad(f); - - cameraLoad(f); - cloudsLoad(f); - fogLoad(f); - lightingLoad(f); - renderLoad(f); - skyLoad(f); - terrainLoad(f); - waterLoad(f); - - fclose(f); } void autoSetDaytime(int hour, int minute) @@ -98,8 +58,8 @@ void autoSetDaytime(int hour, int minute) void autoSetDaytimeFraction(double daytime) { SkyDefinition sky; - ColorGradation grad_sun; - Color sun; + /*ColorGradation grad_sun; + Color sun;*/ daytime = fmod(daytime, 1.0); if (daytime < 0.0) @@ -107,7 +67,7 @@ void autoSetDaytimeFraction(double daytime) daytime += 1.0; } - lightingSetSunAngle(0.0, (daytime + 0.25) * M_PI * 2.0); + /*lightingSetSunAngle(0.0, (daytime + 0.25) * M_PI * 2.0); grad_sun = colorGradationCreate(); colorGradationAddRgba(&grad_sun, 0.2, 0.1, 0.1, 0.1, 1.0); @@ -118,7 +78,7 @@ void autoSetDaytimeFraction(double daytime) colorGradationAddRgba(&grad_sun, 0.75, 0.7, 0.6, 0.5, 1.0); colorGradationAddRgba(&grad_sun, 0.8, 0.1, 0.1, 0.1, 1.0); sun = colorGradationGet(&grad_sun, daytime); - lightingSetSunColor(sun); + lightingSetSunColor(sun);*/ sky = skyGetDefinition(); sky.daytime = daytime; @@ -163,6 +123,7 @@ void autoGenRealisticLandscape(int seed) CloudsDefinition cloud; SkyDefinition sky; TextureDefinition texture; + LightingDefinition lighting; int layer; HeightModifier* mod; Zone* zone; @@ -249,6 +210,12 @@ void autoGenRealisticLandscape(int seed) sky.sun_radius = 0.02; skySetDefinition(sky); + /* Lighting */ + lighting = lightingCreateDefinition(); + lighting.autosetfromsky = 1; + lightingSetDefinition(lighting); + + /* Terrain */ terrain = terrainCreateDefinition(); noiseGenerateBaseNoise(terrain.height_noise, 1048576); noiseAddLevelsSimple(terrain.height_noise, 10, 10.0, 1.0); @@ -275,6 +242,7 @@ void autoGenRealisticLandscape(int seed) terrainSetDefinition(terrain); terrainDeleteDefinition(terrain); + /* Textures */ layer = texturesAddLayer(); texture = texturesCreateDefinition(); noiseGenerateBaseNoise(texture.bump_noise, 102400); @@ -308,6 +276,7 @@ void autoGenRealisticLandscape(int seed) texturesSetDefinition(layer, texture); texturesDeleteDefinition(texture);*/ + /* Fog */ fogSetDistance(20.0, 100.0); } diff --git a/lib_paysages/clouds.c b/lib_paysages/clouds.c index 216bcb6..b03aadd 100644 --- a/lib_paysages/clouds.c +++ b/lib_paysages/clouds.c @@ -1,11 +1,13 @@ +#include "clouds.h" + #include #include +#include "lighting.h" #include "shared/types.h" #include "shared/functions.h" #include "shared/constants.h" #include "shared/globals.h" -#include "clouds.h" #define MAX_LAYERS 10 @@ -378,22 +380,26 @@ static int _findSegments(CloudsDefinition* definition, CloudsQuality* quality, V return segment_count; } -static Color _applyLayerLighting(CloudsDefinition* definition, CloudsQuality* quality, Vector3 position, Color base, double detail) +typedef struct +{ + CloudsDefinition* definition; + CloudsQuality* quality; + Color base; + double detail; +} LightFilterData; + +static Color _lightFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data) { - Vector3 direction, normal; double inside_depth, total_depth; CloudSegment segments[20]; Color result; + LightFilterData data; - normal = _getNormal(definition, position, 0.5); - normal = v3Add(normal, _getNormal(definition, position, 0.2)); - normal = v3Add(normal, _getNormal(definition, position, 0.1)); - result = lightingApply(position, normal, 0.0, base, 0.3, 0.1); + data = *((LightFilterData*)custom_data); + data.detail = (data.detail < 0.1) ? 0.1 : data.detail; - direction = sun_direction_inv; - detail = (detail < 0.1) ? 0.1 : detail; /* FIXME Dont hard-code max_total_length */ - _findSegments(definition, quality, position, direction, detail, 20, 50.0, 300.0, &inside_depth, &total_depth, segments); + _findSegments(data.definition, data.quality, location, direction_to_light, data.detail, 20, 50.0, 300.0, &inside_depth, &total_depth, segments); inside_depth *= 0.02; if (inside_depth > 1.0) @@ -401,13 +407,40 @@ static Color _applyLayerLighting(CloudsDefinition* definition, CloudsQuality* qu inside_depth = 1.0; } - result.r = base.r * sun_color_lum * (0.9 - 0.2 * inside_depth) + result.r * (0.1 + 0.1 * inside_depth) + (0.1 - inside_depth * 0.1) * sun_color_lum; - result.g = base.g * sun_color_lum * (0.9 - 0.2 * inside_depth) + result.g * (0.1 + 0.1 * inside_depth) + (0.1 - inside_depth * 0.1) * sun_color_lum; - result.b = base.b * sun_color_lum * (0.9 - 0.2 * inside_depth) + result.b * (0.1 + 0.1 * inside_depth) + (0.1 - inside_depth * 0.1) * sun_color_lum; + result.r = data.base.r * sun_color_lum * (0.9 - 0.2 * inside_depth) + result.r * (0.1 + 0.1 * inside_depth) + (0.1 - inside_depth * 0.1) * sun_color_lum; + result.g = data.base.g * sun_color_lum * (0.9 - 0.2 * inside_depth) + result.g * (0.1 + 0.1 * inside_depth) + (0.1 - inside_depth * 0.1) * sun_color_lum; + result.b = data.base.b * sun_color_lum * (0.9 - 0.2 * inside_depth) + result.b * (0.1 + 0.1 * inside_depth) + (0.1 - inside_depth * 0.1) * sun_color_lum; return result; } +static Color _applyLayerLighting(CloudsDefinition* definition, CloudsQuality* quality, Vector3 position, Color base, double detail) +{ + Vector3 normal; + ReceiverMaterial material; + LightingEnvironment lighting_environment; + LightFilterData data; + + normal = _getNormal(definition, position, 0.5); + normal = v3Add(normal, _getNormal(definition, position, 0.2)); + normal = v3Add(normal, _getNormal(definition, position, 0.1)); + //normal = v3Normalize(normal); + + data.definition = definition; + data.quality = quality; + data.detail = detail; + data.base = base; + + lighting_environment.filter = _lightFilter; + lighting_environment.custom_data = &data; + + material.base = base; + material.reflection = 0.3; + material.shininess = 0.1; + + return lightingApplyCustom(position, normal, material, NULL, NULL, &lighting_environment); +} + Color cloudsGetColorCustom(Vector3 start, Vector3 end, CloudsDefinition* definition, CloudsQuality* quality, CloudsEnvironment* environment) { int i, segment_count; diff --git a/lib_paysages/lighting.c b/lib_paysages/lighting.c index 2757da3..6c525b7 100644 --- a/lib_paysages/lighting.c +++ b/lib_paysages/lighting.c @@ -1,25 +1,173 @@ +#include "lighting.h" + #include #include +#include +#include #include "shared/types.h" #include "shared/functions.h" #include "shared/constants.h" #include "shared/globals.h" -static Color sun_color; -double sun_color_lum; -Vector3 sun_direction; -Vector3 sun_direction_inv; +static LightingDefinition _definition; +static LightingQuality _quality; +static LightingEnvironment _environment; + +static LightDefinition _LIGHT_NULL; + +static Color _standardFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data) +{ + // TODO Find shadows + return light; +} + +void lightingInit() +{ + _definition = lightingCreateDefinition(); + + _environment.filter = _standardFilter; + _environment.custom_data = NULL; + + _LIGHT_NULL.color = COLOR_BLACK; + _LIGHT_NULL.direction.x = 0.0; + _LIGHT_NULL.direction.y = 1.0; + _LIGHT_NULL.direction.z = 0.0; +} void lightingSave(FILE* f) { + // TODO } void lightingLoad(FILE* f) { + // TODO } -void lightingSetSunDirection(double x, double y, double z) +LightingDefinition lightingCreateDefinition() +{ + LightingDefinition definition; + + definition.autosetfromsky = 0; + definition.nblights = 0; + definition._nbautolights = 0; + + return definition; +} + +void lightingDeleteDefinition(LightingDefinition definition) +{ +} + +void lightingCopyDefinition(LightingDefinition source, LightingDefinition* destination) +{ + *destination = source; +} + +void lightingSetDefinition(LightingDefinition definition) +{ + lightingCopyDefinition(definition, &_definition); +} + +LightingDefinition lightingGetDefinition() +{ + return _definition; +} + +void lightingValidateDefinition(LightingDefinition* definition) +{ + if (!definition) + { + lightingValidateDefinition(&_definition); + } + + if (definition->autosetfromsky) + { + // TODO Get lights from sky + } + else + { + definition->_nbautolights = 0; + } +} + +int lightingGetLightCount(LightingDefinition* definition) +{ + return definition->nblights; +} + +LightDefinition lightingGetLight(LightingDefinition* definition, int light) +{ + if (light >= 0 && light < definition->nblights) + { + return definition->lights[light]; + } + else + { + return _LIGHT_NULL; + } +} + +int lightingAddLight(LightingDefinition* definition, LightDefinition light) +{ + if (definition->nblights < MAX_LIGHTS) + { + definition->lights[definition->nblights] = light; + return definition->nblights++; + } + else + { + return -1; + } +} + +void lightingDeleteLight(LightingDefinition* definition, int light) +{ + if (light >= 0 && light < definition->nblights) + { + if (definition->nblights > 1 && light < definition->nblights - 1) + { + memmove(definition->lights + light, definition->lights + light + 1, sizeof(LightDefinition) * definition->nblights - light - 1); + } + definition->nblights--; + } +} + +void lightingSetQuality(LightingQuality quality) +{ + _quality = quality; +} + +LightingQuality lightingGetQuality() +{ + return _quality; +} + +Color lightingApplyCustom(Vector3 location, Vector3 normal, ReceiverMaterial material, LightingDefinition* definition, LightingQuality* quality, LightingEnvironment* environment) +{ + if (!definition) + { + definition = &_definition; + } + if (!quality) + { + quality = &_quality; + } + if (!environment) + { + environment = &_environment; + } + + return COLOR_RED; +} + +Color lightingApply(Vector3 location, Vector3 normal, ReceiverMaterial material) +{ + return lightingApplyCustom(location, normal, material, &_definition, &_quality, &_environment); +} + +/*void lightingSetSunDirection(double x, double y, double z) { sun_direction.x = x; sun_direction.y = y; @@ -44,15 +192,15 @@ Color lightingApply(Vector3 location, Vector3 normal, double shadowing, Color ba Color result, light; double ambient, diffuse, specular; Vector3 view, reflect; - + light.r = sun_color.r * (1.0 - 0.4 * shadowing); light.g = sun_color.g * (1.0 - 0.4 * shadowing); light.b = sun_color.b * (1.0 - 0.4 * shadowing); - + normal = v3Normalize(normal); view = v3Normalize(v3Sub(location, camera_location)); reflect = v3Sub(v3Scale(normal, 2.0 * v3Dot(sun_direction_inv, normal)), sun_direction_inv); - + ambient = 0.2; diffuse = v3Dot(sun_direction_inv, normal); diffuse = pow(diffuse * 0.5 + 0.5, 2.0) * (1.0 - shadowing) + (diffuse * 0.5 + 0.3) * shadowing; @@ -77,6 +225,6 @@ Color lightingApply(Vector3 location, Vector3 normal, double shadowing, Color ba result.g = base.g * ambient + base.g * diffuse * light.g + base.g * specular * light.g; result.b = base.b * ambient + base.b * diffuse * light.b + base.b * specular * light.b; result.a = base.a; - + return result; -} +}*/ diff --git a/lib_paysages/lighting.h b/lib_paysages/lighting.h new file mode 100644 index 0000000..036c54c --- /dev/null +++ b/lib_paysages/lighting.h @@ -0,0 +1,75 @@ +#ifndef _PAYSAGES_LIGHTING_H_ +#define _PAYSAGES_LIGHTING_H_ + +#include "shared/types.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_LIGHTS 10 + +typedef struct +{ + Vector3 direction; + Color color; + double maxshadow; +} LightDefinition; + +typedef struct +{ + int autosetfromsky; + int nblights; + LightDefinition lights[MAX_LIGHTS]; + int _nbautolights; + LightDefinition _autolights[MAX_LIGHTS]; +} LightingDefinition; + +typedef struct +{ + int unused; +} LightingQuality; + +typedef Color (*LightFilter)(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data); + +typedef struct +{ + LightFilter filter; + void* custom_data; +} LightingEnvironment; + +typedef struct +{ + Color base; + double reflection; + double shininess; +} ReceiverMaterial; + +void lightingInit(); +void lightingSave(FILE* f); +void lightingLoad(FILE* f); + +LightingDefinition lightingCreateDefinition(); +void lightingDeleteDefinition(LightingDefinition definition); +void lightingCopyDefinition(LightingDefinition source, LightingDefinition* destination); +void lightingSetDefinition(LightingDefinition definition); +LightingDefinition lightingGetDefinition(); +void lightingValidateDefinition(LightingDefinition* definition); + +int lightingGetLightCount(LightingDefinition* definition); +LightDefinition lightingGetLight(LightingDefinition* definition, int light); +int lightingAddLight(LightingDefinition* definition, LightDefinition light); +void lightingDeleteLight(LightingDefinition* definition, int light); + +void lightingSetQuality(LightingQuality quality); +LightingQuality lightingGetQuality(); + +Color lightingApplyCustom(Vector3 location, Vector3 normal, ReceiverMaterial material, LightingDefinition* definition, LightingQuality* quality, LightingEnvironment* environment); +Color lightingApply(Vector3 location, Vector3 normal, ReceiverMaterial material); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib_paysages/main.c b/lib_paysages/main.c index 84a3a91..0f39193 100644 --- a/lib_paysages/main.c +++ b/lib_paysages/main.c @@ -1,8 +1,5 @@ #include #include -#include -#include -#include #include "IL/il.h" #include "IL/ilu.h" @@ -12,7 +9,13 @@ #include "shared/functions.h" #include "shared/globals.h" #include "shared/system.h" + #include "terrain.h" +#include "water.h" +#include "lighting.h" +#include "textures.h" +#include "sky.h" +#include "clouds.h" void paysagesInit() { @@ -24,11 +27,17 @@ void paysagesInit() cameraSetTarget(0.0, 5.0, 0.0); autoInit(); + skyInit(); + terrainInit(); + texturesInit(); + waterInit(); + lightingInit(); + renderInit(); autoSetRenderQuality(5); autoGenRealisticLandscape(0); autoSetDaytime(8, 30); - + // DEBUG /*double last_height, height, x; last_height = height = 0.0; @@ -42,3 +51,39 @@ void paysagesInit() cameraSetLocation(x - 2.0, height, 0.0); cameraSetTarget(x - 1.0, height, 0.0);*/ } + +void paysagesSave(char* filepath) +{ + FILE* f = fopen(filepath, "wb"); + + cameraSave(f); + cloudsSave(f); + fogSave(f); + renderSave(f); + skySave(f); + terrainSave(f); + texturesSave(f); + waterSave(f); + + lightingSave(f); + + fclose(f); +} + +void paysagesLoad(char* filepath) +{ + FILE* f = fopen(filepath, "rb"); + + cameraLoad(f); + cloudsLoad(f); + fogLoad(f); + renderLoad(f); + skyLoad(f); + terrainLoad(f); + texturesLoad(f); + waterLoad(f); + + lightingLoad(f); + + fclose(f); +} diff --git a/lib_paysages/noise.c b/lib_paysages/noise.c index 3ff179a..b0066cc 100644 --- a/lib_paysages/noise.c +++ b/lib_paysages/noise.c @@ -180,13 +180,13 @@ void noiseAddLevel(NoiseGenerator* generator, NoiseLevel level) void noiseAddLevelSimple(NoiseGenerator* generator, double scaling, double height) { NoiseLevel level; - + level.scaling = scaling; level.height = height; level.xoffset = toolsRandom(); level.yoffset = toolsRandom(); level.zoffset = toolsRandom(); - + noiseAddLevel(generator, level); } @@ -211,12 +211,24 @@ void noiseAddLevels(NoiseGenerator* generator, int level_count, NoiseLevel start void noiseAddLevelsSimple(NoiseGenerator* generator, int level_count, double scaling, double height) { NoiseLevel level; - + level.scaling = scaling; level.height = height; noiseAddLevels(generator, level_count, level, 0.5, 0.5, 1); } +void noiseRemoveLevel(NoiseGenerator* generator, int level) +{ + if (level >= 0 && level < generator->level_count) + { + if (generator->level_count > 1 && level < generator->level_count - 1) + { + memmove(generator->levels + level, generator->levels + level + 1, sizeof(NoiseLevel) * (generator->level_count - level - 1)); + } + generator->level_count--; + } +} + int noiseGetLevel(NoiseGenerator* generator, int level, NoiseLevel* params) { if (level >= 0 && level < generator->level_count) @@ -241,13 +253,13 @@ void noiseSetLevel(NoiseGenerator* generator, int level, NoiseLevel params) void noiseSetLevelSimple(NoiseGenerator* generator, int level, double scaling, double height) { NoiseLevel params; - + params.scaling = scaling; params.height = height; params.xoffset = toolsRandom(); params.yoffset = toolsRandom(); params.zoffset = toolsRandom(); - + noiseSetLevel(generator, level, params); } diff --git a/lib_paysages/render.c b/lib_paysages/render.c index af0d262..b491a1d 100644 --- a/lib_paysages/render.c +++ b/lib_paysages/render.c @@ -56,6 +56,7 @@ void renderLoad(FILE* f) void renderInit() { _lock = mutexCreate(); + renderSetBackgroundColor(&COLOR_BLACK); } void renderSetSize(int width, int height) @@ -263,12 +264,12 @@ static void _processDirtyPixels() static void _setAllDirty() { int x, y; - + _dirty_left = 0; _dirty_right = render_width - 1; _dirty_down = 0; _dirty_up = render_height - 1; - + for (y = _dirty_down; y <= _dirty_up; y++) { for (x = _dirty_left; x <= _dirty_right; x++) @@ -799,10 +800,10 @@ void renderSetPreviewCallbacks(PreviewCallbackResize resize, PreviewCallbackClea _cb_preview_clear = clear ? clear : _previewClear; _cb_preview_draw = draw ? draw : _previewDraw; _cb_preview_update = update ? update : _previewUpdate; - + _cb_preview_resize(render_width, render_height); _cb_preview_clear(background_color); - + _setAllDirty(); _processDirtyPixels(); diff --git a/lib_paysages/shared/functions.h b/lib_paysages/shared/functions.h index 09bb827..8a15581 100644 --- a/lib_paysages/shared/functions.h +++ b/lib_paysages/shared/functions.h @@ -9,6 +9,8 @@ extern "C" { #include void paysagesInit(); +void paysagesSave(char* filepath); +void paysagesLoad(char* filepath); /* array.c */ void arrayCreate(Array* array, int item_size); @@ -21,8 +23,6 @@ void arrayClear(Array* array); /* auto.c */ void autoInit(); -void autoSave(char* filepath); -void autoLoad(char* filepath); void autoSetDaytime(int hour, int minute); void autoSetDaytimeFraction(double daytime); void autoSetRenderQuality(int quality); @@ -97,14 +97,6 @@ void fogSetColor(Color col); void fogSetDistance(double near, double far); Color fogApplyToLocation(Vector3 location, Color base); -/* lighting.c */ -void lightingSave(FILE* f); -void lightingLoad(FILE* f); -void lightingSetSunDirection(double x, double y, double z); -void lightingSetSunAngle(double hor, double ver); -void lightingSetSunColor(Color col); -Color lightingApply(Vector3 location, Vector3 normal, double shadowing, Color base, double reflection, double shininess); - /* noise.c */ NoiseGenerator* noiseCreateGenerator(); void noiseDeleteGenerator(NoiseGenerator* generator); @@ -120,6 +112,7 @@ void noiseAddLevel(NoiseGenerator* generator, NoiseLevel level); void noiseAddLevelSimple(NoiseGenerator* generator, double scaling, double height); void noiseAddLevels(NoiseGenerator* generator, int level_count, NoiseLevel start_level, double scaling_factor, double height_factor, int randomize_offset); void noiseAddLevelsSimple(NoiseGenerator* generator, int level_count, double scaling, double height); +void noiseRemoveLevel(NoiseGenerator* generator, int level); int noiseGetLevel(NoiseGenerator* generator, int level, NoiseLevel* params); void noiseSetLevel(NoiseGenerator* generator, int level, NoiseLevel params); void noiseSetLevelSimple(NoiseGenerator* generator, int level, double scaling, double height); diff --git a/lib_paysages/terrain.c b/lib_paysages/terrain.c index 892840c..362c6a2 100644 --- a/lib_paysages/terrain.c +++ b/lib_paysages/terrain.c @@ -20,12 +20,14 @@ void terrainInit() { _definition = terrainCreateDefinition(); _max_height = noiseGetMaxValue(_definition.height_noise); + + _environment.toggle_fog = 1; } void terrainSave(FILE* f) { int i; - + noiseSave(_definition.height_noise, f); toolsSaveInt(f, _definition.height_modifiers_count); for (i = 0; i < _definition.height_modifiers_count; i++) @@ -37,7 +39,7 @@ void terrainSave(FILE* f) void terrainLoad(FILE* f) { int i; - + noiseLoad(_definition.height_noise, f); _max_height = noiseGetMaxValue(_definition.height_noise); @@ -56,17 +58,17 @@ void terrainLoad(FILE* f) TerrainDefinition terrainCreateDefinition() { TerrainDefinition definition; - + definition.height_noise = noiseCreateGenerator(); definition.height_modifiers_count = 0; - + return definition; } void terrainDeleteDefinition(TerrainDefinition definition) { int i; - + noiseDeleteGenerator(definition.height_noise); for (i = 0; i < definition.height_modifiers_count; i++) { @@ -77,9 +79,9 @@ void terrainDeleteDefinition(TerrainDefinition definition) void terrainCopyDefinition(TerrainDefinition source, TerrainDefinition* destination) { int i; - + noiseCopy(source.height_noise, destination->height_noise); - + for (i = 0; i < destination->height_modifiers_count; i++) { modifierDelete(destination->height_modifiers[i]); @@ -138,16 +140,16 @@ static inline double _getHeight(TerrainDefinition* definition, double x, double { Vector3 location; int i; - + location.x = x; location.y = noiseGet2DDetail(definition->height_noise, x, z, detail); location.z = z; - + for (i = 0; i < definition->height_modifiers_count; i++) { location = modifierApply(definition->height_modifiers[i], location); } - + return location.y; } @@ -214,13 +216,15 @@ double terrainGetShadow(Vector3 start, Vector3 direction) } } -static Color _getColor(TerrainDefinition* definition, Vector3 point, double precision) +static Color _getColor(TerrainDefinition* definition, TerrainEnvironment* environment, Vector3 point, double precision) { Color color; - /* FIXME Environment for textures should be customized */ color = texturesGetColor(point); - color = fogApplyToLocation(point, color); + if (environment->toggle_fog) + { + color = fogApplyToLocation(point, color); + } //color = cloudsApplySegmentResult(color, camera_location, point); return color; @@ -248,7 +252,7 @@ int terrainProjectRay(Vector3 start, Vector3 direction, Vector3* hit_point, Colo { start.y = height; *hit_point = start; - *hit_color = _getColor(&_definition, start, inc_value); + *hit_color = _getColor(&_definition, &_environment, start, inc_value); return 1; } @@ -279,7 +283,7 @@ static int _postProcessFragment(RenderFragment* fragment) point = _getPoint(&_definition, point.x, point.z, precision); - fragment->vertex.color = _getColor(&_definition, point, precision); + fragment->vertex.color = _getColor(&_definition, &_environment, point, precision); return 1; } @@ -324,7 +328,20 @@ double terrainGetHeightNormalized(double x, double z) Color terrainGetColorCustom(double x, double z, double detail, TerrainDefinition* definition, TerrainQuality* quality, TerrainEnvironment* environment) { - return _getColor(definition, _getPoint(definition, x, z, detail), detail); + if (!definition) + { + definition = &_definition; + } + if (!quality) + { + quality = &_quality; + } + if (!environment) + { + environment = &_environment; + } + + return _getColor(definition, environment, _getPoint(definition, x, z, detail), detail); } Color terrainGetColor(double x, double z, double detail) @@ -351,7 +368,7 @@ void terrainRender(RenderProgressCallback callback) { return; } - + for (i = 0; i < chunk_count - 1; i++) { _renderQuad(cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size); diff --git a/lib_paysages/terrain.h b/lib_paysages/terrain.h index fed8bd4..006911e 100644 --- a/lib_paysages/terrain.h +++ b/lib_paysages/terrain.h @@ -26,7 +26,7 @@ typedef struct typedef struct { - int unused; + int toggle_fog; } TerrainEnvironment; void terrainInit(); diff --git a/lib_paysages/water.c b/lib_paysages/water.c index ced1df8..2373882 100644 --- a/lib_paysages/water.c +++ b/lib_paysages/water.c @@ -5,6 +5,7 @@ #include "water.h" #include "terrain.h" +#include "lighting.h" #include @@ -80,6 +81,9 @@ WaterDefinition waterCreateDefinition() result.main_color = COLOR_BLACK; result.depth_color = COLOR_BLACK; result.height = -1000.0; + result.reflection = 0.0; + result.transparency = 0.0; + result.transparency_depth = 0.0; result.waves_noise = noiseCreateGenerator(); result.waves_noise_height = 0.02; result.waves_noise_scale = 0.2; @@ -181,7 +185,8 @@ WaterResult waterGetColorCustom(Vector3 location, Vector3 look, WaterDefinition* RayCastingResult refracted; Vector3 normal; Color color; - double shadowed, detail, depth; + ReceiverMaterial material; + double detail, depth; if (definition == NULL) { @@ -231,15 +236,10 @@ WaterResult waterGetColorCustom(Vector3 location, Vector3 look, WaterDefinition* color.b = definition->main_color.b * (1.0 - definition->transparency) + result.reflected.b * definition->reflection + result.refracted.b * definition->transparency; color.a = 1.0; - if (environment->toggle_shadows) - { - shadowed = terrainGetShadow(location, sun_direction_inv); - } - else - { - shadowed = 0.0; - } - color = lightingApply(location, normal, shadowed, color, 0.8, 0.6); + material.base = color; + material.reflection = 0.8; + material.shininess = 0.6; + color = lightingApplyCustom(location, normal, material, environment->lighting_definition, NULL, environment->lighting_environment); if (environment->toggle_fog) { color = fogApplyToLocation(location, color); diff --git a/lib_paysages/water.h b/lib_paysages/water.h index bd8cd41..ae3fdf3 100644 --- a/lib_paysages/water.h +++ b/lib_paysages/water.h @@ -2,6 +2,7 @@ #define _PAYSAGES_WATER_H_ #include "shared/types.h" +#include "lighting.h" #include #ifdef __cplusplus @@ -32,7 +33,8 @@ typedef struct RayCastingFunction reflection_function; RayCastingFunction refraction_function; int toggle_fog; - int toggle_shadows; + LightingDefinition* lighting_definition; + LightingEnvironment* lighting_environment; } WaterEnvironment; typedef struct