paysages: Big big refactoring for scenery and renderer (WIP - All broken).
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@232 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
0685f21716
commit
48ea553f49
50 changed files with 1190 additions and 4734 deletions
5
Makefile
5
Makefile
|
@ -1,21 +1,16 @@
|
|||
all:
|
||||
@+cd lib_paysages && make
|
||||
@+cd cli && make
|
||||
@+cd gui_gtk && make
|
||||
@+cd gui_qt && qmake && make
|
||||
|
||||
clean:
|
||||
cd lib_paysages && make clean
|
||||
cd cli && make clean
|
||||
cd gui_gtk && make clean
|
||||
cd gui_qt && make clean && rm -f paysages-qt
|
||||
|
||||
run_cli:
|
||||
LD_LIBRARY_PATH=lib_paysages ./cli/paysages-cli
|
||||
|
||||
run_gtk:
|
||||
LD_LIBRARY_PATH=lib_paysages ./gui_gtk/paysages-gtk
|
||||
|
||||
run_qt:
|
||||
LD_LIBRARY_PATH=lib_paysages ./gui_qt/paysages-qt
|
||||
|
||||
|
|
12
TODO
Normal file
12
TODO
Normal file
|
@ -0,0 +1,12 @@
|
|||
- Create a 'scenery' module that will, for each component :
|
||||
- Hold definitions
|
||||
- Setup standard Renderer
|
||||
- Regroup load/save/render (from auto)
|
||||
- Merge all Quality and Environment, as one Renderer.
|
||||
- No more _definition, _quality, _environment in components.
|
||||
- All component methods become custom.
|
||||
- Refactor fog in a new 'atmosphere' module.
|
||||
- In GUI, revertConfig should lock the previews while reverting.
|
||||
- All Save and Load methods should have same signature : void ...Save(FILE*, ...*)
|
||||
- All noises should use the same entropy pool (saved separately), and avoid reallocs.
|
||||
- Remove all global variables (render_quality, render_width...), it should all be set in Renderer.
|
|
@ -1,21 +0,0 @@
|
|||
SOURCES=$(wildcard *.c)
|
||||
OBJECTS=${SOURCES:.c=.o}
|
||||
HEADERS=$(wildcard ../lib_paysages/shared/*.h ../lib_paysages/*.h *.h)
|
||||
RESULT=paysages-gtk
|
||||
CC_FLAGS=-g -pg -Wall $(shell pkg-config --cflags gtk+-3.0) -I..
|
||||
CC_LDFLAGS=$(shell pkg-config --libs gtk+-3.0) -L../lib_paysages/ -lpaysages
|
||||
|
||||
all:${RESULT}
|
||||
|
||||
clean:
|
||||
rm -f ${OBJECTS}
|
||||
rm -f ${RESULT}
|
||||
|
||||
%.o:%.c ${HEADERS}
|
||||
${CC} -c ${CC_FLAGS} $< -o $@
|
||||
|
||||
${RESULT}:${OBJECTS}
|
||||
${CC} $^ ${CC_LDFLAGS} -o $@
|
||||
|
||||
.PHONY:all clean
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
#include <gtk/gtk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#include "lib_paysages/shared/types.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
typedef void (*GuiNoiseChangedCallback)(NoiseGenerator* generator);
|
||||
|
||||
typedef struct SmallPreview SmallPreview;
|
||||
typedef Color (*SmallPreviewCallback)(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling);
|
||||
|
||||
extern GtkBuilder* gui_definition;
|
||||
|
||||
static inline GtkWidget* _get_widget(const char* name, const char* file, int line)
|
||||
{
|
||||
GtkWidget* result;
|
||||
result = (GtkWidget*)gtk_builder_get_object(gui_definition, (name));
|
||||
if (result == NULL)
|
||||
{
|
||||
printf("Widget not found (%s:%d) : %s\n", file, line, name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#define GET_WIDGET(_name_) (_get_widget(_name_, __FILE__, __LINE__))
|
||||
|
||||
void guiUpdate();
|
||||
|
||||
void guiTerrainInit();
|
||||
|
||||
void guiWaterInit();
|
||||
void guiWaterUpdate();
|
||||
|
||||
void guiSkyInit();
|
||||
void guiSkyUpdate();
|
||||
|
||||
void guiCloudsInit();
|
||||
void guiCloudsUpdate();
|
||||
|
||||
void guiRenderInit();
|
||||
|
||||
void guiNoiseInit();
|
||||
void guiNoiseEdit(NoiseGenerator* generator, GuiNoiseChangedCallback callback);
|
||||
|
||||
void guiPreviewStart();
|
||||
void guiPreviewRedraw(SmallPreview* preview);
|
||||
void guiPreviewRedrawAll();
|
||||
SmallPreview* guiPreviewNew(GtkImage* image);
|
||||
void guiPreviewSetTerrainHeight(SmallPreview* preview);
|
||||
void guiPreviewSetTerrainColor(SmallPreview* preview);
|
||||
void guiPreviewSetNoise1D(SmallPreview* preview, NoiseGenerator* generator);
|
||||
void guiPreviewConfigScrolling(SmallPreview* preview, double xmin, double xmax, double ymin, double ymax);
|
||||
void guiPreviewConfigScaling(SmallPreview* preview, double min, double max, double step);
|
||||
void guiPreviewSetRenderer(SmallPreview* preview, SmallPreviewCallback renderer);
|
||||
void guiPreviewSetViewport(SmallPreview* preview, double xoffset, double yoffset, double scaling);
|
|
@ -1,218 +0,0 @@
|
|||
/* Noise editor dialog */
|
||||
|
||||
#include "common.h"
|
||||
#include "lib_paysages/shared/functions.h"
|
||||
#include "lib_paysages/shared/constants.h"
|
||||
|
||||
static GtkWidget* _dialog;
|
||||
static SmallPreview* _preview;
|
||||
static GtkTreeView* _level_list;
|
||||
static GtkListStore* _level_list_model;
|
||||
static NoiseGenerator* _generator;
|
||||
static GuiNoiseChangedCallback _callback;
|
||||
static int _current_mode;
|
||||
|
||||
static Color _cbPreview1DRenderPixel(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
||||
{
|
||||
if (y > noiseGet1DTotal(_generator, x))
|
||||
{
|
||||
return COLOR_WHITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COLOR_BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
static Color _cbPreview2DRenderPixel(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
||||
{
|
||||
Color col;
|
||||
double max_value;
|
||||
|
||||
/* TODO Cache this value */
|
||||
max_value = noiseGetMaxValue(_generator);
|
||||
|
||||
col.r = col.g = col.b = (noiseGet2DTotal(_generator, x, y) / max_value) * 0.5 + 0.5;
|
||||
col.a = 1.0;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
static void _setPreviewMode(int mode)
|
||||
{
|
||||
GtkButton* button;
|
||||
double max_value;
|
||||
|
||||
max_value = noiseGetMaxValue(_generator);
|
||||
|
||||
button = GTK_BUTTON(GET_WIDGET("noise_editor_preview_mode"));
|
||||
if (mode == 1)
|
||||
{
|
||||
_current_mode = 1;
|
||||
guiPreviewSetRenderer(_preview, _cbPreview1DRenderPixel);
|
||||
gtk_button_set_label(button, "1D");
|
||||
|
||||
guiPreviewConfigScrolling(_preview, -max_value * 100.0, max_value * 100.0, -max_value, max_value);
|
||||
}
|
||||
else if (mode == 2)
|
||||
{
|
||||
_current_mode = 2;
|
||||
guiPreviewSetRenderer(_preview, _cbPreview2DRenderPixel);
|
||||
gtk_button_set_label(button, "2D");
|
||||
|
||||
guiPreviewConfigScrolling(_preview, -max_value * 100.0, max_value * 100.0, -max_value * 100.0, max_value * 100.0);
|
||||
}
|
||||
|
||||
guiPreviewConfigScaling(_preview, max_value * 0.001, max_value * 0.1, max_value * 0.001);
|
||||
guiPreviewSetViewport(_preview, 0.0, 0.0, max_value * 0.01);
|
||||
}
|
||||
|
||||
static void _redrawPreview()
|
||||
{
|
||||
guiPreviewRedraw(_preview);
|
||||
}
|
||||
|
||||
static void _resetPreview()
|
||||
{
|
||||
_setPreviewMode(_current_mode);
|
||||
|
||||
_redrawPreview();
|
||||
}
|
||||
|
||||
static void _applyLayerParams()
|
||||
{
|
||||
GtkTreePath* path;
|
||||
GtkTreeViewColumn* column;
|
||||
GtkTreeIter row;
|
||||
int* indices;
|
||||
double height, scale;
|
||||
|
||||
gtk_tree_view_get_cursor(_level_list, &path, &column);
|
||||
indices = gtk_tree_path_get_indices(path);
|
||||
if (indices)
|
||||
{
|
||||
height = (double)gtk_spin_button_get_value(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_height")));
|
||||
scale = (double)gtk_spin_button_get_value(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_scale")));
|
||||
|
||||
noiseSetLevelSimple(_generator, indices[0], scale, height);
|
||||
|
||||
gtk_tree_model_get_iter(GTK_TREE_MODEL(_level_list_model), &row, path);
|
||||
gtk_list_store_set(_level_list_model, &row, 0, height, 1, scale, -1);
|
||||
}
|
||||
_redrawPreview();
|
||||
}
|
||||
|
||||
static void _cbGenerateClicked(GtkButton* button, gpointer user_data)
|
||||
{
|
||||
noiseGenerateBaseNoise(_generator, gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_base_size"))));
|
||||
_redrawPreview();
|
||||
}
|
||||
|
||||
static void _cbPreviewModeClicked(GtkButton* button, gpointer user_data)
|
||||
{
|
||||
if (_current_mode == 1)
|
||||
{
|
||||
_setPreviewMode(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_setPreviewMode(1);
|
||||
}
|
||||
_redrawPreview();
|
||||
}
|
||||
|
||||
static void _cbPreviewResetClicked(GtkButton* button, gpointer user_data)
|
||||
{
|
||||
_resetPreview();
|
||||
}
|
||||
|
||||
static void _cbApplyClicked(GtkButton* button, gpointer user_data)
|
||||
{
|
||||
gtk_widget_hide(_dialog);
|
||||
_callback(_generator);
|
||||
}
|
||||
|
||||
static void _cbCancelClicked(GtkButton* button, gpointer user_data)
|
||||
{
|
||||
gtk_widget_hide(_dialog);
|
||||
}
|
||||
|
||||
static void _cbLevelParamChanged(GtkWidget* widget, gpointer user_data)
|
||||
{
|
||||
_applyLayerParams();
|
||||
}
|
||||
|
||||
static void _cbRowSelected(GtkTreeView* tree_view, gpointer user_data)
|
||||
{
|
||||
GtkTreePath* path;
|
||||
GtkTreeViewColumn* column;
|
||||
int* indices;
|
||||
NoiseLevel params;
|
||||
|
||||
gtk_tree_view_get_cursor(tree_view, &path, &column);
|
||||
indices = gtk_tree_path_get_indices(path);
|
||||
if (indices)
|
||||
{
|
||||
if (noiseGetLevel(_generator, indices[0], ¶ms))
|
||||
{
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_height")), params.height);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_scale")), params.scaling);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void guiNoiseInit()
|
||||
{
|
||||
_dialog = GET_WIDGET("dialog_noise");
|
||||
_level_list = GTK_TREE_VIEW(GET_WIDGET("noise_editor_levels"));
|
||||
_level_list_model = GTK_LIST_STORE(gtk_tree_view_get_model(_level_list));
|
||||
_generator = noiseCreateGenerator();
|
||||
|
||||
gtk_spin_button_set_range(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_base_size")), 1, 4000000);
|
||||
gtk_spin_button_set_increments(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_base_size")), 100, 100000);
|
||||
|
||||
gtk_spin_button_set_range(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_scale")), 0.0001, 100.0);
|
||||
gtk_spin_button_set_increments(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_scale")), 0.0001, 0.1);
|
||||
gtk_spin_button_set_range(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_height")), 0.0, 100.0);
|
||||
gtk_spin_button_set_increments(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_height")), 0.0001, 0.1);
|
||||
|
||||
_preview = guiPreviewNew(GTK_IMAGE(GET_WIDGET("noise_editor_preview")));
|
||||
_resetPreview();
|
||||
|
||||
g_signal_connect(_dialog, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
|
||||
g_signal_connect(GET_WIDGET("noise_editor_generate"), "clicked", G_CALLBACK(_cbGenerateClicked), NULL);
|
||||
g_signal_connect(GET_WIDGET("noise_editor_preview_reset"), "clicked", G_CALLBACK(_cbPreviewResetClicked), NULL);
|
||||
g_signal_connect(GET_WIDGET("noise_editor_preview_mode"), "clicked", G_CALLBACK(_cbPreviewModeClicked), NULL);
|
||||
g_signal_connect(GET_WIDGET("noise_editor_apply"), "clicked", G_CALLBACK(_cbApplyClicked), NULL);
|
||||
g_signal_connect(GET_WIDGET("noise_editor_cancel"), "clicked", G_CALLBACK(_cbCancelClicked), NULL);
|
||||
g_signal_connect(_level_list, "cursor-changed", G_CALLBACK(_cbRowSelected), NULL);
|
||||
g_signal_connect(GET_WIDGET("noise_editor_height"), "value-changed", G_CALLBACK(_cbLevelParamChanged), NULL);
|
||||
g_signal_connect(GET_WIDGET("noise_editor_scale"), "value-changed", G_CALLBACK(_cbLevelParamChanged), NULL);
|
||||
}
|
||||
|
||||
void guiNoiseEdit(NoiseGenerator* generator, GuiNoiseChangedCallback callback)
|
||||
{
|
||||
int i, n;
|
||||
NoiseLevel level;
|
||||
GtkTreeIter row;
|
||||
|
||||
_callback = callback;
|
||||
noiseCopy(generator, _generator);
|
||||
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_base_size")), noiseGetBaseSize(_generator));
|
||||
|
||||
gtk_list_store_clear(_level_list_model);
|
||||
n = noiseGetLevelCount(_generator);
|
||||
for (i = 0 ; i < n; i++)
|
||||
{
|
||||
noiseGetLevel(_generator, i, &level);
|
||||
gtk_list_store_append(_level_list_model, &row);
|
||||
gtk_list_store_set(_level_list_model, &row, 0, level.height, 1, level.scaling, -1);
|
||||
}
|
||||
|
||||
_setPreviewMode(1);
|
||||
_resetPreview();
|
||||
|
||||
gtk_widget_show(_dialog);
|
||||
}
|
||||
|
116
gui_gtk/global.c
116
gui_gtk/global.c
|
@ -1,116 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#include "lib_paysages/shared/functions.h"
|
||||
#include "lib_paysages/shared/constants.h"
|
||||
#include "common.h"
|
||||
|
||||
GtkBuilder* gui_definition;
|
||||
static GtkWindow* _main_window;
|
||||
|
||||
static void _cbQuit(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void _cbLoad(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
dialog = gtk_file_chooser_dialog_new("Load File",
|
||||
_main_window,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
char *filename;
|
||||
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
paysagesLoad(filename);
|
||||
g_free(filename);
|
||||
}
|
||||
|
||||
/* Update all GUI */
|
||||
guiUpdate();
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
static void _cbSaveAs(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
dialog = gtk_file_chooser_dialog_new("Save File",
|
||||
_main_window,
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
char *filename;
|
||||
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
paysagesSave(filename);
|
||||
g_free(filename);
|
||||
}
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
void guiInit()
|
||||
{
|
||||
GError* p_err = NULL;
|
||||
int argc = 0;
|
||||
char** argv = NULL;
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
gui_definition = gtk_builder_new();
|
||||
gtk_builder_add_from_file(gui_definition, "gui_gtk/gui.glade", &p_err);
|
||||
|
||||
_main_window = GTK_WINDOW(GET_WIDGET("main_window"));
|
||||
g_signal_connect(_main_window, "delete_event", G_CALLBACK(_cbQuit), NULL);
|
||||
|
||||
/* Menu bar */
|
||||
g_signal_connect(GET_WIDGET("menu_quit"), "activate", G_CALLBACK(_cbQuit), NULL);
|
||||
g_signal_connect(GET_WIDGET("menu_load"), "activate", G_CALLBACK(_cbLoad), NULL);
|
||||
g_signal_connect(GET_WIDGET("menu_saveas"), "activate", G_CALLBACK(_cbSaveAs), NULL);
|
||||
|
||||
/* Dialogs */
|
||||
guiNoiseInit();
|
||||
|
||||
/* Tabs */
|
||||
guiRenderInit();
|
||||
guiTerrainInit();
|
||||
guiWaterInit();
|
||||
guiCloudsInit();
|
||||
guiSkyInit();
|
||||
}
|
||||
|
||||
void guiStart()
|
||||
{
|
||||
guiPreviewStart();
|
||||
|
||||
guiUpdate();
|
||||
|
||||
gtk_widget_show_all(GTK_WIDGET(_main_window));
|
||||
gtk_main();
|
||||
}
|
||||
|
||||
void guiUpdate()
|
||||
{
|
||||
guiWaterUpdate();
|
||||
guiCloudsUpdate();
|
||||
guiSkyUpdate();
|
||||
|
||||
guiPreviewRedrawAll();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
paysagesInit();
|
||||
guiInit();
|
||||
guiStart();
|
||||
return 0;
|
||||
}
|
2091
gui_gtk/gui.glade
2091
gui_gtk/gui.glade
File diff suppressed because it is too large
Load diff
|
@ -1,431 +0,0 @@
|
|||
/* Small preview management */
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "common.h"
|
||||
#include "lib_paysages/shared/types.h"
|
||||
#include "lib_paysages/shared/functions.h"
|
||||
#include "lib_paysages/shared/constants.h"
|
||||
#include "lib_paysages/shared/system.h"
|
||||
|
||||
#define MAX_PREVIEWS 30
|
||||
|
||||
struct SmallPreview
|
||||
{
|
||||
double conf_scroll_xmin;
|
||||
double conf_scroll_xmax;
|
||||
double conf_scroll_ymin;
|
||||
double conf_scroll_ymax;
|
||||
|
||||
double conf_scale_min;
|
||||
double conf_scale_max;
|
||||
double conf_scale_step;
|
||||
|
||||
double xoffset;
|
||||
double yoffset;
|
||||
double scaling;
|
||||
|
||||
Mutex* lock;
|
||||
GdkPixbuf* pixbuf;
|
||||
GtkImage* image;
|
||||
|
||||
int mousex;
|
||||
int mousey;
|
||||
|
||||
int need_rerender;
|
||||
int need_render;
|
||||
int need_update;
|
||||
SmallPreviewCallback renderer;
|
||||
};
|
||||
|
||||
static int _previews_count = 0;
|
||||
static SmallPreview _preview[MAX_PREVIEWS];
|
||||
static Thread* _thread_update;
|
||||
|
||||
static inline void _forceRender(SmallPreview* preview)
|
||||
{
|
||||
gdk_pixbuf_fill(preview->pixbuf, 0x00000000);
|
||||
preview->need_rerender = 0;
|
||||
preview->need_render = 1;
|
||||
}
|
||||
|
||||
static inline void _updateImage(SmallPreview* preview)
|
||||
{
|
||||
gtk_image_set_from_pixbuf(preview->image, preview->pixbuf);
|
||||
}
|
||||
|
||||
static inline void _renderPixbuf(SmallPreview* preview)
|
||||
{
|
||||
int x, y, done;
|
||||
Color col;
|
||||
void* pixels = gdk_pixbuf_get_pixels(preview->pixbuf);
|
||||
guint32* pixel;
|
||||
int rowstride = gdk_pixbuf_get_rowstride(preview->pixbuf);
|
||||
|
||||
/* TODO Use pixbuf size */
|
||||
for (x = 0; x < 256; x++)
|
||||
{
|
||||
mutexAcquire(preview->lock);
|
||||
if (preview->need_rerender)
|
||||
{
|
||||
mutexRelease(preview->lock);
|
||||
break;
|
||||
}
|
||||
done = 0;
|
||||
for (y = 0; y < 256; y++)
|
||||
{
|
||||
pixel = (guint32*)(pixels + y * rowstride + x * 4);
|
||||
if (!*pixel)
|
||||
{
|
||||
col = preview->renderer(preview, (double)(x - 128) * preview->scaling + preview->xoffset, (double)(y - 128) * preview->scaling + preview->yoffset, preview->xoffset, preview->yoffset, preview->scaling);
|
||||
*pixel = (guint32)colorTo32BitRGBA(&col);
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
if (done)
|
||||
{
|
||||
preview->need_update = 1;
|
||||
}
|
||||
mutexRelease(preview->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void* _doRenders(void* data)
|
||||
{
|
||||
int i;
|
||||
SmallPreview* preview;
|
||||
|
||||
while (1)
|
||||
{
|
||||
for (i = 0; i < _previews_count; i++)
|
||||
{
|
||||
preview = _preview + i;
|
||||
if (preview->need_rerender)
|
||||
{
|
||||
_forceRender(preview);
|
||||
}
|
||||
if (preview->need_render)
|
||||
{
|
||||
preview->need_render = 0;
|
||||
_renderPixbuf(preview);
|
||||
}
|
||||
}
|
||||
timeSleepMs(100);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _doUpdates(void* data)
|
||||
{
|
||||
int i;
|
||||
SmallPreview* preview;
|
||||
|
||||
for (i = 0; i < _previews_count; i++)
|
||||
{
|
||||
preview = _preview + i;
|
||||
if (preview->need_update)
|
||||
{
|
||||
preview->need_update = 0;
|
||||
_updateImage(preview);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _scrollPixbuf(SmallPreview* preview, int dx, int dy)
|
||||
{
|
||||
int xstart, ystart, xsize, ysize, y;
|
||||
void* pixels = gdk_pixbuf_get_pixels(preview->pixbuf);
|
||||
int rowstride = gdk_pixbuf_get_rowstride(preview->pixbuf);
|
||||
|
||||
preview->xoffset -= (double)dx * preview->scaling;
|
||||
preview->yoffset -= (double)dy * preview->scaling;
|
||||
|
||||
/* TODO Use pixbuf size */
|
||||
if (dx == 0 && dy == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (dx <= -256 || dx >= 256 || dy <= -256 || dy >= 256)
|
||||
{
|
||||
_forceRender(preview);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dx < 0)
|
||||
{
|
||||
xstart = -dx;
|
||||
xsize = 256 + dx;
|
||||
}
|
||||
else
|
||||
{
|
||||
xstart = 0;
|
||||
xsize = 256 - dx;
|
||||
}
|
||||
if (dy < 0)
|
||||
{
|
||||
ystart = -dy;
|
||||
ysize = 256 + dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
ystart = 0;
|
||||
ysize = 256 - dy;
|
||||
}
|
||||
memmove(pixels + (ystart + dy) * rowstride + (xstart + dx) * 4, pixels + ystart * rowstride + xstart * 4, (ysize - 1) * rowstride + xsize * 4);
|
||||
if (dy < 0)
|
||||
{
|
||||
memset(pixels + (256 + dy) * rowstride, 0, (-dy - 1) * rowstride + 256 * 4);
|
||||
}
|
||||
else if (dy > 0)
|
||||
{
|
||||
memset(pixels, 0, (dy - 1) * rowstride + 256 * 4);
|
||||
}
|
||||
if (dx < 0)
|
||||
{
|
||||
for (y = ystart + dy; y < ystart + dy + ysize; y++)
|
||||
{
|
||||
memset(pixels + y * rowstride + xsize * 4, 0, -dx * 4);
|
||||
}
|
||||
}
|
||||
else if (dx > 0)
|
||||
{
|
||||
for (y = ystart + dy; y < ystart + dy + ysize; y++)
|
||||
{
|
||||
memset(pixels + y * rowstride, 0, dx * 4);
|
||||
}
|
||||
}
|
||||
preview->need_render = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int _fixScroll(SmallPreview* preview, int dx, int dy, int* new_dx, int* new_dy)
|
||||
{
|
||||
*new_dx = dx;
|
||||
*new_dy = dy;
|
||||
if (preview->xoffset - dx * preview->scaling > preview->conf_scroll_xmax)
|
||||
{
|
||||
*new_dx = (int)floor((preview->conf_scroll_xmax - preview->xoffset) / preview->scaling);
|
||||
}
|
||||
if (preview->xoffset - dx * preview->scaling < preview->conf_scroll_xmin)
|
||||
{
|
||||
*new_dx = (int)floor((preview->conf_scroll_xmin - preview->xoffset) / preview->scaling);
|
||||
}
|
||||
if (preview->yoffset - dy * preview->scaling > preview->conf_scroll_ymax)
|
||||
{
|
||||
*new_dy = (int)floor((preview->conf_scroll_ymax - preview->yoffset) / preview->scaling);
|
||||
}
|
||||
if (preview->yoffset - dy * preview->scaling < preview->conf_scroll_ymin)
|
||||
{
|
||||
*new_dy = (int)floor((preview->conf_scroll_ymin - preview->yoffset) / preview->scaling);
|
||||
}
|
||||
return (*new_dx == 0 && *new_dy == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
static inline int _fixScaling(SmallPreview* preview, double scaling, double* new_scaling)
|
||||
{
|
||||
double old_scaling = preview->scaling;
|
||||
*new_scaling = scaling;
|
||||
if (scaling < preview->conf_scale_min)
|
||||
{
|
||||
*new_scaling = preview->conf_scale_min;
|
||||
}
|
||||
if (scaling > preview->conf_scale_max)
|
||||
{
|
||||
*new_scaling = preview->conf_scale_max;
|
||||
}
|
||||
return (old_scaling == *new_scaling) ? 0 : 1;
|
||||
}
|
||||
|
||||
static int _cbMouseScroll(GtkEventBox* image, GdkEventScroll* event, gpointer data)
|
||||
{
|
||||
SmallPreview* preview = (SmallPreview*)data;
|
||||
|
||||
/* TODO Center the zoom on the cursor */
|
||||
|
||||
if (event->direction == GDK_SCROLL_UP)
|
||||
{
|
||||
mutexAcquire(preview->lock);
|
||||
if (_fixScaling(preview, preview->scaling - preview->conf_scale_step, &preview->scaling))
|
||||
{
|
||||
preview->need_rerender = 1;
|
||||
}
|
||||
mutexRelease(preview->lock);
|
||||
}
|
||||
else if (event->direction == GDK_SCROLL_DOWN)
|
||||
{
|
||||
mutexAcquire(preview->lock);
|
||||
if (_fixScaling(preview, preview->scaling + preview->conf_scale_step, &preview->scaling))
|
||||
{
|
||||
preview->need_rerender = 1;
|
||||
}
|
||||
mutexRelease(preview->lock);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cbMouseButtonPressed(GtkEventBox* image, GdkEventButton* event, gpointer data)
|
||||
{
|
||||
SmallPreview* preview = (SmallPreview*)data;
|
||||
|
||||
if (event->button == 1)
|
||||
{
|
||||
preview->mousex = (int)event->x;
|
||||
preview->mousey = (int)event->y;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cbMouseMove(GtkEventBox* image, GdkEventMotion* event, gpointer data)
|
||||
{
|
||||
SmallPreview* preview = (SmallPreview*)data;
|
||||
int dx, dy;
|
||||
|
||||
if (event->state & GDK_BUTTON1_MASK)
|
||||
{
|
||||
mutexAcquire(preview->lock);
|
||||
|
||||
dx = (int)event->x - preview->mousex;
|
||||
dy = (int)event->y - preview->mousey;
|
||||
|
||||
if (_fixScroll(preview, dx, dy, &dx, &dy))
|
||||
{
|
||||
_scrollPixbuf(preview, dx, dy);
|
||||
}
|
||||
|
||||
preview->mousex = (int)event->x;
|
||||
preview->mousey = (int)event->y;
|
||||
|
||||
mutexRelease(preview->lock);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Color _renderNone(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
||||
{
|
||||
return COLOR_BLACK;
|
||||
}
|
||||
|
||||
void guiPreviewStart()
|
||||
{
|
||||
_thread_update = threadCreate(_doRenders, NULL);
|
||||
g_timeout_add(200, _doUpdates, NULL);
|
||||
}
|
||||
|
||||
void guiPreviewRedraw(SmallPreview* preview)
|
||||
{
|
||||
mutexAcquire(preview->lock);
|
||||
preview->need_rerender = 1;
|
||||
mutexRelease(preview->lock);
|
||||
}
|
||||
|
||||
void guiPreviewRedrawAll()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _previews_count; i++)
|
||||
{
|
||||
guiPreviewRedraw(_preview + i);
|
||||
}
|
||||
}
|
||||
|
||||
SmallPreview* guiPreviewNew(GtkImage* image)
|
||||
{
|
||||
GtkWidget* parent = gtk_widget_get_parent(GTK_WIDGET(image));
|
||||
SmallPreview* preview;
|
||||
|
||||
/* TODO Check the parent can receive events (or is a GtkEventBox) */
|
||||
if (_previews_count < MAX_PREVIEWS)
|
||||
{
|
||||
preview = _preview + _previews_count;
|
||||
preview->lock = mutexCreate();
|
||||
preview->conf_scroll_xmin = 0.0;
|
||||
preview->conf_scroll_xmax = 0.0;
|
||||
preview->conf_scroll_ymin = 0.0;
|
||||
preview->conf_scroll_ymax = 0.0;
|
||||
preview->conf_scale_min = 1.0;
|
||||
preview->conf_scale_max = 1.0;
|
||||
preview->conf_scale_step = 0.0;
|
||||
preview->scaling = 1.0;
|
||||
preview->xoffset = 0.0;
|
||||
preview->yoffset = 0.0;
|
||||
/* TODO Get size from GtkImage */
|
||||
preview->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 1, 8, 256, 256);
|
||||
preview->image = image;
|
||||
preview->need_rerender = 0;
|
||||
preview->need_render = 0;
|
||||
preview->need_update = 0;
|
||||
preview->renderer = _renderNone;
|
||||
|
||||
gtk_image_clear(image);
|
||||
_forceRender(preview);
|
||||
|
||||
g_signal_connect(parent, "scroll-event", G_CALLBACK(_cbMouseScroll), (gpointer)preview);
|
||||
g_signal_connect(parent, "button-press-event", G_CALLBACK(_cbMouseButtonPressed), (gpointer)preview);
|
||||
g_signal_connect(parent, "motion-notify-event", G_CALLBACK(_cbMouseMove), (gpointer)preview);
|
||||
|
||||
_previews_count++;
|
||||
return preview;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO Return fake preview */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void guiPreviewConfigScrolling(SmallPreview* preview, double xmin, double xmax, double ymin, double ymax)
|
||||
{
|
||||
mutexAcquire(preview->lock);
|
||||
preview->conf_scroll_xmin = xmin;
|
||||
preview->conf_scroll_xmax = xmax;
|
||||
preview->conf_scroll_ymin = ymin;
|
||||
preview->conf_scroll_ymax = ymax;
|
||||
preview->need_rerender = 1;
|
||||
mutexRelease(preview->lock);
|
||||
}
|
||||
|
||||
void guiPreviewConfigScaling(SmallPreview* preview, double min, double max, double step)
|
||||
{
|
||||
mutexAcquire(preview->lock);
|
||||
preview->conf_scale_min = min;
|
||||
preview->conf_scale_max = max;
|
||||
preview->conf_scale_step = step;
|
||||
preview->need_rerender = 1;
|
||||
mutexRelease(preview->lock);
|
||||
}
|
||||
|
||||
void guiPreviewSetRenderer(SmallPreview* preview, SmallPreviewCallback renderer)
|
||||
{
|
||||
mutexAcquire(preview->lock);
|
||||
preview->renderer = renderer;
|
||||
preview->need_rerender = 1;
|
||||
mutexRelease(preview->lock);
|
||||
}
|
||||
|
||||
void guiPreviewSetViewport(SmallPreview* preview, double xoffset, double yoffset, double scaling)
|
||||
{
|
||||
mutexAcquire(preview->lock);
|
||||
preview->xoffset = xoffset;
|
||||
preview->yoffset = yoffset;
|
||||
preview->scaling = scaling;
|
||||
preview->need_rerender = 1;
|
||||
mutexRelease(preview->lock);
|
||||
}
|
||||
|
||||
void guiPreviewSetTerrainHeight(SmallPreview* preview)
|
||||
{
|
||||
/*preview->conf_scroll_x = 1;
|
||||
preview->conf_scroll_y = 1;
|
||||
preview->conf_zoom = 1;
|
||||
preview->init_scaling = preview->scaling = 0.1;
|
||||
preview->init_xoffset = preview->xoffset = 0.0;
|
||||
preview->init_yoffset = preview->yoffset = 0.0;
|
||||
|
||||
preview->renderer = _renderTopDownHeight;*/
|
||||
|
||||
guiPreviewRedraw(preview);
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
/* Terrain tab */
|
||||
|
||||
#include "common.h"
|
||||
#include "lib_paysages/shared/functions.h"
|
||||
#include "lib_paysages/shared/constants.h"
|
||||
#include "lib_paysages/clouds.h"
|
||||
#include <math.h>
|
||||
|
||||
static SmallPreview* _preview;
|
||||
static CloudsDefinition _definition;
|
||||
static int _current_layer;
|
||||
|
||||
static GtkTreeView* _list_layers;
|
||||
static GtkListStore* _list_layers_model;
|
||||
|
||||
/***** Internal functions *****/
|
||||
|
||||
static void _revertCurrentLayer()
|
||||
{
|
||||
if (_current_layer >= 0)
|
||||
{
|
||||
cloudsCopyDefinition(cloudsGetDefinition(_current_layer), &_definition);
|
||||
}
|
||||
|
||||
/* TODO Revert layer from config */
|
||||
|
||||
guiPreviewRedraw(_preview);
|
||||
}
|
||||
|
||||
/*static void _applyCurrentLayer()
|
||||
{
|
||||
guiUpdate();
|
||||
}*/
|
||||
|
||||
static void _revertAll()
|
||||
{
|
||||
int i, n;
|
||||
CloudsDefinition layer;
|
||||
GtkTreeIter row;
|
||||
|
||||
gtk_list_store_clear(_list_layers_model);
|
||||
n = cloudsGetLayerCount();
|
||||
for (i = 0 ; i < n; i++)
|
||||
{
|
||||
layer = cloudsGetDefinition(i);
|
||||
gtk_list_store_append(_list_layers_model, &row);
|
||||
gtk_list_store_set(_list_layers_model, &row, 0, layer.ymin, 1, layer.ymax - layer.ymin, -1);
|
||||
}
|
||||
|
||||
if (_current_layer < 0 || _current_layer >= n)
|
||||
{
|
||||
_current_layer = -1;
|
||||
}
|
||||
_revertCurrentLayer();
|
||||
}
|
||||
|
||||
/***** Preview callbacks *****/
|
||||
|
||||
static Color _cbPreviewPixel(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
||||
{
|
||||
Color result, layer_color;
|
||||
Vector3 start, end;
|
||||
|
||||
if (_current_layer < 0)
|
||||
{
|
||||
return COLOR_BLACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
start.x = end.x = x;
|
||||
start.z = end.z = y;
|
||||
start.y = _definition.ymin;
|
||||
end.y = _definition.ymax;
|
||||
result.r = 0.3;
|
||||
result.g = 0.5;
|
||||
result.b = 0.8;
|
||||
result.a = 1.0;
|
||||
layer_color = cloudsGetColorCustom(start, end, &_definition, NULL, NULL);
|
||||
colorMask(&result, &layer_color);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/***** Config callbacks *****/
|
||||
|
||||
static void _cbLayerSelected(GtkTreeView* tree_view, gpointer user_data)
|
||||
{
|
||||
GtkTreePath* path;
|
||||
GtkTreeViewColumn* column;
|
||||
int* indices;
|
||||
|
||||
gtk_tree_view_get_cursor(tree_view, &path, &column);
|
||||
indices = gtk_tree_path_get_indices(path);
|
||||
if (indices)
|
||||
{
|
||||
_current_layer = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_current_layer = -1;
|
||||
}
|
||||
_revertCurrentLayer();
|
||||
}
|
||||
|
||||
/***** Public functions *****/
|
||||
|
||||
void guiCloudsInit()
|
||||
{
|
||||
_list_layers = GTK_TREE_VIEW(GET_WIDGET("clouds_layers"));
|
||||
_list_layers_model = GTK_LIST_STORE(gtk_tree_view_get_model(_list_layers));
|
||||
|
||||
_definition = cloudsCreateDefinition();
|
||||
|
||||
_preview = guiPreviewNew(GTK_IMAGE(GET_WIDGET("clouds_preview")));
|
||||
guiPreviewConfigScaling(_preview, 1.0, 100.0, 1.0);
|
||||
guiPreviewConfigScrolling(_preview, -10000.0, 10000.0, -10000.0, 10000.0);
|
||||
guiPreviewSetViewport(_preview, 0.0, 0.0, 10.0);
|
||||
guiPreviewSetRenderer(_preview, _cbPreviewPixel);
|
||||
|
||||
g_signal_connect(_list_layers, "cursor-changed", G_CALLBACK(_cbLayerSelected), NULL);
|
||||
|
||||
guiCloudsUpdate();
|
||||
}
|
||||
|
||||
void guiCloudsUpdate()
|
||||
{
|
||||
_revertAll();
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
/* Terrain tab */
|
||||
|
||||
#include "common.h"
|
||||
#include "lib_paysages/shared/functions.h"
|
||||
#include "lib_paysages/shared/constants.h"
|
||||
#include "lib_paysages/shared/globals.h"
|
||||
#include "lib_paysages/shared/system.h"
|
||||
|
||||
static GtkImage* _render_final;
|
||||
static GdkPixbuf* _render_buffer = NULL;
|
||||
static guchar* _render_buffer_pixels = NULL;
|
||||
static int _render_buffer_ymax = 0;
|
||||
static int _render_buffer_rowstride = 0;
|
||||
static int _rendering = 0;
|
||||
|
||||
static void _previewResize(int width, int height)
|
||||
{
|
||||
if (_render_buffer)
|
||||
{
|
||||
gdk_pixbuf_unref(_render_buffer);
|
||||
}
|
||||
_render_buffer = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 1, 8, width, height);
|
||||
_render_buffer_pixels = gdk_pixbuf_get_pixels(_render_buffer);
|
||||
_render_buffer_rowstride = gdk_pixbuf_get_rowstride(_render_buffer);
|
||||
_render_buffer_ymax = height - 1;
|
||||
}
|
||||
|
||||
static void _previewClear(Color col)
|
||||
{
|
||||
gdk_pixbuf_fill(_render_buffer, (guint32)colorTo32BitARGB(&col));
|
||||
}
|
||||
|
||||
static void _previewDraw(int x, int y, Color col)
|
||||
{
|
||||
guint32* pixels = (guint32*)(_render_buffer_pixels + (_render_buffer_ymax - y) * _render_buffer_rowstride + x * 4);
|
||||
*pixels = (guint32)colorTo32BitRGBA(&col);
|
||||
}
|
||||
|
||||
static void _previewUpdate(double progress)
|
||||
{
|
||||
gtk_image_set_from_pixbuf(_render_final, _render_buffer);
|
||||
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(GET_WIDGET("render_progress")), progress);
|
||||
}
|
||||
|
||||
static void* _threadRender(void* data)
|
||||
{
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(GET_WIDGET("render_mode_raytracing"))))
|
||||
{
|
||||
autoRenderSceneRayTracing();
|
||||
}
|
||||
else
|
||||
{
|
||||
autoRenderSceneTwoPass(0);
|
||||
}
|
||||
_rendering = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _cbStartRender(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
Thread* thread;
|
||||
|
||||
/* Prepare render */
|
||||
renderSetSize(gtk_spin_button_get_value(GTK_SPIN_BUTTON(GET_WIDGET("render_width"))), gtk_spin_button_get_value(GTK_SPIN_BUTTON(GET_WIDGET("render_height"))));
|
||||
autoSetRenderQuality((int)gtk_range_get_value(GTK_RANGE(GET_WIDGET("render_quality"))));
|
||||
gtk_widget_set_size_request(GET_WIDGET("render_preview"), render_width, render_height);
|
||||
gtk_image_clear(GTK_IMAGE(GET_WIDGET("render_preview")));
|
||||
renderSetPreviewCallbacks(_previewResize, _previewClear, _previewDraw, _previewUpdate);
|
||||
|
||||
/* Open render dialog */
|
||||
gtk_window_set_deletable(GTK_WINDOW(GET_WIDGET("dialog_render")), 0);
|
||||
gtk_widget_show(GET_WIDGET("dialog_render"));
|
||||
gtk_widget_set_sensitive(GET_WIDGET("render_stop"), 1);
|
||||
gtk_widget_set_sensitive(GET_WIDGET("render_close"), 0);
|
||||
|
||||
/* Do the render */
|
||||
_rendering = 1;
|
||||
thread = threadCreate(_threadRender, NULL);
|
||||
while (_rendering)
|
||||
{
|
||||
timeSleepMs(100);
|
||||
while (gtk_events_pending())
|
||||
{
|
||||
gtk_main_iteration();
|
||||
}
|
||||
}
|
||||
threadJoin(thread);
|
||||
|
||||
/* Clean up */
|
||||
renderSetPreviewCallbacks(NULL, NULL, NULL, NULL);
|
||||
gtk_widget_set_sensitive(GET_WIDGET("render_stop"), 0);
|
||||
gtk_widget_set_sensitive(GET_WIDGET("render_close"), 1);
|
||||
}
|
||||
|
||||
static void _cbStopRender(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
if (_rendering)
|
||||
{
|
||||
renderInterrupt();
|
||||
}
|
||||
}
|
||||
|
||||
static void _cbCloseRender(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
gtk_widget_hide(GET_WIDGET("dialog_render"));
|
||||
}
|
||||
|
||||
static void _cbShowRender(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
gtk_widget_show(GET_WIDGET("dialog_render"));
|
||||
}
|
||||
|
||||
static void _cbSaveRender(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
char *filename;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new("Save last render",
|
||||
GTK_WINDOW(GET_WIDGET("main_window")),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "render.png");
|
||||
|
||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
renderSaveToFile(filename);
|
||||
g_free(filename);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
static int _cbWindowClosed(GtkWidget* widget, GdkEvent* event, gpointer data)
|
||||
{
|
||||
gtk_widget_hide(widget);
|
||||
if (_rendering)
|
||||
{
|
||||
renderInterrupt();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void guiRenderInit()
|
||||
{
|
||||
_render_final = GTK_IMAGE(GET_WIDGET("render_preview"));
|
||||
_previewResize(800, 600);
|
||||
_previewClear(COLOR_BLACK);
|
||||
_previewUpdate(0.0);
|
||||
|
||||
g_signal_connect(GET_WIDGET("render_show"), "clicked", G_CALLBACK(_cbShowRender), NULL);
|
||||
g_signal_connect(GET_WIDGET("render_save"), "clicked", G_CALLBACK(_cbSaveRender), NULL);
|
||||
g_signal_connect(GET_WIDGET("render_start"), "clicked", G_CALLBACK(_cbStartRender), NULL);
|
||||
g_signal_connect(GET_WIDGET("render_stop"), "clicked", G_CALLBACK(_cbStopRender), NULL);
|
||||
g_signal_connect(GET_WIDGET("render_close"), "clicked", G_CALLBACK(_cbCloseRender), NULL);
|
||||
g_signal_connect(GET_WIDGET("dialog_render"), "delete-event", G_CALLBACK(_cbWindowClosed), NULL);
|
||||
|
||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("render_quality")), 1, 10);
|
||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("render_quality")), 5);
|
||||
|
||||
gtk_spin_button_set_range(GTK_SPIN_BUTTON(GET_WIDGET("render_width")), 100, 4000);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_WIDGET("render_width")), 1200);
|
||||
gtk_spin_button_set_increments(GTK_SPIN_BUTTON(GET_WIDGET("render_width")), 10, 100);
|
||||
gtk_spin_button_set_range(GTK_SPIN_BUTTON(GET_WIDGET("render_height")), 100, 4000);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_WIDGET("render_height")), 900);
|
||||
gtk_spin_button_set_increments(GTK_SPIN_BUTTON(GET_WIDGET("render_height")), 10, 100);
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
/* Terrain tab */
|
||||
|
||||
#include "common.h"
|
||||
#include "lib_paysages/shared/functions.h"
|
||||
#include "lib_paysages/shared/constants.h"
|
||||
#include "lib_paysages/sky.h"
|
||||
#include <math.h>
|
||||
|
||||
static SmallPreview* _preview_horizon;
|
||||
static SkyDefinition _definition;
|
||||
|
||||
static Color _cbPreviewHorizon(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
||||
{
|
||||
Vector3 eye = {0.0, 0.0, 0.0};
|
||||
Vector3 look;
|
||||
|
||||
look.x = cos(M_PI * (x / 1.28 + 0.5)) * cos(M_PI * (y / 2.56));
|
||||
look.y = -sin(M_PI * (y / 2.56));
|
||||
look.z = sin(M_PI * (x / 1.28 + 0.5)) * cos(M_PI * (y / 2.56));
|
||||
|
||||
return skyGetColorCustom(eye, look, &_definition, NULL, NULL);
|
||||
}
|
||||
|
||||
static inline void _updatePreview()
|
||||
{
|
||||
skyValidateDefinition(&_definition);
|
||||
guiPreviewRedraw(_preview_horizon);
|
||||
}
|
||||
|
||||
static void _redrawColorGradation(GtkImage* image, ColorGradation* gradation)
|
||||
{
|
||||
GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 1, 8, 200, 30);
|
||||
void* pixels = gdk_pixbuf_get_pixels(pixbuf);
|
||||
int rowstride = gdk_pixbuf_get_rowstride(pixbuf);
|
||||
|
||||
int x, y;
|
||||
guint32* pixel;
|
||||
Color col;
|
||||
|
||||
for (x = 0; x < 200; x++)
|
||||
{
|
||||
for (y = 0; y < 30; y++)
|
||||
{
|
||||
pixel = (guint32*)(pixels + y * rowstride + x * 4);
|
||||
col = colorGradationGet(gradation, (double)x / 200.0);
|
||||
*pixel = (guint32)colorTo32BitRGBA(&col);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_image_set_from_pixbuf(image, pixbuf);
|
||||
gdk_pixbuf_unref(pixbuf);
|
||||
}
|
||||
|
||||
static void _cbDaytimeChanged(GtkRange* range, gpointer data)
|
||||
{
|
||||
_definition.daytime = gtk_range_get_value(range);
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
static void _cbSunSizeChanged(GtkRange* range, gpointer data)
|
||||
{
|
||||
_definition.sun_radius = gtk_range_get_value(range);
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
static void _cbHazeHeightChanged(GtkRange* range, gpointer data)
|
||||
{
|
||||
_definition.haze_height = gtk_range_get_value(range);
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
static void _cbHazeSmoothingChanged(GtkRange* range, gpointer data)
|
||||
{
|
||||
_definition.haze_smoothing = gtk_range_get_value(range);
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
static void _cbRevertConfig(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
skyCopyDefinition(skyGetDefinition(), &_definition);
|
||||
|
||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("sky_daytime")), _definition.daytime);
|
||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("sky_sun_size")), _definition.sun_radius);
|
||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("sky_haze_height")), _definition.haze_height);
|
||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("sky_haze_smoothing")), _definition.haze_smoothing);
|
||||
|
||||
_redrawColorGradation(GTK_IMAGE(GET_WIDGET("sky_colorgradient_sun")), &_definition.sun_color);
|
||||
_redrawColorGradation(GTK_IMAGE(GET_WIDGET("sky_colorgradient_zenith")),& _definition.zenith_color);
|
||||
_redrawColorGradation(GTK_IMAGE(GET_WIDGET("sky_colorgradient_haze")), &_definition.haze_color);
|
||||
|
||||
_updatePreview();
|
||||
}
|
||||
|
||||
static void _cbApplyConfig(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
skySetDefinition(_definition);
|
||||
guiUpdate();
|
||||
}
|
||||
|
||||
void guiSkyInit()
|
||||
{
|
||||
_definition = skyCreateDefinition();
|
||||
|
||||
/* Buttons */
|
||||
g_signal_connect(GET_WIDGET("sky_apply"), "clicked", G_CALLBACK(_cbApplyConfig), NULL);
|
||||
g_signal_connect(GET_WIDGET("sky_revert"), "clicked", G_CALLBACK(_cbRevertConfig), NULL);
|
||||
|
||||
/* Configs */
|
||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("sky_daytime")), 0.0, 1.0);
|
||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("sky_sun_size")), 0.0, 0.3);
|
||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("sky_haze_height")), 0.0, 1.0);
|
||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("sky_haze_smoothing")), 0.0, 1.0);
|
||||
|
||||
/* Config signals */
|
||||
g_signal_connect(GET_WIDGET("sky_daytime"), "value-changed", G_CALLBACK(_cbDaytimeChanged), NULL);
|
||||
g_signal_connect(GET_WIDGET("sky_sun_size"), "value-changed", G_CALLBACK(_cbSunSizeChanged), NULL);
|
||||
g_signal_connect(GET_WIDGET("sky_haze_height"), "value-changed", G_CALLBACK(_cbHazeHeightChanged), NULL);
|
||||
g_signal_connect(GET_WIDGET("sky_haze_smoothing"), "value-changed", G_CALLBACK(_cbHazeSmoothingChanged), NULL);
|
||||
|
||||
/* Previews */
|
||||
_preview_horizon = guiPreviewNew(GTK_IMAGE(GET_WIDGET("sky_preview_horizon")));
|
||||
guiPreviewConfigScaling(_preview_horizon, 0.01, 0.01, 0.0);
|
||||
guiPreviewConfigScrolling(_preview_horizon, 0.0, 0.0, 0.0, 0.0);
|
||||
guiPreviewSetViewport(_preview_horizon, 0.0, 0.0, 0.01);
|
||||
guiPreviewSetRenderer(_preview_horizon, _cbPreviewHorizon);
|
||||
|
||||
guiSkyUpdate();
|
||||
}
|
||||
|
||||
void guiSkyUpdate()
|
||||
{
|
||||
_cbRevertConfig(NULL, NULL);
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/* Terrain tab */
|
||||
|
||||
#include "common.h"
|
||||
#include "lib_paysages/shared/functions.h"
|
||||
#include "lib_paysages/terrain.h"
|
||||
#include "lib_paysages/textures.h"
|
||||
|
||||
static SmallPreview* _preview;
|
||||
static TerrainDefinition _definition;
|
||||
|
||||
static Color _cbPreviewRenderPixel(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
||||
{
|
||||
Color result;
|
||||
|
||||
result.r = result.g = result.b = terrainGetHeightNormalized(x, y);
|
||||
result.a = 1.0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void _cbEditNoiseDone(NoiseGenerator* generator)
|
||||
{
|
||||
noiseCopy(generator, _definition.height_noise);
|
||||
terrainSetDefinition(_definition);
|
||||
|
||||
/* TODO Redraw only affected by terrain */
|
||||
guiPreviewRedrawAll();
|
||||
}
|
||||
|
||||
static void _cbEditNoise(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
guiNoiseEdit(_definition.height_noise, _cbEditNoiseDone);
|
||||
}
|
||||
|
||||
void guiTerrainInit()
|
||||
{
|
||||
g_signal_connect(GET_WIDGET("terrain_noise_edit"), "clicked", G_CALLBACK(_cbEditNoise), NULL);
|
||||
|
||||
_preview = guiPreviewNew(GTK_IMAGE(GET_WIDGET("terrain_preview")));
|
||||
guiPreviewConfigScaling(_preview, 0.01, 1.0, 0.05);
|
||||
guiPreviewConfigScrolling(_preview, -1000.0, 1000.0, -1000.0, 1000.0);
|
||||
guiPreviewSetViewport(_preview, 0.0, 0.0, 0.2);
|
||||
guiPreviewSetRenderer(_preview, _cbPreviewRenderPixel);
|
||||
}
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
/* Terrain tab */
|
||||
|
||||
#include "common.h"
|
||||
#include "lib_paysages/shared/functions.h"
|
||||
#include "lib_paysages/shared/constants.h"
|
||||
#include "lib_paysages/water.h"
|
||||
#include "lib_paysages/terrain.h"
|
||||
#include <math.h>
|
||||
|
||||
static SmallPreview* _preview_coverage;
|
||||
static SmallPreview* _preview_render;
|
||||
static WaterDefinition _definition;
|
||||
|
||||
static RayCastingResult _rayCastFromWater(Vector3 start, Vector3 direction)
|
||||
{
|
||||
RayCastingResult result;
|
||||
double x, y;
|
||||
|
||||
result.hit = 1;
|
||||
if (direction.z < 0.0001)
|
||||
{
|
||||
result.hit_color = COLOR_WHITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = start.x + direction.x * (0.0 - start.z) / direction.z;
|
||||
y = start.y + direction.y * (0.0 - start.z) / direction.z;
|
||||
|
||||
if (((int)ceil(x * 0.2) % 2 == 0) ^ ((int)ceil(y * 0.2 - 0.5) % 2 == 0))
|
||||
{
|
||||
result.hit_color = COLOR_WHITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.hit_color = COLOR_GREY;
|
||||
}
|
||||
}
|
||||
/* TODO hit_location */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static Color _cbPreviewCoverage(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
||||
{
|
||||
Color result;
|
||||
double height;
|
||||
|
||||
height = terrainGetHeight(x, y);
|
||||
if (height <= _definition.height)
|
||||
{
|
||||
return _definition.main_color;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.r = result.g = result.b = terrainGetHeightNormalized(x, y);
|
||||
result.a = 1.0;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static Color _cbPreviewRender(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
||||
{
|
||||
Vector3 eye, look, location;
|
||||
WaterDefinition definition;
|
||||
WaterEnvironment environment;
|
||||
WaterQuality quality;
|
||||
|
||||
eye.x = 0.0;
|
||||
eye.y = scaling;
|
||||
eye.z = -10.0 * scaling;
|
||||
look.x = x * 0.01 / scaling;
|
||||
look.y = -y * 0.01 / scaling - 0.3;
|
||||
look.z = 1.0;
|
||||
look = v3Normalize(look);
|
||||
|
||||
if (look.y > -0.0001)
|
||||
{
|
||||
return _rayCastFromWater(eye, look).hit_color;
|
||||
}
|
||||
|
||||
location.x = eye.x - look.x * eye.y / look.y;
|
||||
location.y = 0.0;
|
||||
location.z = eye.z - look.z * eye.y / look.y;
|
||||
|
||||
if (location.z > 0.0)
|
||||
{
|
||||
return _rayCastFromWater(eye, look).hit_color;
|
||||
}
|
||||
|
||||
definition = _definition;
|
||||
definition.height = 0.0;
|
||||
environment.reflection_function = _rayCastFromWater;
|
||||
environment.refraction_function = _rayCastFromWater;
|
||||
environment.toggle_fog = 0;
|
||||
quality.force_detail = 0.0001;
|
||||
|
||||
return waterGetColorCustom(location, look, &definition, &quality, &environment).final;
|
||||
}
|
||||
|
||||
static void _cbEditNoiseDone(NoiseGenerator* generator)
|
||||
{
|
||||
noiseCopy(generator, _definition.waves_noise);
|
||||
guiPreviewRedraw(_preview_render);
|
||||
}
|
||||
|
||||
static void _cbEditNoise(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
guiNoiseEdit(_definition.waves_noise, _cbEditNoiseDone);
|
||||
}
|
||||
|
||||
static void _cbHeightChanged(GtkRange* range, gpointer data)
|
||||
{
|
||||
_definition.height = gtk_range_get_value(range);
|
||||
guiPreviewRedraw(_preview_coverage);
|
||||
}
|
||||
|
||||
static void _cbTransparencyChanged(GtkRange* range, gpointer data)
|
||||
{
|
||||
_definition.transparency = gtk_range_get_value(range);
|
||||
guiPreviewRedraw(_preview_render);
|
||||
}
|
||||
|
||||
static void _cbReflectionChanged(GtkRange* range, gpointer data)
|
||||
{
|
||||
_definition.reflection = gtk_range_get_value(range);
|
||||
guiPreviewRedraw(_preview_render);
|
||||
}
|
||||
|
||||
static void _cbTransparencyDepthChanged(GtkRange* range, gpointer data)
|
||||
{
|
||||
_definition.transparency_depth = gtk_range_get_value(range);
|
||||
guiPreviewRedraw(_preview_render);
|
||||
}
|
||||
|
||||
static void _cbColorChanged(GtkColorButton* colorbutton, gpointer data)
|
||||
{
|
||||
GdkColor col;
|
||||
|
||||
gtk_color_button_get_color(colorbutton, &col);
|
||||
_definition.main_color.r = (double)col.red / 65535.0;
|
||||
_definition.main_color.g = (double)col.green / 65535.0;
|
||||
_definition.main_color.b = (double)col.blue / 65535.0;
|
||||
_definition.main_color.a = 1.0;
|
||||
|
||||
guiPreviewRedraw(_preview_render);
|
||||
guiPreviewRedraw(_preview_coverage);
|
||||
}
|
||||
|
||||
static void _cbColorDepthChanged(GtkColorButton* colorbutton, gpointer data)
|
||||
{
|
||||
GdkColor col;
|
||||
|
||||
gtk_color_button_get_color(colorbutton, &col);
|
||||
_definition.depth_color.r = (double)col.red / 65535.0;
|
||||
_definition.depth_color.g = (double)col.green / 65535.0;
|
||||
_definition.depth_color.b = (double)col.blue / 65535.0;
|
||||
_definition.depth_color.a = 1.0;
|
||||
|
||||
guiPreviewRedraw(_preview_render);
|
||||
guiPreviewRedraw(_preview_coverage);
|
||||
}
|
||||
|
||||
static void _cbRevertConfig(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
GdkColor col;
|
||||
|
||||
waterCopyDefinition(waterGetDefinition(), &_definition);
|
||||
|
||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_height")), _definition.height);
|
||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_transparency")), _definition.transparency);
|
||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_reflection")), _definition.reflection);
|
||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_transparency_depth")), _definition.transparency_depth);
|
||||
col.red = _definition.main_color.r * 65535.0;
|
||||
col.green = _definition.main_color.g * 65535.0;
|
||||
col.blue = _definition.main_color.b * 65535.0;
|
||||
gtk_color_button_set_color(GTK_COLOR_BUTTON(GET_WIDGET("water_color")), &col);
|
||||
col.red = _definition.depth_color.r * 65535.0;
|
||||
col.green = _definition.depth_color.g * 65535.0;
|
||||
col.blue = _definition.depth_color.b * 65535.0;
|
||||
gtk_color_button_set_color(GTK_COLOR_BUTTON(GET_WIDGET("water_color_depth")), &col);
|
||||
|
||||
guiPreviewRedraw(_preview_render);
|
||||
guiPreviewRedraw(_preview_coverage);
|
||||
}
|
||||
|
||||
static void _cbApplyConfig(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
waterSetDefinition(_definition);
|
||||
guiUpdate();
|
||||
}
|
||||
|
||||
void guiWaterInit()
|
||||
{
|
||||
_definition = waterCreateDefinition();
|
||||
|
||||
/* Buttons */
|
||||
g_signal_connect(GET_WIDGET("water_noise_edit"), "clicked", G_CALLBACK(_cbEditNoise), NULL);
|
||||
g_signal_connect(GET_WIDGET("water_apply"), "clicked", G_CALLBACK(_cbApplyConfig), NULL);
|
||||
g_signal_connect(GET_WIDGET("water_revert"), "clicked", G_CALLBACK(_cbRevertConfig), NULL);
|
||||
|
||||
/* Configs */
|
||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_height")), -20.0, 20.0);
|
||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_transparency")), 0.0, 1.0);
|
||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_reflection")), 0.0, 1.0);
|
||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_transparency_depth")), 0.0, 100.0);
|
||||
|
||||
/* Config signals */
|
||||
g_signal_connect(GET_WIDGET("water_height"), "value-changed", G_CALLBACK(_cbHeightChanged), NULL);
|
||||
g_signal_connect(GET_WIDGET("water_transparency"), "value-changed", G_CALLBACK(_cbTransparencyChanged), NULL);
|
||||
g_signal_connect(GET_WIDGET("water_transparency_depth"), "value-changed", G_CALLBACK(_cbTransparencyDepthChanged), NULL);
|
||||
g_signal_connect(GET_WIDGET("water_reflection"), "value-changed", G_CALLBACK(_cbReflectionChanged), NULL);
|
||||
g_signal_connect(GET_WIDGET("water_color"), "color-set", G_CALLBACK(_cbColorChanged), NULL);
|
||||
g_signal_connect(GET_WIDGET("water_color_depth"), "color-set", G_CALLBACK(_cbColorDepthChanged), NULL);
|
||||
|
||||
/* Previews */
|
||||
_preview_coverage = guiPreviewNew(GTK_IMAGE(GET_WIDGET("water_preview_coverage")));
|
||||
guiPreviewConfigScaling(_preview_coverage, 0.01, 1.0, 0.05);
|
||||
guiPreviewConfigScrolling(_preview_coverage, -1000.0, 1000.0, -1000.0, 1000.0);
|
||||
guiPreviewSetViewport(_preview_coverage, 0.0, 0.0, 0.2);
|
||||
guiPreviewSetRenderer(_preview_coverage, _cbPreviewCoverage);
|
||||
_preview_render = guiPreviewNew(GTK_IMAGE(GET_WIDGET("water_preview_render")));
|
||||
guiPreviewConfigScaling(_preview_render, 0.1, 1.0, 0.1);
|
||||
guiPreviewConfigScrolling(_preview_render, -10.0, 10.0, -10.0, 10.0);
|
||||
guiPreviewSetViewport(_preview_render, 0.0, 0.0, 0.5);
|
||||
guiPreviewSetRenderer(_preview_render, _cbPreviewRender);
|
||||
|
||||
guiWaterUpdate();
|
||||
}
|
||||
|
||||
void guiWaterUpdate()
|
||||
{
|
||||
_cbRevertConfig(NULL, NULL);
|
||||
}
|
|
@ -80,6 +80,7 @@ void BaseForm::revertConfig()
|
|||
|
||||
void BaseForm::applyConfig()
|
||||
{
|
||||
revertConfig();
|
||||
}
|
||||
|
||||
void BaseForm::addPreview(Preview* preview, QString label)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "preview.h"
|
||||
#include "baseinput.h"
|
||||
#include "../lib_paysages/shared/types.h"
|
||||
#include "../lib_paysages/noise.h"
|
||||
|
||||
class BaseForm:public QWidget
|
||||
{
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
#include <QScrollArea>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "../lib_paysages/shared/functions.h"
|
||||
|
||||
/**************** Previews ****************/
|
||||
class PreviewLevel:public Preview
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <QListWidget>
|
||||
#include "preview.h"
|
||||
|
||||
#include "../lib_paysages/shared/types.h"
|
||||
#include "../lib_paysages/noise.h"
|
||||
|
||||
class DialogNoise : public QDialog
|
||||
{
|
||||
|
|
|
@ -24,7 +24,7 @@ protected:
|
|||
{
|
||||
double height;
|
||||
|
||||
height = terrainGetHeightNormalized(x, y);
|
||||
height = terrainGetHeightNormalizedCustom(x, y, &_definition);
|
||||
return QColor((int)(255.0 * height), (int)(255.0 * height), (int)(255.0 * height));
|
||||
}
|
||||
};
|
||||
|
@ -35,7 +35,11 @@ public:
|
|||
PreviewTerrainColor(QWidget* parent):
|
||||
Preview(parent)
|
||||
{
|
||||
_lighting_environment.filter = NULL;
|
||||
|
||||
_environment.toggle_fog = 0;
|
||||
_environment.lighting_definition = NULL;
|
||||
_environment.lighting_environment = &_lighting_environment;
|
||||
}
|
||||
protected:
|
||||
QColor getColor(double x, double y)
|
||||
|
@ -43,6 +47,7 @@ protected:
|
|||
return colorToQColor(terrainGetColorCustom(x, y, scaling, &_definition, NULL, &_environment));
|
||||
}
|
||||
private:
|
||||
LightingEnvironment _lighting_environment;
|
||||
TerrainEnvironment _environment;
|
||||
};
|
||||
|
||||
|
@ -54,10 +59,12 @@ FormTerrain::FormTerrain(QWidget *parent):
|
|||
|
||||
previewHeight = new PreviewTerrainHeight(this);
|
||||
previewColor = new PreviewTerrainColor(this);
|
||||
addPreview(previewHeight, QString("Height preview"));
|
||||
addPreview(previewColor, QString("Color preview"));
|
||||
addPreview(previewHeight, QString("Height preview (normalized)"));
|
||||
addPreview(previewColor, QString("Textured preview (no shadow)"));
|
||||
|
||||
addInputNoise("Height", _definition.height_noise);
|
||||
addInputNoise("Noise", _definition.height_noise);
|
||||
addInputDouble("Height", &_definition.height_factor, 0.0, 20.0, 0.1, 1.0);
|
||||
addInputDouble("Scaling", &_definition.scaling, 1.0, 20.0, 0.1, 1.0);
|
||||
|
||||
revertConfig();
|
||||
}
|
||||
|
@ -73,3 +80,9 @@ void FormTerrain::applyConfig()
|
|||
terrainSetDefinition(_definition);
|
||||
BaseForm::applyConfig();
|
||||
}
|
||||
|
||||
void FormTerrain::applyConfigPreview()
|
||||
{
|
||||
terrainValidateDefinition(&_definition);
|
||||
BaseForm::applyConfigPreview();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@ public slots:
|
|||
virtual void revertConfig();
|
||||
virtual void applyConfig();
|
||||
|
||||
protected slots:
|
||||
virtual void applyConfigPreview();
|
||||
|
||||
private:
|
||||
Preview* previewHeight;
|
||||
Preview* previewColor;
|
||||
|
|
|
@ -51,6 +51,7 @@ protected:
|
|||
Vector3 eye, look, location;
|
||||
WaterDefinition definition;
|
||||
WaterEnvironment environment;
|
||||
LightingEnvironment lighting_environment;
|
||||
WaterQuality quality;
|
||||
Color result;
|
||||
|
||||
|
@ -80,11 +81,12 @@ protected:
|
|||
|
||||
definition = _definition;
|
||||
definition.height = 0.0;
|
||||
lighting_environment.filter = NULL;
|
||||
environment.reflection_function = (RayCastingFunction)(&this->rayCastFromWater);
|
||||
environment.refraction_function = (RayCastingFunction)(&this->rayCastFromWater);
|
||||
environment.toggle_fog = 0;
|
||||
environment.lighting_definition = NULL;
|
||||
environment.lighting_environment = NULL;
|
||||
environment.lighting_environment = &lighting_environment;
|
||||
quality.force_detail = 0.0001;
|
||||
quality.detail_boost = 1.0;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <QWidget>
|
||||
#include "baseinput.h"
|
||||
|
||||
#include "../lib_paysages/shared/types.h"
|
||||
#include "../lib_paysages/noise.h"
|
||||
|
||||
class InputNoise:public BaseInput
|
||||
{
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
#include <QApplication>
|
||||
#include <QMenuBar>
|
||||
#include <QMenu>
|
||||
#include <QFileDialog>
|
||||
#include <QTabWidget>
|
||||
|
||||
#include "formterrain.h"
|
||||
#include "formwater.h"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "terrain.h"
|
||||
#include "textures.h"
|
||||
#include "lighting.h"
|
||||
#include "scenery.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
|
@ -80,53 +81,25 @@ void autoSetDaytimeFraction(double daytime)
|
|||
sun = colorGradationGet(&grad_sun, daytime);
|
||||
lightingSetSunColor(sun);*/
|
||||
|
||||
sky = skyGetDefinition();
|
||||
sky = skyCreateDefinition();
|
||||
sceneryGetSky(&sky);
|
||||
sky.daytime = daytime;
|
||||
skySetDefinition(sky);
|
||||
|
||||
lightingValidateDefinition(NULL);
|
||||
scenerySetSky(&sky);
|
||||
skyDeleteDefinition(&sky);
|
||||
|
||||
fogSetColor(colorGradationGet(&sky.haze_color, daytime));
|
||||
}
|
||||
|
||||
void autoSetRenderQuality(int quality)
|
||||
{
|
||||
TerrainQuality terrain;
|
||||
WaterQuality water;
|
||||
CloudsQuality clouds;
|
||||
|
||||
if (quality < 1)
|
||||
{
|
||||
quality = 1;
|
||||
}
|
||||
if (quality > 10)
|
||||
{
|
||||
quality = 10;
|
||||
}
|
||||
|
||||
renderSetQuality(quality);
|
||||
|
||||
terrain.min_chunk_size = 0.1 / (double)render_quality;
|
||||
terrain.visible_chunk_size = 0.05 / (double)render_quality;
|
||||
terrainSetQuality(terrain);
|
||||
|
||||
water.detail_boost = 5.0;
|
||||
water.force_detail = 0.0;
|
||||
waterSetQuality(water);
|
||||
|
||||
clouds.precision = 3.3 - 0.3 * (double)render_quality;
|
||||
cloudsSetQuality(clouds);
|
||||
}
|
||||
|
||||
void autoGenRealisticLandscape(int seed)
|
||||
{
|
||||
TerrainDefinition terrain;
|
||||
WaterDefinition water;
|
||||
CloudsDefinition cloud;
|
||||
CloudsDefinition clouds;
|
||||
CloudsLayerDefinition* cloud;
|
||||
SkyDefinition sky;
|
||||
TextureDefinition texture;
|
||||
TexturesDefinition textures;
|
||||
TextureLayerDefinition* texture;
|
||||
LightingDefinition lighting;
|
||||
int layer;
|
||||
HeightModifier* mod;
|
||||
Zone* zone;
|
||||
|
||||
|
@ -137,33 +110,34 @@ void autoGenRealisticLandscape(int seed)
|
|||
srand(seed);
|
||||
|
||||
/* Cloud layer */
|
||||
cloud = cloudsCreateDefinition();
|
||||
cloud.ymin = 10.0;
|
||||
cloud.ycenter = 40.0;
|
||||
cloud.ymax = 100.0;
|
||||
cloud.color = COLOR_WHITE;
|
||||
cloud.color.a = 0.1;
|
||||
cloud.scaling = 50.0;
|
||||
cloud.coverage = 0.5;
|
||||
noiseGenerateBaseNoise(cloud.noise, 262144);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0, 0.3);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 2.0, 0.2);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 4.0, 0.1);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 10.0, 0.05);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 20.0, 0.03);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 40.0, 0.02);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 60.0, 0.01);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 80.0, 0.005);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 100.0, 0.02);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 150.0, 0.005);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 200.0, 0.003);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 400.0, 0.008);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 800.0, 0.001);
|
||||
noiseAddLevelSimple(cloud.noise, 50.0 / 1000.0, 0.0005);
|
||||
layer = cloudsAddLayer();
|
||||
cloudsSetDefinition(layer, cloud);
|
||||
clouds = cloudsCreateDefinition();
|
||||
cloud = cloudsGetLayer(&clouds, cloudsAddLayer(&clouds));
|
||||
cloud->ymin = 10.0;
|
||||
cloud->ycenter = 40.0;
|
||||
cloud->ymax = 100.0;
|
||||
cloud->color = COLOR_WHITE;
|
||||
cloud->color.a = 0.1;
|
||||
cloud->scaling = 50.0;
|
||||
cloud->coverage = 0.5;
|
||||
noiseGenerateBaseNoise(cloud->noise, 262144);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0, 0.3);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 2.0, 0.2);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 4.0, 0.1);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 10.0, 0.05);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 20.0, 0.03);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 40.0, 0.02);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 60.0, 0.01);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 80.0, 0.005);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 100.0, 0.02);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 150.0, 0.005);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 200.0, 0.003);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 400.0, 0.008);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 800.0, 0.001);
|
||||
noiseAddLevelSimple(cloud->noise, 50.0 / 1000.0, 0.0005);
|
||||
scenerySetClouds(&clouds);
|
||||
|
||||
/* Water */
|
||||
water = waterCreateDefinition();
|
||||
water.height = 0.0;
|
||||
water.transparency = 0.5;
|
||||
water.reflection = 0.3;
|
||||
|
@ -176,28 +150,25 @@ void autoGenRealisticLandscape(int seed)
|
|||
water.depth_color.g = 0.2;
|
||||
water.depth_color.b = 0.3;
|
||||
water.depth_color.a = 1.0;
|
||||
water.waves_noise = noiseCreateGenerator();
|
||||
water.waves_noise_height = 0.015;
|
||||
water.waves_noise_scale = 0.2;
|
||||
noiseGenerateBaseNoise(water.waves_noise, 262144);
|
||||
noiseAddLevelsSimple(water.waves_noise, 2, 1.0, 1.0);
|
||||
noiseAddLevelsSimple(water.waves_noise, 3, 0.15, 0.1);
|
||||
waterSetDefinition(water);
|
||||
noiseDeleteGenerator(water.waves_noise);
|
||||
scenerySetWater(&water);
|
||||
waterDeleteDefinition(&water);
|
||||
|
||||
/* Sky */
|
||||
sky.sun_color = colorGradationCreate();
|
||||
sky = skyCreateDefinition();
|
||||
colorGradationAddRgba(&sky.sun_color, 0.3, 1.0, 0.91, 0.8, 1.0);
|
||||
colorGradationAddRgba(&sky.sun_color, 0.5, 1.0, 0.95, 0.9, 1.0);
|
||||
colorGradationAddRgba(&sky.sun_color, 0.7, 1.0, 0.91, 0.8, 1.0);
|
||||
sky.zenith_color = colorGradationCreate();
|
||||
colorGradationAddRgba(&sky.zenith_color, 0.2, 0.03, 0.03, 0.05, 1.0);
|
||||
colorGradationAddRgba(&sky.zenith_color, 0.25, 0.25, 0.33, 0.37, 1.0);
|
||||
colorGradationAddRgba(&sky.zenith_color, 0.35, 0.52, 0.63, 0.8, 1.0);
|
||||
colorGradationAddRgba(&sky.zenith_color, 0.65, 0.52, 0.63, 0.8, 1.0);
|
||||
colorGradationAddRgba(&sky.zenith_color, 0.75, 0.25, 0.33, 0.37, 1.0);
|
||||
colorGradationAddRgba(&sky.zenith_color, 0.8, 0.03, 0.03, 0.05, 1.0);
|
||||
sky.haze_color = colorGradationCreate();
|
||||
colorGradationAddRgba(&sky.haze_color, 0.2, 0.05, 0.05, 0.08, 1.0);
|
||||
colorGradationAddRgba(&sky.haze_color, 0.25, 0.55, 0.42, 0.42, 1.0);
|
||||
colorGradationAddRgba(&sky.haze_color, 0.3, 0.6, 0.6, 0.6, 1.0);
|
||||
|
@ -210,18 +181,21 @@ void autoGenRealisticLandscape(int seed)
|
|||
sky.haze_height = 0.75;
|
||||
sky.haze_smoothing = 0.3;
|
||||
sky.sun_radius = 0.02;
|
||||
skySetDefinition(sky);
|
||||
scenerySetSky(&sky);
|
||||
skyDeleteDefinition(&sky);
|
||||
|
||||
/* Lighting */
|
||||
lighting = lightingCreateDefinition();
|
||||
lighting.autosetfromsky = 1;
|
||||
lightingSetDefinition(lighting);
|
||||
scenerySetLighting(&lighting);
|
||||
lightingDeleteDefinition(&lighting);
|
||||
|
||||
/* Terrain */
|
||||
terrain = terrainCreateDefinition();
|
||||
noiseGenerateBaseNoise(terrain.height_noise, 1048576);
|
||||
noiseAddLevelsSimple(terrain.height_noise, 10, 10.0, 1.0);
|
||||
noiseNormalizeHeight(terrain.height_noise, -12.0, 12.0, 0);
|
||||
noiseAddLevelsSimple(terrain.height_noise, 10, 1.0, 1.0);
|
||||
terrain.height_factor = 12.0 / noiseGetMaxValue(terrain.height_noise);
|
||||
terrain.scaling = 10.0;
|
||||
/* DEBUG */
|
||||
mod = modifierCreate();
|
||||
zone = modifierGetZone(mod);
|
||||
|
@ -241,42 +215,36 @@ void autoGenRealisticLandscape(int seed)
|
|||
modifierActionFixValue(mod, -8.0);
|
||||
terrainAddModifier(&terrain, mod);
|
||||
/* DEBUG */
|
||||
terrainSetDefinition(terrain);
|
||||
terrainDeleteDefinition(terrain);
|
||||
scenerySetTerrain(&terrain);
|
||||
terrainDeleteDefinition(&terrain);
|
||||
|
||||
/* Textures */
|
||||
layer = texturesAddLayer();
|
||||
texture = texturesCreateDefinition();
|
||||
noiseGenerateBaseNoise(texture.bump_noise, 102400);
|
||||
noiseAddLevelsSimple(texture.bump_noise, 6, 0.01, 0.01);
|
||||
texture.color.r = 0.6;
|
||||
texture.color.g = 0.55;
|
||||
texture.color.b = 0.57;
|
||||
texturesSetDefinition(layer, texture);
|
||||
texturesDeleteDefinition(texture);
|
||||
|
||||
layer = texturesAddLayer();
|
||||
texture = texturesCreateDefinition();
|
||||
zoneAddHeightRange(texture.zone, 1.0, -1.0, 0.0, 3.0, 15.0);
|
||||
zoneAddSteepnessRange(texture.zone, 1.0, 0.0, 0.0, 0.3, 0.4);
|
||||
noiseGenerateBaseNoise(texture.bump_noise, 102400);
|
||||
noiseAddLevelsSimple(texture.bump_noise, 6, 0.02, 0.008);
|
||||
texture.color.r = 0.2;
|
||||
texture.color.g = 0.24;
|
||||
texture.color.b = 0.05;
|
||||
texturesSetDefinition(layer, texture);
|
||||
texturesDeleteDefinition(texture);
|
||||
|
||||
/*layer = texturesAddLayer();
|
||||
texture = texturesCreateDefinition();
|
||||
zoneAddHeightRange(texture.zone, 1.0, 3.0, 4.0, 100.0, 100.0);
|
||||
noiseGenerateBaseNoise(texture.bump_noise, 102400);
|
||||
noiseAddLevelsSimple(texture.bump_noise, 6, 0.04, 0.003);
|
||||
texture.color.r = 1.0;
|
||||
texture.color.g = 1.0;
|
||||
texture.color.b = 1.0;
|
||||
textures = texturesCreateDefinition();
|
||||
texture = texturesGetLayer(&textures, texturesAddLayer(&textures));
|
||||
noiseGenerateBaseNoise(texture->bump_noise, 102400);
|
||||
noiseAddLevelsSimple(texture->bump_noise, 6, 0.01, 0.01);
|
||||
texture->color.r = 0.6;
|
||||
texture->color.g = 0.55;
|
||||
texture->color.b = 0.57;
|
||||
texture = texturesGetLayer(&textures, texturesAddLayer(&textures));
|
||||
zoneAddHeightRange(texture->zone, 1.0, -1.0, 0.0, 3.0, 15.0);
|
||||
zoneAddSteepnessRange(texture->zone, 1.0, 0.0, 0.0, 0.3, 0.4);
|
||||
noiseGenerateBaseNoise(texture->bump_noise, 102400);
|
||||
noiseAddLevelsSimple(texture->bump_noise, 6, 0.02, 0.008);
|
||||
texture->color.r = 0.2;
|
||||
texture->color.g = 0.24;
|
||||
texture->color.b = 0.05;
|
||||
/*texture = texturesGetLayer(&textures, texturesAddLayer(&textures));
|
||||
zoneAddHeightRange(texture->zone, 1.0, 3.0, 4.0, 100.0, 100.0);
|
||||
noiseGenerateBaseNoise(texture->bump_noise, 102400);
|
||||
noiseAddLevelsSimple(texture->bump_noise, 6, 0.04, 0.003);
|
||||
texture->color.r = 1.0;
|
||||
texture->color.g = 1.0;
|
||||
texture->color.b = 1.0;
|
||||
texturesSetDefinition(layer, texture);
|
||||
texturesDeleteDefinition(texture);*/
|
||||
scenerySetTextures(&textures);
|
||||
texturesDeleteDefinition(&textures);
|
||||
|
||||
/* Fog */
|
||||
fogSetDistance(20.0, 100.0);
|
||||
|
@ -342,23 +310,25 @@ static int _postProcessRayTracingOverlay(RenderFragment* fragment)
|
|||
{
|
||||
Vector3 terrain_hit, look;
|
||||
|
||||
look = v3Sub(fragment->vertex.location, camera_location);
|
||||
// TODO
|
||||
/*look = v3Sub(fragment->vertex.location, camera_location);
|
||||
if (!terrainProjectRay(camera_location, look, &terrain_hit, &fragment->vertex.color))
|
||||
{
|
||||
fragment->vertex.color = skyProjectRay(camera_location, look);
|
||||
}
|
||||
}*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void autoRenderSceneRayTracing()
|
||||
{
|
||||
renderClear();
|
||||
// TODO
|
||||
/*renderClear();
|
||||
cameraPushOverlay(COLOR_RED, _postProcessRayTracingOverlay);
|
||||
renderUpdate();
|
||||
|
||||
if (renderSetNextProgressStep(0.0, 1.0))
|
||||
{
|
||||
renderPostProcess(_cpu_count);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "camera.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
|
@ -6,71 +8,102 @@
|
|||
#include "shared/constants.h"
|
||||
#include "shared/functions.h"
|
||||
|
||||
Vector3 camera_location;
|
||||
static Vector3 camera_target;
|
||||
static Vector3 camera_up;
|
||||
static Matrix4 matrix_project;
|
||||
static Matrix4 matrix_project_inverse;
|
||||
void cameraInit()
|
||||
{
|
||||
}
|
||||
|
||||
static void __updateMatrix()
|
||||
void cameraSave(FILE* f, CameraDefinition* camera)
|
||||
{
|
||||
v3Save(camera->location, f);
|
||||
v3Save(camera->target, f);
|
||||
}
|
||||
|
||||
void cameraLoad(FILE* f, CameraDefinition* camera)
|
||||
{
|
||||
camera->location = v3Load(f);
|
||||
camera->target = v3Load(f);
|
||||
|
||||
cameraValidateDefinition(camera);
|
||||
}
|
||||
|
||||
CameraDefinition cameraCreateDefinition()
|
||||
{
|
||||
CameraDefinition definition;
|
||||
|
||||
definition.location.x = -1.0;
|
||||
definition.location.y = 0.0;
|
||||
definition.location.z = 0.0;
|
||||
definition.target.x = 0.0;
|
||||
definition.target.y = 0.0;
|
||||
definition.target.z = 0.0;
|
||||
|
||||
cameraValidateDefinition(&definition);
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
void cameraDeleteDefinition(CameraDefinition* definition)
|
||||
{
|
||||
}
|
||||
|
||||
void cameraCopyDefinition(CameraDefinition* source, CameraDefinition* destination)
|
||||
{
|
||||
*destination = *source;
|
||||
}
|
||||
|
||||
void cameraValidateDefinition(CameraDefinition* definition)
|
||||
{
|
||||
/* TODO Recompute up vector */
|
||||
camera_up.x = 0.0;
|
||||
camera_up.y = 1.0;
|
||||
camera_up.z = 0.0;
|
||||
definition->up.x = 0.0;
|
||||
definition->up.y = 1.0;
|
||||
definition->up.z = 0.0;
|
||||
|
||||
matrix_project = m4Mult(m4NewPerspective(1.57, 1.333333, 1.0, 1000.0), m4NewLookAt(VECTOR_ZERO, v3Sub(camera_target, camera_location), camera_up));
|
||||
matrix_project_inverse = m4Inverse(matrix_project);
|
||||
definition->project = m4Mult(m4NewPerspective(1.57, 1.333333, 1.0, 1000.0), m4NewLookAt(VECTOR_ZERO, v3Sub(definition->target, definition->location), definition->up));
|
||||
definition->unproject = m4Inverse(definition->project);
|
||||
}
|
||||
|
||||
void cameraSave(FILE* f)
|
||||
void cameraSetLocation(CameraDefinition* camera, double x, double y, double z)
|
||||
{
|
||||
camera->location.x = x;
|
||||
camera->location.y = y;
|
||||
camera->location.z = z;
|
||||
|
||||
cameraValidateDefinition(camera);
|
||||
}
|
||||
|
||||
void cameraLoad(FILE* f)
|
||||
void cameraSetTarget(CameraDefinition* camera, double x, double y, double z)
|
||||
{
|
||||
camera->target.x = x;
|
||||
camera->target.y = y;
|
||||
camera->target.z = z;
|
||||
|
||||
cameraValidateDefinition(camera);
|
||||
}
|
||||
|
||||
void cameraSetLocation(double x, double y, double z)
|
||||
{
|
||||
camera_location.x = x;
|
||||
camera_location.y = y;
|
||||
camera_location.z = z;
|
||||
__updateMatrix();
|
||||
}
|
||||
|
||||
void cameraSetTarget(double x, double y, double z)
|
||||
{
|
||||
camera_target.x = x;
|
||||
camera_target.y = y;
|
||||
camera_target.z = z;
|
||||
__updateMatrix();
|
||||
}
|
||||
|
||||
void cameraSetAngle(double angle)
|
||||
void cameraSetAngle(CameraDefinition* camera, double angle)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
Vector3 cameraProject(Vector3 point)
|
||||
Vector3 cameraProject(CameraDefinition* camera, Vector3 point)
|
||||
{
|
||||
point = m4Transform(matrix_project, v3Sub(point, camera_location));
|
||||
point = m4Transform(camera->project, v3Sub(point, camera->location));
|
||||
point.x = (-point.x + 1.0) * 0.5 * (double)render_width;
|
||||
point.y = (-point.y + 1.0) * 0.5 * (double)render_height;
|
||||
return point;
|
||||
}
|
||||
|
||||
Vector3 cameraUnproject(Vector3 point)
|
||||
Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point)
|
||||
{
|
||||
point.x = -(point.x / (0.5 * (double)render_width) - 1.0);
|
||||
point.y = -(point.y / (0.5 * (double)render_height) - 1.0);
|
||||
return v3Add(m4Transform(matrix_project_inverse, point), camera_location);
|
||||
return v3Add(m4Transform(camera->unproject, point), camera->location);
|
||||
}
|
||||
|
||||
void cameraProjectToFragment(double x, double y, double z, RenderFragment* result)
|
||||
void cameraProjectToFragment(CameraDefinition* camera, double x, double y, double z, RenderFragment* result)
|
||||
{
|
||||
Vector3 point = {x, y, z};
|
||||
point = m4Transform(matrix_project, v3Sub(point, camera_location));
|
||||
point = m4Transform(camera->project, v3Sub(point, camera->location));
|
||||
result->x = lround((-point.x + 1.0) * 0.5 * (double)render_width);
|
||||
result->y = lround((-point.y + 1.0) * 0.5 * (double)render_height);
|
||||
result->z = point.z;
|
||||
|
@ -83,7 +116,7 @@ void cameraProjectToFragment(double x, double y, double z, RenderFragment* resul
|
|||
* @param col Color of the polygon.
|
||||
* @param callback Post-processing callback.
|
||||
*/
|
||||
void cameraPushOverlay(Color col, f_RenderFragmentCallback callback)
|
||||
void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback)
|
||||
{
|
||||
Vertex v1, v2, v3, v4;
|
||||
Vector3 v;
|
||||
|
@ -91,28 +124,28 @@ void cameraPushOverlay(Color col, f_RenderFragmentCallback callback)
|
|||
v.x = 0.0;
|
||||
v.y = 0.0;
|
||||
v.z = 10.0;
|
||||
v1.location = cameraUnproject(v);
|
||||
v1.location = cameraUnproject(camera, v);
|
||||
v1.color = col;
|
||||
v1.callback = callback;
|
||||
|
||||
v.x = 0.0;
|
||||
v.y = (double)render_height;
|
||||
v.z = 10.0;
|
||||
v2.location = cameraUnproject(v);
|
||||
v2.location = cameraUnproject(camera, v);
|
||||
v2.color = col;
|
||||
v2.callback = callback;
|
||||
|
||||
v.x = (double)render_width;
|
||||
v.y = (double)render_height;
|
||||
v.z = 10.0;
|
||||
v3.location = cameraUnproject(v);
|
||||
v3.location = cameraUnproject(camera, v);
|
||||
v3.color = col;
|
||||
v3.callback = callback;
|
||||
|
||||
v.x = (double)render_width;
|
||||
v.y = 0.0;
|
||||
v.z = 10.0;
|
||||
v4.location = cameraUnproject(v);
|
||||
v4.location = cameraUnproject(camera, v);
|
||||
v4.color = col;
|
||||
v4.callback = callback;
|
||||
|
||||
|
|
41
lib_paysages/camera.h
Normal file
41
lib_paysages/camera.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef _PAYSAGES_CAMERA_H_
|
||||
#define _PAYSAGES_CAMERA_H_
|
||||
|
||||
#include "shared/types.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Vector3 location;
|
||||
Vector3 target;
|
||||
Vector3 up;
|
||||
Matrix4 project;
|
||||
Matrix4 unproject;
|
||||
} CameraDefinition;
|
||||
|
||||
void cameraInit();
|
||||
void cameraSave(FILE* f, CameraDefinition* camera);
|
||||
void cameraLoad(FILE* f, CameraDefinition* camera);
|
||||
|
||||
CameraDefinition cameraCreateDefinition();
|
||||
void cameraDeleteDefinition(CameraDefinition* definition);
|
||||
void cameraCopyDefinition(CameraDefinition* source, CameraDefinition* destination);
|
||||
void cameraValidateDefinition(CameraDefinition* definition);
|
||||
|
||||
void cameraSetLocation(CameraDefinition* camera, double x, double y, double z);
|
||||
void cameraSetTarget(CameraDefinition* camera, double x, double y, double z);
|
||||
void cameraSetAngle(CameraDefinition* camera, double angle);
|
||||
Vector3 cameraProject(CameraDefinition* camera, Vector3 point);
|
||||
Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point);
|
||||
void cameraProjectToFragment(CameraDefinition* camera, double x, double y, double z, RenderFragment* result);
|
||||
void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -9,13 +9,6 @@
|
|||
#include "shared/constants.h"
|
||||
#include "shared/globals.h"
|
||||
|
||||
#define MAX_LAYERS 10
|
||||
|
||||
static int _layers_count = 0;
|
||||
static CloudsDefinition _layers[MAX_LAYERS];
|
||||
static CloudsQuality _quality;
|
||||
static CloudsEnvironment _environment;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Vector3 start;
|
||||
|
@ -23,22 +16,23 @@ typedef struct
|
|||
double length;
|
||||
} CloudSegment;
|
||||
|
||||
static CloudsLayerDefinition NULL_LAYER;
|
||||
|
||||
void cloudsInit()
|
||||
{
|
||||
_layers_count = 0;
|
||||
|
||||
_quality.precision = 0.5;
|
||||
NULL_LAYER.noise = noiseCreateGenerator();
|
||||
NULL_LAYER.coverage = 0.0;
|
||||
}
|
||||
|
||||
void cloudsSave(FILE* f)
|
||||
void cloudsSave(FILE* f, CloudsDefinition* definition)
|
||||
{
|
||||
int i;
|
||||
CloudsDefinition* layer;
|
||||
CloudsLayerDefinition* layer;
|
||||
|
||||
toolsSaveInt(f, _layers_count);
|
||||
for (i = 0; i < _layers_count; i++)
|
||||
toolsSaveInt(f, definition->nblayers);
|
||||
for (i = 0; i < definition->nblayers; i++)
|
||||
{
|
||||
layer = _layers + i;
|
||||
layer = definition->layers + i;
|
||||
toolsSaveDouble(f, layer->ycenter);
|
||||
toolsSaveDouble(f, layer->ymin);
|
||||
toolsSaveDouble(f, layer->ymax);
|
||||
|
@ -49,20 +43,20 @@ void cloudsSave(FILE* f)
|
|||
}
|
||||
}
|
||||
|
||||
void cloudsLoad(FILE* f)
|
||||
void cloudsLoad(FILE* f, CloudsDefinition* definition)
|
||||
{
|
||||
int i, n;
|
||||
CloudsDefinition* layer;
|
||||
CloudsLayerDefinition* layer;
|
||||
|
||||
while (_layers_count > 0)
|
||||
while (definition->nblayers > 0)
|
||||
{
|
||||
cloudsDeleteLayer(0);
|
||||
cloudsDeleteLayer(definition, 0);
|
||||
}
|
||||
|
||||
n = toolsLoadInt(f);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
layer = _layers + cloudsAddLayer();
|
||||
layer = definition->layers + cloudsAddLayer(definition);
|
||||
|
||||
layer->ycenter = toolsLoadDouble(f);
|
||||
layer->ymin = toolsLoadDouble(f);
|
||||
|
@ -74,107 +68,139 @@ void cloudsLoad(FILE* f)
|
|||
}
|
||||
}
|
||||
|
||||
int cloudsGetLayerCount()
|
||||
{
|
||||
return _layers_count;
|
||||
}
|
||||
|
||||
int cloudsAddLayer()
|
||||
{
|
||||
CloudsDefinition* layer;
|
||||
|
||||
if (_layers_count < MAX_LAYERS)
|
||||
{
|
||||
layer = _layers + _layers_count;
|
||||
layer->noise = noiseCreateGenerator();
|
||||
layer->coverage = 0.0;
|
||||
|
||||
return _layers_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _layers_count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void cloudsDeleteLayer(int layer)
|
||||
{
|
||||
if (layer >= 0 && layer < _layers_count)
|
||||
{
|
||||
noiseDeleteGenerator(_layers[layer].noise);
|
||||
if (_layers_count > 1 && layer < _layers_count - 1)
|
||||
{
|
||||
memmove(_layers + layer, _layers + layer + 1, sizeof(CloudsDefinition) * (_layers_count - layer - 1));
|
||||
}
|
||||
_layers_count--;
|
||||
}
|
||||
}
|
||||
|
||||
CloudsDefinition cloudsCreateDefinition()
|
||||
{
|
||||
CloudsDefinition result;
|
||||
|
||||
result.color = COLOR_WHITE;
|
||||
result.coverage = 0.0;
|
||||
result.noise = noiseCreateGenerator();
|
||||
result.scaling = 1.0;
|
||||
result.ymin = 0.0;
|
||||
result.ycenter = 0.0;
|
||||
result.ymax = 0.0;
|
||||
result.nblayers = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void cloudsDeleteDefinition(CloudsDefinition definition)
|
||||
void cloudsDeleteDefinition(CloudsDefinition* definition)
|
||||
{
|
||||
noiseDeleteGenerator(definition.noise);
|
||||
while (definition->nblayers > 0)
|
||||
{
|
||||
cloudsDeleteLayer(definition, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void cloudsCopyDefinition(CloudsDefinition source, CloudsDefinition* destination)
|
||||
void cloudsCopyDefinition(CloudsDefinition* source, CloudsDefinition* destination)
|
||||
{
|
||||
CloudsLayerDefinition* layer;
|
||||
int i;
|
||||
|
||||
while (destination->nblayers > 0)
|
||||
{
|
||||
cloudsDeleteLayer(destination, 0);
|
||||
}
|
||||
for (i = 0; i < source->nblayers; i++)
|
||||
{
|
||||
layer = cloudsGetLayer(destination, cloudsAddLayer(destination));
|
||||
cloudsLayerCopyDefinition(source->layers + i, layer);
|
||||
}
|
||||
}
|
||||
|
||||
void cloudsValidateDefinition(CloudsDefinition* definition)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < definition->nblayers; i++)
|
||||
{
|
||||
cloudsLayerValidateDefinition(&definition->layers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
CloudsLayerDefinition cloudsLayerCreateDefinition()
|
||||
{
|
||||
CloudsLayerDefinition result;
|
||||
|
||||
result.color = COLOR_BLACK;
|
||||
result.coverage = 0.0;
|
||||
result.noise = noiseCreateGenerator();
|
||||
result.scaling = 1.0;
|
||||
result.ymin = 0.0;
|
||||
result.ycenter = 0.5;
|
||||
result.ymax = 1.0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition)
|
||||
{
|
||||
noiseDeleteGenerator(definition->noise);
|
||||
}
|
||||
|
||||
void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination)
|
||||
{
|
||||
NoiseGenerator* noise;
|
||||
|
||||
noise = destination->noise;
|
||||
*destination = source;
|
||||
*destination = *source;
|
||||
destination->noise = noise;
|
||||
noiseCopy(source.noise, destination->noise);
|
||||
noiseCopy(source->noise, destination->noise);
|
||||
}
|
||||
|
||||
void cloudsSetDefinition(int layer, CloudsDefinition definition)
|
||||
void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition)
|
||||
{
|
||||
CloudsDefinition* destination;
|
||||
|
||||
if (layer >= 0 && layer < _layers_count)
|
||||
if (definition->coverage < 0.5)
|
||||
{
|
||||
destination = _layers + layer;
|
||||
cloudsCopyDefinition(definition, destination);
|
||||
if (destination->coverage < 0.5)
|
||||
{
|
||||
noiseNormalizeHeight(destination->noise, -1.0, destination->coverage * 2.0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
noiseNormalizeHeight(destination->noise, -(1.0 - destination->coverage) * 2.0, 1.0, 0);
|
||||
}
|
||||
noiseNormalizeHeight(definition->noise, -1.0, definition->coverage * 2.0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
noiseNormalizeHeight(definition->noise, -(1.0 - definition->coverage) * 2.0, 1.0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
CloudsDefinition cloudsGetDefinition(int layer)
|
||||
int cloudsGetLayerCount(CloudsDefinition* definition)
|
||||
{
|
||||
return _layers[layer];
|
||||
return definition->nblayers;
|
||||
}
|
||||
|
||||
void cloudsSetQuality(CloudsQuality quality)
|
||||
CloudsLayerDefinition* cloudsGetLayer(CloudsDefinition* definition, int layer)
|
||||
{
|
||||
_quality = quality;
|
||||
if (layer >= 0 && layer < definition->nblayers)
|
||||
{
|
||||
return definition->layers + layer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &NULL_LAYER;
|
||||
}
|
||||
}
|
||||
|
||||
CloudsQuality cloudsGetQuality()
|
||||
int cloudsAddLayer(CloudsDefinition* definition)
|
||||
{
|
||||
return _quality;
|
||||
CloudsLayerDefinition* layer;
|
||||
|
||||
if (definition->nblayers < CLOUDS_MAX_LAYERS)
|
||||
{
|
||||
layer = definition->layers + definition->nblayers;
|
||||
layer->noise = noiseCreateGenerator();
|
||||
layer->coverage = 0.0;
|
||||
|
||||
return definition->nblayers++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline double _getDistanceToBorder(CloudsDefinition* layer, Vector3 position, double detail)
|
||||
void cloudsDeleteLayer(CloudsDefinition* definition, int layer)
|
||||
{
|
||||
if (layer >= 0 && layer < definition->nblayers)
|
||||
{
|
||||
cloudsLayerDeleteDefinition(definition->layers + layer);
|
||||
if (definition->nblayers > 1 && layer < definition->nblayers - 1)
|
||||
{
|
||||
memmove(definition->layers + layer, definition->layers + layer + 1, sizeof(CloudsLayerDefinition) * (definition->nblayers - layer - 1));
|
||||
}
|
||||
definition->nblayers--;
|
||||
}
|
||||
}
|
||||
|
||||
static inline double _getDistanceToBorder(CloudsLayerDefinition* layer, Vector3 position, double detail)
|
||||
{
|
||||
double val, min;
|
||||
|
||||
|
@ -192,7 +218,7 @@ static inline double _getDistanceToBorder(CloudsDefinition* layer, Vector3 posit
|
|||
return (val - min) * layer->scaling;
|
||||
}
|
||||
|
||||
static inline Vector3 _getNormal(CloudsDefinition* layer, Vector3 position, double detail)
|
||||
static inline Vector3 _getNormal(CloudsLayerDefinition* layer, Vector3 position, double detail)
|
||||
{
|
||||
Vector3 result = {0.0, 0.0, 0.0};
|
||||
double val, dval;
|
||||
|
@ -217,7 +243,7 @@ static inline Vector3 _getNormal(CloudsDefinition* layer, Vector3 position, doub
|
|||
dval = val - noiseGet3DDetail(layer->noise, position.x, position.y, position.z - detail, detail);
|
||||
result.z -= dval;
|
||||
|
||||
return result;
|
||||
return v3Normalize(result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -228,7 +254,7 @@ static inline Vector3 _getNormal(CloudsDefinition* layer, Vector3 position, doub
|
|||
* @param end End of the search to optimize
|
||||
* @return 0 if the search is useless
|
||||
*/
|
||||
static int _optimizeSearchLimits(CloudsDefinition* layer, Vector3* start, Vector3* end)
|
||||
static int _optimizeSearchLimits(CloudsLayerDefinition* layer, Vector3* start, Vector3* end)
|
||||
{
|
||||
Vector3 diff;
|
||||
|
||||
|
@ -285,7 +311,7 @@ static int _optimizeSearchLimits(CloudsDefinition* layer, Vector3* start, Vector
|
|||
* Go through the cloud layer to find segments (parts of the lookup that are inside the cloud).
|
||||
*
|
||||
* @param definition The cloud layer
|
||||
* @param quality Render quality
|
||||
* @param renderer The renderer environment
|
||||
* @param start Start position of the lookup (already optimized)
|
||||
* @param direction Normalized direction of the lookup
|
||||
* @param detail Level of noise detail required
|
||||
|
@ -297,34 +323,37 @@ static int _optimizeSearchLimits(CloudsDefinition* layer, Vector3* start, Vector
|
|||
* @param out_segments Allocated space to fill found segments
|
||||
* @return Number of segments found
|
||||
*/
|
||||
static int _findSegments(CloudsDefinition* definition, CloudsQuality* quality, Vector3 start, Vector3 direction, double detail, int max_segments, double max_inside_length, double max_total_length, double* inside_length, double* total_length, CloudSegment* out_segments)
|
||||
static int _findSegments(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 start, Vector3 direction, double detail, int max_segments, double max_inside_length, double max_total_length, double* inside_length, double* total_length, CloudSegment* out_segments)
|
||||
{
|
||||
int inside, segment_count;
|
||||
double current_total_length, current_inside_length;
|
||||
double step_length, segment_length, remaining_length;
|
||||
double noise_distance, last_noise_distance;
|
||||
Vector3 walker, step, segment_start;
|
||||
double render_precision;
|
||||
|
||||
if (max_segments <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
render_precision = 3.3 - 0.3 * (double)renderer->render_quality;
|
||||
|
||||
segment_count = 0;
|
||||
current_total_length = 0.0;
|
||||
current_inside_length = 0.0;
|
||||
segment_length = 0.0;
|
||||
walker = start;
|
||||
noise_distance = _getDistanceToBorder(definition, start, detail) * quality->precision;
|
||||
noise_distance = _getDistanceToBorder(definition, start, detail) * render_precision;
|
||||
inside = (noise_distance > 0.0) ? 1 : 0;
|
||||
step = v3Scale(direction, quality->precision);
|
||||
step = v3Scale(direction, render_precision);
|
||||
|
||||
do
|
||||
{
|
||||
walker = v3Add(walker, step);
|
||||
step_length = v3Norm(step);
|
||||
last_noise_distance = noise_distance;
|
||||
noise_distance = _getDistanceToBorder(definition, walker, detail) * quality->precision;
|
||||
noise_distance = _getDistanceToBorder(definition, walker, detail) * render_precision;
|
||||
current_total_length += step_length;
|
||||
|
||||
if (noise_distance > 0.0)
|
||||
|
@ -334,7 +363,7 @@ static int _findSegments(CloudsDefinition* definition, CloudsQuality* quality, V
|
|||
// inside the cloud
|
||||
segment_length += step_length;
|
||||
current_inside_length += step_length;
|
||||
step = v3Scale(direction, (noise_distance < quality->precision) ? quality->precision : noise_distance);
|
||||
step = v3Scale(direction, (noise_distance < render_precision) ? render_precision : noise_distance);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -343,7 +372,7 @@ static int _findSegments(CloudsDefinition* definition, CloudsQuality* quality, V
|
|||
segment_length = step_length * noise_distance / (noise_distance - last_noise_distance);
|
||||
segment_start = v3Add(walker, v3Scale(direction, -segment_length));
|
||||
current_inside_length += segment_length;
|
||||
step = v3Scale(direction, quality->precision);
|
||||
step = v3Scale(direction, render_precision);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -365,12 +394,12 @@ static int _findSegments(CloudsDefinition* definition, CloudsQuality* quality, V
|
|||
}
|
||||
|
||||
inside = 0;
|
||||
step = v3Scale(direction, quality->precision);
|
||||
step = v3Scale(direction, render_precision);
|
||||
}
|
||||
else
|
||||
{
|
||||
// searching for a cloud
|
||||
step = v3Scale(direction, (noise_distance > -quality->precision) ? quality->precision : -noise_distance);
|
||||
step = v3Scale(direction, (noise_distance > -render_precision) ? render_precision : -noise_distance);
|
||||
}
|
||||
}
|
||||
} while (inside || (walker.y <= definition->ymax + 0.001 && walker.y >= definition->ymin - 0.001 && current_total_length < max_total_length && current_inside_length < max_inside_length));
|
||||
|
@ -380,25 +409,16 @@ static int _findSegments(CloudsDefinition* definition, CloudsQuality* quality, V
|
|||
return segment_count;
|
||||
}
|
||||
|
||||
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)
|
||||
/*static Color _lightFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data)
|
||||
{
|
||||
double inside_depth, total_depth;
|
||||
CloudSegment segments[20];
|
||||
Color result;
|
||||
LightFilterData data;
|
||||
|
||||
data = *((LightFilterData*)custom_data);
|
||||
data.detail = (data.detail < 0.1) ? 0.1 : data.detail;
|
||||
|
||||
/* FIXME Dont hard-code max_total_length */
|
||||
// FIXME Dont hard-code max_total_length
|
||||
_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;
|
||||
|
@ -407,29 +427,30 @@ static Color _lightFilter(Color light, Vector3 location, Vector3 light_location,
|
|||
inside_depth = 1.0;
|
||||
}
|
||||
|
||||
result.r = data.base.r * - 0.2 * inside_depth;
|
||||
result.g = data.base.g * - 0.2 * inside_depth;
|
||||
result.b = data.base.b * - 0.2 * inside_depth;
|
||||
light.r = light.r * (1.0 - 0.2 * inside_depth);
|
||||
light.g = light.g * (1.0 - 0.2 * inside_depth);
|
||||
light.b = light.b * (1.0 - 0.2 * inside_depth);
|
||||
|
||||
return result;
|
||||
}
|
||||
return light;
|
||||
}*/
|
||||
|
||||
static Color _applyLayerLighting(CloudsDefinition* definition, CloudsQuality* quality, Vector3 position, Color base, double detail)
|
||||
static Color _applyLayerLighting(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 position, Color base, double detail)
|
||||
{
|
||||
Vector3 normal;
|
||||
return base;
|
||||
/*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);
|
||||
normal = v3Scale(_getNormal(definition, position, 1.0), 0.25);
|
||||
normal = v3Add(normal, v3Scale(_getNormal(definition, position, 0.5), 0.25));
|
||||
normal = v3Add(normal, v3Scale(_getNormal(definition, position, 0.2), 0.25));
|
||||
normal = v3Add(normal, v3Scale(_getNormal(definition, position, 0.1), 0.25));
|
||||
normal = v3Normalize(normal);
|
||||
|
||||
data.definition = definition;
|
||||
data.quality = quality;
|
||||
data.detail = detail;
|
||||
data.base = base;
|
||||
|
||||
lighting_environment.filter = _lightFilter;
|
||||
lighting_environment.custom_data = &data;
|
||||
|
@ -438,10 +459,10 @@ static Color _applyLayerLighting(CloudsDefinition* definition, CloudsQuality* qu
|
|||
material.reflection = 0.3;
|
||||
material.shininess = 0.1;
|
||||
|
||||
return lightingApplyCustom(position, normal, material, NULL, NULL, &lighting_environment);
|
||||
return lightingApplyCustom(position, normal, material, NULL, NULL, &lighting_environment);*/
|
||||
}
|
||||
|
||||
Color cloudsGetColorCustom(Vector3 start, Vector3 end, CloudsDefinition* definition, CloudsQuality* quality, CloudsEnvironment* environment)
|
||||
Color cloudsGetLayerColor(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 start, Vector3 end)
|
||||
{
|
||||
int i, segment_count;
|
||||
double max_length, detail, total_length, inside_length;
|
||||
|
@ -449,15 +470,6 @@ Color cloudsGetColorCustom(Vector3 start, Vector3 end, CloudsDefinition* definit
|
|||
Color result, col;
|
||||
CloudSegment segments[20];
|
||||
|
||||
if (quality == NULL)
|
||||
{
|
||||
quality = &_quality;
|
||||
}
|
||||
if (environment == NULL)
|
||||
{
|
||||
environment = &_environment;
|
||||
}
|
||||
|
||||
if (!_optimizeSearchLimits(definition, &start, &end))
|
||||
{
|
||||
return COLOR_TRANSPARENT;
|
||||
|
@ -471,35 +483,35 @@ Color cloudsGetColorCustom(Vector3 start, Vector3 end, CloudsDefinition* definit
|
|||
/* TODO Flexible precision */
|
||||
detail = renderGetPrecision(start) / definition->scaling;
|
||||
|
||||
segment_count = _findSegments(definition, quality, start, direction, detail, 20, 60.0, max_length, &inside_length, &total_length, segments);
|
||||
segment_count = _findSegments(definition, renderer, start, direction, detail, 20, 60.0, max_length, &inside_length, &total_length, segments);
|
||||
for (i = 0; i < segment_count; i++)
|
||||
{
|
||||
col = _applyLayerLighting(definition, quality, segments[i].start, definition->color, detail);
|
||||
col = _applyLayerLighting(definition, renderer, segments[i].start, definition->color, detail);
|
||||
col.a = (segments[i].length >= 50.0) ? 1.0 : (segments[i].length / 50.0);
|
||||
colorMask(&result, &col);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Color cloudsGetColor(Vector3 start, Vector3 end)
|
||||
Color cloudsGetColor(CloudsDefinition* definition, Renderer* renderer, Vector3 start, Vector3 end)
|
||||
{
|
||||
int i;
|
||||
Color layer_color, result;
|
||||
|
||||
if (end.y < start.y)
|
||||
{
|
||||
return cloudsGetColor(end, start);
|
||||
return cloudsGetColor(definition, renderer, end, start);
|
||||
}
|
||||
|
||||
if (_layers_count < 1 || end.y - start.y < 0.001)
|
||||
if (definition->nblayers < 1 || end.y - start.y < 0.001)
|
||||
{
|
||||
return COLOR_TRANSPARENT;
|
||||
}
|
||||
|
||||
result = COLOR_TRANSPARENT;
|
||||
for (i = 0; i < _layers_count; i++)
|
||||
for (i = 0; i < definition->nblayers; i++)
|
||||
{
|
||||
layer_color = cloudsGetColorCustom(start, end, _layers + i, &_quality, &_environment);
|
||||
layer_color = cloudsGetLayerColor(definition->layers + i, renderer, start, end);
|
||||
if (layer_color.a > 0.0)
|
||||
{
|
||||
colorMask(&result, &layer_color);
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
#define _PAYSAGES_CLOUDS_H_
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "noise.h"
|
||||
#include "renderer.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CLOUDS_MAX_LAYERS 6
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double ycenter;
|
||||
|
@ -17,37 +21,35 @@ typedef struct
|
|||
Color color;
|
||||
double scaling;
|
||||
double coverage;
|
||||
} CloudsLayerDefinition;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int nblayers;
|
||||
CloudsLayerDefinition layers[CLOUDS_MAX_LAYERS];
|
||||
} CloudsDefinition;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double precision;
|
||||
} CloudsQuality;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int unused;
|
||||
} CloudsEnvironment;
|
||||
|
||||
void cloudsInit();
|
||||
void cloudsSave(FILE* f);
|
||||
void cloudsLoad(FILE* f);
|
||||
|
||||
int cloudsGetLayerCount();
|
||||
int cloudsAddLayer();
|
||||
void cloudsDeleteLayer(int layer);
|
||||
void cloudsSave(FILE* f, CloudsDefinition* definition);
|
||||
void cloudsLoad(FILE* f, CloudsDefinition* definition);
|
||||
|
||||
CloudsDefinition cloudsCreateDefinition();
|
||||
void cloudsDeleteDefinition(CloudsDefinition definition);
|
||||
void cloudsCopyDefinition(CloudsDefinition source, CloudsDefinition* destination);
|
||||
void cloudsSetDefinition(int layer, CloudsDefinition definition);
|
||||
CloudsDefinition cloudsGetDefinition(int layer);
|
||||
void cloudsDeleteDefinition(CloudsDefinition* definition);
|
||||
void cloudsCopyDefinition(CloudsDefinition* source, CloudsDefinition* destination);
|
||||
void cloudsValidateDefinition(CloudsDefinition* definition);
|
||||
|
||||
void cloudsSetQuality(CloudsQuality quality);
|
||||
CloudsQuality cloudsGetQuality();
|
||||
CloudsLayerDefinition cloudsLayerCreateDefinition();
|
||||
void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition);
|
||||
void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination);
|
||||
void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition);
|
||||
|
||||
Color cloudsGetColorCustom(Vector3 start, Vector3 end, CloudsDefinition* definition, CloudsQuality* quality, CloudsEnvironment* environment);
|
||||
Color cloudsGetColor(Vector3 start, Vector3 end);
|
||||
int cloudsGetLayerCount(CloudsDefinition* definition);
|
||||
CloudsLayerDefinition* cloudsGetLayer(CloudsDefinition* definition, int layer);
|
||||
int cloudsAddLayer(CloudsDefinition* definition);
|
||||
void cloudsDeleteLayer(CloudsDefinition* definition, int layer);
|
||||
|
||||
Color cloudsGetLayerColor(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 start, Vector3 end);
|
||||
Color cloudsGetColor(CloudsDefinition* definition, Renderer* renderer, Vector3 start, Vector3 end);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@ void fogSetDistance(double near, double far)
|
|||
|
||||
Color fogApplyToLocation(Vector3 location, Color base)
|
||||
{
|
||||
Color mask = _col;
|
||||
// TODO Don't use camera_location
|
||||
/*Color mask = _col;
|
||||
double distance = v3Norm(v3Sub(camera_location, location));
|
||||
double value;
|
||||
|
||||
|
@ -44,6 +45,6 @@ Color fogApplyToLocation(Vector3 location, Color base)
|
|||
|
||||
mask.a *= value;
|
||||
colorMask(&base, &mask);
|
||||
return base;
|
||||
return base;*/
|
||||
}
|
||||
|
||||
|
|
|
@ -12,32 +12,13 @@
|
|||
#include "sky.h"
|
||||
#include "water.h"
|
||||
#include "terrain.h"
|
||||
|
||||
static LightingDefinition _definition;
|
||||
static LightingQuality _quality;
|
||||
static LightingEnvironment _environment;
|
||||
#include "renderer.h"
|
||||
#include "scenery.h"
|
||||
|
||||
static LightDefinition _LIGHT_NULL;
|
||||
|
||||
static Color _standardFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data)
|
||||
{
|
||||
Color result;
|
||||
|
||||
result = waterLightFilter(light, location, light_location, direction_to_light, custom_data);
|
||||
result = terrainLightFilter(result, location, light_location, direction_to_light, custom_data);
|
||||
// TODO atmosphere filter
|
||||
// TODO clouds filter
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -65,38 +46,25 @@ LightingDefinition lightingCreateDefinition()
|
|||
return definition;
|
||||
}
|
||||
|
||||
void lightingDeleteDefinition(LightingDefinition definition)
|
||||
void lightingDeleteDefinition(LightingDefinition* definition)
|
||||
{
|
||||
}
|
||||
|
||||
void lightingCopyDefinition(LightingDefinition source, LightingDefinition* destination)
|
||||
void lightingCopyDefinition(LightingDefinition* source, LightingDefinition* destination)
|
||||
{
|
||||
*destination = source;
|
||||
}
|
||||
|
||||
void lightingSetDefinition(LightingDefinition definition)
|
||||
{
|
||||
lightingValidateDefinition(&definition);
|
||||
lightingCopyDefinition(definition, &_definition);
|
||||
}
|
||||
|
||||
LightingDefinition lightingGetDefinition()
|
||||
{
|
||||
return _definition;
|
||||
*destination = *source;
|
||||
}
|
||||
|
||||
void lightingValidateDefinition(LightingDefinition* definition)
|
||||
{
|
||||
if (!definition)
|
||||
{
|
||||
lightingValidateDefinition(&_definition);
|
||||
return;
|
||||
}
|
||||
|
||||
if (definition->autosetfromsky)
|
||||
{
|
||||
// TODO Get lights from sky
|
||||
definition->_nbautolights = skyGetLights(definition->_autolights, MAX_LIGHTS);
|
||||
SkyDefinition sky;
|
||||
|
||||
sky = skyCreateDefinition();
|
||||
sceneryGetSky(&sky);
|
||||
definition->_nbautolights = skyGetLights(&sky, definition->_autolights, LIGHTING_MAX_LIGHTS);
|
||||
skyDeleteDefinition(&sky);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -123,7 +91,7 @@ LightDefinition lightingGetLight(LightingDefinition* definition, int light)
|
|||
|
||||
int lightingAddLight(LightingDefinition* definition, LightDefinition light)
|
||||
{
|
||||
if (definition->nblights < MAX_LIGHTS)
|
||||
if (definition->nblights < LIGHTING_MAX_LIGHTS)
|
||||
{
|
||||
definition->lights[definition->nblights] = light;
|
||||
return definition->nblights++;
|
||||
|
@ -146,17 +114,7 @@ void lightingDeleteLight(LightingDefinition* definition, int light)
|
|||
}
|
||||
}
|
||||
|
||||
void lightingSetQuality(LightingQuality quality)
|
||||
{
|
||||
_quality = quality;
|
||||
}
|
||||
|
||||
LightingQuality lightingGetQuality()
|
||||
{
|
||||
return _quality;
|
||||
}
|
||||
|
||||
static Color _applyLightCustom(Vector3 location, Vector3 normal, ReceiverMaterial material, LightDefinition* definition, LightingQuality* quality, LightingEnvironment* environment)
|
||||
static Color _applyLightCustom(LightDefinition* definition, Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material)
|
||||
{
|
||||
Color result, light;
|
||||
double diffuse, specular;
|
||||
|
@ -165,14 +123,15 @@ static Color _applyLightCustom(Vector3 location, Vector3 normal, ReceiverMateria
|
|||
light = definition->color;
|
||||
|
||||
direction_inv = v3Scale(definition->direction, -1.0);
|
||||
light = environment->filter(light, location, v3Add(location, direction_inv), direction_inv, environment->custom_data);
|
||||
light = renderer->filterLight(renderer, light, location, v3Add(location, direction_inv), direction_inv);
|
||||
|
||||
normal = v3Normalize(normal);
|
||||
view = v3Normalize(v3Sub(location, camera_location)); // TODO Configurable
|
||||
view = v3Normalize(v3Sub(location, renderer->camera_location));
|
||||
reflect = v3Sub(v3Scale(normal, 2.0 * v3Dot(direction_inv, normal)), direction_inv);
|
||||
|
||||
diffuse = v3Dot(direction_inv, normal);
|
||||
//diffuse = pow(diffuse * 0.5 + 0.5, 2.0);
|
||||
diffuse = diffuse * 0.5 + 0.5;
|
||||
if (diffuse > 0.0)
|
||||
{
|
||||
if (material.shininess > 0.0)
|
||||
|
@ -198,38 +157,20 @@ static Color _applyLightCustom(Vector3 location, Vector3 normal, ReceiverMateria
|
|||
return result;
|
||||
}
|
||||
|
||||
Color lightingApplyCustom(Vector3 location, Vector3 normal, ReceiverMaterial material, LightingDefinition* definition, LightingQuality* quality, LightingEnvironment* environment)
|
||||
Color lightingApplyToSurface(LightingDefinition* definition, Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material)
|
||||
{
|
||||
Color result;
|
||||
int i;
|
||||
|
||||
if (!definition)
|
||||
{
|
||||
definition = &_definition;
|
||||
}
|
||||
if (!quality)
|
||||
{
|
||||
quality = &_quality;
|
||||
}
|
||||
if (!environment)
|
||||
{
|
||||
environment = &_environment;
|
||||
}
|
||||
|
||||
/* TODO Merge lights */
|
||||
result = material.base;
|
||||
for (i = 0; i < definition->nblights; i++)
|
||||
{
|
||||
result = _applyLightCustom(location, normal, material, definition->lights + i, quality, environment);
|
||||
result = _applyLightCustom(definition->lights + i, renderer, location, normal, material);
|
||||
}
|
||||
for (i = 0; i < definition->_nbautolights; i++)
|
||||
{
|
||||
result = _applyLightCustom(location, normal, material, definition->_autolights + i, quality, environment);
|
||||
result = _applyLightCustom(definition->_autolights + i, renderer, location, normal, material);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Color lightingApply(Vector3 location, Vector3 normal, ReceiverMaterial material)
|
||||
{
|
||||
return lightingApplyCustom(location, normal, material, &_definition, &_quality, &_environment);
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
#define _PAYSAGES_LIGHTING_H_
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "renderer.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_LIGHTS 10
|
||||
#define LIGHTING_MAX_LIGHTS 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -21,40 +22,25 @@ typedef struct
|
|||
{
|
||||
int autosetfromsky;
|
||||
int nblights;
|
||||
LightDefinition lights[MAX_LIGHTS];
|
||||
LightDefinition lights[LIGHTING_MAX_LIGHTS];
|
||||
int _nbautolights;
|
||||
LightDefinition _autolights[MAX_LIGHTS];
|
||||
LightDefinition _autolights[LIGHTING_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;
|
||||
} SurfaceMaterial;
|
||||
|
||||
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 lightingDeleteDefinition(LightingDefinition* definition);
|
||||
void lightingCopyDefinition(LightingDefinition* source, LightingDefinition* destination);
|
||||
void lightingValidateDefinition(LightingDefinition* definition);
|
||||
|
||||
int lightingGetLightCount(LightingDefinition* definition);
|
||||
|
@ -62,11 +48,7 @@ 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);
|
||||
Color lightingApplyToSurface(LightingDefinition* definition, Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -23,17 +23,12 @@ void paysagesInit()
|
|||
ilInit();
|
||||
iluInit();
|
||||
|
||||
autoInit();
|
||||
renderInit();
|
||||
|
||||
cameraSetLocation(-12.0, 5.0, 2.0);
|
||||
cameraSetTarget(0.0, 5.0, 0.0);
|
||||
|
||||
autoInit();
|
||||
skyInit();
|
||||
terrainInit();
|
||||
texturesInit();
|
||||
waterInit();
|
||||
lightingInit();
|
||||
renderInit();
|
||||
|
||||
autoSetRenderQuality(5);
|
||||
autoGenRealisticLandscape(0);
|
||||
autoSetDaytime(8, 30);
|
||||
|
@ -54,36 +49,10 @@ void paysagesInit()
|
|||
|
||||
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);
|
||||
scenerySaveToFile(filepath);
|
||||
}
|
||||
|
||||
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);
|
||||
sceneryLoadFromFile(filepath);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef _PAYSAGES_MODIFIERS_H_
|
||||
#define _PAYSAGES_MODIFIERS_H_
|
||||
|
||||
#include "shared/types.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
struct NoiseLevel;
|
||||
|
||||
struct NoiseGenerator
|
||||
|
@ -15,7 +11,12 @@ struct NoiseGenerator
|
|||
struct NoiseLevel* levels;
|
||||
};
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "noise.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "shared/functions.h"
|
||||
|
||||
static inline double _cubicInterpolate(double* p, double x)
|
||||
|
@ -23,7 +24,6 @@ static inline double _cubicInterpolate(double* p, double x)
|
|||
return p[1] + 0.5 * x * (p[2] - p[0] + x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + x * (3.0 * (p[1] - p[2]) + p[3] - p[0])));
|
||||
}
|
||||
|
||||
|
||||
NoiseGenerator* noiseCreateGenerator()
|
||||
{
|
||||
NoiseGenerator* result;
|
||||
|
|
54
lib_paysages/noise.h
Normal file
54
lib_paysages/noise.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
#ifndef _PAYSAGES_NOISE_H_
|
||||
#define _PAYSAGES_NOISE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct NoiseLevel
|
||||
{
|
||||
double scaling;
|
||||
double height;
|
||||
double xoffset;
|
||||
double yoffset;
|
||||
double zoffset;
|
||||
};
|
||||
typedef struct NoiseLevel NoiseLevel;
|
||||
typedef struct NoiseGenerator NoiseGenerator;
|
||||
|
||||
NoiseGenerator* noiseCreateGenerator();
|
||||
void noiseDeleteGenerator(NoiseGenerator* generator);
|
||||
void noiseSave(NoiseGenerator* perlin, FILE* f);
|
||||
void noiseLoad(NoiseGenerator* perlin, FILE* f);
|
||||
void noiseCopy(NoiseGenerator* source, NoiseGenerator* destination);
|
||||
void noiseGenerateBaseNoise(NoiseGenerator* generator, int size);
|
||||
int noiseGetBaseSize(NoiseGenerator* generator);
|
||||
double noiseGetMaxValue(NoiseGenerator* generator);
|
||||
int noiseGetLevelCount(NoiseGenerator* generator);
|
||||
void noiseClearLevels(NoiseGenerator* generator);
|
||||
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);
|
||||
void noiseNormalizeHeight(NoiseGenerator* generator, double min_height, double max_height, int adjust_scaling);
|
||||
double noiseGet1DLevel(NoiseGenerator* generator, int level, double x);
|
||||
double noiseGet1DTotal(NoiseGenerator* generator, double x);
|
||||
double noiseGet1DDetail(NoiseGenerator* generator, double x, double detail);
|
||||
double noiseGet2DLevel(NoiseGenerator* generator, int level, double x, double y);
|
||||
double noiseGet2DTotal(NoiseGenerator* generator, double x, double y);
|
||||
double noiseGet2DDetail(NoiseGenerator* generator, double x, double y, double detail);
|
||||
double noiseGet3DLevel(NoiseGenerator* generator, int level, double x, double y, double z);
|
||||
double noiseGet3DTotal(NoiseGenerator* generator, double x, double y, double z);
|
||||
double noiseGet3DDetail(NoiseGenerator* generator, double x, double y, double z, double detail);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -108,16 +108,21 @@ void renderSetSize(int width, int height)
|
|||
_cb_preview_clear(background_color);
|
||||
}
|
||||
|
||||
void renderSetQuality(int quality)
|
||||
int renderSetQuality(int quality)
|
||||
{
|
||||
if (quality < 1)
|
||||
{
|
||||
render_quality = 1;
|
||||
}
|
||||
else if (quality > 10)
|
||||
{
|
||||
render_quality = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
render_quality = quality;
|
||||
}
|
||||
return render_quality;
|
||||
}
|
||||
|
||||
void renderClear()
|
||||
|
|
19
lib_paysages/renderer.c
Normal file
19
lib_paysages/renderer.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "renderer.h"
|
||||
#include "shared/constants.h"
|
||||
|
||||
static Color _fakeFilterLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light)
|
||||
{
|
||||
return light_color;
|
||||
}
|
||||
|
||||
Renderer rendererGetFake()
|
||||
{
|
||||
Renderer result;
|
||||
|
||||
result.render_quality = 5;
|
||||
result.camera_location = VECTOR_ZERO;
|
||||
|
||||
result.filterLight = _fakeFilterLight;
|
||||
|
||||
return result;
|
||||
}
|
31
lib_paysages/renderer.h
Normal file
31
lib_paysages/renderer.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef _PAYSAGES_RENDERER_H_
|
||||
#define _PAYSAGES_RENDERER_H_
|
||||
|
||||
#include "shared/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct Renderer Renderer;
|
||||
|
||||
struct Renderer
|
||||
{
|
||||
/* Quality configuration */
|
||||
int render_quality;
|
||||
Vector3 camera_location;
|
||||
|
||||
/* Lighting related */
|
||||
Color (*filterLight)(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light);
|
||||
|
||||
/* Custom data */
|
||||
void* customData[10];
|
||||
};
|
||||
|
||||
Renderer rendererGetFake();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
197
lib_paysages/scenery.c
Normal file
197
lib_paysages/scenery.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
#include "scenery.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
CameraDefinition _camera;
|
||||
CloudsDefinition _clouds;
|
||||
LightingDefinition _lighting;
|
||||
SkyDefinition _sky;
|
||||
TerrainDefinition _terrain;
|
||||
TexturesDefinition _textures;
|
||||
WaterDefinition _water;
|
||||
|
||||
static Color _filterLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light)
|
||||
{
|
||||
Color result;
|
||||
|
||||
result = waterLightFilter(&_water, renderer, light_color, at_location, light_location, direction_to_light);
|
||||
result = terrainLightFilter(&_terrain, renderer, result, at_location, light_location, direction_to_light);
|
||||
// TODO atmosphere filter
|
||||
// TODO clouds filter
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static RayCastingResult _reflectionFunction(Vector3 start, Vector3 direction)
|
||||
{
|
||||
RayCastingResult result;
|
||||
|
||||
if (!terrainProjectRay(start, direction, &result.hit_location, &result.hit_color))
|
||||
{
|
||||
result.hit_color = skyProjectRay(start, direction);
|
||||
/* TODO hit_location */
|
||||
}
|
||||
|
||||
result.hit = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
static RayCastingResult _refractionFunction(Vector3 start, Vector3 direction)
|
||||
{
|
||||
RayCastingResult result;
|
||||
|
||||
result.hit = terrainProjectRay(start, direction, &result.hit_location, &result.hit_color);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void sceneryInit()
|
||||
{
|
||||
cameraInit();
|
||||
cloudsInit();
|
||||
lightingInit();
|
||||
skyInit();
|
||||
terrainInit();
|
||||
texturesInit();
|
||||
waterInit();
|
||||
|
||||
_camera = cameraCreateDefinition();
|
||||
_clouds = cloudsCreateDefinition();
|
||||
_lighting = lightingCreateDefinition();
|
||||
_sky = skyCreateDefinition();
|
||||
_terrain = terrainCreateDefinition();
|
||||
_textures = texturesCreateDefinition();
|
||||
_water = waterCreateDefinition();
|
||||
}
|
||||
|
||||
void scenerySaveToFile(char* filepath)
|
||||
{
|
||||
FILE* f = fopen(filepath, "wb");
|
||||
|
||||
cameraSave(f, &_camera);
|
||||
cloudsSave(f, &_clouds);
|
||||
lightingSave(f, &_lighting);
|
||||
skySave(f, &_sky);
|
||||
terrainSave(f, &_terrain);
|
||||
texturesSave(f, &_textures);
|
||||
waterSave(f, &_water);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void sceneryLoadFromFile(char* filepath)
|
||||
{
|
||||
FILE* f = fopen(filepath, "rb");
|
||||
|
||||
/* TODO Use intermediary definitions ? */
|
||||
|
||||
cameraLoad(f, &_camera);
|
||||
cameraValidateDefinition(&_camera);
|
||||
|
||||
cloudsLoad(f, &_clouds);
|
||||
cloudsValidateDefinition(&_clouds);
|
||||
|
||||
lightingLoad(f, &_lighting);
|
||||
lightingValidateDefinition(&_lighting);
|
||||
|
||||
skyLoad(f, &_sky);
|
||||
skyValidateDefinition(&_sky);
|
||||
|
||||
terrainLoad(f, &_terrain);
|
||||
terrainValidateDefinition(&_terrain);
|
||||
|
||||
texturesLoad(f, &_textures);
|
||||
texturesValidateDefinition(&_textures);
|
||||
|
||||
waterLoad(f, &_water);
|
||||
waterValidateDefinition(&_water);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void scenerySetCamera(CameraDefinition* camera)
|
||||
{
|
||||
cameraCopyDefinition(camera, &_camera);
|
||||
cameraValidateDefinition(&_camera);
|
||||
}
|
||||
|
||||
void sceneryGetCamera(CameraDefinition* camera)
|
||||
{
|
||||
cameraCopyDefinition(&_camera, camera);
|
||||
}
|
||||
|
||||
void scenerySetClouds(CloudsDefinition* clouds)
|
||||
{
|
||||
cloudsCopyDefinition(clouds, &_clouds);
|
||||
cloudsValidateDefinition(&_clouds);
|
||||
}
|
||||
|
||||
void sceneryGetClouds(CloudsDefinition* clouds)
|
||||
{
|
||||
cloudsCopyDefinition(_clouds, clouds);
|
||||
}
|
||||
|
||||
void scenerySetLighting(LightingDefinition* lighting)
|
||||
{
|
||||
lightingCopyDefinition(lighting, &_lighting);
|
||||
lightingValidateDefinition(&_lighting);
|
||||
}
|
||||
|
||||
void sceneryGetLighting(LightingDefinition* lighting)
|
||||
{
|
||||
lightingCopyDefinition(&_lighting, lighting);
|
||||
}
|
||||
|
||||
void scenerySetSky(SkyDefinition* sky)
|
||||
{
|
||||
skyCopyDefinition(sky, &_sky);
|
||||
skyValidateDefinition(&_sky);
|
||||
|
||||
lightingValidateDefinition(&_lighting);
|
||||
}
|
||||
|
||||
void sceneryGetSky(SkyDefinition* sky)
|
||||
{
|
||||
skyCopyDefinition(&_sky, sky);
|
||||
}
|
||||
|
||||
void scenerySetTerrain(TerrainDefinition* terrain)
|
||||
{
|
||||
terrainCopyDefinition(terrain, &_terrain);
|
||||
terrainValidateDefinition(&_terrain);
|
||||
}
|
||||
|
||||
void sceneryGetTerrain(TerrainDefinition* terrain)
|
||||
{
|
||||
terrainCopyDefinition(&_terrain, terrain);
|
||||
}
|
||||
|
||||
void scenerySetTextures(TexturesDefinition* textures)
|
||||
{
|
||||
texturesCopyDefinition(textures, &_textures);
|
||||
texturesValidateDefinition(&_textures);
|
||||
}
|
||||
|
||||
void sceneryGetTextures(TexturesDefinition* textures)
|
||||
{
|
||||
texturesCopyDefinition(&_textures, textures);
|
||||
}
|
||||
|
||||
void scenerySetWater(WaterDefinition* water)
|
||||
{
|
||||
waterCopyDefinition(water, &_water);
|
||||
waterValidateDefinition(&_water);
|
||||
}
|
||||
|
||||
void sceneryGetWater(WaterDefinition* water)
|
||||
{
|
||||
waterCopyDefinition(&_water, water);
|
||||
}
|
||||
|
||||
Renderer sceneryGetStandardRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
void sceneryRender()
|
||||
{
|
||||
}
|
57
lib_paysages/scenery.h
Normal file
57
lib_paysages/scenery.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
#ifndef _PAYSAGES_SCENERY_H_
|
||||
#define _PAYSAGES_SCENERY_H_
|
||||
|
||||
/*
|
||||
* Scenery management.
|
||||
*
|
||||
* This module handles all scenery components (terrain, water...) definitions and maintains
|
||||
* a standard renderer.
|
||||
*/
|
||||
|
||||
#include "camera.h"
|
||||
#include "clouds.h"
|
||||
#include "lighting.h"
|
||||
#include "sky.h"
|
||||
#include "terrain.h"
|
||||
#include "textures.h"
|
||||
#include "water.h"
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void sceneryInit();
|
||||
void scenerySaveToFile(char* filepath);
|
||||
void sceneryLoadFromFile(char* filepath);
|
||||
|
||||
void scenerySetCamera(CameraDefinition* camera);
|
||||
void sceneryGetCamera(CameraDefinition* camera);
|
||||
|
||||
void scenerySetClouds(CloudsDefinition* clouds);
|
||||
void sceneryGetClouds(CloudsDefinition* clouds);
|
||||
|
||||
void scenerySetLighting(LightingDefinition* lighting);
|
||||
void sceneryGetLighting(LightingDefinition* lighting);
|
||||
|
||||
void scenerySetSky(SkyDefinition* sky);
|
||||
void sceneryGetSky(SkyDefinition* sky);
|
||||
|
||||
void scenerySetTerrain(TerrainDefinition* terrain);
|
||||
void sceneryGetTerrain(TerrainDefinition* terrain);
|
||||
|
||||
void scenerySetTextures(TexturesDefinition* textures);
|
||||
void sceneryGetTextures(TexturesDefinition* textures);
|
||||
|
||||
void scenerySetWater(WaterDefinition* water);
|
||||
void sceneryGetWater(WaterDefinition* water);
|
||||
|
||||
Renderer sceneryGetStandardRenderer();
|
||||
void sceneryRender();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -25,22 +25,10 @@ void arrayClear(Array* array);
|
|||
void autoInit();
|
||||
void autoSetDaytime(int hour, int minute);
|
||||
void autoSetDaytimeFraction(double daytime);
|
||||
void autoSetRenderQuality(int quality);
|
||||
void autoGenRealisticLandscape(int seed);
|
||||
void autoRenderSceneTwoPass(int postonly);
|
||||
void autoRenderSceneRayTracing();
|
||||
|
||||
/* camera.c */
|
||||
void cameraSave(FILE* f);
|
||||
void cameraLoad(FILE* f);
|
||||
void cameraSetLocation(double x, double y, double z);
|
||||
void cameraSetTarget(double x, double y, double z);
|
||||
void cameraSetAngle(double angle);
|
||||
Vector3 cameraProject(Vector3 point);
|
||||
Vector3 cameraUnproject(Vector3 point);
|
||||
void cameraProjectToFragment(double x, double y, double z, RenderFragment* result);
|
||||
void cameraPushOverlay(Color col, f_RenderFragmentCallback callback);
|
||||
|
||||
/* color.c */
|
||||
void colorSave(Color col, FILE* f);
|
||||
Color colorLoad(FILE* f);
|
||||
|
@ -97,42 +85,12 @@ void fogSetColor(Color col);
|
|||
void fogSetDistance(double near, double far);
|
||||
Color fogApplyToLocation(Vector3 location, Color base);
|
||||
|
||||
/* noise.c */
|
||||
NoiseGenerator* noiseCreateGenerator();
|
||||
void noiseDeleteGenerator(NoiseGenerator* generator);
|
||||
void noiseSave(NoiseGenerator* perlin, FILE* f);
|
||||
void noiseLoad(NoiseGenerator* perlin, FILE* f);
|
||||
void noiseCopy(NoiseGenerator* source, NoiseGenerator* destination);
|
||||
void noiseGenerateBaseNoise(NoiseGenerator* generator, int size);
|
||||
int noiseGetBaseSize(NoiseGenerator* generator);
|
||||
double noiseGetMaxValue(NoiseGenerator* generator);
|
||||
int noiseGetLevelCount(NoiseGenerator* generator);
|
||||
void noiseClearLevels(NoiseGenerator* generator);
|
||||
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);
|
||||
void noiseNormalizeHeight(NoiseGenerator* generator, double min_height, double max_height, int adjust_scaling);
|
||||
double noiseGet1DLevel(NoiseGenerator* generator, int level, double x);
|
||||
double noiseGet1DTotal(NoiseGenerator* generator, double x);
|
||||
double noiseGet1DDetail(NoiseGenerator* generator, double x, double detail);
|
||||
double noiseGet2DLevel(NoiseGenerator* generator, int level, double x, double y);
|
||||
double noiseGet2DTotal(NoiseGenerator* generator, double x, double y);
|
||||
double noiseGet2DDetail(NoiseGenerator* generator, double x, double y, double detail);
|
||||
double noiseGet3DLevel(NoiseGenerator* generator, int level, double x, double y, double z);
|
||||
double noiseGet3DTotal(NoiseGenerator* generator, double x, double y, double z);
|
||||
double noiseGet3DDetail(NoiseGenerator* generator, double x, double y, double z, double detail);
|
||||
|
||||
/* render.c */
|
||||
void renderInit();
|
||||
void renderSave(FILE* f);
|
||||
void renderLoad(FILE* f);
|
||||
void renderSetSize(int width, int height);
|
||||
void renderSetQuality(int quality);
|
||||
int renderSetQuality(int quality);
|
||||
void renderClear();
|
||||
void renderUpdate();
|
||||
void renderInterrupt();
|
||||
|
@ -148,14 +106,6 @@ void renderSetPreviewCallbacks(PreviewCallbackResize resize, PreviewCallbackClea
|
|||
int renderSetNextProgressStep(double start, double end);
|
||||
int renderTellProgress(double progress);
|
||||
|
||||
/* sky.c */
|
||||
void skySave(FILE* f);
|
||||
void skyLoad(FILE* f);
|
||||
Color skyGetColor(Vector3 start, Vector3 direction);
|
||||
Color skyProjectRay(Vector3 start, Vector3 direction);
|
||||
void skySetGradation(ColorGradation grad);
|
||||
void skyRender(RenderProgressCallback callback);
|
||||
|
||||
/* tools.c */
|
||||
double toolsRandom();
|
||||
double toolsBicubicInterpolate(double stencil[16], double x, double y);
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern Vector3 camera_location;
|
||||
|
||||
extern int render_width;
|
||||
extern int render_height;
|
||||
extern int render_quality;
|
||||
|
|
|
@ -87,17 +87,6 @@ typedef struct
|
|||
void* data;
|
||||
} Array;
|
||||
|
||||
struct NoiseLevel
|
||||
{
|
||||
double scaling;
|
||||
double height;
|
||||
double xoffset;
|
||||
double yoffset;
|
||||
double zoffset;
|
||||
};
|
||||
typedef struct NoiseLevel NoiseLevel;
|
||||
typedef struct NoiseGenerator NoiseGenerator;
|
||||
|
||||
typedef struct Zone Zone;
|
||||
|
||||
typedef void (*PreviewCallbackResize)(int width, int height);
|
||||
|
|
|
@ -11,40 +11,32 @@
|
|||
|
||||
#define SPHERE_SIZE 1000.0
|
||||
|
||||
static SkyDefinition _definition;
|
||||
static SkyQuality _quality;
|
||||
static SkyEnvironment _environment;
|
||||
|
||||
void skyInit()
|
||||
{
|
||||
skySetDefinition(skyCreateDefinition());
|
||||
}
|
||||
|
||||
void skySave(FILE* f)
|
||||
void skySave(FILE* f, SkyDefinition* definition)
|
||||
{
|
||||
toolsSaveDouble(f, _definition.daytime);
|
||||
colorGradationSave(f, _definition.sun_color);
|
||||
toolsSaveDouble(f, _definition.sun_radius);
|
||||
colorGradationSave(f, _definition.zenith_color);
|
||||
colorGradationSave(f, _definition.haze_color);
|
||||
toolsSaveDouble(f, _definition.haze_height);
|
||||
toolsSaveDouble(f, _definition.haze_smoothing);
|
||||
toolsSaveDouble(f, definition->daytime);
|
||||
colorGradationSave(f, definition->sun_color);
|
||||
toolsSaveDouble(f, definition->sun_radius);
|
||||
colorGradationSave(f, definition->zenith_color);
|
||||
colorGradationSave(f, definition->haze_color);
|
||||
toolsSaveDouble(f, definition->haze_height);
|
||||
toolsSaveDouble(f, definition->haze_smoothing);
|
||||
}
|
||||
|
||||
void skyLoad(FILE* f)
|
||||
void skyLoad(FILE* f, SkyDefinition* definition)
|
||||
{
|
||||
definition->daytime = toolsLoadDouble(f);
|
||||
definition->sun_color = colorGradationLoad(f);
|
||||
definition->sun_radius = toolsLoadDouble(f);
|
||||
definition->zenith_color = colorGradationLoad(f);
|
||||
definition->haze_color = colorGradationLoad(f);
|
||||
definition->haze_height = toolsLoadDouble(f);
|
||||
definition->haze_smoothing = toolsLoadDouble(f);
|
||||
|
||||
SkyDefinition def;
|
||||
|
||||
def.daytime = toolsLoadDouble(f);
|
||||
def.sun_color = colorGradationLoad(f);
|
||||
def.sun_radius = toolsLoadDouble(f);
|
||||
def.zenith_color = colorGradationLoad(f);
|
||||
def.haze_color = colorGradationLoad(f);
|
||||
def.haze_height = toolsLoadDouble(f);
|
||||
def.haze_smoothing = toolsLoadDouble(f);
|
||||
|
||||
skySetDefinition(def);
|
||||
skyValidateDefinition(definition);
|
||||
}
|
||||
|
||||
SkyDefinition skyCreateDefinition()
|
||||
|
@ -64,13 +56,13 @@ SkyDefinition skyCreateDefinition()
|
|||
return def;
|
||||
}
|
||||
|
||||
void skyDeleteDefinition(SkyDefinition definition)
|
||||
void skyDeleteDefinition(SkyDefinition* definition)
|
||||
{
|
||||
}
|
||||
|
||||
void skyCopyDefinition(SkyDefinition source, SkyDefinition* destination)
|
||||
void skyCopyDefinition(SkyDefinition* source, SkyDefinition* destination)
|
||||
{
|
||||
*destination = source;
|
||||
*destination = *source;
|
||||
}
|
||||
|
||||
void skyValidateDefinition(SkyDefinition* definition)
|
||||
|
@ -87,31 +79,20 @@ void skyValidateDefinition(SkyDefinition* definition)
|
|||
colorGradationAdd(&definition->_sky_gradation, 1.0, &zenith);
|
||||
}
|
||||
|
||||
void skySetDefinition(SkyDefinition definition)
|
||||
{
|
||||
skyValidateDefinition(&definition);
|
||||
_definition = definition;
|
||||
}
|
||||
|
||||
SkyDefinition skyGetDefinition()
|
||||
{
|
||||
return _definition;
|
||||
}
|
||||
|
||||
int skyGetLights(LightDefinition* lights, int max_lights)
|
||||
int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights)
|
||||
{
|
||||
double sun_angle;
|
||||
Vector3 sun_direction;
|
||||
int nblights = 0;
|
||||
|
||||
sun_angle = (_definition.daytime + 0.75) * M_PI * 2.0;
|
||||
sun_angle = (sky->daytime + 0.75) * M_PI * 2.0;
|
||||
sun_direction.x = cos(sun_angle);
|
||||
sun_direction.y = sin(sun_angle);
|
||||
sun_direction.z = 0.0;
|
||||
|
||||
if (max_lights > 0)
|
||||
{
|
||||
lights[0].color = colorGradationGet(&_definition.sun_color, _definition.daytime);
|
||||
lights[0].color = colorGradationGet(sky->sun_color, sky->daytime);
|
||||
lights[0].direction = v3Scale(sun_direction, -1.0);
|
||||
lights[0].maxshadow = 1.0;
|
||||
nblights = 1;
|
||||
|
@ -120,25 +101,12 @@ int skyGetLights(LightDefinition* lights, int max_lights)
|
|||
return nblights;
|
||||
}
|
||||
|
||||
Color skyGetColorCustom(Vector3 eye, Vector3 look, SkyDefinition* definition, SkyQuality* quality, SkyEnvironment* environment)
|
||||
Color skyGetColor(SkyDefinition* definition, Renderer* renderer, Vector3 eye, Vector3 look)
|
||||
{
|
||||
double sun_angle, dist;
|
||||
Vector3 sun_position;
|
||||
Color sun_color, sky_color;
|
||||
|
||||
if (definition == NULL)
|
||||
{
|
||||
definition = &_definition;
|
||||
}
|
||||
if (quality == NULL)
|
||||
{
|
||||
quality = &_quality;
|
||||
}
|
||||
if (environment == NULL)
|
||||
{
|
||||
environment = &_environment;
|
||||
}
|
||||
|
||||
sun_angle = (definition->daytime + 0.75) * M_PI * 2.0;
|
||||
sun_position.x = cos(sun_angle);
|
||||
sun_position.y = sin(sun_angle);
|
||||
|
@ -169,28 +137,10 @@ Color skyGetColorCustom(Vector3 eye, Vector3 look, SkyDefinition* definition, Sk
|
|||
}
|
||||
}
|
||||
|
||||
Color skyGetColor(Vector3 eye, Vector3 look)
|
||||
static int _postProcessFragment(RenderFragment* fragment, Renderer* renderer)
|
||||
{
|
||||
return skyGetColorCustom(eye, look, &_definition, &_quality, &_environment);
|
||||
}
|
||||
|
||||
Color skyProjectRay(Vector3 start, Vector3 direction)
|
||||
{
|
||||
Color color_sky, color_clouds;
|
||||
|
||||
direction = v3Normalize(direction);
|
||||
|
||||
color_sky = skyGetColor(start, direction);
|
||||
color_clouds = cloudsGetColor(start, v3Add(start, v3Scale(direction, SPHERE_SIZE)));
|
||||
|
||||
colorMask(&color_sky, &color_clouds);
|
||||
|
||||
return color_sky;
|
||||
}
|
||||
|
||||
static int _postProcessFragment(RenderFragment* fragment)
|
||||
{
|
||||
Vector3 location, direction;
|
||||
// TODO
|
||||
/*Vector3 location, direction;
|
||||
Color color_sky, color_clouds;
|
||||
|
||||
location = fragment->vertex.location;
|
||||
|
@ -200,12 +150,12 @@ static int _postProcessFragment(RenderFragment* fragment)
|
|||
color_clouds = cloudsGetColor(camera_location, v3Add(camera_location, v3Scale(direction, 10.0)));
|
||||
|
||||
colorMask(&color_sky, &color_clouds);
|
||||
fragment->vertex.color = color_sky;
|
||||
fragment->vertex.color = color_sky;*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void skyRender(RenderProgressCallback callback)
|
||||
void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCallback callback)
|
||||
{
|
||||
int res_i, res_j;
|
||||
int i, j;
|
||||
|
@ -215,8 +165,8 @@ void skyRender(RenderProgressCallback callback)
|
|||
Color col;
|
||||
Vector3 direction;
|
||||
|
||||
res_i = render_quality * 40;
|
||||
res_j = render_quality * 20;
|
||||
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;
|
||||
|
||||
|
@ -240,7 +190,7 @@ void skyRender(RenderProgressCallback callback)
|
|||
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.location = v3Add(camera_location, direction);
|
||||
vertex1.location = v3Add(renderer->camera_location, direction);
|
||||
col.b = sin(direction.x) * sin(direction.x) * cos(direction.z) * cos(direction.z);
|
||||
vertex1.color = col;
|
||||
vertex1.callback = _postProcessFragment;
|
||||
|
@ -248,7 +198,7 @@ void skyRender(RenderProgressCallback callback)
|
|||
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.location = v3Add(camera_location, direction);
|
||||
vertex2.location = v3Add(renderer->camera_location, direction);
|
||||
col.b = sin(direction.x) * sin(direction.x) * cos(direction.z) * cos(direction.z);
|
||||
vertex2.color = col;
|
||||
vertex2.callback = _postProcessFragment;
|
||||
|
@ -256,7 +206,7 @@ void skyRender(RenderProgressCallback callback)
|
|||
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.location = v3Add(camera_location, direction);
|
||||
vertex3.location = v3Add(renderer->camera_location, direction);
|
||||
col.b = sin(direction.x) * sin(direction.x) * cos(direction.z) * cos(direction.z);
|
||||
vertex3.color = col;
|
||||
vertex3.callback = _postProcessFragment;
|
||||
|
@ -264,7 +214,7 @@ void skyRender(RenderProgressCallback callback)
|
|||
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.location = v3Add(camera_location, direction);
|
||||
vertex4.location = v3Add(renderer->camera_location, direction);
|
||||
col.b = sin(direction.x) * sin(direction.x) * cos(direction.z) * cos(direction.z);
|
||||
vertex4.color = col;
|
||||
vertex4.callback = _postProcessFragment;
|
||||
|
|
|
@ -21,37 +21,21 @@ typedef struct
|
|||
ColorGradation _sky_gradation;
|
||||
} SkyDefinition;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int unused;
|
||||
} SkyQuality;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int unused;
|
||||
} SkyEnvironment;
|
||||
|
||||
void skyInit();
|
||||
void skySave(FILE* f);
|
||||
void skyLoad(FILE* f);
|
||||
void skySave(FILE* f, SkyDefinition* definition);
|
||||
void skyLoad(FILE* f, SkyDefinition* definition);
|
||||
|
||||
SkyDefinition skyCreateDefinition();
|
||||
void skyDeleteDefinition(SkyDefinition definition);
|
||||
void skyCopyDefinition(SkyDefinition source, SkyDefinition* destination);
|
||||
void skyDeleteDefinition(SkyDefinition* definition);
|
||||
void skyCopyDefinition(SkyDefinition* source, SkyDefinition* destination);
|
||||
void skyValidateDefinition(SkyDefinition* definition);
|
||||
void skySetDefinition(SkyDefinition definition);
|
||||
SkyDefinition skyGetDefinition();
|
||||
|
||||
void skySetQuality(SkyQuality quality);
|
||||
SkyQuality skyGetQuality();
|
||||
int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights);
|
||||
|
||||
int skyGetLights(LightDefinition* lights, int max_lights);
|
||||
Color skyGetColor(SkyDefinition* definition, Renderer* renderer, Vector3 eye, Vector3 look);
|
||||
Color skyProjectRay(SkyDefinition* definition, Renderer* renderer, Vector3 start, Vector3 direction);
|
||||
|
||||
Color skyGetColorCustom(Vector3 eye, Vector3 look, SkyDefinition* definition, SkyQuality* quality, SkyEnvironment* environment);
|
||||
Color skyGetColor(Vector3 eye, Vector3 look);
|
||||
|
||||
Color skyProjectRay(Vector3 start, Vector3 direction);
|
||||
void skyRender(RenderProgressCallback callback);
|
||||
void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCallback callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "terrain.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "shared/functions.h"
|
||||
|
@ -9,52 +12,49 @@
|
|||
|
||||
#include "textures.h"
|
||||
#include "water.h"
|
||||
#include "terrain.h"
|
||||
|
||||
static TerrainDefinition _definition;
|
||||
static TerrainQuality _quality;
|
||||
static TerrainEnvironment _environment;
|
||||
static double _max_height = 1.0;
|
||||
|
||||
void terrainInit()
|
||||
{
|
||||
_definition = terrainCreateDefinition();
|
||||
_max_height = noiseGetMaxValue(_definition.height_noise);
|
||||
|
||||
_environment.toggle_fog = 1;
|
||||
_environment.lighting_definition = NULL;
|
||||
_environment.lighting_environment = NULL;
|
||||
}
|
||||
|
||||
void terrainSave(FILE* f)
|
||||
void terrainSave(FILE* f, TerrainDefinition* definition)
|
||||
{
|
||||
int i;
|
||||
|
||||
noiseSave(_definition.height_noise, f);
|
||||
toolsSaveInt(f, _definition.height_modifiers_count);
|
||||
for (i = 0; i < _definition.height_modifiers_count; i++)
|
||||
noiseSave(definition->height_noise, f);
|
||||
toolsSaveDouble(f, definition->height_factor);
|
||||
toolsSaveDouble(f, definition->scaling);
|
||||
|
||||
toolsSaveInt(f, definition->height_modifiers_count);
|
||||
for (i = 0; i < definition->height_modifiers_count; i++)
|
||||
{
|
||||
modifierSave(_definition.height_modifiers[i], f);
|
||||
modifierSave(definition->height_modifiers[i], f);
|
||||
}
|
||||
}
|
||||
|
||||
void terrainLoad(FILE* f)
|
||||
void terrainLoad(FILE* f, TerrainDefinition* definition)
|
||||
{
|
||||
int i;
|
||||
int i, n;
|
||||
HeightModifier* modifier;
|
||||
|
||||
noiseLoad(_definition.height_noise, f);
|
||||
_max_height = noiseGetMaxValue(_definition.height_noise);
|
||||
noiseLoad(definition->height_noise, f);
|
||||
definition->height_factor = toolsLoadDouble(f);
|
||||
definition->scaling = toolsLoadDouble(f);
|
||||
|
||||
for (i = 0; i < _definition.height_modifiers_count; i++)
|
||||
while (definition->height_modifiers_count > 0)
|
||||
{
|
||||
modifierDelete(_definition.height_modifiers[i]);
|
||||
terrainDelModifier(definition, 0);
|
||||
}
|
||||
_definition.height_modifiers_count = toolsLoadInt(f);
|
||||
for (i = 0; i < _definition.height_modifiers_count; i++)
|
||||
n = toolsLoadInt(f);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
_definition.height_modifiers[i] = modifierCreate();
|
||||
modifierLoad(_definition.height_modifiers[i], f);
|
||||
modifier = modifierCreate();
|
||||
modifierLoad(modifier, f);
|
||||
terrainAddModifier(&definition, modifier);
|
||||
modifierDelete(modifier);
|
||||
}
|
||||
|
||||
terrainValidateDefinition(definition);
|
||||
}
|
||||
|
||||
TerrainDefinition terrainCreateDefinition()
|
||||
|
@ -62,54 +62,57 @@ TerrainDefinition terrainCreateDefinition()
|
|||
TerrainDefinition definition;
|
||||
|
||||
definition.height_noise = noiseCreateGenerator();
|
||||
definition.height_factor = 0.0;
|
||||
definition.scaling = 1.0;
|
||||
definition.height_modifiers_count = 0;
|
||||
|
||||
terrainValidateDefinition(&definition);
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
void terrainDeleteDefinition(TerrainDefinition definition)
|
||||
void terrainDeleteDefinition(TerrainDefinition* definition)
|
||||
{
|
||||
int i;
|
||||
|
||||
noiseDeleteGenerator(definition.height_noise);
|
||||
for (i = 0; i < definition.height_modifiers_count; i++)
|
||||
noiseDeleteGenerator(definition->height_noise);
|
||||
for (i = 0; i < definition->height_modifiers_count; i++)
|
||||
{
|
||||
modifierDelete(definition.height_modifiers[i]);
|
||||
modifierDelete(definition->height_modifiers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void terrainCopyDefinition(TerrainDefinition source, TerrainDefinition* destination)
|
||||
void terrainCopyDefinition(TerrainDefinition* source, TerrainDefinition* destination)
|
||||
{
|
||||
int i;
|
||||
|
||||
noiseCopy(source.height_noise, destination->height_noise);
|
||||
destination->height_factor = source->height_factor;
|
||||
destination->scaling = source->scaling;
|
||||
|
||||
for (i = 0; i < destination->height_modifiers_count; i++)
|
||||
{
|
||||
modifierDelete(destination->height_modifiers[i]);
|
||||
}
|
||||
destination->height_modifiers_count = source.height_modifiers_count;
|
||||
for (i = 0; i < destination->height_modifiers_count; i++)
|
||||
destination->height_modifiers_count = 0;
|
||||
|
||||
for (i = 0; i < source->height_modifiers_count; i++)
|
||||
{
|
||||
destination->height_modifiers[i] = modifierCreateCopy(source.height_modifiers[i]);
|
||||
terrainAddModifier(destination, source->height_modifiers[i]);
|
||||
}
|
||||
|
||||
terrainValidateDefinition(destination);
|
||||
}
|
||||
|
||||
void terrainSetDefinition(TerrainDefinition definition)
|
||||
void terrainValidateDefinition(TerrainDefinition* definition)
|
||||
{
|
||||
terrainCopyDefinition(definition, &_definition);
|
||||
_max_height = noiseGetMaxValue(_definition.height_noise);
|
||||
definition->_max_height = noiseGetMaxValue(definition->height_noise) * definition->height_factor;
|
||||
/* FIXME _max_height depends on modifiers */
|
||||
}
|
||||
|
||||
TerrainDefinition terrainGetDefinition()
|
||||
{
|
||||
return _definition;
|
||||
}
|
||||
|
||||
int terrainAddModifier(TerrainDefinition* definition, HeightModifier* modifier)
|
||||
{
|
||||
if (definition->height_modifiers_count < MAX_HEIGHT_MODIFIER_COUNT)
|
||||
if (definition->height_modifiers_count < TERRAIN_MAX_MODIFIERS)
|
||||
{
|
||||
definition->height_modifiers[definition->height_modifiers_count] = modifierCreateCopy(modifier);
|
||||
return definition->height_modifiers_count++;
|
||||
|
@ -124,27 +127,22 @@ void terrainDelModifier(TerrainDefinition* definition, int modifier_position)
|
|||
{
|
||||
if (modifier_position >= 0 && modifier_position < definition->height_modifiers_count)
|
||||
{
|
||||
/* TODO */
|
||||
modifierDelete(definition->height_modifiers[modifier_position]);
|
||||
if (definition->height_modifiers_count > 1 && modifier_position < definition->height_modifiers_count - 1)
|
||||
{
|
||||
memmove(definition->height_modifiers + modifier_position, definition->height_modifiers + modifier_position + 1, sizeof(HeightModifier*) * (definition->height_modifiers_count - modifier_position - 1));
|
||||
}
|
||||
definition->height_modifiers_count--;
|
||||
}
|
||||
}
|
||||
|
||||
void terrainSetQuality(TerrainQuality quality)
|
||||
{
|
||||
_quality = quality;
|
||||
}
|
||||
|
||||
TerrainQuality terrainGetQuality()
|
||||
{
|
||||
return _quality;
|
||||
}
|
||||
|
||||
static inline double _getHeight(TerrainDefinition* definition, double x, double z, double detail)
|
||||
{
|
||||
Vector3 location;
|
||||
int i;
|
||||
|
||||
location.x = x;
|
||||
location.y = noiseGet2DDetail(definition->height_noise, x, z, detail);
|
||||
location.y = noiseGet2DDetail(definition->height_noise, x / definition->scaling, z / definition->scaling, detail) * definition->height_factor;
|
||||
location.z = z;
|
||||
|
||||
for (i = 0; i < definition->height_modifiers_count; i++)
|
||||
|
@ -166,16 +164,16 @@ static inline Vector3 _getPoint(TerrainDefinition* definition, double x, double
|
|||
return result;
|
||||
}
|
||||
|
||||
Color terrainLightFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data)
|
||||
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);
|
||||
inc_factor = (double)render_quality; // TODO Configurable
|
||||
inc_factor = (double)renderer->render_quality;
|
||||
inc_base = 1.0;
|
||||
inc_value = inc_base / inc_factor;
|
||||
smoothing = 0.03 * inc_factor;;
|
||||
smoothing = 0.03 * inc_factor;
|
||||
|
||||
light_factor = 1.0;
|
||||
length = 0.0;
|
||||
|
@ -184,7 +182,7 @@ Color terrainLightFilter(Color light, Vector3 location, Vector3 light_location,
|
|||
inc_vector = v3Scale(direction_to_light, inc_value);
|
||||
length += v3Norm(inc_vector);
|
||||
location = v3Add(location, inc_vector);
|
||||
height = _getHeight(&_definition, location.x, location.z, inc_value);
|
||||
height = _getHeight(definition, location.x, location.z, inc_value);
|
||||
diff = location.y - height;
|
||||
if (diff < 0.0)
|
||||
{
|
||||
|
@ -203,7 +201,7 @@ Color terrainLightFilter(Color light, Vector3 location, Vector3 light_location,
|
|||
{
|
||||
inc_value = diff;
|
||||
}
|
||||
} while (light_factor > 0.0 && length < 50.0 && location.y <= _max_height);
|
||||
} while (light_factor > 0.0 && length < 50.0 && location.y <= definition._max_height);
|
||||
|
||||
if (light_factor <= 0.0)
|
||||
{
|
||||
|
@ -219,31 +217,29 @@ Color terrainLightFilter(Color light, Vector3 location, Vector3 light_location,
|
|||
}
|
||||
}
|
||||
|
||||
static Color _getColor(TerrainDefinition* definition, TerrainEnvironment* environment, Vector3 point, double precision)
|
||||
static Color _getColor(TerrainDefinition* definition, Renderer* renderer, Vector3 point, double precision)
|
||||
{
|
||||
Color color;
|
||||
TextureEnvironment texenv;
|
||||
|
||||
texenv.lighting_definition = environment->lighting_definition;
|
||||
texenv.lighting_environment = environment->lighting_environment;
|
||||
|
||||
color = texturesGetColorCustom(point, precision, NULL, &texenv);
|
||||
if (environment->toggle_fog)
|
||||
color = COLOR_RED;
|
||||
//color = texturesGetColorCustom(point, precision, NULL, &texenv);
|
||||
/*if (environment->toggle_fog)
|
||||
{
|
||||
color = fogApplyToLocation(point, color);
|
||||
}
|
||||
}*/
|
||||
//color = cloudsApplySegmentResult(color, camera_location, point);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
int terrainProjectRay(Vector3 start, Vector3 direction, Vector3* hit_point, Color* hit_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, length;
|
||||
|
||||
direction = v3Normalize(direction);
|
||||
inc_factor = (double)render_quality;
|
||||
inc_factor = (double)renderer->render_quality;
|
||||
inc_base = 1.0;
|
||||
inc_value = inc_base / inc_factor;
|
||||
|
||||
|
@ -253,13 +249,13 @@ int terrainProjectRay(Vector3 start, Vector3 direction, Vector3* hit_point, Colo
|
|||
inc_vector = v3Scale(direction, inc_value);
|
||||
length += v3Norm(inc_vector);
|
||||
start = v3Add(start, inc_vector);
|
||||
height = _getHeight(&_definition, start.x, start.z, inc_value);
|
||||
height = _getHeight(definition, start.x, start.z, inc_value);
|
||||
diff = start.y - height;
|
||||
if (diff < 0.0)
|
||||
{
|
||||
start.y = height;
|
||||
*hit_point = start;
|
||||
*hit_color = _getColor(&_definition, &_environment, start, inc_value);
|
||||
*hit_color = _getColor(definition, renderer, start, inc_value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -275,14 +271,14 @@ int terrainProjectRay(Vector3 start, Vector3 direction, Vector3* hit_point, Colo
|
|||
{
|
||||
inc_value = diff;
|
||||
}
|
||||
} while (length < 50.0 && start.y <= _max_height);
|
||||
} while (length < 50.0 && start.y <= definition._max_height);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _postProcessFragment(RenderFragment* fragment)
|
||||
{
|
||||
Vector3 point;
|
||||
/*Vector3 point;
|
||||
double precision;
|
||||
|
||||
point = fragment->vertex.location;
|
||||
|
@ -290,17 +286,17 @@ static int _postProcessFragment(RenderFragment* fragment)
|
|||
|
||||
point = _getPoint(&_definition, point.x, point.z, precision);
|
||||
|
||||
fragment->vertex.color = _getColor(&_definition, &_environment, point, precision);
|
||||
fragment->vertex.color = _getColor(&_definition, &_environment, point, precision);*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Vertex _getFirstPassVertex(double x, double z, double detail)
|
||||
static Vertex _getFirstPassVertex(TerrainDefinition* definition, double x, double z, double detail)
|
||||
{
|
||||
Vertex result;
|
||||
double value;
|
||||
|
||||
result.location = _getPoint(&_definition, x, z, 0.0);
|
||||
result.location = _getPoint(definition, x, z, 0.0);
|
||||
value = sin(x) * sin(x) * cos(z) * cos(z);
|
||||
result.color.r = value;
|
||||
result.color.g = value;
|
||||
|
@ -312,63 +308,50 @@ static Vertex _getFirstPassVertex(double x, double z, double detail)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void _renderQuad(double x, double z, double size)
|
||||
static void _renderQuad(TerrainDefinition* definition, double x, double z, double size)
|
||||
{
|
||||
Vertex v1, v2, v3, v4;
|
||||
|
||||
v1 = _getFirstPassVertex(x, z, size);
|
||||
v2 = _getFirstPassVertex(x, z + size, size);
|
||||
v3 = _getFirstPassVertex(x + size, z + size, size);
|
||||
v4 = _getFirstPassVertex(x + size, z, size);
|
||||
v1 = _getFirstPassVertex(definition, x, z, size);
|
||||
v2 = _getFirstPassVertex(definition, x, z + size, size);
|
||||
v3 = _getFirstPassVertex(definition, x + size, z + size, size);
|
||||
v4 = _getFirstPassVertex(definition, x + size, z, size);
|
||||
renderPushQuad(&v1, &v2, &v3, &v4);
|
||||
}
|
||||
|
||||
double terrainGetHeight(double x, double z)
|
||||
double terrainGetHeight(TerrainDefinition* definition, double x, double z)
|
||||
{
|
||||
return _getHeight(&_definition, x, z, 0.0);
|
||||
return _getHeight(definition, x, z, 0.0);
|
||||
}
|
||||
|
||||
double terrainGetHeightNormalized(double x, double z)
|
||||
double terrainGetHeightNormalized(TerrainDefinition* definition, double x, double z)
|
||||
{
|
||||
return 0.5 + _getHeight(&_definition, x, z, 0.0) / (_max_height * 2.0);
|
||||
return 0.5 + _getHeight(definition, x, z, 0.0) / (definition->_max_height * 2.0);
|
||||
}
|
||||
|
||||
Color terrainGetColorCustom(double x, double z, double detail, TerrainDefinition* definition, TerrainQuality* quality, TerrainEnvironment* environment)
|
||||
Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double x, double z, double detail)
|
||||
{
|
||||
if (!definition)
|
||||
{
|
||||
definition = &_definition;
|
||||
}
|
||||
if (!quality)
|
||||
{
|
||||
quality = &_quality;
|
||||
}
|
||||
if (!environment)
|
||||
{
|
||||
environment = &_environment;
|
||||
}
|
||||
|
||||
Vector3 point = _getPoint(definition, x, z, detail);
|
||||
return _getColor(definition, environment, point, detail);
|
||||
return _getColor(definition, renderer, point, detail);
|
||||
}
|
||||
|
||||
Color terrainGetColor(double x, double z, double detail)
|
||||
{
|
||||
return terrainGetColorCustom(x, z, detail, &_definition, &_quality, &_environment);
|
||||
}
|
||||
|
||||
void terrainRender(RenderProgressCallback callback)
|
||||
void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProgressCallback callback)
|
||||
{
|
||||
int chunk_factor, chunk_count, i;
|
||||
double cx = camera_location.x;
|
||||
double cz = camera_location.z;
|
||||
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;
|
||||
|
||||
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 = _quality.min_chunk_size;
|
||||
chunk_size = _quality.min_chunk_size;
|
||||
radius_ext = min_chunk_size;
|
||||
chunk_size = min_chunk_size;
|
||||
|
||||
|
||||
while (radius_ext < 1000.0)
|
||||
{
|
||||
|
@ -379,20 +362,20 @@ void terrainRender(RenderProgressCallback callback)
|
|||
|
||||
for (i = 0; i < chunk_count - 1; i++)
|
||||
{
|
||||
_renderQuad(cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size);
|
||||
_renderQuad(cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size);
|
||||
_renderQuad(cx + radius_int - chunk_size * i, cz + radius_int, chunk_size);
|
||||
_renderQuad(cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size);
|
||||
_renderQuad(definition, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size);
|
||||
_renderQuad(definition, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size);
|
||||
_renderQuad(definition, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size);
|
||||
_renderQuad(definition, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size);
|
||||
}
|
||||
|
||||
if (chunk_count % 64 == 0 && chunk_size / radius_int < _quality.visible_chunk_size)
|
||||
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 = _quality.min_chunk_size * chunk_factor;
|
||||
chunk_size = min_chunk_size * chunk_factor;
|
||||
radius_int = radius_ext;
|
||||
radius_ext += chunk_size;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "shared/types.h"
|
||||
#include "modifiers.h"
|
||||
#include "noise.h"
|
||||
#include "lighting.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -10,53 +11,37 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_HEIGHT_MODIFIER_COUNT 50
|
||||
#define TERRAIN_MAX_MODIFIERS 50
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NoiseGenerator* height_noise;
|
||||
double height_factor;
|
||||
double scaling;
|
||||
int height_modifiers_count;
|
||||
HeightModifier* height_modifiers[MAX_HEIGHT_MODIFIER_COUNT];
|
||||
HeightModifier* height_modifiers[TERRAIN_MAX_MODIFIERS];
|
||||
|
||||
double _max_height;
|
||||
} TerrainDefinition;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double min_chunk_size;
|
||||
double visible_chunk_size;
|
||||
} TerrainQuality;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int toggle_fog;
|
||||
LightingDefinition* lighting_definition;
|
||||
LightingEnvironment* lighting_environment;
|
||||
} TerrainEnvironment;
|
||||
|
||||
void terrainInit();
|
||||
void terrainSave(FILE* f);
|
||||
void terrainLoad(FILE* f);
|
||||
void terrainSave(FILE* f, TerrainDefinition* definition);
|
||||
void terrainLoad(FILE* f, TerrainDefinition* definition);
|
||||
|
||||
TerrainDefinition terrainCreateDefinition();
|
||||
void terrainDeleteDefinition(TerrainDefinition definition);
|
||||
void terrainCopyDefinition(TerrainDefinition source, TerrainDefinition* destination);
|
||||
void terrainSetDefinition(TerrainDefinition definition);
|
||||
TerrainDefinition terrainGetDefinition();
|
||||
void terrainDeleteDefinition(TerrainDefinition* definition);
|
||||
void terrainCopyDefinition(TerrainDefinition* source, TerrainDefinition* destination);
|
||||
void terrainValidateDefinition(TerrainDefinition* definition);
|
||||
|
||||
int terrainAddModifier(TerrainDefinition* definition, HeightModifier* modifier);
|
||||
void terrainDelModifier(TerrainDefinition* definition, int modifier_position);
|
||||
|
||||
void terrainSetQuality(TerrainQuality quality);
|
||||
TerrainQuality terrainGetQuality();
|
||||
|
||||
Color terrainLightFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data);
|
||||
int terrainProjectRay(Vector3 start, Vector3 direction, Vector3* hit_point, Color* hit_color);
|
||||
double terrainGetHeightCustom(double x, double z, TerrainDefinition* definition);
|
||||
double terrainGetHeight(double x, double z);
|
||||
double terrainGetHeightNormalizedCustom(double x, double z, TerrainDefinition* definition);
|
||||
double terrainGetHeightNormalized(double x, double z);
|
||||
Color terrainGetColorCustom(double x, double z, double detail, TerrainDefinition* definition, TerrainQuality* quality, TerrainEnvironment* environment);
|
||||
Color terrainGetColor(double x, double z, double detail);
|
||||
void terrainRender(RenderProgressCallback callback);
|
||||
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, RenderProgressCallback callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -12,90 +12,94 @@
|
|||
#include "terrain.h"
|
||||
#include "lighting.h"
|
||||
|
||||
#define TEXTURES_MAX 50
|
||||
static TextureQuality _quality;
|
||||
static TextureEnvironment _environment;
|
||||
static int _textures_count = 0;
|
||||
static TextureDefinition _textures[TEXTURES_MAX];
|
||||
static TextureLayerDefinition _NULL_LAYER;
|
||||
|
||||
void texturesInit()
|
||||
{
|
||||
_textures_count = 0;
|
||||
|
||||
_environment.lighting_definition = NULL;
|
||||
_environment.lighting_environment = NULL;
|
||||
_NULL_LAYER = texturesLayerCreateDefinition();
|
||||
}
|
||||
|
||||
void texturesSave(FILE* f)
|
||||
void texturesSave(FILE* f, TexturesDefinition* definition)
|
||||
{
|
||||
int i;
|
||||
|
||||
toolsSaveInt(f, _textures_count);
|
||||
for (i = 0; i < _textures_count; i++)
|
||||
toolsSaveInt(f, definition->nbtextures);
|
||||
for (i = 0; i < definition->nbtextures; i++)
|
||||
{
|
||||
zoneSave(_textures[i].zone, f);
|
||||
noiseSave(_textures[i].bump_noise, f);
|
||||
colorSave(_textures[i].color, f);
|
||||
zoneSave(definition->textures[i].zone, f);
|
||||
noiseSave(definition->textures[i].bump_noise, f);
|
||||
colorSave(definition->textures[i].color, f);
|
||||
}
|
||||
}
|
||||
|
||||
void texturesLoad(FILE* f)
|
||||
void texturesLoad(FILE* f, TexturesDefinition* definition)
|
||||
{
|
||||
TextureLayerDefinition* layer;
|
||||
int i, n;
|
||||
TextureDefinition* texture;
|
||||
|
||||
while (_textures_count > 0)
|
||||
while (definition->nbtextures > 0)
|
||||
{
|
||||
texturesDeleteLayer(0);
|
||||
texturesDeleteLayer(definition, 0);
|
||||
}
|
||||
|
||||
n = toolsLoadInt(f);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
texture = _textures + texturesAddLayer();
|
||||
layer = definition->nbtextures + texturesAddLayer(definition);
|
||||
|
||||
zoneLoad(texture->zone, f);
|
||||
noiseLoad(texture->bump_noise, f);
|
||||
texture->color = colorLoad(f);
|
||||
zoneLoad(layer->zone, f);
|
||||
noiseLoad(layer->bump_noise, f);
|
||||
layer->color = colorLoad(f);
|
||||
}
|
||||
|
||||
texturesValidateDefinition(definition);
|
||||
}
|
||||
|
||||
int texturesGetLayerCount()
|
||||
TexturesDefinition texturesCreateDefinition()
|
||||
{
|
||||
return _textures_count;
|
||||
TexturesDefinition result;
|
||||
|
||||
result.nbtextures = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int texturesAddLayer()
|
||||
void texturesDeleteDefinition(TexturesDefinition* definition)
|
||||
{
|
||||
if (_textures_count < TEXTURES_MAX)
|
||||
while (definition->nbtextures > 0)
|
||||
{
|
||||
_textures[_textures_count] = texturesCreateDefinition();
|
||||
|
||||
return _textures_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
texturesDeleteLayer(definition, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void texturesDeleteLayer(int layer)
|
||||
void texturesCopyDefinition(TexturesDefinition* source, TexturesDefinition* destination)
|
||||
{
|
||||
if (layer >= 0 && layer < _textures_count)
|
||||
TextureLayerDefinition* layer;
|
||||
int i;
|
||||
|
||||
while (destination->nbtextures > 0)
|
||||
{
|
||||
zoneDelete(_textures[layer].zone);
|
||||
noiseDeleteGenerator(_textures[layer].bump_noise);
|
||||
if (_textures_count > 1 && layer < _textures_count - 1)
|
||||
{
|
||||
memmove(_textures + layer, _textures + layer + 1, sizeof(TextureDefinition) * (_textures_count - layer - 1));
|
||||
}
|
||||
_textures_count--;
|
||||
texturesDeleteLayer(destination, 0);
|
||||
}
|
||||
for (i = 0; i < source->nbtextures; i++)
|
||||
{
|
||||
layer = texturesGetLayer(destination, texturesAddLayer(destination));
|
||||
texturesLayerCopyDefinition(source->textures + i, layer);
|
||||
}
|
||||
}
|
||||
|
||||
TextureDefinition texturesCreateDefinition()
|
||||
void texturesValidateDefinition(TexturesDefinition* definition)
|
||||
{
|
||||
TextureDefinition result;
|
||||
int i;
|
||||
for (i = 0; i < definition->nbtextures; i++)
|
||||
{
|
||||
texturesLayerValidateDefinition(definition->textures + i);
|
||||
}
|
||||
}
|
||||
|
||||
TextureLayerDefinition texturesLayerCreateDefinition()
|
||||
{
|
||||
TextureLayerDefinition result;
|
||||
|
||||
result.zone = zoneCreate();
|
||||
result.bump_noise = noiseCreateGenerator();
|
||||
|
@ -104,49 +108,68 @@ TextureDefinition texturesCreateDefinition()
|
|||
return result;
|
||||
}
|
||||
|
||||
void texturesDeleteDefinition(TextureDefinition definition)
|
||||
void texturesLayerDeleteDefinition(TextureLayerDefinition* definition)
|
||||
{
|
||||
zoneDelete(definition.zone);
|
||||
noiseDeleteGenerator(definition.bump_noise);
|
||||
}
|
||||
|
||||
void texturesCopyDefinition(TextureDefinition source, TextureDefinition* destination)
|
||||
void texturesLayerCopyDefinition(TextureLayerDefinition* source, TextureLayerDefinition* destination)
|
||||
{
|
||||
destination->color = source.color;
|
||||
noiseCopy(source.bump_noise, destination->bump_noise);
|
||||
zoneCopy(source.zone, destination->zone);
|
||||
}
|
||||
|
||||
void texturesSetDefinition(int layer, TextureDefinition definition)
|
||||
void texturesLayerValidateDefinition(TextureLayerDefinition* definition)
|
||||
{
|
||||
TextureDefinition* destination;
|
||||
}
|
||||
|
||||
if (layer >= 0 && layer < _textures_count)
|
||||
int texturesGetLayerCount(TexturesDefinition* definition)
|
||||
{
|
||||
return definition->nbtextures;
|
||||
}
|
||||
|
||||
TextureLayerDefinition* texturesGetLayer(TexturesDefinition* definition, int layer)
|
||||
{
|
||||
if (layer >= 0 && layer < definition->nbtextures)
|
||||
{
|
||||
destination = _textures + layer;
|
||||
texturesCopyDefinition(definition, destination);
|
||||
return definition->textures + layer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &_NULL_LAYER;
|
||||
}
|
||||
}
|
||||
|
||||
TextureDefinition texturesGetDefinition(int layer)
|
||||
int texturesAddLayer(TexturesDefinition* definition)
|
||||
{
|
||||
assert(layer >= 0);
|
||||
assert(layer < _textures_count);
|
||||
if (definition->nbtextures < TEXTURES_MAX_LAYERS)
|
||||
{
|
||||
_textures[definition->nbtextures] = texturesCreateDefinition();
|
||||
|
||||
return _textures[layer];
|
||||
return definition->nbtextures++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void texturesSetQuality(TextureQuality quality)
|
||||
void texturesDeleteLayer(TexturesDefinition* definition, int layer)
|
||||
{
|
||||
_quality = quality;
|
||||
if (layer >= 0 && layer < definition->nbtextures)
|
||||
{
|
||||
texturesLayerDeleteDefinition(definition->textures + layer);
|
||||
if (definition->nbtextures > 1 && layer < definition->nbtextures - 1)
|
||||
{
|
||||
memmove(definition->textures + layer, definition->textures + layer + 1, sizeof(TextureLayerDefinition) * (definition->nbtextures - layer - 1));
|
||||
}
|
||||
definition->nbtextures--;
|
||||
}
|
||||
}
|
||||
|
||||
TextureQuality texturesGetQuality()
|
||||
{
|
||||
return _quality;
|
||||
}
|
||||
|
||||
static inline Vector3 _getNormal(TextureDefinition* definition, Vector3 point, double scale)
|
||||
static inline Vector3 _getNormal(TextureLayerDefinition* definition, Vector3 point, double scale)
|
||||
{
|
||||
Vector3 dpoint, ref, normal;
|
||||
|
||||
|
@ -183,12 +206,12 @@ static inline Vector3 _getNormal(TextureDefinition* definition, Vector3 point, d
|
|||
return v3Normalize(normal);
|
||||
}
|
||||
|
||||
Color texturesGetLayerColorCustom(Vector3 location, double detail, TextureDefinition* definition, TextureQuality* quality, TextureEnvironment* environment)
|
||||
Color texturesGetLayerColor(TextureLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail)
|
||||
{
|
||||
Color result;
|
||||
Vector3 normal;
|
||||
double coverage;
|
||||
ReceiverMaterial material;
|
||||
SurfaceMaterial material;
|
||||
|
||||
result = COLOR_TRANSPARENT;
|
||||
normal = _getNormal(definition, location, detail * 0.3);
|
||||
|
@ -200,31 +223,22 @@ Color texturesGetLayerColorCustom(Vector3 location, double detail, TextureDefini
|
|||
material.reflection = 0.1;
|
||||
material.shininess = 0.1;
|
||||
|
||||
result = lightingApplyCustom(location, normal, material, environment->lighting_definition, NULL, environment->lighting_environment);
|
||||
result = renderer->applyLightingToSurface(renderer, location, normal, material);
|
||||
result.a = coverage;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Color texturesGetColorCustom(Vector3 location, double detail, TextureQuality* quality, TextureEnvironment* environment)
|
||||
Color texturesGetColorCustom(TexturesDefinition* definition, Renderer* renderer, Vector3 location, double detail)
|
||||
{
|
||||
Color result, tex_color;
|
||||
int i;
|
||||
|
||||
/*if (!quality)
|
||||
{
|
||||
quality = &_quality;
|
||||
}
|
||||
if (!environment)
|
||||
{
|
||||
environment = &_environment;
|
||||
}*/
|
||||
|
||||
result = COLOR_GREEN;
|
||||
for (i = 0; i < _textures_count; i++)
|
||||
for (i = 0; i < definition->nbtextures; i++)
|
||||
{
|
||||
/* TODO Do not compute layers fully covered */
|
||||
tex_color = texturesGetLayerColorCustom(location, detail, _textures + i, quality, environment);
|
||||
tex_color = texturesGetLayerColor(_textures + i, renderer, location, detail);
|
||||
if (tex_color.a > 0.0001)
|
||||
{
|
||||
colorMask(&result, &tex_color);
|
||||
|
@ -233,8 +247,3 @@ Color texturesGetColorCustom(Vector3 location, double detail, TextureQuality* qu
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
Color texturesGetColor(Vector3 location)
|
||||
{
|
||||
return texturesGetColorCustom(location, renderGetPrecision(location), &_quality, &_environment);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _PAYSAGES_TEXTURES_H_
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "noise.h"
|
||||
#include "lighting.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -9,44 +10,42 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TEXTURES_MAX_LAYERS 50
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Zone* zone;
|
||||
NoiseGenerator* bump_noise;
|
||||
Color color;
|
||||
} TextureDefinition;
|
||||
} TextureLayerDefinition;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int unused;
|
||||
} TextureQuality;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LightingDefinition* lighting_definition;
|
||||
LightingEnvironment* lighting_environment;
|
||||
} TextureEnvironment;
|
||||
int nbtextures;
|
||||
TextureLayerDefinition textures[TEXTURES_MAX_LAYERS];
|
||||
} TexturesDefinition;
|
||||
|
||||
void texturesInit();
|
||||
void texturesSave(FILE* f);
|
||||
void texturesLoad(FILE* f);
|
||||
void texturesSave(FILE* f, TexturesDefinition* definition);
|
||||
void texturesLoad(FILE* f, TexturesDefinition* definition);
|
||||
|
||||
int texturesGetLayerCount();
|
||||
int texturesAddLayer();
|
||||
void texturesDeleteLayer(int layer);
|
||||
TexturesDefinition texturesCreateDefinition();
|
||||
void texturesDeleteDefinition(TexturesDefinition* definition);
|
||||
void texturesCopyDefinition(TexturesDefinition* source, TexturesDefinition* destination);
|
||||
void texturesValidateDefinition(TexturesDefinition* definition);
|
||||
|
||||
TextureDefinition texturesCreateDefinition();
|
||||
void texturesDeleteDefinition(TextureDefinition definition);
|
||||
void texturesCopyDefinition(TextureDefinition source, TextureDefinition* destination);
|
||||
void texturesSetDefinition(int layer, TextureDefinition definition);
|
||||
TextureDefinition texturesGetDefinition(int layer);
|
||||
TextureLayerDefinition texturesLayerCreateDefinition();
|
||||
void texturesLayerDeleteDefinition(TextureLayerDefinition* definition);
|
||||
void texturesLayerCopyDefinition(TextureLayerDefinition* source, TextureLayerDefinition* destination);
|
||||
void texturesLayerValidateDefinition(TextureLayerDefinition* definition);
|
||||
|
||||
void texturesSetQuality(TextureQuality quality);
|
||||
TextureQuality texturesGetQuality();
|
||||
int texturesGetLayerCount(TexturesDefinition* definition);
|
||||
TextureLayerDefinition* texturesGetLayer(TexturesDefinition* definition, int layer);
|
||||
int texturesAddLayer(TexturesDefinition* definition);
|
||||
void texturesDeleteLayer(TexturesDefinition* definition, int layer);
|
||||
|
||||
Color texturesGetLayerColorCustom(Vector3 location, double detail, TextureDefinition* definition, TextureQuality* quality, TextureEnvironment* environment);
|
||||
Color texturesGetColorCustom(Vector3 location, double detail, TextureQuality* quality, TextureEnvironment* environment);
|
||||
Color texturesGetColor(Vector3 location);
|
||||
Color texturesGetLayerColor(TextureLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail);
|
||||
Color texturesGetColorCustom(TexturesDefinition* definition, Renderer* renderer, Vector3 location, double detail);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1,78 +1,45 @@
|
|||
#include "water.h"
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "shared/functions.h"
|
||||
#include "shared/constants.h"
|
||||
#include "shared/globals.h"
|
||||
|
||||
#include "water.h"
|
||||
#include "terrain.h"
|
||||
#include "lighting.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
static WaterDefinition _definition;
|
||||
static WaterQuality _quality;
|
||||
static WaterEnvironment _environment;
|
||||
|
||||
static RayCastingResult _reflectionFunction(Vector3 start, Vector3 direction)
|
||||
{
|
||||
RayCastingResult result;
|
||||
|
||||
if (!terrainProjectRay(start, direction, &result.hit_location, &result.hit_color))
|
||||
{
|
||||
result.hit_color = skyProjectRay(start, direction);
|
||||
/* TODO hit_location */
|
||||
}
|
||||
|
||||
result.hit = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
static RayCastingResult _refractionFunction(Vector3 start, Vector3 direction)
|
||||
{
|
||||
RayCastingResult result;
|
||||
|
||||
result.hit = terrainProjectRay(start, direction, &result.hit_location, &result.hit_color);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void waterInit()
|
||||
{
|
||||
_definition = waterCreateDefinition();
|
||||
|
||||
/* TODO quality */
|
||||
|
||||
_environment.reflection_function = _reflectionFunction;
|
||||
_environment.refraction_function = _refractionFunction;
|
||||
_environment.toggle_fog = 1;
|
||||
_environment.lighting_definition = NULL;
|
||||
_environment.lighting_environment = NULL;
|
||||
}
|
||||
|
||||
void waterSave(FILE* f)
|
||||
void waterSave(FILE* f, WaterDefinition* definition)
|
||||
{
|
||||
toolsSaveDouble(f, _definition.height);
|
||||
colorSave(_definition.main_color, f);
|
||||
colorSave(_definition.depth_color, f);
|
||||
toolsSaveDouble(f, _definition.transparency_depth);
|
||||
toolsSaveDouble(f, _definition.transparency);
|
||||
toolsSaveDouble(f, _definition.reflection);
|
||||
noiseSave(_definition.waves_noise, f);
|
||||
toolsSaveDouble(f, _definition.waves_noise_height);
|
||||
toolsSaveDouble(f, _definition.waves_noise_scale);
|
||||
toolsSaveDouble(f, definition.height);
|
||||
colorSave(definition->main_color, f);
|
||||
colorSave(definition->depth_color, f);
|
||||
toolsSaveDouble(f, definition->transparency_depth);
|
||||
toolsSaveDouble(f, definition->transparency);
|
||||
toolsSaveDouble(f, definition->reflection);
|
||||
noiseSave(definition->waves_noise, f);
|
||||
toolsSaveDouble(f, definition->waves_noise_height);
|
||||
toolsSaveDouble(f, definition->waves_noise_scale);
|
||||
}
|
||||
|
||||
void waterLoad(FILE* f)
|
||||
void waterLoad(FILE* f, WaterDefinition* definition)
|
||||
{
|
||||
_definition.height = toolsLoadDouble(f);
|
||||
_definition.main_color = colorLoad(f);
|
||||
_definition.depth_color = colorLoad(f);
|
||||
_definition.transparency_depth = toolsLoadDouble(f);
|
||||
_definition.transparency = toolsLoadDouble(f);
|
||||
_definition.reflection = toolsLoadDouble(f);
|
||||
noiseLoad(_definition.waves_noise, f);
|
||||
_definition.waves_noise_height = toolsLoadDouble(f);
|
||||
_definition.waves_noise_scale = toolsLoadDouble(f);
|
||||
definition->height = toolsLoadDouble(f);
|
||||
definition->main_color = colorLoad(f);
|
||||
definition->depth_color = colorLoad(f);
|
||||
definition->transparency_depth = toolsLoadDouble(f);
|
||||
definition->transparency = toolsLoadDouble(f);
|
||||
definition->reflection = toolsLoadDouble(f);
|
||||
noiseLoad(definition->waves_noise, f);
|
||||
definition->waves_noise_height = toolsLoadDouble(f);
|
||||
definition->waves_noise_scale = toolsLoadDouble(f);
|
||||
|
||||
waterValidateDefinition(definition);
|
||||
}
|
||||
|
||||
WaterDefinition waterCreateDefinition()
|
||||
|
@ -92,41 +59,23 @@ WaterDefinition waterCreateDefinition()
|
|||
return result;
|
||||
}
|
||||
|
||||
void waterDeleteDefinition(WaterDefinition definition)
|
||||
void waterDeleteDefinition(WaterDefinition* definition)
|
||||
{
|
||||
noiseDeleteGenerator(definition.waves_noise);
|
||||
noiseDeleteGenerator(definition->waves_noise);
|
||||
}
|
||||
|
||||
void waterCopyDefinition(WaterDefinition source, WaterDefinition* destination)
|
||||
void waterCopyDefinition(WaterDefinition* source, WaterDefinition* destination)
|
||||
{
|
||||
NoiseGenerator* noise;
|
||||
|
||||
noise = destination->waves_noise;
|
||||
*destination = source;
|
||||
destination->waves_noise = noise;
|
||||
noiseCopy(source.waves_noise, destination->waves_noise);
|
||||
noiseCopy(source->waves_noise, destination->waves_noise);
|
||||
}
|
||||
|
||||
void waterSetDefinition(WaterDefinition config)
|
||||
void waterValidateDefinition(WaterDefinition* definition)
|
||||
{
|
||||
waterCopyDefinition(config, &_definition);
|
||||
}
|
||||
|
||||
WaterDefinition waterGetDefinition()
|
||||
{
|
||||
return _definition;
|
||||
}
|
||||
|
||||
void waterSetQuality(WaterQuality quality)
|
||||
{
|
||||
_quality = quality;
|
||||
|
||||
_quality.detail_boost = (_quality.detail_boost < 0.1) ? 0.1 : _quality.detail_boost;
|
||||
}
|
||||
|
||||
WaterQuality waterGetQuality()
|
||||
{
|
||||
return _quality;
|
||||
}
|
||||
|
||||
static inline double _getHeight(WaterDefinition* definition, double x, double z, double detail)
|
||||
|
@ -180,44 +129,56 @@ static inline Vector3 _refractRay(Vector3 incoming, Vector3 normal)
|
|||
}
|
||||
}
|
||||
|
||||
WaterResult waterGetColorCustom(Vector3 location, Vector3 look, WaterDefinition* definition, WaterQuality* quality, WaterEnvironment* environment)
|
||||
Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light)
|
||||
{
|
||||
double factor;
|
||||
|
||||
if (location.y < definition->height)
|
||||
{
|
||||
if (direction_to_light.y > 0.00001)
|
||||
{
|
||||
factor = (definition->height - location.y) / (direction_to_light.y * 5.0); // TODO Configurable
|
||||
if (factor > 1.0)
|
||||
{
|
||||
factor = 1.0;
|
||||
}
|
||||
factor = 1.0 - 0.8 * factor;
|
||||
|
||||
light.r *= factor;
|
||||
light.g *= factor;
|
||||
light.b *= factor;
|
||||
|
||||
return light;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COLOR_BLACK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return light;
|
||||
}
|
||||
}
|
||||
|
||||
WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look)
|
||||
{
|
||||
WaterResult result;
|
||||
RayCastingResult refracted;
|
||||
Vector3 normal;
|
||||
Color color;
|
||||
ReceiverMaterial material;
|
||||
SurfaceMaterial material;
|
||||
double detail, depth;
|
||||
|
||||
if (definition == NULL)
|
||||
{
|
||||
definition = &_definition;
|
||||
}
|
||||
if (quality == NULL)
|
||||
{
|
||||
quality = &_quality;
|
||||
}
|
||||
if (environment == NULL)
|
||||
{
|
||||
environment = &_environment;
|
||||
}
|
||||
|
||||
if (quality->force_detail != 0.0)
|
||||
{
|
||||
detail = quality->force_detail;
|
||||
}
|
||||
else
|
||||
{
|
||||
detail = renderGetPrecision(location) / quality->detail_boost;
|
||||
}
|
||||
detail = renderer->getPrecision(renderer, location);
|
||||
|
||||
location.y = _getHeight(definition, location.x, location.z, detail);
|
||||
result.location = location;
|
||||
|
||||
normal = _getNormal(definition, location, detail);
|
||||
look = v3Normalize(look);
|
||||
result.reflected = environment->reflection_function(location, _reflectRay(look, normal)).hit_color;
|
||||
refracted = environment->refraction_function(location, _refractRay(look, normal));
|
||||
result.reflected = renderer->rayWalking(renderer, location, _reflectRay(look, normal), 0).hit_color;
|
||||
refracted = renderer->rayWalking(renderer, location, _refractRay(look, normal), 0);
|
||||
depth = v3Norm(v3Sub(location, refracted.hit_location));
|
||||
if (depth > definition->transparency_depth)
|
||||
{
|
||||
|
@ -240,11 +201,11 @@ WaterResult waterGetColorCustom(Vector3 location, Vector3 look, WaterDefinition*
|
|||
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 = renderer->applyLightingToSurface(renderer, location, normal, material);
|
||||
/*if (environment->toggle_fog)
|
||||
{
|
||||
color = fogApplyToLocation(location, color);
|
||||
}
|
||||
}*/
|
||||
|
||||
result.base = definition->main_color;
|
||||
result.final = color;
|
||||
|
@ -252,14 +213,14 @@ WaterResult waterGetColorCustom(Vector3 location, Vector3 look, WaterDefinition*
|
|||
return result;
|
||||
}
|
||||
|
||||
Color waterGetColor(Vector3 location, Vector3 look)
|
||||
Color waterGetColor(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look)
|
||||
{
|
||||
return waterGetColorCustom(location, look, &_definition, &_quality, &_environment).final;
|
||||
return waterGetColorDetail(definition, renderer, location, look).final;
|
||||
}
|
||||
|
||||
static int _postProcessFragment(RenderFragment* fragment)
|
||||
{
|
||||
fragment->vertex.color = waterGetColor(fragment->vertex.location, v3Sub(fragment->vertex.location, camera_location));
|
||||
/* fragment->vertex.color = waterGetColor(fragment->vertex.location, v3Sub(fragment->vertex.location, camera_location)); */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -293,46 +254,14 @@ static void _renderQuad(double x, double z, double size)
|
|||
renderPushQuad(&v1, &v2, &v3, &v4);
|
||||
}
|
||||
|
||||
Color waterLightFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data)
|
||||
{
|
||||
double factor;
|
||||
|
||||
if (location.y < _definition.height)
|
||||
{
|
||||
if (direction_to_light.y > 0.00001)
|
||||
{
|
||||
factor = (_definition.height - location.y) / (direction_to_light.y * 5.0); // TODO Configurable
|
||||
if (factor > 1.0)
|
||||
{
|
||||
factor = 1.0;
|
||||
}
|
||||
factor = 1.0 - 0.8 * factor;
|
||||
|
||||
light.r *= factor;
|
||||
light.g *= factor;
|
||||
light.b *= factor;
|
||||
|
||||
return light;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COLOR_BLACK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return light;
|
||||
}
|
||||
}
|
||||
|
||||
void waterRender(RenderProgressCallback callback)
|
||||
void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgressCallback callback)
|
||||
{
|
||||
int chunk_factor, chunk_count, i;
|
||||
double cx = camera_location.x;
|
||||
double cz = camera_location.z;
|
||||
double cx = renderer->camera_location.x;
|
||||
double cz = renderer->camera_location.z;
|
||||
double radius_int, radius_ext, base_chunk_size, chunk_size;
|
||||
|
||||
base_chunk_size = 2.0 / (double)render_quality;
|
||||
base_chunk_size = 2.0 / (double)renderer->render_quality;
|
||||
|
||||
chunk_factor = 1;
|
||||
chunk_count = 2;
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
#define _PAYSAGES_WATER_H_
|
||||
|
||||
#include "shared/types.h"
|
||||
#include "renderer.h"
|
||||
#include "lighting.h"
|
||||
#include "noise.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -22,21 +24,6 @@ typedef struct
|
|||
double waves_noise_scale;
|
||||
} WaterDefinition;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double detail_boost;
|
||||
double force_detail;
|
||||
} WaterQuality;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
RayCastingFunction reflection_function;
|
||||
RayCastingFunction refraction_function;
|
||||
int toggle_fog;
|
||||
LightingDefinition* lighting_definition;
|
||||
LightingEnvironment* lighting_environment;
|
||||
} WaterEnvironment;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Vector3 location;
|
||||
|
@ -47,21 +34,18 @@ typedef struct
|
|||
} WaterResult;
|
||||
|
||||
void waterInit();
|
||||
void waterSave(FILE* f);
|
||||
void waterLoad(FILE* f);
|
||||
void waterSave(FILE* f, WaterDefinition* definition);
|
||||
void waterLoad(FILE* f, WaterDefinition* definition);
|
||||
|
||||
WaterDefinition waterCreateDefinition();
|
||||
void waterDeleteDefinition(WaterDefinition definition);
|
||||
void waterCopyDefinition(WaterDefinition source, WaterDefinition* destination);
|
||||
void waterSetDefinition(WaterDefinition definition);
|
||||
WaterDefinition waterGetDefinition();
|
||||
void waterSetQuality(WaterQuality quality);
|
||||
WaterQuality waterGetQuality();
|
||||
void waterDeleteDefinition(WaterDefinition* definition);
|
||||
void waterCopyDefinition(WaterDefinition* source, WaterDefinition* destination);
|
||||
void waterValidateDefinition(WaterDefinition* definition);
|
||||
|
||||
Color waterLightFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data);
|
||||
WaterResult waterGetColorCustom(Vector3 location, Vector3 look, WaterDefinition* definition, WaterQuality* quality, WaterEnvironment* environment);
|
||||
Color waterGetColor(Vector3 location, Vector3 look);
|
||||
void waterRender(RenderProgressCallback callback);
|
||||
Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
|
||||
WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
|
||||
Color waterGetColor(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
|
||||
void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgressCallback callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue