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:
Michaël Lemaire 2012-01-23 23:45:33 +00:00 committed by ThunderK
parent 0685f21716
commit 48ea553f49
50 changed files with 1190 additions and 4734 deletions

View file

@ -1,21 +1,16 @@
all: all:
@+cd lib_paysages && make @+cd lib_paysages && make
@+cd cli && make @+cd cli && make
@+cd gui_gtk && make
@+cd gui_qt && qmake && make @+cd gui_qt && qmake && make
clean: clean:
cd lib_paysages && make clean cd lib_paysages && make clean
cd cli && make clean cd cli && make clean
cd gui_gtk && make clean
cd gui_qt && make clean && rm -f paysages-qt cd gui_qt && make clean && rm -f paysages-qt
run_cli: run_cli:
LD_LIBRARY_PATH=lib_paysages ./cli/paysages-cli LD_LIBRARY_PATH=lib_paysages ./cli/paysages-cli
run_gtk:
LD_LIBRARY_PATH=lib_paysages ./gui_gtk/paysages-gtk
run_qt: run_qt:
LD_LIBRARY_PATH=lib_paysages ./gui_qt/paysages-qt LD_LIBRARY_PATH=lib_paysages ./gui_qt/paysages-qt

12
TODO Normal file
View 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.

View file

@ -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

View file

@ -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);

View file

@ -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], &params))
{
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);
}

View file

@ -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;
}

File diff suppressed because it is too large Load diff

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -80,6 +80,7 @@ void BaseForm::revertConfig()
void BaseForm::applyConfig() void BaseForm::applyConfig()
{ {
revertConfig();
} }
void BaseForm::addPreview(Preview* preview, QString label) void BaseForm::addPreview(Preview* preview, QString label)

View file

@ -6,6 +6,7 @@
#include "preview.h" #include "preview.h"
#include "baseinput.h" #include "baseinput.h"
#include "../lib_paysages/shared/types.h" #include "../lib_paysages/shared/types.h"
#include "../lib_paysages/noise.h"
class BaseForm:public QWidget class BaseForm:public QWidget
{ {

View file

@ -9,8 +9,6 @@
#include <QScrollArea> #include <QScrollArea>
#include <QPushButton> #include <QPushButton>
#include "../lib_paysages/shared/functions.h"
/**************** Previews ****************/ /**************** Previews ****************/
class PreviewLevel:public Preview class PreviewLevel:public Preview
{ {

View file

@ -5,7 +5,7 @@
#include <QListWidget> #include <QListWidget>
#include "preview.h" #include "preview.h"
#include "../lib_paysages/shared/types.h" #include "../lib_paysages/noise.h"
class DialogNoise : public QDialog class DialogNoise : public QDialog
{ {

View file

@ -24,7 +24,7 @@ protected:
{ {
double height; 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)); return QColor((int)(255.0 * height), (int)(255.0 * height), (int)(255.0 * height));
} }
}; };
@ -35,7 +35,11 @@ public:
PreviewTerrainColor(QWidget* parent): PreviewTerrainColor(QWidget* parent):
Preview(parent) Preview(parent)
{ {
_lighting_environment.filter = NULL;
_environment.toggle_fog = 0; _environment.toggle_fog = 0;
_environment.lighting_definition = NULL;
_environment.lighting_environment = &_lighting_environment;
} }
protected: protected:
QColor getColor(double x, double y) QColor getColor(double x, double y)
@ -43,6 +47,7 @@ protected:
return colorToQColor(terrainGetColorCustom(x, y, scaling, &_definition, NULL, &_environment)); return colorToQColor(terrainGetColorCustom(x, y, scaling, &_definition, NULL, &_environment));
} }
private: private:
LightingEnvironment _lighting_environment;
TerrainEnvironment _environment; TerrainEnvironment _environment;
}; };
@ -54,10 +59,12 @@ FormTerrain::FormTerrain(QWidget *parent):
previewHeight = new PreviewTerrainHeight(this); previewHeight = new PreviewTerrainHeight(this);
previewColor = new PreviewTerrainColor(this); previewColor = new PreviewTerrainColor(this);
addPreview(previewHeight, QString("Height preview")); addPreview(previewHeight, QString("Height preview (normalized)"));
addPreview(previewColor, QString("Color preview")); 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(); revertConfig();
} }
@ -73,3 +80,9 @@ void FormTerrain::applyConfig()
terrainSetDefinition(_definition); terrainSetDefinition(_definition);
BaseForm::applyConfig(); BaseForm::applyConfig();
} }
void FormTerrain::applyConfigPreview()
{
terrainValidateDefinition(&_definition);
BaseForm::applyConfigPreview();
}

View file

@ -16,6 +16,9 @@ public slots:
virtual void revertConfig(); virtual void revertConfig();
virtual void applyConfig(); virtual void applyConfig();
protected slots:
virtual void applyConfigPreview();
private: private:
Preview* previewHeight; Preview* previewHeight;
Preview* previewColor; Preview* previewColor;

View file

@ -51,6 +51,7 @@ protected:
Vector3 eye, look, location; Vector3 eye, look, location;
WaterDefinition definition; WaterDefinition definition;
WaterEnvironment environment; WaterEnvironment environment;
LightingEnvironment lighting_environment;
WaterQuality quality; WaterQuality quality;
Color result; Color result;
@ -80,11 +81,12 @@ protected:
definition = _definition; definition = _definition;
definition.height = 0.0; definition.height = 0.0;
lighting_environment.filter = NULL;
environment.reflection_function = (RayCastingFunction)(&this->rayCastFromWater); environment.reflection_function = (RayCastingFunction)(&this->rayCastFromWater);
environment.refraction_function = (RayCastingFunction)(&this->rayCastFromWater); environment.refraction_function = (RayCastingFunction)(&this->rayCastFromWater);
environment.toggle_fog = 0; environment.toggle_fog = 0;
environment.lighting_definition = NULL; environment.lighting_definition = NULL;
environment.lighting_environment = NULL; environment.lighting_environment = &lighting_environment;
quality.force_detail = 0.0001; quality.force_detail = 0.0001;
quality.detail_boost = 1.0; quality.detail_boost = 1.0;

View file

@ -4,7 +4,7 @@
#include <QWidget> #include <QWidget>
#include "baseinput.h" #include "baseinput.h"
#include "../lib_paysages/shared/types.h" #include "../lib_paysages/noise.h"
class InputNoise:public BaseInput class InputNoise:public BaseInput
{ {

View file

@ -2,7 +2,9 @@
#include <QApplication> #include <QApplication>
#include <QMenuBar> #include <QMenuBar>
#include <QMenu>
#include <QFileDialog> #include <QFileDialog>
#include <QTabWidget>
#include "formterrain.h" #include "formterrain.h"
#include "formwater.h" #include "formwater.h"

View file

@ -16,6 +16,7 @@
#include "terrain.h" #include "terrain.h"
#include "textures.h" #include "textures.h"
#include "lighting.h" #include "lighting.h"
#include "scenery.h"
#ifdef WIN32 #ifdef WIN32
#include <windows.h> #include <windows.h>
@ -80,53 +81,25 @@ void autoSetDaytimeFraction(double daytime)
sun = colorGradationGet(&grad_sun, daytime); sun = colorGradationGet(&grad_sun, daytime);
lightingSetSunColor(sun);*/ lightingSetSunColor(sun);*/
sky = skyGetDefinition(); sky = skyCreateDefinition();
sceneryGetSky(&sky);
sky.daytime = daytime; sky.daytime = daytime;
skySetDefinition(sky); scenerySetSky(&sky);
skyDeleteDefinition(&sky);
lightingValidateDefinition(NULL);
fogSetColor(colorGradationGet(&sky.haze_color, daytime)); 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) void autoGenRealisticLandscape(int seed)
{ {
TerrainDefinition terrain; TerrainDefinition terrain;
WaterDefinition water; WaterDefinition water;
CloudsDefinition cloud; CloudsDefinition clouds;
CloudsLayerDefinition* cloud;
SkyDefinition sky; SkyDefinition sky;
TextureDefinition texture; TexturesDefinition textures;
TextureLayerDefinition* texture;
LightingDefinition lighting; LightingDefinition lighting;
int layer;
HeightModifier* mod; HeightModifier* mod;
Zone* zone; Zone* zone;
@ -137,33 +110,34 @@ void autoGenRealisticLandscape(int seed)
srand(seed); srand(seed);
/* Cloud layer */ /* Cloud layer */
cloud = cloudsCreateDefinition(); clouds = cloudsCreateDefinition();
cloud.ymin = 10.0; cloud = cloudsGetLayer(&clouds, cloudsAddLayer(&clouds));
cloud.ycenter = 40.0; cloud->ymin = 10.0;
cloud.ymax = 100.0; cloud->ycenter = 40.0;
cloud.color = COLOR_WHITE; cloud->ymax = 100.0;
cloud.color.a = 0.1; cloud->color = COLOR_WHITE;
cloud.scaling = 50.0; cloud->color.a = 0.1;
cloud.coverage = 0.5; cloud->scaling = 50.0;
noiseGenerateBaseNoise(cloud.noise, 262144); cloud->coverage = 0.5;
noiseAddLevelSimple(cloud.noise, 50.0, 0.3); noiseGenerateBaseNoise(cloud->noise, 262144);
noiseAddLevelSimple(cloud.noise, 50.0 / 2.0, 0.2); noiseAddLevelSimple(cloud->noise, 50.0, 0.3);
noiseAddLevelSimple(cloud.noise, 50.0 / 4.0, 0.1); noiseAddLevelSimple(cloud->noise, 50.0 / 2.0, 0.2);
noiseAddLevelSimple(cloud.noise, 50.0 / 10.0, 0.05); noiseAddLevelSimple(cloud->noise, 50.0 / 4.0, 0.1);
noiseAddLevelSimple(cloud.noise, 50.0 / 20.0, 0.03); noiseAddLevelSimple(cloud->noise, 50.0 / 10.0, 0.05);
noiseAddLevelSimple(cloud.noise, 50.0 / 40.0, 0.02); noiseAddLevelSimple(cloud->noise, 50.0 / 20.0, 0.03);
noiseAddLevelSimple(cloud.noise, 50.0 / 60.0, 0.01); noiseAddLevelSimple(cloud->noise, 50.0 / 40.0, 0.02);
noiseAddLevelSimple(cloud.noise, 50.0 / 80.0, 0.005); noiseAddLevelSimple(cloud->noise, 50.0 / 60.0, 0.01);
noiseAddLevelSimple(cloud.noise, 50.0 / 100.0, 0.02); noiseAddLevelSimple(cloud->noise, 50.0 / 80.0, 0.005);
noiseAddLevelSimple(cloud.noise, 50.0 / 150.0, 0.005); noiseAddLevelSimple(cloud->noise, 50.0 / 100.0, 0.02);
noiseAddLevelSimple(cloud.noise, 50.0 / 200.0, 0.003); noiseAddLevelSimple(cloud->noise, 50.0 / 150.0, 0.005);
noiseAddLevelSimple(cloud.noise, 50.0 / 400.0, 0.008); noiseAddLevelSimple(cloud->noise, 50.0 / 200.0, 0.003);
noiseAddLevelSimple(cloud.noise, 50.0 / 800.0, 0.001); noiseAddLevelSimple(cloud->noise, 50.0 / 400.0, 0.008);
noiseAddLevelSimple(cloud.noise, 50.0 / 1000.0, 0.0005); noiseAddLevelSimple(cloud->noise, 50.0 / 800.0, 0.001);
layer = cloudsAddLayer(); noiseAddLevelSimple(cloud->noise, 50.0 / 1000.0, 0.0005);
cloudsSetDefinition(layer, cloud); scenerySetClouds(&clouds);
/* Water */ /* Water */
water = waterCreateDefinition();
water.height = 0.0; water.height = 0.0;
water.transparency = 0.5; water.transparency = 0.5;
water.reflection = 0.3; water.reflection = 0.3;
@ -176,28 +150,25 @@ void autoGenRealisticLandscape(int seed)
water.depth_color.g = 0.2; water.depth_color.g = 0.2;
water.depth_color.b = 0.3; water.depth_color.b = 0.3;
water.depth_color.a = 1.0; water.depth_color.a = 1.0;
water.waves_noise = noiseCreateGenerator();
water.waves_noise_height = 0.015; water.waves_noise_height = 0.015;
water.waves_noise_scale = 0.2; water.waves_noise_scale = 0.2;
noiseGenerateBaseNoise(water.waves_noise, 262144); noiseGenerateBaseNoise(water.waves_noise, 262144);
noiseAddLevelsSimple(water.waves_noise, 2, 1.0, 1.0); noiseAddLevelsSimple(water.waves_noise, 2, 1.0, 1.0);
noiseAddLevelsSimple(water.waves_noise, 3, 0.15, 0.1); noiseAddLevelsSimple(water.waves_noise, 3, 0.15, 0.1);
waterSetDefinition(water); scenerySetWater(&water);
noiseDeleteGenerator(water.waves_noise); waterDeleteDefinition(&water);
/* Sky */ /* 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.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.5, 1.0, 0.95, 0.9, 1.0);
colorGradationAddRgba(&sky.sun_color, 0.7, 1.0, 0.91, 0.8, 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.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.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.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.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.75, 0.25, 0.33, 0.37, 1.0);
colorGradationAddRgba(&sky.zenith_color, 0.8, 0.03, 0.03, 0.05, 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.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.25, 0.55, 0.42, 0.42, 1.0);
colorGradationAddRgba(&sky.haze_color, 0.3, 0.6, 0.6, 0.6, 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_height = 0.75;
sky.haze_smoothing = 0.3; sky.haze_smoothing = 0.3;
sky.sun_radius = 0.02; sky.sun_radius = 0.02;
skySetDefinition(sky); scenerySetSky(&sky);
skyDeleteDefinition(&sky);
/* Lighting */ /* Lighting */
lighting = lightingCreateDefinition(); lighting = lightingCreateDefinition();
lighting.autosetfromsky = 1; lighting.autosetfromsky = 1;
lightingSetDefinition(lighting); scenerySetLighting(&lighting);
lightingDeleteDefinition(&lighting);
/* Terrain */ /* Terrain */
terrain = terrainCreateDefinition(); terrain = terrainCreateDefinition();
noiseGenerateBaseNoise(terrain.height_noise, 1048576); noiseGenerateBaseNoise(terrain.height_noise, 1048576);
noiseAddLevelsSimple(terrain.height_noise, 10, 10.0, 1.0); noiseAddLevelsSimple(terrain.height_noise, 10, 1.0, 1.0);
noiseNormalizeHeight(terrain.height_noise, -12.0, 12.0, 0); terrain.height_factor = 12.0 / noiseGetMaxValue(terrain.height_noise);
terrain.scaling = 10.0;
/* DEBUG */ /* DEBUG */
mod = modifierCreate(); mod = modifierCreate();
zone = modifierGetZone(mod); zone = modifierGetZone(mod);
@ -241,42 +215,36 @@ void autoGenRealisticLandscape(int seed)
modifierActionFixValue(mod, -8.0); modifierActionFixValue(mod, -8.0);
terrainAddModifier(&terrain, mod); terrainAddModifier(&terrain, mod);
/* DEBUG */ /* DEBUG */
terrainSetDefinition(terrain); scenerySetTerrain(&terrain);
terrainDeleteDefinition(terrain); terrainDeleteDefinition(&terrain);
/* Textures */ /* Textures */
layer = texturesAddLayer(); textures = texturesCreateDefinition();
texture = texturesCreateDefinition(); texture = texturesGetLayer(&textures, texturesAddLayer(&textures));
noiseGenerateBaseNoise(texture.bump_noise, 102400); noiseGenerateBaseNoise(texture->bump_noise, 102400);
noiseAddLevelsSimple(texture.bump_noise, 6, 0.01, 0.01); noiseAddLevelsSimple(texture->bump_noise, 6, 0.01, 0.01);
texture.color.r = 0.6; texture->color.r = 0.6;
texture.color.g = 0.55; texture->color.g = 0.55;
texture.color.b = 0.57; texture->color.b = 0.57;
texturesSetDefinition(layer, texture); texture = texturesGetLayer(&textures, texturesAddLayer(&textures));
texturesDeleteDefinition(texture); 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);
layer = texturesAddLayer(); noiseGenerateBaseNoise(texture->bump_noise, 102400);
texture = texturesCreateDefinition(); noiseAddLevelsSimple(texture->bump_noise, 6, 0.02, 0.008);
zoneAddHeightRange(texture.zone, 1.0, -1.0, 0.0, 3.0, 15.0); texture->color.r = 0.2;
zoneAddSteepnessRange(texture.zone, 1.0, 0.0, 0.0, 0.3, 0.4); texture->color.g = 0.24;
noiseGenerateBaseNoise(texture.bump_noise, 102400); texture->color.b = 0.05;
noiseAddLevelsSimple(texture.bump_noise, 6, 0.02, 0.008); /*texture = texturesGetLayer(&textures, texturesAddLayer(&textures));
texture.color.r = 0.2; zoneAddHeightRange(texture->zone, 1.0, 3.0, 4.0, 100.0, 100.0);
texture.color.g = 0.24; noiseGenerateBaseNoise(texture->bump_noise, 102400);
texture.color.b = 0.05; noiseAddLevelsSimple(texture->bump_noise, 6, 0.04, 0.003);
texturesSetDefinition(layer, texture); texture->color.r = 1.0;
texturesDeleteDefinition(texture); texture->color.g = 1.0;
texture->color.b = 1.0;
/*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;
texturesSetDefinition(layer, texture); texturesSetDefinition(layer, texture);
texturesDeleteDefinition(texture);*/ texturesDeleteDefinition(texture);*/
scenerySetTextures(&textures);
texturesDeleteDefinition(&textures);
/* Fog */ /* Fog */
fogSetDistance(20.0, 100.0); fogSetDistance(20.0, 100.0);
@ -342,23 +310,25 @@ static int _postProcessRayTracingOverlay(RenderFragment* fragment)
{ {
Vector3 terrain_hit, look; 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)) if (!terrainProjectRay(camera_location, look, &terrain_hit, &fragment->vertex.color))
{ {
fragment->vertex.color = skyProjectRay(camera_location, look); fragment->vertex.color = skyProjectRay(camera_location, look);
} }*/
return 1; return 1;
} }
void autoRenderSceneRayTracing() void autoRenderSceneRayTracing()
{ {
renderClear(); // TODO
/*renderClear();
cameraPushOverlay(COLOR_RED, _postProcessRayTracingOverlay); cameraPushOverlay(COLOR_RED, _postProcessRayTracingOverlay);
renderUpdate(); renderUpdate();
if (renderSetNextProgressStep(0.0, 1.0)) if (renderSetNextProgressStep(0.0, 1.0))
{ {
renderPostProcess(_cpu_count); renderPostProcess(_cpu_count);
} }*/
} }

View file

@ -1,3 +1,5 @@
#include "camera.h"
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
@ -6,71 +8,102 @@
#include "shared/constants.h" #include "shared/constants.h"
#include "shared/functions.h" #include "shared/functions.h"
Vector3 camera_location; void cameraInit()
static Vector3 camera_target; {
static Vector3 camera_up; }
static Matrix4 matrix_project;
static Matrix4 matrix_project_inverse;
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 */ /* TODO Recompute up vector */
camera_up.x = 0.0; definition->up.x = 0.0;
camera_up.y = 1.0; definition->up.y = 1.0;
camera_up.z = 0.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)); definition->project = m4Mult(m4NewPerspective(1.57, 1.333333, 1.0, 1000.0), m4NewLookAt(VECTOR_ZERO, v3Sub(definition->target, definition->location), definition->up));
matrix_project_inverse = m4Inverse(matrix_project); 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) void cameraSetAngle(CameraDefinition* camera, double angle)
{
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)
{ {
/* TODO */ /* 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.x = (-point.x + 1.0) * 0.5 * (double)render_width;
point.y = (-point.y + 1.0) * 0.5 * (double)render_height; point.y = (-point.y + 1.0) * 0.5 * (double)render_height;
return point; return point;
} }
Vector3 cameraUnproject(Vector3 point) Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point)
{ {
point.x = -(point.x / (0.5 * (double)render_width) - 1.0); point.x = -(point.x / (0.5 * (double)render_width) - 1.0);
point.y = -(point.y / (0.5 * (double)render_height) - 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}; 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->x = lround((-point.x + 1.0) * 0.5 * (double)render_width);
result->y = lround((-point.y + 1.0) * 0.5 * (double)render_height); result->y = lround((-point.y + 1.0) * 0.5 * (double)render_height);
result->z = point.z; 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 col Color of the polygon.
* @param callback Post-processing callback. * @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; Vertex v1, v2, v3, v4;
Vector3 v; Vector3 v;
@ -91,28 +124,28 @@ void cameraPushOverlay(Color col, f_RenderFragmentCallback callback)
v.x = 0.0; v.x = 0.0;
v.y = 0.0; v.y = 0.0;
v.z = 10.0; v.z = 10.0;
v1.location = cameraUnproject(v); v1.location = cameraUnproject(camera, v);
v1.color = col; v1.color = col;
v1.callback = callback; v1.callback = callback;
v.x = 0.0; v.x = 0.0;
v.y = (double)render_height; v.y = (double)render_height;
v.z = 10.0; v.z = 10.0;
v2.location = cameraUnproject(v); v2.location = cameraUnproject(camera, v);
v2.color = col; v2.color = col;
v2.callback = callback; v2.callback = callback;
v.x = (double)render_width; v.x = (double)render_width;
v.y = (double)render_height; v.y = (double)render_height;
v.z = 10.0; v.z = 10.0;
v3.location = cameraUnproject(v); v3.location = cameraUnproject(camera, v);
v3.color = col; v3.color = col;
v3.callback = callback; v3.callback = callback;
v.x = (double)render_width; v.x = (double)render_width;
v.y = 0.0; v.y = 0.0;
v.z = 10.0; v.z = 10.0;
v4.location = cameraUnproject(v); v4.location = cameraUnproject(camera, v);
v4.color = col; v4.color = col;
v4.callback = callback; v4.callback = callback;

41
lib_paysages/camera.h Normal file
View 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

View file

@ -9,13 +9,6 @@
#include "shared/constants.h" #include "shared/constants.h"
#include "shared/globals.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 typedef struct
{ {
Vector3 start; Vector3 start;
@ -23,22 +16,23 @@ typedef struct
double length; double length;
} CloudSegment; } CloudSegment;
static CloudsLayerDefinition NULL_LAYER;
void cloudsInit() void cloudsInit()
{ {
_layers_count = 0; NULL_LAYER.noise = noiseCreateGenerator();
NULL_LAYER.coverage = 0.0;
_quality.precision = 0.5;
} }
void cloudsSave(FILE* f) void cloudsSave(FILE* f, CloudsDefinition* definition)
{ {
int i; int i;
CloudsDefinition* layer; CloudsLayerDefinition* layer;
toolsSaveInt(f, _layers_count); toolsSaveInt(f, definition->nblayers);
for (i = 0; i < _layers_count; i++) for (i = 0; i < definition->nblayers; i++)
{ {
layer = _layers + i; layer = definition->layers + i;
toolsSaveDouble(f, layer->ycenter); toolsSaveDouble(f, layer->ycenter);
toolsSaveDouble(f, layer->ymin); toolsSaveDouble(f, layer->ymin);
toolsSaveDouble(f, layer->ymax); 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; int i, n;
CloudsDefinition* layer; CloudsLayerDefinition* layer;
while (_layers_count > 0) while (definition->nblayers > 0)
{ {
cloudsDeleteLayer(0); cloudsDeleteLayer(definition, 0);
} }
n = toolsLoadInt(f); n = toolsLoadInt(f);
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
layer = _layers + cloudsAddLayer(); layer = definition->layers + cloudsAddLayer(definition);
layer->ycenter = toolsLoadDouble(f); layer->ycenter = toolsLoadDouble(f);
layer->ymin = 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 cloudsCreateDefinition()
{ {
CloudsDefinition result; CloudsDefinition result;
result.color = COLOR_WHITE; result.nblayers = 0;
result.coverage = 0.0;
result.noise = noiseCreateGenerator();
result.scaling = 1.0;
result.ymin = 0.0;
result.ycenter = 0.0;
result.ymax = 0.0;
return result; 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; NoiseGenerator* noise;
noise = destination->noise; noise = destination->noise;
*destination = source; *destination = *source;
destination->noise = noise; 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 (definition->coverage < 0.5)
if (layer >= 0 && layer < _layers_count)
{ {
destination = _layers + layer; noiseNormalizeHeight(definition->noise, -1.0, definition->coverage * 2.0, 0);
cloudsCopyDefinition(definition, destination);
if (destination->coverage < 0.5)
{
noiseNormalizeHeight(destination->noise, -1.0, destination->coverage * 2.0, 0);
} }
else else
{ {
noiseNormalizeHeight(destination->noise, -(1.0 - destination->coverage) * 2.0, 1.0, 0); 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)
}
CloudsQuality cloudsGetQuality()
{ {
return _quality; return definition->layers + layer;
}
else
{
return &NULL_LAYER;
}
} }
static inline double _getDistanceToBorder(CloudsDefinition* layer, Vector3 position, double detail) int cloudsAddLayer(CloudsDefinition* definition)
{
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;
}
}
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; double val, min;
@ -192,7 +218,7 @@ static inline double _getDistanceToBorder(CloudsDefinition* layer, Vector3 posit
return (val - min) * layer->scaling; 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}; Vector3 result = {0.0, 0.0, 0.0};
double val, dval; 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); dval = val - noiseGet3DDetail(layer->noise, position.x, position.y, position.z - detail, detail);
result.z -= dval; 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 * @param end End of the search to optimize
* @return 0 if the search is useless * @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; 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). * Go through the cloud layer to find segments (parts of the lookup that are inside the cloud).
* *
* @param definition The cloud layer * @param definition The cloud layer
* @param quality Render quality * @param renderer The renderer environment
* @param start Start position of the lookup (already optimized) * @param start Start position of the lookup (already optimized)
* @param direction Normalized direction of the lookup * @param direction Normalized direction of the lookup
* @param detail Level of noise detail required * @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 * @param out_segments Allocated space to fill found segments
* @return Number of segments found * @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; int inside, segment_count;
double current_total_length, current_inside_length; double current_total_length, current_inside_length;
double step_length, segment_length, remaining_length; double step_length, segment_length, remaining_length;
double noise_distance, last_noise_distance; double noise_distance, last_noise_distance;
Vector3 walker, step, segment_start; Vector3 walker, step, segment_start;
double render_precision;
if (max_segments <= 0) if (max_segments <= 0)
{ {
return 0; return 0;
} }
render_precision = 3.3 - 0.3 * (double)renderer->render_quality;
segment_count = 0; segment_count = 0;
current_total_length = 0.0; current_total_length = 0.0;
current_inside_length = 0.0; current_inside_length = 0.0;
segment_length = 0.0; segment_length = 0.0;
walker = start; 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; inside = (noise_distance > 0.0) ? 1 : 0;
step = v3Scale(direction, quality->precision); step = v3Scale(direction, render_precision);
do do
{ {
walker = v3Add(walker, step); walker = v3Add(walker, step);
step_length = v3Norm(step); step_length = v3Norm(step);
last_noise_distance = noise_distance; 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; current_total_length += step_length;
if (noise_distance > 0.0) if (noise_distance > 0.0)
@ -334,7 +363,7 @@ static int _findSegments(CloudsDefinition* definition, CloudsQuality* quality, V
// inside the cloud // inside the cloud
segment_length += step_length; segment_length += step_length;
current_inside_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 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_length = step_length * noise_distance / (noise_distance - last_noise_distance);
segment_start = v3Add(walker, v3Scale(direction, -segment_length)); segment_start = v3Add(walker, v3Scale(direction, -segment_length));
current_inside_length += segment_length; current_inside_length += segment_length;
step = v3Scale(direction, quality->precision); step = v3Scale(direction, render_precision);
} }
} }
else else
@ -365,12 +394,12 @@ static int _findSegments(CloudsDefinition* definition, CloudsQuality* quality, V
} }
inside = 0; inside = 0;
step = v3Scale(direction, quality->precision); step = v3Scale(direction, render_precision);
} }
else else
{ {
// searching for a cloud // 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)); } 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; return segment_count;
} }
typedef struct /*static Color _lightFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data)
{
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)
{ {
double inside_depth, total_depth; double inside_depth, total_depth;
CloudSegment segments[20]; CloudSegment segments[20];
Color result;
LightFilterData data; LightFilterData data;
data = *((LightFilterData*)custom_data); data = *((LightFilterData*)custom_data);
data.detail = (data.detail < 0.1) ? 0.1 : data.detail; 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); _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; inside_depth *= 0.02;
@ -407,29 +427,30 @@ static Color _lightFilter(Color light, Vector3 location, Vector3 light_location,
inside_depth = 1.0; inside_depth = 1.0;
} }
result.r = data.base.r * - 0.2 * inside_depth; light.r = light.r * (1.0 - 0.2 * inside_depth);
result.g = data.base.g * - 0.2 * inside_depth; light.g = light.g * (1.0 - 0.2 * inside_depth);
result.b = data.base.b * - 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; ReceiverMaterial material;
LightingEnvironment lighting_environment; LightingEnvironment lighting_environment;
LightFilterData data; LightFilterData data;
normal = _getNormal(definition, position, 0.5); normal = v3Scale(_getNormal(definition, position, 1.0), 0.25);
normal = v3Add(normal, _getNormal(definition, position, 0.2)); normal = v3Add(normal, v3Scale(_getNormal(definition, position, 0.5), 0.25));
normal = v3Add(normal, _getNormal(definition, position, 0.1)); normal = v3Add(normal, v3Scale(_getNormal(definition, position, 0.2), 0.25));
//normal = v3Normalize(normal); normal = v3Add(normal, v3Scale(_getNormal(definition, position, 0.1), 0.25));
normal = v3Normalize(normal);
data.definition = definition; data.definition = definition;
data.quality = quality; data.quality = quality;
data.detail = detail; data.detail = detail;
data.base = base;
lighting_environment.filter = _lightFilter; lighting_environment.filter = _lightFilter;
lighting_environment.custom_data = &data; lighting_environment.custom_data = &data;
@ -438,10 +459,10 @@ static Color _applyLayerLighting(CloudsDefinition* definition, CloudsQuality* qu
material.reflection = 0.3; material.reflection = 0.3;
material.shininess = 0.1; 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; int i, segment_count;
double max_length, detail, total_length, inside_length; double max_length, detail, total_length, inside_length;
@ -449,15 +470,6 @@ Color cloudsGetColorCustom(Vector3 start, Vector3 end, CloudsDefinition* definit
Color result, col; Color result, col;
CloudSegment segments[20]; CloudSegment segments[20];
if (quality == NULL)
{
quality = &_quality;
}
if (environment == NULL)
{
environment = &_environment;
}
if (!_optimizeSearchLimits(definition, &start, &end)) if (!_optimizeSearchLimits(definition, &start, &end))
{ {
return COLOR_TRANSPARENT; return COLOR_TRANSPARENT;
@ -471,35 +483,35 @@ Color cloudsGetColorCustom(Vector3 start, Vector3 end, CloudsDefinition* definit
/* TODO Flexible precision */ /* TODO Flexible precision */
detail = renderGetPrecision(start) / definition->scaling; 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++) 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); col.a = (segments[i].length >= 50.0) ? 1.0 : (segments[i].length / 50.0);
colorMask(&result, &col); colorMask(&result, &col);
} }
return result; return result;
} }
Color cloudsGetColor(Vector3 start, Vector3 end) Color cloudsGetColor(CloudsDefinition* definition, Renderer* renderer, Vector3 start, Vector3 end)
{ {
int i; int i;
Color layer_color, result; Color layer_color, result;
if (end.y < start.y) 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; return COLOR_TRANSPARENT;
} }
result = 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) if (layer_color.a > 0.0)
{ {
colorMask(&result, &layer_color); colorMask(&result, &layer_color);

View file

@ -2,12 +2,16 @@
#define _PAYSAGES_CLOUDS_H_ #define _PAYSAGES_CLOUDS_H_
#include "shared/types.h" #include "shared/types.h"
#include "noise.h"
#include "renderer.h"
#include <stdio.h> #include <stdio.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define CLOUDS_MAX_LAYERS 6
typedef struct typedef struct
{ {
double ycenter; double ycenter;
@ -17,37 +21,35 @@ typedef struct
Color color; Color color;
double scaling; double scaling;
double coverage; double coverage;
} CloudsLayerDefinition;
typedef struct
{
int nblayers;
CloudsLayerDefinition layers[CLOUDS_MAX_LAYERS];
} CloudsDefinition; } CloudsDefinition;
typedef struct
{
double precision;
} CloudsQuality;
typedef struct
{
int unused;
} CloudsEnvironment;
void cloudsInit(); void cloudsInit();
void cloudsSave(FILE* f); void cloudsSave(FILE* f, CloudsDefinition* definition);
void cloudsLoad(FILE* f); void cloudsLoad(FILE* f, CloudsDefinition* definition);
int cloudsGetLayerCount();
int cloudsAddLayer();
void cloudsDeleteLayer(int layer);
CloudsDefinition cloudsCreateDefinition(); CloudsDefinition cloudsCreateDefinition();
void cloudsDeleteDefinition(CloudsDefinition definition); void cloudsDeleteDefinition(CloudsDefinition* definition);
void cloudsCopyDefinition(CloudsDefinition source, CloudsDefinition* destination); void cloudsCopyDefinition(CloudsDefinition* source, CloudsDefinition* destination);
void cloudsSetDefinition(int layer, CloudsDefinition definition); void cloudsValidateDefinition(CloudsDefinition* definition);
CloudsDefinition cloudsGetDefinition(int layer);
void cloudsSetQuality(CloudsQuality quality); CloudsLayerDefinition cloudsLayerCreateDefinition();
CloudsQuality cloudsGetQuality(); 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); int cloudsGetLayerCount(CloudsDefinition* definition);
Color cloudsGetColor(Vector3 start, Vector3 end); 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 #ifdef __cplusplus
} }

View file

@ -27,7 +27,8 @@ void fogSetDistance(double near, double far)
Color fogApplyToLocation(Vector3 location, Color base) 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 distance = v3Norm(v3Sub(camera_location, location));
double value; double value;
@ -44,6 +45,6 @@ Color fogApplyToLocation(Vector3 location, Color base)
mask.a *= value; mask.a *= value;
colorMask(&base, &mask); colorMask(&base, &mask);
return base; return base;*/
} }

View file

@ -12,32 +12,13 @@
#include "sky.h" #include "sky.h"
#include "water.h" #include "water.h"
#include "terrain.h" #include "terrain.h"
#include "renderer.h"
static LightingDefinition _definition; #include "scenery.h"
static LightingQuality _quality;
static LightingEnvironment _environment;
static LightDefinition _LIGHT_NULL; 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() void lightingInit()
{ {
_definition = lightingCreateDefinition();
_environment.filter = _standardFilter;
_environment.custom_data = NULL;
_LIGHT_NULL.color = COLOR_BLACK; _LIGHT_NULL.color = COLOR_BLACK;
_LIGHT_NULL.direction.x = 0.0; _LIGHT_NULL.direction.x = 0.0;
_LIGHT_NULL.direction.y = 1.0; _LIGHT_NULL.direction.y = 1.0;
@ -65,38 +46,25 @@ LightingDefinition lightingCreateDefinition()
return definition; return definition;
} }
void lightingDeleteDefinition(LightingDefinition definition) void lightingDeleteDefinition(LightingDefinition* definition)
{ {
} }
void lightingCopyDefinition(LightingDefinition source, LightingDefinition* destination) void lightingCopyDefinition(LightingDefinition* source, LightingDefinition* destination)
{ {
*destination = source; *destination = *source;
}
void lightingSetDefinition(LightingDefinition definition)
{
lightingValidateDefinition(&definition);
lightingCopyDefinition(definition, &_definition);
}
LightingDefinition lightingGetDefinition()
{
return _definition;
} }
void lightingValidateDefinition(LightingDefinition* definition) void lightingValidateDefinition(LightingDefinition* definition)
{ {
if (!definition)
{
lightingValidateDefinition(&_definition);
return;
}
if (definition->autosetfromsky) if (definition->autosetfromsky)
{ {
// TODO Get lights from sky SkyDefinition sky;
definition->_nbautolights = skyGetLights(definition->_autolights, MAX_LIGHTS);
sky = skyCreateDefinition();
sceneryGetSky(&sky);
definition->_nbautolights = skyGetLights(&sky, definition->_autolights, LIGHTING_MAX_LIGHTS);
skyDeleteDefinition(&sky);
} }
else else
{ {
@ -123,7 +91,7 @@ LightDefinition lightingGetLight(LightingDefinition* definition, int light)
int lightingAddLight(LightingDefinition* definition, LightDefinition light) int lightingAddLight(LightingDefinition* definition, LightDefinition light)
{ {
if (definition->nblights < MAX_LIGHTS) if (definition->nblights < LIGHTING_MAX_LIGHTS)
{ {
definition->lights[definition->nblights] = light; definition->lights[definition->nblights] = light;
return definition->nblights++; return definition->nblights++;
@ -146,17 +114,7 @@ void lightingDeleteLight(LightingDefinition* definition, int light)
} }
} }
void lightingSetQuality(LightingQuality quality) static Color _applyLightCustom(LightDefinition* definition, Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material)
{
_quality = quality;
}
LightingQuality lightingGetQuality()
{
return _quality;
}
static Color _applyLightCustom(Vector3 location, Vector3 normal, ReceiverMaterial material, LightDefinition* definition, LightingQuality* quality, LightingEnvironment* environment)
{ {
Color result, light; Color result, light;
double diffuse, specular; double diffuse, specular;
@ -165,14 +123,15 @@ static Color _applyLightCustom(Vector3 location, Vector3 normal, ReceiverMateria
light = definition->color; light = definition->color;
direction_inv = v3Scale(definition->direction, -1.0); 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); 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); reflect = v3Sub(v3Scale(normal, 2.0 * v3Dot(direction_inv, normal)), direction_inv);
diffuse = v3Dot(direction_inv, normal); diffuse = v3Dot(direction_inv, normal);
//diffuse = pow(diffuse * 0.5 + 0.5, 2.0); //diffuse = pow(diffuse * 0.5 + 0.5, 2.0);
diffuse = diffuse * 0.5 + 0.5;
if (diffuse > 0.0) if (diffuse > 0.0)
{ {
if (material.shininess > 0.0) if (material.shininess > 0.0)
@ -198,38 +157,20 @@ static Color _applyLightCustom(Vector3 location, Vector3 normal, ReceiverMateria
return result; 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; Color result;
int i; int i;
if (!definition)
{
definition = &_definition;
}
if (!quality)
{
quality = &_quality;
}
if (!environment)
{
environment = &_environment;
}
/* TODO Merge lights */ /* TODO Merge lights */
result = material.base; result = material.base;
for (i = 0; i < definition->nblights; i++) 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++) 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; return result;
} }
Color lightingApply(Vector3 location, Vector3 normal, ReceiverMaterial material)
{
return lightingApplyCustom(location, normal, material, &_definition, &_quality, &_environment);
}

View file

@ -2,13 +2,14 @@
#define _PAYSAGES_LIGHTING_H_ #define _PAYSAGES_LIGHTING_H_
#include "shared/types.h" #include "shared/types.h"
#include "renderer.h"
#include <stdio.h> #include <stdio.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define MAX_LIGHTS 10 #define LIGHTING_MAX_LIGHTS 10
typedef struct typedef struct
{ {
@ -21,40 +22,25 @@ typedef struct
{ {
int autosetfromsky; int autosetfromsky;
int nblights; int nblights;
LightDefinition lights[MAX_LIGHTS]; LightDefinition lights[LIGHTING_MAX_LIGHTS];
int _nbautolights; int _nbautolights;
LightDefinition _autolights[MAX_LIGHTS]; LightDefinition _autolights[LIGHTING_MAX_LIGHTS];
} LightingDefinition; } 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 typedef struct
{ {
Color base; Color base;
double reflection; double reflection;
double shininess; double shininess;
} ReceiverMaterial; } SurfaceMaterial;
void lightingInit(); void lightingInit();
void lightingSave(FILE* f); void lightingSave(FILE* f);
void lightingLoad(FILE* f); void lightingLoad(FILE* f);
LightingDefinition lightingCreateDefinition(); LightingDefinition lightingCreateDefinition();
void lightingDeleteDefinition(LightingDefinition definition); void lightingDeleteDefinition(LightingDefinition* definition);
void lightingCopyDefinition(LightingDefinition source, LightingDefinition* destination); void lightingCopyDefinition(LightingDefinition* source, LightingDefinition* destination);
void lightingSetDefinition(LightingDefinition definition);
LightingDefinition lightingGetDefinition();
void lightingValidateDefinition(LightingDefinition* definition); void lightingValidateDefinition(LightingDefinition* definition);
int lightingGetLightCount(LightingDefinition* definition); int lightingGetLightCount(LightingDefinition* definition);
@ -62,11 +48,7 @@ LightDefinition lightingGetLight(LightingDefinition* definition, int light);
int lightingAddLight(LightingDefinition* definition, LightDefinition light); int lightingAddLight(LightingDefinition* definition, LightDefinition light);
void lightingDeleteLight(LightingDefinition* definition, int light); void lightingDeleteLight(LightingDefinition* definition, int light);
void lightingSetQuality(LightingQuality quality); Color lightingApplyToSurface(LightingDefinition* definition, Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material);
LightingQuality lightingGetQuality();
Color lightingApplyCustom(Vector3 location, Vector3 normal, ReceiverMaterial material, LightingDefinition* definition, LightingQuality* quality, LightingEnvironment* environment);
Color lightingApply(Vector3 location, Vector3 normal, ReceiverMaterial material);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -23,17 +23,12 @@ void paysagesInit()
ilInit(); ilInit();
iluInit(); iluInit();
autoInit();
renderInit();
cameraSetLocation(-12.0, 5.0, 2.0); cameraSetLocation(-12.0, 5.0, 2.0);
cameraSetTarget(0.0, 5.0, 0.0); cameraSetTarget(0.0, 5.0, 0.0);
autoInit();
skyInit();
terrainInit();
texturesInit();
waterInit();
lightingInit();
renderInit();
autoSetRenderQuality(5); autoSetRenderQuality(5);
autoGenRealisticLandscape(0); autoGenRealisticLandscape(0);
autoSetDaytime(8, 30); autoSetDaytime(8, 30);
@ -54,36 +49,10 @@ void paysagesInit()
void paysagesSave(char* filepath) void paysagesSave(char* filepath)
{ {
FILE* f = fopen(filepath, "wb"); scenerySaveToFile(filepath);
cameraSave(f);
cloudsSave(f);
fogSave(f);
renderSave(f);
skySave(f);
terrainSave(f);
texturesSave(f);
waterSave(f);
lightingSave(f);
fclose(f);
} }
void paysagesLoad(char* filepath) void paysagesLoad(char* filepath)
{ {
FILE* f = fopen(filepath, "rb"); sceneryLoadFromFile(filepath);
cameraLoad(f);
cloudsLoad(f);
fogLoad(f);
renderLoad(f);
skyLoad(f);
terrainLoad(f);
texturesLoad(f);
waterLoad(f);
lightingLoad(f);
fclose(f);
} }

View file

@ -1,7 +1,6 @@
#ifndef _PAYSAGES_MODIFIERS_H_ #ifndef _PAYSAGES_MODIFIERS_H_
#define _PAYSAGES_MODIFIERS_H_ #define _PAYSAGES_MODIFIERS_H_
#include "shared/types.h"
#include <stdio.h> #include <stdio.h>
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -1,7 +1,3 @@
#include <stdlib.h>
#include <math.h>
#include <string.h>
struct NoiseLevel; struct NoiseLevel;
struct NoiseGenerator struct NoiseGenerator
@ -15,7 +11,12 @@ struct NoiseGenerator
struct NoiseLevel* levels; struct NoiseLevel* levels;
}; };
#include "shared/types.h" #include "noise.h"
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "shared/functions.h" #include "shared/functions.h"
static inline double _cubicInterpolate(double* p, double x) 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]))); 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* noiseCreateGenerator()
{ {
NoiseGenerator* result; NoiseGenerator* result;

54
lib_paysages/noise.h Normal file
View 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

View file

@ -108,16 +108,21 @@ void renderSetSize(int width, int height)
_cb_preview_clear(background_color); _cb_preview_clear(background_color);
} }
void renderSetQuality(int quality) int renderSetQuality(int quality)
{ {
if (quality < 1) if (quality < 1)
{ {
render_quality = 1; render_quality = 1;
} }
else if (quality > 10)
{
render_quality = 10;
}
else else
{ {
render_quality = quality; render_quality = quality;
} }
return render_quality;
} }
void renderClear() void renderClear()

19
lib_paysages/renderer.c Normal file
View 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
View 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
View 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
View 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

View file

@ -25,22 +25,10 @@ void arrayClear(Array* array);
void autoInit(); void autoInit();
void autoSetDaytime(int hour, int minute); void autoSetDaytime(int hour, int minute);
void autoSetDaytimeFraction(double daytime); void autoSetDaytimeFraction(double daytime);
void autoSetRenderQuality(int quality);
void autoGenRealisticLandscape(int seed); void autoGenRealisticLandscape(int seed);
void autoRenderSceneTwoPass(int postonly); void autoRenderSceneTwoPass(int postonly);
void autoRenderSceneRayTracing(); 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 */ /* color.c */
void colorSave(Color col, FILE* f); void colorSave(Color col, FILE* f);
Color colorLoad(FILE* f); Color colorLoad(FILE* f);
@ -97,42 +85,12 @@ void fogSetColor(Color col);
void fogSetDistance(double near, double far); void fogSetDistance(double near, double far);
Color fogApplyToLocation(Vector3 location, Color base); 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 */ /* render.c */
void renderInit(); void renderInit();
void renderSave(FILE* f); void renderSave(FILE* f);
void renderLoad(FILE* f); void renderLoad(FILE* f);
void renderSetSize(int width, int height); void renderSetSize(int width, int height);
void renderSetQuality(int quality); int renderSetQuality(int quality);
void renderClear(); void renderClear();
void renderUpdate(); void renderUpdate();
void renderInterrupt(); void renderInterrupt();
@ -148,14 +106,6 @@ void renderSetPreviewCallbacks(PreviewCallbackResize resize, PreviewCallbackClea
int renderSetNextProgressStep(double start, double end); int renderSetNextProgressStep(double start, double end);
int renderTellProgress(double progress); 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 */ /* tools.c */
double toolsRandom(); double toolsRandom();
double toolsBicubicInterpolate(double stencil[16], double x, double y); double toolsBicubicInterpolate(double stencil[16], double x, double y);

View file

@ -7,8 +7,6 @@
extern "C" { extern "C" {
#endif #endif
extern Vector3 camera_location;
extern int render_width; extern int render_width;
extern int render_height; extern int render_height;
extern int render_quality; extern int render_quality;

View file

@ -87,17 +87,6 @@ typedef struct
void* data; void* data;
} Array; } 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 struct Zone Zone;
typedef void (*PreviewCallbackResize)(int width, int height); typedef void (*PreviewCallbackResize)(int width, int height);

View file

@ -11,40 +11,32 @@
#define SPHERE_SIZE 1000.0 #define SPHERE_SIZE 1000.0
static SkyDefinition _definition;
static SkyQuality _quality;
static SkyEnvironment _environment;
void skyInit() void skyInit()
{ {
skySetDefinition(skyCreateDefinition());
} }
void skySave(FILE* f) void skySave(FILE* f, SkyDefinition* definition)
{ {
toolsSaveDouble(f, _definition.daytime); toolsSaveDouble(f, definition->daytime);
colorGradationSave(f, _definition.sun_color); colorGradationSave(f, definition->sun_color);
toolsSaveDouble(f, _definition.sun_radius); toolsSaveDouble(f, definition->sun_radius);
colorGradationSave(f, _definition.zenith_color); colorGradationSave(f, definition->zenith_color);
colorGradationSave(f, _definition.haze_color); colorGradationSave(f, definition->haze_color);
toolsSaveDouble(f, _definition.haze_height); toolsSaveDouble(f, definition->haze_height);
toolsSaveDouble(f, _definition.haze_smoothing); 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; skyValidateDefinition(definition);
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);
} }
SkyDefinition skyCreateDefinition() SkyDefinition skyCreateDefinition()
@ -64,13 +56,13 @@ SkyDefinition skyCreateDefinition()
return def; 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) void skyValidateDefinition(SkyDefinition* definition)
@ -87,31 +79,20 @@ void skyValidateDefinition(SkyDefinition* definition)
colorGradationAdd(&definition->_sky_gradation, 1.0, &zenith); colorGradationAdd(&definition->_sky_gradation, 1.0, &zenith);
} }
void skySetDefinition(SkyDefinition definition) int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights)
{
skyValidateDefinition(&definition);
_definition = definition;
}
SkyDefinition skyGetDefinition()
{
return _definition;
}
int skyGetLights(LightDefinition* lights, int max_lights)
{ {
double sun_angle; double sun_angle;
Vector3 sun_direction; Vector3 sun_direction;
int nblights = 0; 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.x = cos(sun_angle);
sun_direction.y = sin(sun_angle); sun_direction.y = sin(sun_angle);
sun_direction.z = 0.0; sun_direction.z = 0.0;
if (max_lights > 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].direction = v3Scale(sun_direction, -1.0);
lights[0].maxshadow = 1.0; lights[0].maxshadow = 1.0;
nblights = 1; nblights = 1;
@ -120,25 +101,12 @@ int skyGetLights(LightDefinition* lights, int max_lights)
return nblights; 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; double sun_angle, dist;
Vector3 sun_position; Vector3 sun_position;
Color sun_color, sky_color; 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_angle = (definition->daytime + 0.75) * M_PI * 2.0;
sun_position.x = cos(sun_angle); sun_position.x = cos(sun_angle);
sun_position.y = sin(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); // TODO
} /*Vector3 location, direction;
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;
Color color_sky, color_clouds; Color color_sky, color_clouds;
location = fragment->vertex.location; 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))); color_clouds = cloudsGetColor(camera_location, v3Add(camera_location, v3Scale(direction, 10.0)));
colorMask(&color_sky, &color_clouds); colorMask(&color_sky, &color_clouds);
fragment->vertex.color = color_sky; fragment->vertex.color = color_sky;*/
return 1; return 1;
} }
void skyRender(RenderProgressCallback callback) void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCallback callback)
{ {
int res_i, res_j; int res_i, res_j;
int i, j; int i, j;
@ -215,8 +165,8 @@ void skyRender(RenderProgressCallback callback)
Color col; Color col;
Vector3 direction; Vector3 direction;
res_i = render_quality * 40; res_i = renderer->render_quality * 40;
res_j = render_quality * 20; res_j = renderer->render_quality * 20;
step_i = M_PI * 2.0 / (double)res_i; step_i = M_PI * 2.0 / (double)res_i;
step_j = M_PI / (double)res_j; 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.x = SPHERE_SIZE * cos(current_i) * cos(current_j);
direction.y = SPHERE_SIZE * sin(current_j); direction.y = SPHERE_SIZE * sin(current_j);
direction.z = SPHERE_SIZE * sin(current_i) * cos(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); col.b = sin(direction.x) * sin(direction.x) * cos(direction.z) * cos(direction.z);
vertex1.color = col; vertex1.color = col;
vertex1.callback = _postProcessFragment; vertex1.callback = _postProcessFragment;
@ -248,7 +198,7 @@ void skyRender(RenderProgressCallback callback)
direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j); direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j);
direction.y = SPHERE_SIZE * sin(current_j); direction.y = SPHERE_SIZE * sin(current_j);
direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(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); col.b = sin(direction.x) * sin(direction.x) * cos(direction.z) * cos(direction.z);
vertex2.color = col; vertex2.color = col;
vertex2.callback = _postProcessFragment; 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.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j + step_j);
direction.y = SPHERE_SIZE * sin(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); 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); col.b = sin(direction.x) * sin(direction.x) * cos(direction.z) * cos(direction.z);
vertex3.color = col; vertex3.color = col;
vertex3.callback = _postProcessFragment; vertex3.callback = _postProcessFragment;
@ -264,7 +214,7 @@ void skyRender(RenderProgressCallback callback)
direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j + step_j); direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j + step_j);
direction.y = SPHERE_SIZE * sin(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); 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); col.b = sin(direction.x) * sin(direction.x) * cos(direction.z) * cos(direction.z);
vertex4.color = col; vertex4.color = col;
vertex4.callback = _postProcessFragment; vertex4.callback = _postProcessFragment;

View file

@ -21,37 +21,21 @@ typedef struct
ColorGradation _sky_gradation; ColorGradation _sky_gradation;
} SkyDefinition; } SkyDefinition;
typedef struct
{
int unused;
} SkyQuality;
typedef struct
{
int unused;
} SkyEnvironment;
void skyInit(); void skyInit();
void skySave(FILE* f); void skySave(FILE* f, SkyDefinition* definition);
void skyLoad(FILE* f); void skyLoad(FILE* f, SkyDefinition* definition);
SkyDefinition skyCreateDefinition(); SkyDefinition skyCreateDefinition();
void skyDeleteDefinition(SkyDefinition definition); void skyDeleteDefinition(SkyDefinition* definition);
void skyCopyDefinition(SkyDefinition source, SkyDefinition* destination); void skyCopyDefinition(SkyDefinition* source, SkyDefinition* destination);
void skyValidateDefinition(SkyDefinition* definition); void skyValidateDefinition(SkyDefinition* definition);
void skySetDefinition(SkyDefinition definition);
SkyDefinition skyGetDefinition();
void skySetQuality(SkyQuality quality); int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights);
SkyQuality skyGetQuality();
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); void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCallback callback);
Color skyGetColor(Vector3 eye, Vector3 look);
Color skyProjectRay(Vector3 start, Vector3 direction);
void skyRender(RenderProgressCallback callback);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,6 +1,9 @@
#include "terrain.h"
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include "shared/types.h" #include "shared/types.h"
#include "shared/functions.h" #include "shared/functions.h"
@ -9,52 +12,49 @@
#include "textures.h" #include "textures.h"
#include "water.h" #include "water.h"
#include "terrain.h"
static TerrainDefinition _definition;
static TerrainQuality _quality;
static TerrainEnvironment _environment;
static double _max_height = 1.0;
void terrainInit() 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; int i;
noiseSave(_definition.height_noise, f); noiseSave(definition->height_noise, f);
toolsSaveInt(f, _definition.height_modifiers_count); toolsSaveDouble(f, definition->height_factor);
for (i = 0; i < _definition.height_modifiers_count; i++) 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); noiseLoad(definition->height_noise, f);
_max_height = noiseGetMaxValue(_definition.height_noise); 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); n = toolsLoadInt(f);
for (i = 0; i < _definition.height_modifiers_count; i++) for (i = 0; i < n; i++)
{ {
_definition.height_modifiers[i] = modifierCreate(); modifier = modifierCreate();
modifierLoad(_definition.height_modifiers[i], f); modifierLoad(modifier, f);
terrainAddModifier(&definition, modifier);
modifierDelete(modifier);
} }
terrainValidateDefinition(definition);
} }
TerrainDefinition terrainCreateDefinition() TerrainDefinition terrainCreateDefinition()
@ -62,54 +62,57 @@ TerrainDefinition terrainCreateDefinition()
TerrainDefinition definition; TerrainDefinition definition;
definition.height_noise = noiseCreateGenerator(); definition.height_noise = noiseCreateGenerator();
definition.height_factor = 0.0;
definition.scaling = 1.0;
definition.height_modifiers_count = 0; definition.height_modifiers_count = 0;
terrainValidateDefinition(&definition);
return definition; return definition;
} }
void terrainDeleteDefinition(TerrainDefinition definition) void terrainDeleteDefinition(TerrainDefinition* definition)
{ {
int i; int i;
noiseDeleteGenerator(definition.height_noise); noiseDeleteGenerator(definition->height_noise);
for (i = 0; i < definition.height_modifiers_count; i++) 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; int i;
noiseCopy(source.height_noise, destination->height_noise); 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++) for (i = 0; i < destination->height_modifiers_count; i++)
{ {
modifierDelete(destination->height_modifiers[i]); modifierDelete(destination->height_modifiers[i]);
} }
destination->height_modifiers_count = source.height_modifiers_count; destination->height_modifiers_count = 0;
for (i = 0; i < destination->height_modifiers_count; i++)
for (i = 0; i < source->height_modifiers_count; i++)
{ {
destination->height_modifiers[i] = modifierCreateCopy(source.height_modifiers[i]); terrainAddModifier(destination, source->height_modifiers[i]);
}
} }
void terrainSetDefinition(TerrainDefinition definition) terrainValidateDefinition(destination);
}
void terrainValidateDefinition(TerrainDefinition* definition)
{ {
terrainCopyDefinition(definition, &_definition); definition->_max_height = noiseGetMaxValue(definition->height_noise) * definition->height_factor;
_max_height = noiseGetMaxValue(_definition.height_noise);
/* FIXME _max_height depends on modifiers */ /* FIXME _max_height depends on modifiers */
} }
TerrainDefinition terrainGetDefinition()
{
return _definition;
}
int terrainAddModifier(TerrainDefinition* definition, HeightModifier* modifier) 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); definition->height_modifiers[definition->height_modifiers_count] = modifierCreateCopy(modifier);
return definition->height_modifiers_count++; return definition->height_modifiers_count++;
@ -124,18 +127,13 @@ void terrainDelModifier(TerrainDefinition* definition, int modifier_position)
{ {
if (modifier_position >= 0 && modifier_position < definition->height_modifiers_count) 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)
}
void terrainSetQuality(TerrainQuality quality)
{ {
_quality = quality; 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--;
} }
TerrainQuality terrainGetQuality()
{
return _quality;
} }
static inline double _getHeight(TerrainDefinition* definition, double x, double z, double detail) static inline double _getHeight(TerrainDefinition* definition, double x, double z, double detail)
@ -144,7 +142,7 @@ static inline double _getHeight(TerrainDefinition* definition, double x, double
int i; int i;
location.x = x; 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; location.z = z;
for (i = 0; i < definition->height_modifiers_count; i++) for (i = 0; i < definition->height_modifiers_count; i++)
@ -166,16 +164,16 @@ static inline Vector3 _getPoint(TerrainDefinition* definition, double x, double
return result; 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; Vector3 inc_vector;
double inc_value, inc_base, inc_factor, height, diff, light_factor, smoothing, length; double inc_value, inc_base, inc_factor, height, diff, light_factor, smoothing, length;
direction_to_light = v3Normalize(direction_to_light); 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_base = 1.0;
inc_value = inc_base / inc_factor; inc_value = inc_base / inc_factor;
smoothing = 0.03 * inc_factor;; smoothing = 0.03 * inc_factor;
light_factor = 1.0; light_factor = 1.0;
length = 0.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); inc_vector = v3Scale(direction_to_light, inc_value);
length += v3Norm(inc_vector); length += v3Norm(inc_vector);
location = v3Add(location, 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; diff = location.y - height;
if (diff < 0.0) if (diff < 0.0)
{ {
@ -203,7 +201,7 @@ Color terrainLightFilter(Color light, Vector3 location, Vector3 light_location,
{ {
inc_value = diff; 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) 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; Color color;
TextureEnvironment texenv; TextureEnvironment texenv;
texenv.lighting_definition = environment->lighting_definition; color = COLOR_RED;
texenv.lighting_environment = environment->lighting_environment; //color = texturesGetColorCustom(point, precision, NULL, &texenv);
/*if (environment->toggle_fog)
color = texturesGetColorCustom(point, precision, NULL, &texenv);
if (environment->toggle_fog)
{ {
color = fogApplyToLocation(point, color); color = fogApplyToLocation(point, color);
} }*/
//color = cloudsApplySegmentResult(color, camera_location, point); //color = cloudsApplySegmentResult(color, camera_location, point);
return color; 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; Vector3 inc_vector;
double inc_value, inc_base, inc_factor, height, diff, length; double inc_value, inc_base, inc_factor, height, diff, length;
direction = v3Normalize(direction); direction = v3Normalize(direction);
inc_factor = (double)render_quality; inc_factor = (double)renderer->render_quality;
inc_base = 1.0; inc_base = 1.0;
inc_value = inc_base / inc_factor; 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); inc_vector = v3Scale(direction, inc_value);
length += v3Norm(inc_vector); length += v3Norm(inc_vector);
start = v3Add(start, 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; diff = start.y - height;
if (diff < 0.0) if (diff < 0.0)
{ {
start.y = height; start.y = height;
*hit_point = start; *hit_point = start;
*hit_color = _getColor(&_definition, &_environment, start, inc_value); *hit_color = _getColor(definition, renderer, start, inc_value);
return 1; return 1;
} }
@ -275,14 +271,14 @@ int terrainProjectRay(Vector3 start, Vector3 direction, Vector3* hit_point, Colo
{ {
inc_value = diff; inc_value = diff;
} }
} while (length < 50.0 && start.y <= _max_height); } while (length < 50.0 && start.y <= definition._max_height);
return 0; return 0;
} }
static int _postProcessFragment(RenderFragment* fragment) static int _postProcessFragment(RenderFragment* fragment)
{ {
Vector3 point; /*Vector3 point;
double precision; double precision;
point = fragment->vertex.location; point = fragment->vertex.location;
@ -290,17 +286,17 @@ static int _postProcessFragment(RenderFragment* fragment)
point = _getPoint(&_definition, point.x, point.z, precision); 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; return 1;
} }
static Vertex _getFirstPassVertex(double x, double z, double detail) static Vertex _getFirstPassVertex(TerrainDefinition* definition, double x, double z, double detail)
{ {
Vertex result; Vertex result;
double value; 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); value = sin(x) * sin(x) * cos(z) * cos(z);
result.color.r = value; result.color.r = value;
result.color.g = value; result.color.g = value;
@ -312,63 +308,50 @@ static Vertex _getFirstPassVertex(double x, double z, double detail)
return result; 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; Vertex v1, v2, v3, v4;
v1 = _getFirstPassVertex(x, z, size); v1 = _getFirstPassVertex(definition, x, z, size);
v2 = _getFirstPassVertex(x, z + size, size); v2 = _getFirstPassVertex(definition, x, z + size, size);
v3 = _getFirstPassVertex(x + size, z + size, size); v3 = _getFirstPassVertex(definition, x + size, z + size, size);
v4 = _getFirstPassVertex(x + size, z, size); v4 = _getFirstPassVertex(definition, x + size, z, size);
renderPushQuad(&v1, &v2, &v3, &v4); 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); 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) void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProgressCallback callback)
{
return terrainGetColorCustom(x, z, detail, &_definition, &_quality, &_environment);
}
void terrainRender(RenderProgressCallback callback)
{ {
int chunk_factor, chunk_count, i; int chunk_factor, chunk_count, i;
double cx = camera_location.x; double cx = renderer->camera_location.x;
double cz = camera_location.z; double cz = renderer->camera_location.z;
double min_chunk_size, visible_chunk_size;
double radius_int, radius_ext, 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_factor = 1;
chunk_count = 2; chunk_count = 2;
radius_int = 0.0; radius_int = 0.0;
radius_ext = _quality.min_chunk_size; radius_ext = min_chunk_size;
chunk_size = _quality.min_chunk_size; chunk_size = min_chunk_size;
while (radius_ext < 1000.0) while (radius_ext < 1000.0)
{ {
@ -379,20 +362,20 @@ void terrainRender(RenderProgressCallback callback)
for (i = 0; i < chunk_count - 1; i++) for (i = 0; i < chunk_count - 1; i++)
{ {
_renderQuad(cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size); _renderQuad(definition, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size);
_renderQuad(cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size); _renderQuad(definition, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size);
_renderQuad(cx + radius_int - chunk_size * i, cz + radius_int, chunk_size); _renderQuad(definition, 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, 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_count /= 2;
chunk_factor *= 2; chunk_factor *= 2;
/* TODO Fill in gaps with triangles */ /* TODO Fill in gaps with triangles */
} }
chunk_count += 2; chunk_count += 2;
chunk_size = _quality.min_chunk_size * chunk_factor; chunk_size = min_chunk_size * chunk_factor;
radius_int = radius_ext; radius_int = radius_ext;
radius_ext += chunk_size; radius_ext += chunk_size;
} }

View file

@ -3,6 +3,7 @@
#include "shared/types.h" #include "shared/types.h"
#include "modifiers.h" #include "modifiers.h"
#include "noise.h"
#include "lighting.h" #include "lighting.h"
#include <stdio.h> #include <stdio.h>
@ -10,53 +11,37 @@
extern "C" { extern "C" {
#endif #endif
#define MAX_HEIGHT_MODIFIER_COUNT 50 #define TERRAIN_MAX_MODIFIERS 50
typedef struct typedef struct
{ {
NoiseGenerator* height_noise; NoiseGenerator* height_noise;
double height_factor;
double scaling;
int height_modifiers_count; int height_modifiers_count;
HeightModifier* height_modifiers[MAX_HEIGHT_MODIFIER_COUNT]; HeightModifier* height_modifiers[TERRAIN_MAX_MODIFIERS];
double _max_height;
} TerrainDefinition; } 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 terrainInit();
void terrainSave(FILE* f); void terrainSave(FILE* f, TerrainDefinition* definition);
void terrainLoad(FILE* f); void terrainLoad(FILE* f, TerrainDefinition* definition);
TerrainDefinition terrainCreateDefinition(); TerrainDefinition terrainCreateDefinition();
void terrainDeleteDefinition(TerrainDefinition definition); void terrainDeleteDefinition(TerrainDefinition* definition);
void terrainCopyDefinition(TerrainDefinition source, TerrainDefinition* destination); void terrainCopyDefinition(TerrainDefinition* source, TerrainDefinition* destination);
void terrainSetDefinition(TerrainDefinition definition); void terrainValidateDefinition(TerrainDefinition* definition);
TerrainDefinition terrainGetDefinition();
int terrainAddModifier(TerrainDefinition* definition, HeightModifier* modifier); int terrainAddModifier(TerrainDefinition* definition, HeightModifier* modifier);
void terrainDelModifier(TerrainDefinition* definition, int modifier_position); void terrainDelModifier(TerrainDefinition* definition, int modifier_position);
void terrainSetQuality(TerrainQuality quality); Color terrainLightFilter(TerrainDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
TerrainQuality terrainGetQuality(); int terrainProjectRay(TerrainDefinition* definition, Renderer* renderer, Vector3 start, Vector3 direction, Vector3* hit_point, Color* hit_color);
double terrainGetHeight(TerrainDefinition* definition, double x, double z);
Color terrainLightFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data); double terrainGetHeightNormalized(TerrainDefinition* definition, double x, double z);
int terrainProjectRay(Vector3 start, Vector3 direction, Vector3* hit_point, Color* hit_color); Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double x, double z, double detail);
double terrainGetHeightCustom(double x, double z, TerrainDefinition* definition); void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProgressCallback callback);
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);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -12,90 +12,94 @@
#include "terrain.h" #include "terrain.h"
#include "lighting.h" #include "lighting.h"
#define TEXTURES_MAX 50 static TextureLayerDefinition _NULL_LAYER;
static TextureQuality _quality;
static TextureEnvironment _environment;
static int _textures_count = 0;
static TextureDefinition _textures[TEXTURES_MAX];
void texturesInit() void texturesInit()
{ {
_textures_count = 0; _NULL_LAYER = texturesLayerCreateDefinition();
_environment.lighting_definition = NULL;
_environment.lighting_environment = NULL;
} }
void texturesSave(FILE* f) void texturesSave(FILE* f, TexturesDefinition* definition)
{ {
int i; int i;
toolsSaveInt(f, _textures_count); toolsSaveInt(f, definition->nbtextures);
for (i = 0; i < _textures_count; i++) for (i = 0; i < definition->nbtextures; i++)
{ {
zoneSave(_textures[i].zone, f); zoneSave(definition->textures[i].zone, f);
noiseSave(_textures[i].bump_noise, f); noiseSave(definition->textures[i].bump_noise, f);
colorSave(_textures[i].color, f); colorSave(definition->textures[i].color, f);
} }
} }
void texturesLoad(FILE* f) void texturesLoad(FILE* f, TexturesDefinition* definition)
{ {
TextureLayerDefinition* layer;
int i, n; int i, n;
TextureDefinition* texture;
while (_textures_count > 0) while (definition->nbtextures > 0)
{ {
texturesDeleteLayer(0); texturesDeleteLayer(definition, 0);
} }
n = toolsLoadInt(f); n = toolsLoadInt(f);
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
texture = _textures + texturesAddLayer(); layer = definition->nbtextures + texturesAddLayer(definition);
zoneLoad(texture->zone, f); zoneLoad(layer->zone, f);
noiseLoad(texture->bump_noise, f); noiseLoad(layer->bump_noise, f);
texture->color = colorLoad(f); layer->color = colorLoad(f);
}
texturesValidateDefinition(definition);
}
TexturesDefinition texturesCreateDefinition()
{
TexturesDefinition result;
result.nbtextures = 0;
return result;
}
void texturesDeleteDefinition(TexturesDefinition* definition)
{
while (definition->nbtextures > 0)
{
texturesDeleteLayer(definition, 0);
} }
} }
int texturesGetLayerCount() void texturesCopyDefinition(TexturesDefinition* source, TexturesDefinition* destination)
{ {
return _textures_count; TextureLayerDefinition* layer;
} int i;
int texturesAddLayer() while (destination->nbtextures > 0)
{ {
if (_textures_count < TEXTURES_MAX) texturesDeleteLayer(destination, 0);
{
_textures[_textures_count] = texturesCreateDefinition();
return _textures_count++;
} }
else for (i = 0; i < source->nbtextures; i++)
{ {
return -1; layer = texturesGetLayer(destination, texturesAddLayer(destination));
texturesLayerCopyDefinition(source->textures + i, layer);
} }
} }
void texturesDeleteLayer(int layer) void texturesValidateDefinition(TexturesDefinition* definition)
{ {
if (layer >= 0 && layer < _textures_count) int i;
for (i = 0; i < definition->nbtextures; i++)
{ {
zoneDelete(_textures[layer].zone); texturesLayerValidateDefinition(definition->textures + i);
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--;
} }
} }
TextureDefinition texturesCreateDefinition() TextureLayerDefinition texturesLayerCreateDefinition()
{ {
TextureDefinition result; TextureLayerDefinition result;
result.zone = zoneCreate(); result.zone = zoneCreate();
result.bump_noise = noiseCreateGenerator(); result.bump_noise = noiseCreateGenerator();
@ -104,49 +108,68 @@ TextureDefinition texturesCreateDefinition()
return result; return result;
} }
void texturesDeleteDefinition(TextureDefinition definition) void texturesLayerDeleteDefinition(TextureLayerDefinition* definition)
{ {
zoneDelete(definition.zone); zoneDelete(definition.zone);
noiseDeleteGenerator(definition.bump_noise); noiseDeleteGenerator(definition.bump_noise);
} }
void texturesCopyDefinition(TextureDefinition source, TextureDefinition* destination) void texturesLayerCopyDefinition(TextureLayerDefinition* source, TextureLayerDefinition* destination)
{ {
destination->color = source.color; destination->color = source.color;
noiseCopy(source.bump_noise, destination->bump_noise); noiseCopy(source.bump_noise, destination->bump_noise);
zoneCopy(source.zone, destination->zone); 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)
{ {
destination = _textures + layer; return definition->nbtextures;
texturesCopyDefinition(definition, destination); }
TextureLayerDefinition* texturesGetLayer(TexturesDefinition* definition, int layer)
{
if (layer >= 0 && layer < definition->nbtextures)
{
return definition->textures + layer;
}
else
{
return &_NULL_LAYER;
} }
} }
TextureDefinition texturesGetDefinition(int layer) int texturesAddLayer(TexturesDefinition* definition)
{ {
assert(layer >= 0); if (definition->nbtextures < TEXTURES_MAX_LAYERS)
assert(layer < _textures_count); {
_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() static inline Vector3 _getNormal(TextureLayerDefinition* definition, Vector3 point, double scale)
{
return _quality;
}
static inline Vector3 _getNormal(TextureDefinition* definition, Vector3 point, double scale)
{ {
Vector3 dpoint, ref, normal; Vector3 dpoint, ref, normal;
@ -183,12 +206,12 @@ static inline Vector3 _getNormal(TextureDefinition* definition, Vector3 point, d
return v3Normalize(normal); 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; Color result;
Vector3 normal; Vector3 normal;
double coverage; double coverage;
ReceiverMaterial material; SurfaceMaterial material;
result = COLOR_TRANSPARENT; result = COLOR_TRANSPARENT;
normal = _getNormal(definition, location, detail * 0.3); normal = _getNormal(definition, location, detail * 0.3);
@ -200,31 +223,22 @@ Color texturesGetLayerColorCustom(Vector3 location, double detail, TextureDefini
material.reflection = 0.1; material.reflection = 0.1;
material.shininess = 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; result.a = coverage;
} }
return result; 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; Color result, tex_color;
int i; int i;
/*if (!quality)
{
quality = &_quality;
}
if (!environment)
{
environment = &_environment;
}*/
result = COLOR_GREEN; result = COLOR_GREEN;
for (i = 0; i < _textures_count; i++) for (i = 0; i < definition->nbtextures; i++)
{ {
/* TODO Do not compute layers fully covered */ /* 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) if (tex_color.a > 0.0001)
{ {
colorMask(&result, &tex_color); colorMask(&result, &tex_color);
@ -233,8 +247,3 @@ Color texturesGetColorCustom(Vector3 location, double detail, TextureQuality* qu
return result; return result;
} }
Color texturesGetColor(Vector3 location)
{
return texturesGetColorCustom(location, renderGetPrecision(location), &_quality, &_environment);
}

View file

@ -2,6 +2,7 @@
#define _PAYSAGES_TEXTURES_H_ #define _PAYSAGES_TEXTURES_H_
#include "shared/types.h" #include "shared/types.h"
#include "noise.h"
#include "lighting.h" #include "lighting.h"
#include <stdio.h> #include <stdio.h>
@ -9,44 +10,42 @@
extern "C" { extern "C" {
#endif #endif
#define TEXTURES_MAX_LAYERS 50
typedef struct typedef struct
{ {
Zone* zone; Zone* zone;
NoiseGenerator* bump_noise; NoiseGenerator* bump_noise;
Color color; Color color;
} TextureDefinition; } TextureLayerDefinition;
typedef struct typedef struct
{ {
int unused; int nbtextures;
} TextureQuality; TextureLayerDefinition textures[TEXTURES_MAX_LAYERS];
} TexturesDefinition;
typedef struct
{
LightingDefinition* lighting_definition;
LightingEnvironment* lighting_environment;
} TextureEnvironment;
void texturesInit(); void texturesInit();
void texturesSave(FILE* f); void texturesSave(FILE* f, TexturesDefinition* definition);
void texturesLoad(FILE* f); void texturesLoad(FILE* f, TexturesDefinition* definition);
int texturesGetLayerCount(); TexturesDefinition texturesCreateDefinition();
int texturesAddLayer(); void texturesDeleteDefinition(TexturesDefinition* definition);
void texturesDeleteLayer(int layer); void texturesCopyDefinition(TexturesDefinition* source, TexturesDefinition* destination);
void texturesValidateDefinition(TexturesDefinition* definition);
TextureDefinition texturesCreateDefinition(); TextureLayerDefinition texturesLayerCreateDefinition();
void texturesDeleteDefinition(TextureDefinition definition); void texturesLayerDeleteDefinition(TextureLayerDefinition* definition);
void texturesCopyDefinition(TextureDefinition source, TextureDefinition* destination); void texturesLayerCopyDefinition(TextureLayerDefinition* source, TextureLayerDefinition* destination);
void texturesSetDefinition(int layer, TextureDefinition definition); void texturesLayerValidateDefinition(TextureLayerDefinition* definition);
TextureDefinition texturesGetDefinition(int layer);
void texturesSetQuality(TextureQuality quality); int texturesGetLayerCount(TexturesDefinition* definition);
TextureQuality texturesGetQuality(); 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 texturesGetLayerColor(TextureLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail);
Color texturesGetColorCustom(Vector3 location, double detail, TextureQuality* quality, TextureEnvironment* environment); Color texturesGetColorCustom(TexturesDefinition* definition, Renderer* renderer, Vector3 location, double detail);
Color texturesGetColor(Vector3 location);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,78 +1,45 @@
#include "water.h"
#include "shared/types.h" #include "shared/types.h"
#include "shared/functions.h" #include "shared/functions.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "shared/globals.h" #include "shared/globals.h"
#include "water.h"
#include "terrain.h" #include "terrain.h"
#include "lighting.h" #include "lighting.h"
#include <math.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() 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); toolsSaveDouble(f, definition.height);
colorSave(_definition.main_color, f); colorSave(definition->main_color, f);
colorSave(_definition.depth_color, f); colorSave(definition->depth_color, f);
toolsSaveDouble(f, _definition.transparency_depth); toolsSaveDouble(f, definition->transparency_depth);
toolsSaveDouble(f, _definition.transparency); toolsSaveDouble(f, definition->transparency);
toolsSaveDouble(f, _definition.reflection); toolsSaveDouble(f, definition->reflection);
noiseSave(_definition.waves_noise, f); noiseSave(definition->waves_noise, f);
toolsSaveDouble(f, _definition.waves_noise_height); toolsSaveDouble(f, definition->waves_noise_height);
toolsSaveDouble(f, _definition.waves_noise_scale); toolsSaveDouble(f, definition->waves_noise_scale);
} }
void waterLoad(FILE* f) void waterLoad(FILE* f, WaterDefinition* definition)
{ {
_definition.height = toolsLoadDouble(f); definition->height = toolsLoadDouble(f);
_definition.main_color = colorLoad(f); definition->main_color = colorLoad(f);
_definition.depth_color = colorLoad(f); definition->depth_color = colorLoad(f);
_definition.transparency_depth = toolsLoadDouble(f); definition->transparency_depth = toolsLoadDouble(f);
_definition.transparency = toolsLoadDouble(f); definition->transparency = toolsLoadDouble(f);
_definition.reflection = toolsLoadDouble(f); definition->reflection = toolsLoadDouble(f);
noiseLoad(_definition.waves_noise, f); noiseLoad(definition->waves_noise, f);
_definition.waves_noise_height = toolsLoadDouble(f); definition->waves_noise_height = toolsLoadDouble(f);
_definition.waves_noise_scale = toolsLoadDouble(f); definition->waves_noise_scale = toolsLoadDouble(f);
waterValidateDefinition(definition);
} }
WaterDefinition waterCreateDefinition() WaterDefinition waterCreateDefinition()
@ -92,41 +59,23 @@ WaterDefinition waterCreateDefinition()
return result; 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; NoiseGenerator* noise;
noise = destination->waves_noise; noise = destination->waves_noise;
*destination = source; *destination = source;
destination->waves_noise = noise; 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) 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; WaterResult result;
RayCastingResult refracted; RayCastingResult refracted;
Vector3 normal; Vector3 normal;
Color color; Color color;
ReceiverMaterial material; SurfaceMaterial material;
double detail, depth; double detail, depth;
if (definition == NULL) detail = renderer->getPrecision(renderer, location);
{
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;
}
location.y = _getHeight(definition, location.x, location.z, detail); location.y = _getHeight(definition, location.x, location.z, detail);
result.location = location; result.location = location;
normal = _getNormal(definition, location, detail); normal = _getNormal(definition, location, detail);
look = v3Normalize(look); look = v3Normalize(look);
result.reflected = environment->reflection_function(location, _reflectRay(look, normal)).hit_color; result.reflected = renderer->rayWalking(renderer, location, _reflectRay(look, normal), 0).hit_color;
refracted = environment->refraction_function(location, _refractRay(look, normal)); refracted = renderer->rayWalking(renderer, location, _refractRay(look, normal), 0);
depth = v3Norm(v3Sub(location, refracted.hit_location)); depth = v3Norm(v3Sub(location, refracted.hit_location));
if (depth > definition->transparency_depth) if (depth > definition->transparency_depth)
{ {
@ -240,11 +201,11 @@ WaterResult waterGetColorCustom(Vector3 location, Vector3 look, WaterDefinition*
material.base = color; material.base = color;
material.reflection = 0.8; material.reflection = 0.8;
material.shininess = 0.6; material.shininess = 0.6;
color = lightingApplyCustom(location, normal, material, environment->lighting_definition, NULL, environment->lighting_environment); color = renderer->applyLightingToSurface(renderer, location, normal, material);
if (environment->toggle_fog) /*if (environment->toggle_fog)
{ {
color = fogApplyToLocation(location, color); color = fogApplyToLocation(location, color);
} }*/
result.base = definition->main_color; result.base = definition->main_color;
result.final = color; result.final = color;
@ -252,14 +213,14 @@ WaterResult waterGetColorCustom(Vector3 location, Vector3 look, WaterDefinition*
return result; 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) 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; return 1;
} }
@ -293,46 +254,14 @@ static void _renderQuad(double x, double z, double size)
renderPushQuad(&v1, &v2, &v3, &v4); renderPushQuad(&v1, &v2, &v3, &v4);
} }
Color waterLightFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data) void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgressCallback callback)
{
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)
{ {
int chunk_factor, chunk_count, i; int chunk_factor, chunk_count, i;
double cx = camera_location.x; double cx = renderer->camera_location.x;
double cz = camera_location.z; double cz = renderer->camera_location.z;
double radius_int, radius_ext, base_chunk_size, chunk_size; 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_factor = 1;
chunk_count = 2; chunk_count = 2;

View file

@ -2,7 +2,9 @@
#define _PAYSAGES_WATER_H_ #define _PAYSAGES_WATER_H_
#include "shared/types.h" #include "shared/types.h"
#include "renderer.h"
#include "lighting.h" #include "lighting.h"
#include "noise.h"
#include <stdio.h> #include <stdio.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -22,21 +24,6 @@ typedef struct
double waves_noise_scale; double waves_noise_scale;
} WaterDefinition; } 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 typedef struct
{ {
Vector3 location; Vector3 location;
@ -47,21 +34,18 @@ typedef struct
} WaterResult; } WaterResult;
void waterInit(); void waterInit();
void waterSave(FILE* f); void waterSave(FILE* f, WaterDefinition* definition);
void waterLoad(FILE* f); void waterLoad(FILE* f, WaterDefinition* definition);
WaterDefinition waterCreateDefinition(); WaterDefinition waterCreateDefinition();
void waterDeleteDefinition(WaterDefinition definition); void waterDeleteDefinition(WaterDefinition* definition);
void waterCopyDefinition(WaterDefinition source, WaterDefinition* destination); void waterCopyDefinition(WaterDefinition* source, WaterDefinition* destination);
void waterSetDefinition(WaterDefinition definition); void waterValidateDefinition(WaterDefinition* definition);
WaterDefinition waterGetDefinition();
void waterSetQuality(WaterQuality quality);
WaterQuality waterGetQuality();
Color waterLightFilter(Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light, void* custom_data); Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
WaterResult waterGetColorCustom(Vector3 location, Vector3 look, WaterDefinition* definition, WaterQuality* quality, WaterEnvironment* environment); WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
Color waterGetColor(Vector3 location, Vector3 look); Color waterGetColor(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
void waterRender(RenderProgressCallback callback); void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgressCallback callback);
#ifdef __cplusplus #ifdef __cplusplus
} }