paysages: Big big refactoring for scenery and renderer (WIP - All broken).
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@232 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
0685f21716
commit
48ea553f49
50 changed files with 1190 additions and 4734 deletions
5
Makefile
5
Makefile
|
@ -1,21 +1,16 @@
|
||||||
all:
|
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
12
TODO
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
- Create a 'scenery' module that will, for each component :
|
||||||
|
- Hold definitions
|
||||||
|
- Setup standard Renderer
|
||||||
|
- Regroup load/save/render (from auto)
|
||||||
|
- Merge all Quality and Environment, as one Renderer.
|
||||||
|
- No more _definition, _quality, _environment in components.
|
||||||
|
- All component methods become custom.
|
||||||
|
- Refactor fog in a new 'atmosphere' module.
|
||||||
|
- In GUI, revertConfig should lock the previews while reverting.
|
||||||
|
- All Save and Load methods should have same signature : void ...Save(FILE*, ...*)
|
||||||
|
- All noises should use the same entropy pool (saved separately), and avoid reallocs.
|
||||||
|
- Remove all global variables (render_quality, render_width...), it should all be set in Renderer.
|
|
@ -1,21 +0,0 @@
|
||||||
SOURCES=$(wildcard *.c)
|
|
||||||
OBJECTS=${SOURCES:.c=.o}
|
|
||||||
HEADERS=$(wildcard ../lib_paysages/shared/*.h ../lib_paysages/*.h *.h)
|
|
||||||
RESULT=paysages-gtk
|
|
||||||
CC_FLAGS=-g -pg -Wall $(shell pkg-config --cflags gtk+-3.0) -I..
|
|
||||||
CC_LDFLAGS=$(shell pkg-config --libs gtk+-3.0) -L../lib_paysages/ -lpaysages
|
|
||||||
|
|
||||||
all:${RESULT}
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f ${OBJECTS}
|
|
||||||
rm -f ${RESULT}
|
|
||||||
|
|
||||||
%.o:%.c ${HEADERS}
|
|
||||||
${CC} -c ${CC_FLAGS} $< -o $@
|
|
||||||
|
|
||||||
${RESULT}:${OBJECTS}
|
|
||||||
${CC} $^ ${CC_LDFLAGS} -o $@
|
|
||||||
|
|
||||||
.PHONY:all clean
|
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
#include <gtk/gtk.h>
|
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
||||||
|
|
||||||
#include "lib_paysages/shared/types.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
typedef void (*GuiNoiseChangedCallback)(NoiseGenerator* generator);
|
|
||||||
|
|
||||||
typedef struct SmallPreview SmallPreview;
|
|
||||||
typedef Color (*SmallPreviewCallback)(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling);
|
|
||||||
|
|
||||||
extern GtkBuilder* gui_definition;
|
|
||||||
|
|
||||||
static inline GtkWidget* _get_widget(const char* name, const char* file, int line)
|
|
||||||
{
|
|
||||||
GtkWidget* result;
|
|
||||||
result = (GtkWidget*)gtk_builder_get_object(gui_definition, (name));
|
|
||||||
if (result == NULL)
|
|
||||||
{
|
|
||||||
printf("Widget not found (%s:%d) : %s\n", file, line, name);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#define GET_WIDGET(_name_) (_get_widget(_name_, __FILE__, __LINE__))
|
|
||||||
|
|
||||||
void guiUpdate();
|
|
||||||
|
|
||||||
void guiTerrainInit();
|
|
||||||
|
|
||||||
void guiWaterInit();
|
|
||||||
void guiWaterUpdate();
|
|
||||||
|
|
||||||
void guiSkyInit();
|
|
||||||
void guiSkyUpdate();
|
|
||||||
|
|
||||||
void guiCloudsInit();
|
|
||||||
void guiCloudsUpdate();
|
|
||||||
|
|
||||||
void guiRenderInit();
|
|
||||||
|
|
||||||
void guiNoiseInit();
|
|
||||||
void guiNoiseEdit(NoiseGenerator* generator, GuiNoiseChangedCallback callback);
|
|
||||||
|
|
||||||
void guiPreviewStart();
|
|
||||||
void guiPreviewRedraw(SmallPreview* preview);
|
|
||||||
void guiPreviewRedrawAll();
|
|
||||||
SmallPreview* guiPreviewNew(GtkImage* image);
|
|
||||||
void guiPreviewSetTerrainHeight(SmallPreview* preview);
|
|
||||||
void guiPreviewSetTerrainColor(SmallPreview* preview);
|
|
||||||
void guiPreviewSetNoise1D(SmallPreview* preview, NoiseGenerator* generator);
|
|
||||||
void guiPreviewConfigScrolling(SmallPreview* preview, double xmin, double xmax, double ymin, double ymax);
|
|
||||||
void guiPreviewConfigScaling(SmallPreview* preview, double min, double max, double step);
|
|
||||||
void guiPreviewSetRenderer(SmallPreview* preview, SmallPreviewCallback renderer);
|
|
||||||
void guiPreviewSetViewport(SmallPreview* preview, double xoffset, double yoffset, double scaling);
|
|
|
@ -1,218 +0,0 @@
|
||||||
/* Noise editor dialog */
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "lib_paysages/shared/functions.h"
|
|
||||||
#include "lib_paysages/shared/constants.h"
|
|
||||||
|
|
||||||
static GtkWidget* _dialog;
|
|
||||||
static SmallPreview* _preview;
|
|
||||||
static GtkTreeView* _level_list;
|
|
||||||
static GtkListStore* _level_list_model;
|
|
||||||
static NoiseGenerator* _generator;
|
|
||||||
static GuiNoiseChangedCallback _callback;
|
|
||||||
static int _current_mode;
|
|
||||||
|
|
||||||
static Color _cbPreview1DRenderPixel(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
|
||||||
{
|
|
||||||
if (y > noiseGet1DTotal(_generator, x))
|
|
||||||
{
|
|
||||||
return COLOR_WHITE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return COLOR_BLACK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _cbPreview2DRenderPixel(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
|
||||||
{
|
|
||||||
Color col;
|
|
||||||
double max_value;
|
|
||||||
|
|
||||||
/* TODO Cache this value */
|
|
||||||
max_value = noiseGetMaxValue(_generator);
|
|
||||||
|
|
||||||
col.r = col.g = col.b = (noiseGet2DTotal(_generator, x, y) / max_value) * 0.5 + 0.5;
|
|
||||||
col.a = 1.0;
|
|
||||||
|
|
||||||
return col;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _setPreviewMode(int mode)
|
|
||||||
{
|
|
||||||
GtkButton* button;
|
|
||||||
double max_value;
|
|
||||||
|
|
||||||
max_value = noiseGetMaxValue(_generator);
|
|
||||||
|
|
||||||
button = GTK_BUTTON(GET_WIDGET("noise_editor_preview_mode"));
|
|
||||||
if (mode == 1)
|
|
||||||
{
|
|
||||||
_current_mode = 1;
|
|
||||||
guiPreviewSetRenderer(_preview, _cbPreview1DRenderPixel);
|
|
||||||
gtk_button_set_label(button, "1D");
|
|
||||||
|
|
||||||
guiPreviewConfigScrolling(_preview, -max_value * 100.0, max_value * 100.0, -max_value, max_value);
|
|
||||||
}
|
|
||||||
else if (mode == 2)
|
|
||||||
{
|
|
||||||
_current_mode = 2;
|
|
||||||
guiPreviewSetRenderer(_preview, _cbPreview2DRenderPixel);
|
|
||||||
gtk_button_set_label(button, "2D");
|
|
||||||
|
|
||||||
guiPreviewConfigScrolling(_preview, -max_value * 100.0, max_value * 100.0, -max_value * 100.0, max_value * 100.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
guiPreviewConfigScaling(_preview, max_value * 0.001, max_value * 0.1, max_value * 0.001);
|
|
||||||
guiPreviewSetViewport(_preview, 0.0, 0.0, max_value * 0.01);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _redrawPreview()
|
|
||||||
{
|
|
||||||
guiPreviewRedraw(_preview);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _resetPreview()
|
|
||||||
{
|
|
||||||
_setPreviewMode(_current_mode);
|
|
||||||
|
|
||||||
_redrawPreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _applyLayerParams()
|
|
||||||
{
|
|
||||||
GtkTreePath* path;
|
|
||||||
GtkTreeViewColumn* column;
|
|
||||||
GtkTreeIter row;
|
|
||||||
int* indices;
|
|
||||||
double height, scale;
|
|
||||||
|
|
||||||
gtk_tree_view_get_cursor(_level_list, &path, &column);
|
|
||||||
indices = gtk_tree_path_get_indices(path);
|
|
||||||
if (indices)
|
|
||||||
{
|
|
||||||
height = (double)gtk_spin_button_get_value(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_height")));
|
|
||||||
scale = (double)gtk_spin_button_get_value(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_scale")));
|
|
||||||
|
|
||||||
noiseSetLevelSimple(_generator, indices[0], scale, height);
|
|
||||||
|
|
||||||
gtk_tree_model_get_iter(GTK_TREE_MODEL(_level_list_model), &row, path);
|
|
||||||
gtk_list_store_set(_level_list_model, &row, 0, height, 1, scale, -1);
|
|
||||||
}
|
|
||||||
_redrawPreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbGenerateClicked(GtkButton* button, gpointer user_data)
|
|
||||||
{
|
|
||||||
noiseGenerateBaseNoise(_generator, gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_base_size"))));
|
|
||||||
_redrawPreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbPreviewModeClicked(GtkButton* button, gpointer user_data)
|
|
||||||
{
|
|
||||||
if (_current_mode == 1)
|
|
||||||
{
|
|
||||||
_setPreviewMode(2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_setPreviewMode(1);
|
|
||||||
}
|
|
||||||
_redrawPreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbPreviewResetClicked(GtkButton* button, gpointer user_data)
|
|
||||||
{
|
|
||||||
_resetPreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbApplyClicked(GtkButton* button, gpointer user_data)
|
|
||||||
{
|
|
||||||
gtk_widget_hide(_dialog);
|
|
||||||
_callback(_generator);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbCancelClicked(GtkButton* button, gpointer user_data)
|
|
||||||
{
|
|
||||||
gtk_widget_hide(_dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbLevelParamChanged(GtkWidget* widget, gpointer user_data)
|
|
||||||
{
|
|
||||||
_applyLayerParams();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbRowSelected(GtkTreeView* tree_view, gpointer user_data)
|
|
||||||
{
|
|
||||||
GtkTreePath* path;
|
|
||||||
GtkTreeViewColumn* column;
|
|
||||||
int* indices;
|
|
||||||
NoiseLevel params;
|
|
||||||
|
|
||||||
gtk_tree_view_get_cursor(tree_view, &path, &column);
|
|
||||||
indices = gtk_tree_path_get_indices(path);
|
|
||||||
if (indices)
|
|
||||||
{
|
|
||||||
if (noiseGetLevel(_generator, indices[0], ¶ms))
|
|
||||||
{
|
|
||||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_height")), params.height);
|
|
||||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_scale")), params.scaling);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiNoiseInit()
|
|
||||||
{
|
|
||||||
_dialog = GET_WIDGET("dialog_noise");
|
|
||||||
_level_list = GTK_TREE_VIEW(GET_WIDGET("noise_editor_levels"));
|
|
||||||
_level_list_model = GTK_LIST_STORE(gtk_tree_view_get_model(_level_list));
|
|
||||||
_generator = noiseCreateGenerator();
|
|
||||||
|
|
||||||
gtk_spin_button_set_range(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_base_size")), 1, 4000000);
|
|
||||||
gtk_spin_button_set_increments(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_base_size")), 100, 100000);
|
|
||||||
|
|
||||||
gtk_spin_button_set_range(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_scale")), 0.0001, 100.0);
|
|
||||||
gtk_spin_button_set_increments(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_scale")), 0.0001, 0.1);
|
|
||||||
gtk_spin_button_set_range(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_height")), 0.0, 100.0);
|
|
||||||
gtk_spin_button_set_increments(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_height")), 0.0001, 0.1);
|
|
||||||
|
|
||||||
_preview = guiPreviewNew(GTK_IMAGE(GET_WIDGET("noise_editor_preview")));
|
|
||||||
_resetPreview();
|
|
||||||
|
|
||||||
g_signal_connect(_dialog, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("noise_editor_generate"), "clicked", G_CALLBACK(_cbGenerateClicked), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("noise_editor_preview_reset"), "clicked", G_CALLBACK(_cbPreviewResetClicked), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("noise_editor_preview_mode"), "clicked", G_CALLBACK(_cbPreviewModeClicked), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("noise_editor_apply"), "clicked", G_CALLBACK(_cbApplyClicked), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("noise_editor_cancel"), "clicked", G_CALLBACK(_cbCancelClicked), NULL);
|
|
||||||
g_signal_connect(_level_list, "cursor-changed", G_CALLBACK(_cbRowSelected), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("noise_editor_height"), "value-changed", G_CALLBACK(_cbLevelParamChanged), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("noise_editor_scale"), "value-changed", G_CALLBACK(_cbLevelParamChanged), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiNoiseEdit(NoiseGenerator* generator, GuiNoiseChangedCallback callback)
|
|
||||||
{
|
|
||||||
int i, n;
|
|
||||||
NoiseLevel level;
|
|
||||||
GtkTreeIter row;
|
|
||||||
|
|
||||||
_callback = callback;
|
|
||||||
noiseCopy(generator, _generator);
|
|
||||||
|
|
||||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_WIDGET("noise_editor_base_size")), noiseGetBaseSize(_generator));
|
|
||||||
|
|
||||||
gtk_list_store_clear(_level_list_model);
|
|
||||||
n = noiseGetLevelCount(_generator);
|
|
||||||
for (i = 0 ; i < n; i++)
|
|
||||||
{
|
|
||||||
noiseGetLevel(_generator, i, &level);
|
|
||||||
gtk_list_store_append(_level_list_model, &row);
|
|
||||||
gtk_list_store_set(_level_list_model, &row, 0, level.height, 1, level.scaling, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_setPreviewMode(1);
|
|
||||||
_resetPreview();
|
|
||||||
|
|
||||||
gtk_widget_show(_dialog);
|
|
||||||
}
|
|
||||||
|
|
116
gui_gtk/global.c
116
gui_gtk/global.c
|
@ -1,116 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
||||||
|
|
||||||
#include "lib_paysages/shared/functions.h"
|
|
||||||
#include "lib_paysages/shared/constants.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
GtkBuilder* gui_definition;
|
|
||||||
static GtkWindow* _main_window;
|
|
||||||
|
|
||||||
static void _cbQuit(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
gtk_main_quit();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbLoad(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
GtkWidget *dialog;
|
|
||||||
dialog = gtk_file_chooser_dialog_new("Load File",
|
|
||||||
_main_window,
|
|
||||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
||||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
||||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
|
||||||
NULL);
|
|
||||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
|
||||||
paysagesLoad(filename);
|
|
||||||
g_free(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update all GUI */
|
|
||||||
guiUpdate();
|
|
||||||
|
|
||||||
gtk_widget_destroy(dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbSaveAs(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
GtkWidget *dialog;
|
|
||||||
dialog = gtk_file_chooser_dialog_new("Save File",
|
|
||||||
_main_window,
|
|
||||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
||||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
||||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
|
||||||
NULL);
|
|
||||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
|
||||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
|
||||||
paysagesSave(filename);
|
|
||||||
g_free(filename);
|
|
||||||
}
|
|
||||||
gtk_widget_destroy(dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiInit()
|
|
||||||
{
|
|
||||||
GError* p_err = NULL;
|
|
||||||
int argc = 0;
|
|
||||||
char** argv = NULL;
|
|
||||||
|
|
||||||
gtk_init(&argc, &argv);
|
|
||||||
|
|
||||||
gui_definition = gtk_builder_new();
|
|
||||||
gtk_builder_add_from_file(gui_definition, "gui_gtk/gui.glade", &p_err);
|
|
||||||
|
|
||||||
_main_window = GTK_WINDOW(GET_WIDGET("main_window"));
|
|
||||||
g_signal_connect(_main_window, "delete_event", G_CALLBACK(_cbQuit), NULL);
|
|
||||||
|
|
||||||
/* Menu bar */
|
|
||||||
g_signal_connect(GET_WIDGET("menu_quit"), "activate", G_CALLBACK(_cbQuit), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("menu_load"), "activate", G_CALLBACK(_cbLoad), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("menu_saveas"), "activate", G_CALLBACK(_cbSaveAs), NULL);
|
|
||||||
|
|
||||||
/* Dialogs */
|
|
||||||
guiNoiseInit();
|
|
||||||
|
|
||||||
/* Tabs */
|
|
||||||
guiRenderInit();
|
|
||||||
guiTerrainInit();
|
|
||||||
guiWaterInit();
|
|
||||||
guiCloudsInit();
|
|
||||||
guiSkyInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiStart()
|
|
||||||
{
|
|
||||||
guiPreviewStart();
|
|
||||||
|
|
||||||
guiUpdate();
|
|
||||||
|
|
||||||
gtk_widget_show_all(GTK_WIDGET(_main_window));
|
|
||||||
gtk_main();
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiUpdate()
|
|
||||||
{
|
|
||||||
guiWaterUpdate();
|
|
||||||
guiCloudsUpdate();
|
|
||||||
guiSkyUpdate();
|
|
||||||
|
|
||||||
guiPreviewRedrawAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
paysagesInit();
|
|
||||||
guiInit();
|
|
||||||
guiStart();
|
|
||||||
return 0;
|
|
||||||
}
|
|
2091
gui_gtk/gui.glade
2091
gui_gtk/gui.glade
File diff suppressed because it is too large
Load diff
|
@ -1,431 +0,0 @@
|
||||||
/* Small preview management */
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include "common.h"
|
|
||||||
#include "lib_paysages/shared/types.h"
|
|
||||||
#include "lib_paysages/shared/functions.h"
|
|
||||||
#include "lib_paysages/shared/constants.h"
|
|
||||||
#include "lib_paysages/shared/system.h"
|
|
||||||
|
|
||||||
#define MAX_PREVIEWS 30
|
|
||||||
|
|
||||||
struct SmallPreview
|
|
||||||
{
|
|
||||||
double conf_scroll_xmin;
|
|
||||||
double conf_scroll_xmax;
|
|
||||||
double conf_scroll_ymin;
|
|
||||||
double conf_scroll_ymax;
|
|
||||||
|
|
||||||
double conf_scale_min;
|
|
||||||
double conf_scale_max;
|
|
||||||
double conf_scale_step;
|
|
||||||
|
|
||||||
double xoffset;
|
|
||||||
double yoffset;
|
|
||||||
double scaling;
|
|
||||||
|
|
||||||
Mutex* lock;
|
|
||||||
GdkPixbuf* pixbuf;
|
|
||||||
GtkImage* image;
|
|
||||||
|
|
||||||
int mousex;
|
|
||||||
int mousey;
|
|
||||||
|
|
||||||
int need_rerender;
|
|
||||||
int need_render;
|
|
||||||
int need_update;
|
|
||||||
SmallPreviewCallback renderer;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int _previews_count = 0;
|
|
||||||
static SmallPreview _preview[MAX_PREVIEWS];
|
|
||||||
static Thread* _thread_update;
|
|
||||||
|
|
||||||
static inline void _forceRender(SmallPreview* preview)
|
|
||||||
{
|
|
||||||
gdk_pixbuf_fill(preview->pixbuf, 0x00000000);
|
|
||||||
preview->need_rerender = 0;
|
|
||||||
preview->need_render = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void _updateImage(SmallPreview* preview)
|
|
||||||
{
|
|
||||||
gtk_image_set_from_pixbuf(preview->image, preview->pixbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void _renderPixbuf(SmallPreview* preview)
|
|
||||||
{
|
|
||||||
int x, y, done;
|
|
||||||
Color col;
|
|
||||||
void* pixels = gdk_pixbuf_get_pixels(preview->pixbuf);
|
|
||||||
guint32* pixel;
|
|
||||||
int rowstride = gdk_pixbuf_get_rowstride(preview->pixbuf);
|
|
||||||
|
|
||||||
/* TODO Use pixbuf size */
|
|
||||||
for (x = 0; x < 256; x++)
|
|
||||||
{
|
|
||||||
mutexAcquire(preview->lock);
|
|
||||||
if (preview->need_rerender)
|
|
||||||
{
|
|
||||||
mutexRelease(preview->lock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
done = 0;
|
|
||||||
for (y = 0; y < 256; y++)
|
|
||||||
{
|
|
||||||
pixel = (guint32*)(pixels + y * rowstride + x * 4);
|
|
||||||
if (!*pixel)
|
|
||||||
{
|
|
||||||
col = preview->renderer(preview, (double)(x - 128) * preview->scaling + preview->xoffset, (double)(y - 128) * preview->scaling + preview->yoffset, preview->xoffset, preview->yoffset, preview->scaling);
|
|
||||||
*pixel = (guint32)colorTo32BitRGBA(&col);
|
|
||||||
done = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (done)
|
|
||||||
{
|
|
||||||
preview->need_update = 1;
|
|
||||||
}
|
|
||||||
mutexRelease(preview->lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* _doRenders(void* data)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
SmallPreview* preview;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
for (i = 0; i < _previews_count; i++)
|
|
||||||
{
|
|
||||||
preview = _preview + i;
|
|
||||||
if (preview->need_rerender)
|
|
||||||
{
|
|
||||||
_forceRender(preview);
|
|
||||||
}
|
|
||||||
if (preview->need_render)
|
|
||||||
{
|
|
||||||
preview->need_render = 0;
|
|
||||||
_renderPixbuf(preview);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timeSleepMs(100);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _doUpdates(void* data)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
SmallPreview* preview;
|
|
||||||
|
|
||||||
for (i = 0; i < _previews_count; i++)
|
|
||||||
{
|
|
||||||
preview = _preview + i;
|
|
||||||
if (preview->need_update)
|
|
||||||
{
|
|
||||||
preview->need_update = 0;
|
|
||||||
_updateImage(preview);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _scrollPixbuf(SmallPreview* preview, int dx, int dy)
|
|
||||||
{
|
|
||||||
int xstart, ystart, xsize, ysize, y;
|
|
||||||
void* pixels = gdk_pixbuf_get_pixels(preview->pixbuf);
|
|
||||||
int rowstride = gdk_pixbuf_get_rowstride(preview->pixbuf);
|
|
||||||
|
|
||||||
preview->xoffset -= (double)dx * preview->scaling;
|
|
||||||
preview->yoffset -= (double)dy * preview->scaling;
|
|
||||||
|
|
||||||
/* TODO Use pixbuf size */
|
|
||||||
if (dx == 0 && dy == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (dx <= -256 || dx >= 256 || dy <= -256 || dy >= 256)
|
|
||||||
{
|
|
||||||
_forceRender(preview);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dx < 0)
|
|
||||||
{
|
|
||||||
xstart = -dx;
|
|
||||||
xsize = 256 + dx;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xstart = 0;
|
|
||||||
xsize = 256 - dx;
|
|
||||||
}
|
|
||||||
if (dy < 0)
|
|
||||||
{
|
|
||||||
ystart = -dy;
|
|
||||||
ysize = 256 + dy;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ystart = 0;
|
|
||||||
ysize = 256 - dy;
|
|
||||||
}
|
|
||||||
memmove(pixels + (ystart + dy) * rowstride + (xstart + dx) * 4, pixels + ystart * rowstride + xstart * 4, (ysize - 1) * rowstride + xsize * 4);
|
|
||||||
if (dy < 0)
|
|
||||||
{
|
|
||||||
memset(pixels + (256 + dy) * rowstride, 0, (-dy - 1) * rowstride + 256 * 4);
|
|
||||||
}
|
|
||||||
else if (dy > 0)
|
|
||||||
{
|
|
||||||
memset(pixels, 0, (dy - 1) * rowstride + 256 * 4);
|
|
||||||
}
|
|
||||||
if (dx < 0)
|
|
||||||
{
|
|
||||||
for (y = ystart + dy; y < ystart + dy + ysize; y++)
|
|
||||||
{
|
|
||||||
memset(pixels + y * rowstride + xsize * 4, 0, -dx * 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (dx > 0)
|
|
||||||
{
|
|
||||||
for (y = ystart + dy; y < ystart + dy + ysize; y++)
|
|
||||||
{
|
|
||||||
memset(pixels + y * rowstride, 0, dx * 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
preview->need_render = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int _fixScroll(SmallPreview* preview, int dx, int dy, int* new_dx, int* new_dy)
|
|
||||||
{
|
|
||||||
*new_dx = dx;
|
|
||||||
*new_dy = dy;
|
|
||||||
if (preview->xoffset - dx * preview->scaling > preview->conf_scroll_xmax)
|
|
||||||
{
|
|
||||||
*new_dx = (int)floor((preview->conf_scroll_xmax - preview->xoffset) / preview->scaling);
|
|
||||||
}
|
|
||||||
if (preview->xoffset - dx * preview->scaling < preview->conf_scroll_xmin)
|
|
||||||
{
|
|
||||||
*new_dx = (int)floor((preview->conf_scroll_xmin - preview->xoffset) / preview->scaling);
|
|
||||||
}
|
|
||||||
if (preview->yoffset - dy * preview->scaling > preview->conf_scroll_ymax)
|
|
||||||
{
|
|
||||||
*new_dy = (int)floor((preview->conf_scroll_ymax - preview->yoffset) / preview->scaling);
|
|
||||||
}
|
|
||||||
if (preview->yoffset - dy * preview->scaling < preview->conf_scroll_ymin)
|
|
||||||
{
|
|
||||||
*new_dy = (int)floor((preview->conf_scroll_ymin - preview->yoffset) / preview->scaling);
|
|
||||||
}
|
|
||||||
return (*new_dx == 0 && *new_dy == 0) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int _fixScaling(SmallPreview* preview, double scaling, double* new_scaling)
|
|
||||||
{
|
|
||||||
double old_scaling = preview->scaling;
|
|
||||||
*new_scaling = scaling;
|
|
||||||
if (scaling < preview->conf_scale_min)
|
|
||||||
{
|
|
||||||
*new_scaling = preview->conf_scale_min;
|
|
||||||
}
|
|
||||||
if (scaling > preview->conf_scale_max)
|
|
||||||
{
|
|
||||||
*new_scaling = preview->conf_scale_max;
|
|
||||||
}
|
|
||||||
return (old_scaling == *new_scaling) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cbMouseScroll(GtkEventBox* image, GdkEventScroll* event, gpointer data)
|
|
||||||
{
|
|
||||||
SmallPreview* preview = (SmallPreview*)data;
|
|
||||||
|
|
||||||
/* TODO Center the zoom on the cursor */
|
|
||||||
|
|
||||||
if (event->direction == GDK_SCROLL_UP)
|
|
||||||
{
|
|
||||||
mutexAcquire(preview->lock);
|
|
||||||
if (_fixScaling(preview, preview->scaling - preview->conf_scale_step, &preview->scaling))
|
|
||||||
{
|
|
||||||
preview->need_rerender = 1;
|
|
||||||
}
|
|
||||||
mutexRelease(preview->lock);
|
|
||||||
}
|
|
||||||
else if (event->direction == GDK_SCROLL_DOWN)
|
|
||||||
{
|
|
||||||
mutexAcquire(preview->lock);
|
|
||||||
if (_fixScaling(preview, preview->scaling + preview->conf_scale_step, &preview->scaling))
|
|
||||||
{
|
|
||||||
preview->need_rerender = 1;
|
|
||||||
}
|
|
||||||
mutexRelease(preview->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cbMouseButtonPressed(GtkEventBox* image, GdkEventButton* event, gpointer data)
|
|
||||||
{
|
|
||||||
SmallPreview* preview = (SmallPreview*)data;
|
|
||||||
|
|
||||||
if (event->button == 1)
|
|
||||||
{
|
|
||||||
preview->mousex = (int)event->x;
|
|
||||||
preview->mousey = (int)event->y;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cbMouseMove(GtkEventBox* image, GdkEventMotion* event, gpointer data)
|
|
||||||
{
|
|
||||||
SmallPreview* preview = (SmallPreview*)data;
|
|
||||||
int dx, dy;
|
|
||||||
|
|
||||||
if (event->state & GDK_BUTTON1_MASK)
|
|
||||||
{
|
|
||||||
mutexAcquire(preview->lock);
|
|
||||||
|
|
||||||
dx = (int)event->x - preview->mousex;
|
|
||||||
dy = (int)event->y - preview->mousey;
|
|
||||||
|
|
||||||
if (_fixScroll(preview, dx, dy, &dx, &dy))
|
|
||||||
{
|
|
||||||
_scrollPixbuf(preview, dx, dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
preview->mousex = (int)event->x;
|
|
||||||
preview->mousey = (int)event->y;
|
|
||||||
|
|
||||||
mutexRelease(preview->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _renderNone(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
|
||||||
{
|
|
||||||
return COLOR_BLACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiPreviewStart()
|
|
||||||
{
|
|
||||||
_thread_update = threadCreate(_doRenders, NULL);
|
|
||||||
g_timeout_add(200, _doUpdates, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiPreviewRedraw(SmallPreview* preview)
|
|
||||||
{
|
|
||||||
mutexAcquire(preview->lock);
|
|
||||||
preview->need_rerender = 1;
|
|
||||||
mutexRelease(preview->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiPreviewRedrawAll()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < _previews_count; i++)
|
|
||||||
{
|
|
||||||
guiPreviewRedraw(_preview + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SmallPreview* guiPreviewNew(GtkImage* image)
|
|
||||||
{
|
|
||||||
GtkWidget* parent = gtk_widget_get_parent(GTK_WIDGET(image));
|
|
||||||
SmallPreview* preview;
|
|
||||||
|
|
||||||
/* TODO Check the parent can receive events (or is a GtkEventBox) */
|
|
||||||
if (_previews_count < MAX_PREVIEWS)
|
|
||||||
{
|
|
||||||
preview = _preview + _previews_count;
|
|
||||||
preview->lock = mutexCreate();
|
|
||||||
preview->conf_scroll_xmin = 0.0;
|
|
||||||
preview->conf_scroll_xmax = 0.0;
|
|
||||||
preview->conf_scroll_ymin = 0.0;
|
|
||||||
preview->conf_scroll_ymax = 0.0;
|
|
||||||
preview->conf_scale_min = 1.0;
|
|
||||||
preview->conf_scale_max = 1.0;
|
|
||||||
preview->conf_scale_step = 0.0;
|
|
||||||
preview->scaling = 1.0;
|
|
||||||
preview->xoffset = 0.0;
|
|
||||||
preview->yoffset = 0.0;
|
|
||||||
/* TODO Get size from GtkImage */
|
|
||||||
preview->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 1, 8, 256, 256);
|
|
||||||
preview->image = image;
|
|
||||||
preview->need_rerender = 0;
|
|
||||||
preview->need_render = 0;
|
|
||||||
preview->need_update = 0;
|
|
||||||
preview->renderer = _renderNone;
|
|
||||||
|
|
||||||
gtk_image_clear(image);
|
|
||||||
_forceRender(preview);
|
|
||||||
|
|
||||||
g_signal_connect(parent, "scroll-event", G_CALLBACK(_cbMouseScroll), (gpointer)preview);
|
|
||||||
g_signal_connect(parent, "button-press-event", G_CALLBACK(_cbMouseButtonPressed), (gpointer)preview);
|
|
||||||
g_signal_connect(parent, "motion-notify-event", G_CALLBACK(_cbMouseMove), (gpointer)preview);
|
|
||||||
|
|
||||||
_previews_count++;
|
|
||||||
return preview;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* TODO Return fake preview */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiPreviewConfigScrolling(SmallPreview* preview, double xmin, double xmax, double ymin, double ymax)
|
|
||||||
{
|
|
||||||
mutexAcquire(preview->lock);
|
|
||||||
preview->conf_scroll_xmin = xmin;
|
|
||||||
preview->conf_scroll_xmax = xmax;
|
|
||||||
preview->conf_scroll_ymin = ymin;
|
|
||||||
preview->conf_scroll_ymax = ymax;
|
|
||||||
preview->need_rerender = 1;
|
|
||||||
mutexRelease(preview->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiPreviewConfigScaling(SmallPreview* preview, double min, double max, double step)
|
|
||||||
{
|
|
||||||
mutexAcquire(preview->lock);
|
|
||||||
preview->conf_scale_min = min;
|
|
||||||
preview->conf_scale_max = max;
|
|
||||||
preview->conf_scale_step = step;
|
|
||||||
preview->need_rerender = 1;
|
|
||||||
mutexRelease(preview->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiPreviewSetRenderer(SmallPreview* preview, SmallPreviewCallback renderer)
|
|
||||||
{
|
|
||||||
mutexAcquire(preview->lock);
|
|
||||||
preview->renderer = renderer;
|
|
||||||
preview->need_rerender = 1;
|
|
||||||
mutexRelease(preview->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiPreviewSetViewport(SmallPreview* preview, double xoffset, double yoffset, double scaling)
|
|
||||||
{
|
|
||||||
mutexAcquire(preview->lock);
|
|
||||||
preview->xoffset = xoffset;
|
|
||||||
preview->yoffset = yoffset;
|
|
||||||
preview->scaling = scaling;
|
|
||||||
preview->need_rerender = 1;
|
|
||||||
mutexRelease(preview->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiPreviewSetTerrainHeight(SmallPreview* preview)
|
|
||||||
{
|
|
||||||
/*preview->conf_scroll_x = 1;
|
|
||||||
preview->conf_scroll_y = 1;
|
|
||||||
preview->conf_zoom = 1;
|
|
||||||
preview->init_scaling = preview->scaling = 0.1;
|
|
||||||
preview->init_xoffset = preview->xoffset = 0.0;
|
|
||||||
preview->init_yoffset = preview->yoffset = 0.0;
|
|
||||||
|
|
||||||
preview->renderer = _renderTopDownHeight;*/
|
|
||||||
|
|
||||||
guiPreviewRedraw(preview);
|
|
||||||
}
|
|
|
@ -1,128 +0,0 @@
|
||||||
/* Terrain tab */
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "lib_paysages/shared/functions.h"
|
|
||||||
#include "lib_paysages/shared/constants.h"
|
|
||||||
#include "lib_paysages/clouds.h"
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
static SmallPreview* _preview;
|
|
||||||
static CloudsDefinition _definition;
|
|
||||||
static int _current_layer;
|
|
||||||
|
|
||||||
static GtkTreeView* _list_layers;
|
|
||||||
static GtkListStore* _list_layers_model;
|
|
||||||
|
|
||||||
/***** Internal functions *****/
|
|
||||||
|
|
||||||
static void _revertCurrentLayer()
|
|
||||||
{
|
|
||||||
if (_current_layer >= 0)
|
|
||||||
{
|
|
||||||
cloudsCopyDefinition(cloudsGetDefinition(_current_layer), &_definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO Revert layer from config */
|
|
||||||
|
|
||||||
guiPreviewRedraw(_preview);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static void _applyCurrentLayer()
|
|
||||||
{
|
|
||||||
guiUpdate();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
static void _revertAll()
|
|
||||||
{
|
|
||||||
int i, n;
|
|
||||||
CloudsDefinition layer;
|
|
||||||
GtkTreeIter row;
|
|
||||||
|
|
||||||
gtk_list_store_clear(_list_layers_model);
|
|
||||||
n = cloudsGetLayerCount();
|
|
||||||
for (i = 0 ; i < n; i++)
|
|
||||||
{
|
|
||||||
layer = cloudsGetDefinition(i);
|
|
||||||
gtk_list_store_append(_list_layers_model, &row);
|
|
||||||
gtk_list_store_set(_list_layers_model, &row, 0, layer.ymin, 1, layer.ymax - layer.ymin, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_current_layer < 0 || _current_layer >= n)
|
|
||||||
{
|
|
||||||
_current_layer = -1;
|
|
||||||
}
|
|
||||||
_revertCurrentLayer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Preview callbacks *****/
|
|
||||||
|
|
||||||
static Color _cbPreviewPixel(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
|
||||||
{
|
|
||||||
Color result, layer_color;
|
|
||||||
Vector3 start, end;
|
|
||||||
|
|
||||||
if (_current_layer < 0)
|
|
||||||
{
|
|
||||||
return COLOR_BLACK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
start.x = end.x = x;
|
|
||||||
start.z = end.z = y;
|
|
||||||
start.y = _definition.ymin;
|
|
||||||
end.y = _definition.ymax;
|
|
||||||
result.r = 0.3;
|
|
||||||
result.g = 0.5;
|
|
||||||
result.b = 0.8;
|
|
||||||
result.a = 1.0;
|
|
||||||
layer_color = cloudsGetColorCustom(start, end, &_definition, NULL, NULL);
|
|
||||||
colorMask(&result, &layer_color);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Config callbacks *****/
|
|
||||||
|
|
||||||
static void _cbLayerSelected(GtkTreeView* tree_view, gpointer user_data)
|
|
||||||
{
|
|
||||||
GtkTreePath* path;
|
|
||||||
GtkTreeViewColumn* column;
|
|
||||||
int* indices;
|
|
||||||
|
|
||||||
gtk_tree_view_get_cursor(tree_view, &path, &column);
|
|
||||||
indices = gtk_tree_path_get_indices(path);
|
|
||||||
if (indices)
|
|
||||||
{
|
|
||||||
_current_layer = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_current_layer = -1;
|
|
||||||
}
|
|
||||||
_revertCurrentLayer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Public functions *****/
|
|
||||||
|
|
||||||
void guiCloudsInit()
|
|
||||||
{
|
|
||||||
_list_layers = GTK_TREE_VIEW(GET_WIDGET("clouds_layers"));
|
|
||||||
_list_layers_model = GTK_LIST_STORE(gtk_tree_view_get_model(_list_layers));
|
|
||||||
|
|
||||||
_definition = cloudsCreateDefinition();
|
|
||||||
|
|
||||||
_preview = guiPreviewNew(GTK_IMAGE(GET_WIDGET("clouds_preview")));
|
|
||||||
guiPreviewConfigScaling(_preview, 1.0, 100.0, 1.0);
|
|
||||||
guiPreviewConfigScrolling(_preview, -10000.0, 10000.0, -10000.0, 10000.0);
|
|
||||||
guiPreviewSetViewport(_preview, 0.0, 0.0, 10.0);
|
|
||||||
guiPreviewSetRenderer(_preview, _cbPreviewPixel);
|
|
||||||
|
|
||||||
g_signal_connect(_list_layers, "cursor-changed", G_CALLBACK(_cbLayerSelected), NULL);
|
|
||||||
|
|
||||||
guiCloudsUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiCloudsUpdate()
|
|
||||||
{
|
|
||||||
_revertAll();
|
|
||||||
}
|
|
|
@ -1,172 +0,0 @@
|
||||||
/* Terrain tab */
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "lib_paysages/shared/functions.h"
|
|
||||||
#include "lib_paysages/shared/constants.h"
|
|
||||||
#include "lib_paysages/shared/globals.h"
|
|
||||||
#include "lib_paysages/shared/system.h"
|
|
||||||
|
|
||||||
static GtkImage* _render_final;
|
|
||||||
static GdkPixbuf* _render_buffer = NULL;
|
|
||||||
static guchar* _render_buffer_pixels = NULL;
|
|
||||||
static int _render_buffer_ymax = 0;
|
|
||||||
static int _render_buffer_rowstride = 0;
|
|
||||||
static int _rendering = 0;
|
|
||||||
|
|
||||||
static void _previewResize(int width, int height)
|
|
||||||
{
|
|
||||||
if (_render_buffer)
|
|
||||||
{
|
|
||||||
gdk_pixbuf_unref(_render_buffer);
|
|
||||||
}
|
|
||||||
_render_buffer = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 1, 8, width, height);
|
|
||||||
_render_buffer_pixels = gdk_pixbuf_get_pixels(_render_buffer);
|
|
||||||
_render_buffer_rowstride = gdk_pixbuf_get_rowstride(_render_buffer);
|
|
||||||
_render_buffer_ymax = height - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _previewClear(Color col)
|
|
||||||
{
|
|
||||||
gdk_pixbuf_fill(_render_buffer, (guint32)colorTo32BitARGB(&col));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _previewDraw(int x, int y, Color col)
|
|
||||||
{
|
|
||||||
guint32* pixels = (guint32*)(_render_buffer_pixels + (_render_buffer_ymax - y) * _render_buffer_rowstride + x * 4);
|
|
||||||
*pixels = (guint32)colorTo32BitRGBA(&col);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _previewUpdate(double progress)
|
|
||||||
{
|
|
||||||
gtk_image_set_from_pixbuf(_render_final, _render_buffer);
|
|
||||||
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(GET_WIDGET("render_progress")), progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* _threadRender(void* data)
|
|
||||||
{
|
|
||||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(GET_WIDGET("render_mode_raytracing"))))
|
|
||||||
{
|
|
||||||
autoRenderSceneRayTracing();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
autoRenderSceneTwoPass(0);
|
|
||||||
}
|
|
||||||
_rendering = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbStartRender(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
Thread* thread;
|
|
||||||
|
|
||||||
/* Prepare render */
|
|
||||||
renderSetSize(gtk_spin_button_get_value(GTK_SPIN_BUTTON(GET_WIDGET("render_width"))), gtk_spin_button_get_value(GTK_SPIN_BUTTON(GET_WIDGET("render_height"))));
|
|
||||||
autoSetRenderQuality((int)gtk_range_get_value(GTK_RANGE(GET_WIDGET("render_quality"))));
|
|
||||||
gtk_widget_set_size_request(GET_WIDGET("render_preview"), render_width, render_height);
|
|
||||||
gtk_image_clear(GTK_IMAGE(GET_WIDGET("render_preview")));
|
|
||||||
renderSetPreviewCallbacks(_previewResize, _previewClear, _previewDraw, _previewUpdate);
|
|
||||||
|
|
||||||
/* Open render dialog */
|
|
||||||
gtk_window_set_deletable(GTK_WINDOW(GET_WIDGET("dialog_render")), 0);
|
|
||||||
gtk_widget_show(GET_WIDGET("dialog_render"));
|
|
||||||
gtk_widget_set_sensitive(GET_WIDGET("render_stop"), 1);
|
|
||||||
gtk_widget_set_sensitive(GET_WIDGET("render_close"), 0);
|
|
||||||
|
|
||||||
/* Do the render */
|
|
||||||
_rendering = 1;
|
|
||||||
thread = threadCreate(_threadRender, NULL);
|
|
||||||
while (_rendering)
|
|
||||||
{
|
|
||||||
timeSleepMs(100);
|
|
||||||
while (gtk_events_pending())
|
|
||||||
{
|
|
||||||
gtk_main_iteration();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
threadJoin(thread);
|
|
||||||
|
|
||||||
/* Clean up */
|
|
||||||
renderSetPreviewCallbacks(NULL, NULL, NULL, NULL);
|
|
||||||
gtk_widget_set_sensitive(GET_WIDGET("render_stop"), 0);
|
|
||||||
gtk_widget_set_sensitive(GET_WIDGET("render_close"), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbStopRender(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
if (_rendering)
|
|
||||||
{
|
|
||||||
renderInterrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbCloseRender(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
gtk_widget_hide(GET_WIDGET("dialog_render"));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbShowRender(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
gtk_widget_show(GET_WIDGET("dialog_render"));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbSaveRender(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
GtkWidget *dialog;
|
|
||||||
char *filename;
|
|
||||||
|
|
||||||
dialog = gtk_file_chooser_dialog_new("Save last render",
|
|
||||||
GTK_WINDOW(GET_WIDGET("main_window")),
|
|
||||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
||||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
||||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
|
||||||
NULL);
|
|
||||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
|
||||||
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
|
|
||||||
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "render.png");
|
|
||||||
|
|
||||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
|
|
||||||
{
|
|
||||||
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
|
||||||
renderSaveToFile(filename);
|
|
||||||
g_free(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_widget_destroy(dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cbWindowClosed(GtkWidget* widget, GdkEvent* event, gpointer data)
|
|
||||||
{
|
|
||||||
gtk_widget_hide(widget);
|
|
||||||
if (_rendering)
|
|
||||||
{
|
|
||||||
renderInterrupt();
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiRenderInit()
|
|
||||||
{
|
|
||||||
_render_final = GTK_IMAGE(GET_WIDGET("render_preview"));
|
|
||||||
_previewResize(800, 600);
|
|
||||||
_previewClear(COLOR_BLACK);
|
|
||||||
_previewUpdate(0.0);
|
|
||||||
|
|
||||||
g_signal_connect(GET_WIDGET("render_show"), "clicked", G_CALLBACK(_cbShowRender), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("render_save"), "clicked", G_CALLBACK(_cbSaveRender), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("render_start"), "clicked", G_CALLBACK(_cbStartRender), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("render_stop"), "clicked", G_CALLBACK(_cbStopRender), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("render_close"), "clicked", G_CALLBACK(_cbCloseRender), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("dialog_render"), "delete-event", G_CALLBACK(_cbWindowClosed), NULL);
|
|
||||||
|
|
||||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("render_quality")), 1, 10);
|
|
||||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("render_quality")), 5);
|
|
||||||
|
|
||||||
gtk_spin_button_set_range(GTK_SPIN_BUTTON(GET_WIDGET("render_width")), 100, 4000);
|
|
||||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_WIDGET("render_width")), 1200);
|
|
||||||
gtk_spin_button_set_increments(GTK_SPIN_BUTTON(GET_WIDGET("render_width")), 10, 100);
|
|
||||||
gtk_spin_button_set_range(GTK_SPIN_BUTTON(GET_WIDGET("render_height")), 100, 4000);
|
|
||||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_WIDGET("render_height")), 900);
|
|
||||||
gtk_spin_button_set_increments(GTK_SPIN_BUTTON(GET_WIDGET("render_height")), 10, 100);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,133 +0,0 @@
|
||||||
/* Terrain tab */
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "lib_paysages/shared/functions.h"
|
|
||||||
#include "lib_paysages/shared/constants.h"
|
|
||||||
#include "lib_paysages/sky.h"
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
static SmallPreview* _preview_horizon;
|
|
||||||
static SkyDefinition _definition;
|
|
||||||
|
|
||||||
static Color _cbPreviewHorizon(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
|
||||||
{
|
|
||||||
Vector3 eye = {0.0, 0.0, 0.0};
|
|
||||||
Vector3 look;
|
|
||||||
|
|
||||||
look.x = cos(M_PI * (x / 1.28 + 0.5)) * cos(M_PI * (y / 2.56));
|
|
||||||
look.y = -sin(M_PI * (y / 2.56));
|
|
||||||
look.z = sin(M_PI * (x / 1.28 + 0.5)) * cos(M_PI * (y / 2.56));
|
|
||||||
|
|
||||||
return skyGetColorCustom(eye, look, &_definition, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void _updatePreview()
|
|
||||||
{
|
|
||||||
skyValidateDefinition(&_definition);
|
|
||||||
guiPreviewRedraw(_preview_horizon);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _redrawColorGradation(GtkImage* image, ColorGradation* gradation)
|
|
||||||
{
|
|
||||||
GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 1, 8, 200, 30);
|
|
||||||
void* pixels = gdk_pixbuf_get_pixels(pixbuf);
|
|
||||||
int rowstride = gdk_pixbuf_get_rowstride(pixbuf);
|
|
||||||
|
|
||||||
int x, y;
|
|
||||||
guint32* pixel;
|
|
||||||
Color col;
|
|
||||||
|
|
||||||
for (x = 0; x < 200; x++)
|
|
||||||
{
|
|
||||||
for (y = 0; y < 30; y++)
|
|
||||||
{
|
|
||||||
pixel = (guint32*)(pixels + y * rowstride + x * 4);
|
|
||||||
col = colorGradationGet(gradation, (double)x / 200.0);
|
|
||||||
*pixel = (guint32)colorTo32BitRGBA(&col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_image_set_from_pixbuf(image, pixbuf);
|
|
||||||
gdk_pixbuf_unref(pixbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbDaytimeChanged(GtkRange* range, gpointer data)
|
|
||||||
{
|
|
||||||
_definition.daytime = gtk_range_get_value(range);
|
|
||||||
_updatePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbSunSizeChanged(GtkRange* range, gpointer data)
|
|
||||||
{
|
|
||||||
_definition.sun_radius = gtk_range_get_value(range);
|
|
||||||
_updatePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbHazeHeightChanged(GtkRange* range, gpointer data)
|
|
||||||
{
|
|
||||||
_definition.haze_height = gtk_range_get_value(range);
|
|
||||||
_updatePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbHazeSmoothingChanged(GtkRange* range, gpointer data)
|
|
||||||
{
|
|
||||||
_definition.haze_smoothing = gtk_range_get_value(range);
|
|
||||||
_updatePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbRevertConfig(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
skyCopyDefinition(skyGetDefinition(), &_definition);
|
|
||||||
|
|
||||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("sky_daytime")), _definition.daytime);
|
|
||||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("sky_sun_size")), _definition.sun_radius);
|
|
||||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("sky_haze_height")), _definition.haze_height);
|
|
||||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("sky_haze_smoothing")), _definition.haze_smoothing);
|
|
||||||
|
|
||||||
_redrawColorGradation(GTK_IMAGE(GET_WIDGET("sky_colorgradient_sun")), &_definition.sun_color);
|
|
||||||
_redrawColorGradation(GTK_IMAGE(GET_WIDGET("sky_colorgradient_zenith")),& _definition.zenith_color);
|
|
||||||
_redrawColorGradation(GTK_IMAGE(GET_WIDGET("sky_colorgradient_haze")), &_definition.haze_color);
|
|
||||||
|
|
||||||
_updatePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbApplyConfig(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
skySetDefinition(_definition);
|
|
||||||
guiUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiSkyInit()
|
|
||||||
{
|
|
||||||
_definition = skyCreateDefinition();
|
|
||||||
|
|
||||||
/* Buttons */
|
|
||||||
g_signal_connect(GET_WIDGET("sky_apply"), "clicked", G_CALLBACK(_cbApplyConfig), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("sky_revert"), "clicked", G_CALLBACK(_cbRevertConfig), NULL);
|
|
||||||
|
|
||||||
/* Configs */
|
|
||||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("sky_daytime")), 0.0, 1.0);
|
|
||||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("sky_sun_size")), 0.0, 0.3);
|
|
||||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("sky_haze_height")), 0.0, 1.0);
|
|
||||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("sky_haze_smoothing")), 0.0, 1.0);
|
|
||||||
|
|
||||||
/* Config signals */
|
|
||||||
g_signal_connect(GET_WIDGET("sky_daytime"), "value-changed", G_CALLBACK(_cbDaytimeChanged), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("sky_sun_size"), "value-changed", G_CALLBACK(_cbSunSizeChanged), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("sky_haze_height"), "value-changed", G_CALLBACK(_cbHazeHeightChanged), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("sky_haze_smoothing"), "value-changed", G_CALLBACK(_cbHazeSmoothingChanged), NULL);
|
|
||||||
|
|
||||||
/* Previews */
|
|
||||||
_preview_horizon = guiPreviewNew(GTK_IMAGE(GET_WIDGET("sky_preview_horizon")));
|
|
||||||
guiPreviewConfigScaling(_preview_horizon, 0.01, 0.01, 0.0);
|
|
||||||
guiPreviewConfigScrolling(_preview_horizon, 0.0, 0.0, 0.0, 0.0);
|
|
||||||
guiPreviewSetViewport(_preview_horizon, 0.0, 0.0, 0.01);
|
|
||||||
guiPreviewSetRenderer(_preview_horizon, _cbPreviewHorizon);
|
|
||||||
|
|
||||||
guiSkyUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiSkyUpdate()
|
|
||||||
{
|
|
||||||
_cbRevertConfig(NULL, NULL);
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/* Terrain tab */
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "lib_paysages/shared/functions.h"
|
|
||||||
#include "lib_paysages/terrain.h"
|
|
||||||
#include "lib_paysages/textures.h"
|
|
||||||
|
|
||||||
static SmallPreview* _preview;
|
|
||||||
static TerrainDefinition _definition;
|
|
||||||
|
|
||||||
static Color _cbPreviewRenderPixel(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
|
||||||
{
|
|
||||||
Color result;
|
|
||||||
|
|
||||||
result.r = result.g = result.b = terrainGetHeightNormalized(x, y);
|
|
||||||
result.a = 1.0;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbEditNoiseDone(NoiseGenerator* generator)
|
|
||||||
{
|
|
||||||
noiseCopy(generator, _definition.height_noise);
|
|
||||||
terrainSetDefinition(_definition);
|
|
||||||
|
|
||||||
/* TODO Redraw only affected by terrain */
|
|
||||||
guiPreviewRedrawAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbEditNoise(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
guiNoiseEdit(_definition.height_noise, _cbEditNoiseDone);
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiTerrainInit()
|
|
||||||
{
|
|
||||||
g_signal_connect(GET_WIDGET("terrain_noise_edit"), "clicked", G_CALLBACK(_cbEditNoise), NULL);
|
|
||||||
|
|
||||||
_preview = guiPreviewNew(GTK_IMAGE(GET_WIDGET("terrain_preview")));
|
|
||||||
guiPreviewConfigScaling(_preview, 0.01, 1.0, 0.05);
|
|
||||||
guiPreviewConfigScrolling(_preview, -1000.0, 1000.0, -1000.0, 1000.0);
|
|
||||||
guiPreviewSetViewport(_preview, 0.0, 0.0, 0.2);
|
|
||||||
guiPreviewSetRenderer(_preview, _cbPreviewRenderPixel);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,234 +0,0 @@
|
||||||
/* Terrain tab */
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "lib_paysages/shared/functions.h"
|
|
||||||
#include "lib_paysages/shared/constants.h"
|
|
||||||
#include "lib_paysages/water.h"
|
|
||||||
#include "lib_paysages/terrain.h"
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
static SmallPreview* _preview_coverage;
|
|
||||||
static SmallPreview* _preview_render;
|
|
||||||
static WaterDefinition _definition;
|
|
||||||
|
|
||||||
static RayCastingResult _rayCastFromWater(Vector3 start, Vector3 direction)
|
|
||||||
{
|
|
||||||
RayCastingResult result;
|
|
||||||
double x, y;
|
|
||||||
|
|
||||||
result.hit = 1;
|
|
||||||
if (direction.z < 0.0001)
|
|
||||||
{
|
|
||||||
result.hit_color = COLOR_WHITE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = start.x + direction.x * (0.0 - start.z) / direction.z;
|
|
||||||
y = start.y + direction.y * (0.0 - start.z) / direction.z;
|
|
||||||
|
|
||||||
if (((int)ceil(x * 0.2) % 2 == 0) ^ ((int)ceil(y * 0.2 - 0.5) % 2 == 0))
|
|
||||||
{
|
|
||||||
result.hit_color = COLOR_WHITE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.hit_color = COLOR_GREY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* TODO hit_location */
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _cbPreviewCoverage(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
|
||||||
{
|
|
||||||
Color result;
|
|
||||||
double height;
|
|
||||||
|
|
||||||
height = terrainGetHeight(x, y);
|
|
||||||
if (height <= _definition.height)
|
|
||||||
{
|
|
||||||
return _definition.main_color;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.r = result.g = result.b = terrainGetHeightNormalized(x, y);
|
|
||||||
result.a = 1.0;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _cbPreviewRender(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
|
|
||||||
{
|
|
||||||
Vector3 eye, look, location;
|
|
||||||
WaterDefinition definition;
|
|
||||||
WaterEnvironment environment;
|
|
||||||
WaterQuality quality;
|
|
||||||
|
|
||||||
eye.x = 0.0;
|
|
||||||
eye.y = scaling;
|
|
||||||
eye.z = -10.0 * scaling;
|
|
||||||
look.x = x * 0.01 / scaling;
|
|
||||||
look.y = -y * 0.01 / scaling - 0.3;
|
|
||||||
look.z = 1.0;
|
|
||||||
look = v3Normalize(look);
|
|
||||||
|
|
||||||
if (look.y > -0.0001)
|
|
||||||
{
|
|
||||||
return _rayCastFromWater(eye, look).hit_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
location.x = eye.x - look.x * eye.y / look.y;
|
|
||||||
location.y = 0.0;
|
|
||||||
location.z = eye.z - look.z * eye.y / look.y;
|
|
||||||
|
|
||||||
if (location.z > 0.0)
|
|
||||||
{
|
|
||||||
return _rayCastFromWater(eye, look).hit_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
definition = _definition;
|
|
||||||
definition.height = 0.0;
|
|
||||||
environment.reflection_function = _rayCastFromWater;
|
|
||||||
environment.refraction_function = _rayCastFromWater;
|
|
||||||
environment.toggle_fog = 0;
|
|
||||||
quality.force_detail = 0.0001;
|
|
||||||
|
|
||||||
return waterGetColorCustom(location, look, &definition, &quality, &environment).final;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbEditNoiseDone(NoiseGenerator* generator)
|
|
||||||
{
|
|
||||||
noiseCopy(generator, _definition.waves_noise);
|
|
||||||
guiPreviewRedraw(_preview_render);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbEditNoise(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
guiNoiseEdit(_definition.waves_noise, _cbEditNoiseDone);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbHeightChanged(GtkRange* range, gpointer data)
|
|
||||||
{
|
|
||||||
_definition.height = gtk_range_get_value(range);
|
|
||||||
guiPreviewRedraw(_preview_coverage);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbTransparencyChanged(GtkRange* range, gpointer data)
|
|
||||||
{
|
|
||||||
_definition.transparency = gtk_range_get_value(range);
|
|
||||||
guiPreviewRedraw(_preview_render);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbReflectionChanged(GtkRange* range, gpointer data)
|
|
||||||
{
|
|
||||||
_definition.reflection = gtk_range_get_value(range);
|
|
||||||
guiPreviewRedraw(_preview_render);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbTransparencyDepthChanged(GtkRange* range, gpointer data)
|
|
||||||
{
|
|
||||||
_definition.transparency_depth = gtk_range_get_value(range);
|
|
||||||
guiPreviewRedraw(_preview_render);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbColorChanged(GtkColorButton* colorbutton, gpointer data)
|
|
||||||
{
|
|
||||||
GdkColor col;
|
|
||||||
|
|
||||||
gtk_color_button_get_color(colorbutton, &col);
|
|
||||||
_definition.main_color.r = (double)col.red / 65535.0;
|
|
||||||
_definition.main_color.g = (double)col.green / 65535.0;
|
|
||||||
_definition.main_color.b = (double)col.blue / 65535.0;
|
|
||||||
_definition.main_color.a = 1.0;
|
|
||||||
|
|
||||||
guiPreviewRedraw(_preview_render);
|
|
||||||
guiPreviewRedraw(_preview_coverage);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbColorDepthChanged(GtkColorButton* colorbutton, gpointer data)
|
|
||||||
{
|
|
||||||
GdkColor col;
|
|
||||||
|
|
||||||
gtk_color_button_get_color(colorbutton, &col);
|
|
||||||
_definition.depth_color.r = (double)col.red / 65535.0;
|
|
||||||
_definition.depth_color.g = (double)col.green / 65535.0;
|
|
||||||
_definition.depth_color.b = (double)col.blue / 65535.0;
|
|
||||||
_definition.depth_color.a = 1.0;
|
|
||||||
|
|
||||||
guiPreviewRedraw(_preview_render);
|
|
||||||
guiPreviewRedraw(_preview_coverage);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbRevertConfig(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
GdkColor col;
|
|
||||||
|
|
||||||
waterCopyDefinition(waterGetDefinition(), &_definition);
|
|
||||||
|
|
||||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_height")), _definition.height);
|
|
||||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_transparency")), _definition.transparency);
|
|
||||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_reflection")), _definition.reflection);
|
|
||||||
gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_transparency_depth")), _definition.transparency_depth);
|
|
||||||
col.red = _definition.main_color.r * 65535.0;
|
|
||||||
col.green = _definition.main_color.g * 65535.0;
|
|
||||||
col.blue = _definition.main_color.b * 65535.0;
|
|
||||||
gtk_color_button_set_color(GTK_COLOR_BUTTON(GET_WIDGET("water_color")), &col);
|
|
||||||
col.red = _definition.depth_color.r * 65535.0;
|
|
||||||
col.green = _definition.depth_color.g * 65535.0;
|
|
||||||
col.blue = _definition.depth_color.b * 65535.0;
|
|
||||||
gtk_color_button_set_color(GTK_COLOR_BUTTON(GET_WIDGET("water_color_depth")), &col);
|
|
||||||
|
|
||||||
guiPreviewRedraw(_preview_render);
|
|
||||||
guiPreviewRedraw(_preview_coverage);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cbApplyConfig(GtkWidget* widget, gpointer data)
|
|
||||||
{
|
|
||||||
waterSetDefinition(_definition);
|
|
||||||
guiUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiWaterInit()
|
|
||||||
{
|
|
||||||
_definition = waterCreateDefinition();
|
|
||||||
|
|
||||||
/* Buttons */
|
|
||||||
g_signal_connect(GET_WIDGET("water_noise_edit"), "clicked", G_CALLBACK(_cbEditNoise), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("water_apply"), "clicked", G_CALLBACK(_cbApplyConfig), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("water_revert"), "clicked", G_CALLBACK(_cbRevertConfig), NULL);
|
|
||||||
|
|
||||||
/* Configs */
|
|
||||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_height")), -20.0, 20.0);
|
|
||||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_transparency")), 0.0, 1.0);
|
|
||||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_reflection")), 0.0, 1.0);
|
|
||||||
gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_transparency_depth")), 0.0, 100.0);
|
|
||||||
|
|
||||||
/* Config signals */
|
|
||||||
g_signal_connect(GET_WIDGET("water_height"), "value-changed", G_CALLBACK(_cbHeightChanged), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("water_transparency"), "value-changed", G_CALLBACK(_cbTransparencyChanged), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("water_transparency_depth"), "value-changed", G_CALLBACK(_cbTransparencyDepthChanged), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("water_reflection"), "value-changed", G_CALLBACK(_cbReflectionChanged), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("water_color"), "color-set", G_CALLBACK(_cbColorChanged), NULL);
|
|
||||||
g_signal_connect(GET_WIDGET("water_color_depth"), "color-set", G_CALLBACK(_cbColorDepthChanged), NULL);
|
|
||||||
|
|
||||||
/* Previews */
|
|
||||||
_preview_coverage = guiPreviewNew(GTK_IMAGE(GET_WIDGET("water_preview_coverage")));
|
|
||||||
guiPreviewConfigScaling(_preview_coverage, 0.01, 1.0, 0.05);
|
|
||||||
guiPreviewConfigScrolling(_preview_coverage, -1000.0, 1000.0, -1000.0, 1000.0);
|
|
||||||
guiPreviewSetViewport(_preview_coverage, 0.0, 0.0, 0.2);
|
|
||||||
guiPreviewSetRenderer(_preview_coverage, _cbPreviewCoverage);
|
|
||||||
_preview_render = guiPreviewNew(GTK_IMAGE(GET_WIDGET("water_preview_render")));
|
|
||||||
guiPreviewConfigScaling(_preview_render, 0.1, 1.0, 0.1);
|
|
||||||
guiPreviewConfigScrolling(_preview_render, -10.0, 10.0, -10.0, 10.0);
|
|
||||||
guiPreviewSetViewport(_preview_render, 0.0, 0.0, 0.5);
|
|
||||||
guiPreviewSetRenderer(_preview_render, _cbPreviewRender);
|
|
||||||
|
|
||||||
guiWaterUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void guiWaterUpdate()
|
|
||||||
{
|
|
||||||
_cbRevertConfig(NULL, NULL);
|
|
||||||
}
|
|
|
@ -80,6 +80,7 @@ void BaseForm::revertConfig()
|
||||||
|
|
||||||
void BaseForm::applyConfig()
|
void BaseForm::applyConfig()
|
||||||
{
|
{
|
||||||
|
revertConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseForm::addPreview(Preview* preview, QString label)
|
void BaseForm::addPreview(Preview* preview, QString label)
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -13,7 +13,7 @@ class DialogNoise : public QDialog
|
||||||
public:
|
public:
|
||||||
explicit DialogNoise(QWidget* parent, NoiseGenerator* noise);
|
explicit DialogNoise(QWidget* parent, NoiseGenerator* noise);
|
||||||
~DialogNoise();
|
~DialogNoise();
|
||||||
|
|
||||||
static bool getNoise(QWidget* parent, NoiseGenerator* noise);
|
static bool getNoise(QWidget* parent, NoiseGenerator* noise);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -32,7 +32,7 @@ private slots:
|
||||||
void levelChanged(int row);
|
void levelChanged(int row);
|
||||||
void heightChanged(int value);
|
void heightChanged(int value);
|
||||||
void scalingChanged(int value);
|
void scalingChanged(int value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NoiseGenerator* _base;
|
NoiseGenerator* _base;
|
||||||
NoiseGenerator* _current;
|
NoiseGenerator* _current;
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -79,42 +112,42 @@ void cameraProjectToFragment(double x, double y, double z, RenderFragment* resul
|
||||||
/**
|
/**
|
||||||
* Render a quad that will fill the view in front of the camera.
|
* Render a quad that will fill the view in front of the camera.
|
||||||
* This quad can be used for post-processing.
|
* This quad can be used for post-processing.
|
||||||
*
|
*
|
||||||
* @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;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
renderPushQuad(&v1, &v2, &v3, &v4);
|
renderPushQuad(&v1, &v2, &v3, &v4);
|
||||||
}
|
}
|
||||||
|
|
41
lib_paysages/camera.h
Normal file
41
lib_paysages/camera.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef _PAYSAGES_CAMERA_H_
|
||||||
|
#define _PAYSAGES_CAMERA_H_
|
||||||
|
|
||||||
|
#include "shared/types.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Vector3 location;
|
||||||
|
Vector3 target;
|
||||||
|
Vector3 up;
|
||||||
|
Matrix4 project;
|
||||||
|
Matrix4 unproject;
|
||||||
|
} CameraDefinition;
|
||||||
|
|
||||||
|
void cameraInit();
|
||||||
|
void cameraSave(FILE* f, CameraDefinition* camera);
|
||||||
|
void cameraLoad(FILE* f, CameraDefinition* camera);
|
||||||
|
|
||||||
|
CameraDefinition cameraCreateDefinition();
|
||||||
|
void cameraDeleteDefinition(CameraDefinition* definition);
|
||||||
|
void cameraCopyDefinition(CameraDefinition* source, CameraDefinition* destination);
|
||||||
|
void cameraValidateDefinition(CameraDefinition* definition);
|
||||||
|
|
||||||
|
void cameraSetLocation(CameraDefinition* camera, double x, double y, double z);
|
||||||
|
void cameraSetTarget(CameraDefinition* camera, double x, double y, double z);
|
||||||
|
void cameraSetAngle(CameraDefinition* camera, double angle);
|
||||||
|
Vector3 cameraProject(CameraDefinition* camera, Vector3 point);
|
||||||
|
Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point);
|
||||||
|
void cameraProjectToFragment(CameraDefinition* camera, double x, double y, double z, RenderFragment* result);
|
||||||
|
void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -9,13 +9,6 @@
|
||||||
#include "shared/constants.h"
|
#include "shared/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)
|
else
|
||||||
{
|
{
|
||||||
noiseNormalizeHeight(destination->noise, -1.0, destination->coverage * 2.0, 0);
|
noiseNormalizeHeight(definition->noise, -(1.0 - definition->coverage) * 2.0, 1.0, 0);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
noiseNormalizeHeight(destination->noise, -(1.0 - destination->coverage) * 2.0, 1.0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CloudsDefinition cloudsGetDefinition(int layer)
|
int cloudsGetLayerCount(CloudsDefinition* definition)
|
||||||
{
|
{
|
||||||
return _layers[layer];
|
return definition->nblayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cloudsSetQuality(CloudsQuality quality)
|
CloudsLayerDefinition* cloudsGetLayer(CloudsDefinition* definition, int layer)
|
||||||
{
|
{
|
||||||
_quality = quality;
|
if (layer >= 0 && layer < definition->nblayers)
|
||||||
|
{
|
||||||
|
return definition->layers + layer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return &NULL_LAYER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CloudsQuality cloudsGetQuality()
|
int cloudsAddLayer(CloudsDefinition* definition)
|
||||||
{
|
{
|
||||||
return _quality;
|
CloudsLayerDefinition* layer;
|
||||||
|
|
||||||
|
if (definition->nblayers < CLOUDS_MAX_LAYERS)
|
||||||
|
{
|
||||||
|
layer = definition->layers + definition->nblayers;
|
||||||
|
layer->noise = noiseCreateGenerator();
|
||||||
|
layer->coverage = 0.0;
|
||||||
|
|
||||||
|
return definition->nblayers++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double _getDistanceToBorder(CloudsDefinition* layer, Vector3 position, double detail)
|
void cloudsDeleteLayer(CloudsDefinition* definition, int layer)
|
||||||
|
{
|
||||||
|
if (layer >= 0 && layer < definition->nblayers)
|
||||||
|
{
|
||||||
|
cloudsLayerDeleteDefinition(definition->layers + layer);
|
||||||
|
if (definition->nblayers > 1 && layer < definition->nblayers - 1)
|
||||||
|
{
|
||||||
|
memmove(definition->layers + layer, definition->layers + layer + 1, sizeof(CloudsLayerDefinition) * (definition->nblayers - layer - 1));
|
||||||
|
}
|
||||||
|
definition->nblayers--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double _getDistanceToBorder(CloudsLayerDefinition* layer, Vector3 position, double detail)
|
||||||
{
|
{
|
||||||
double val, min;
|
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);
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,11 @@ 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;
|
||||||
|
|
||||||
if (distance < _near)
|
if (distance < _near)
|
||||||
{
|
{
|
||||||
return base;
|
return base;
|
||||||
|
@ -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;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
54
lib_paysages/noise.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef _PAYSAGES_NOISE_H_
|
||||||
|
#define _PAYSAGES_NOISE_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct NoiseLevel
|
||||||
|
{
|
||||||
|
double scaling;
|
||||||
|
double height;
|
||||||
|
double xoffset;
|
||||||
|
double yoffset;
|
||||||
|
double zoffset;
|
||||||
|
};
|
||||||
|
typedef struct NoiseLevel NoiseLevel;
|
||||||
|
typedef struct NoiseGenerator NoiseGenerator;
|
||||||
|
|
||||||
|
NoiseGenerator* noiseCreateGenerator();
|
||||||
|
void noiseDeleteGenerator(NoiseGenerator* generator);
|
||||||
|
void noiseSave(NoiseGenerator* perlin, FILE* f);
|
||||||
|
void noiseLoad(NoiseGenerator* perlin, FILE* f);
|
||||||
|
void noiseCopy(NoiseGenerator* source, NoiseGenerator* destination);
|
||||||
|
void noiseGenerateBaseNoise(NoiseGenerator* generator, int size);
|
||||||
|
int noiseGetBaseSize(NoiseGenerator* generator);
|
||||||
|
double noiseGetMaxValue(NoiseGenerator* generator);
|
||||||
|
int noiseGetLevelCount(NoiseGenerator* generator);
|
||||||
|
void noiseClearLevels(NoiseGenerator* generator);
|
||||||
|
void noiseAddLevel(NoiseGenerator* generator, NoiseLevel level);
|
||||||
|
void noiseAddLevelSimple(NoiseGenerator* generator, double scaling, double height);
|
||||||
|
void noiseAddLevels(NoiseGenerator* generator, int level_count, NoiseLevel start_level, double scaling_factor, double height_factor, int randomize_offset);
|
||||||
|
void noiseAddLevelsSimple(NoiseGenerator* generator, int level_count, double scaling, double height);
|
||||||
|
void noiseRemoveLevel(NoiseGenerator* generator, int level);
|
||||||
|
int noiseGetLevel(NoiseGenerator* generator, int level, NoiseLevel* params);
|
||||||
|
void noiseSetLevel(NoiseGenerator* generator, int level, NoiseLevel params);
|
||||||
|
void noiseSetLevelSimple(NoiseGenerator* generator, int level, double scaling, double height);
|
||||||
|
void noiseNormalizeHeight(NoiseGenerator* generator, double min_height, double max_height, int adjust_scaling);
|
||||||
|
double noiseGet1DLevel(NoiseGenerator* generator, int level, double x);
|
||||||
|
double noiseGet1DTotal(NoiseGenerator* generator, double x);
|
||||||
|
double noiseGet1DDetail(NoiseGenerator* generator, double x, double detail);
|
||||||
|
double noiseGet2DLevel(NoiseGenerator* generator, int level, double x, double y);
|
||||||
|
double noiseGet2DTotal(NoiseGenerator* generator, double x, double y);
|
||||||
|
double noiseGet2DDetail(NoiseGenerator* generator, double x, double y, double detail);
|
||||||
|
double noiseGet3DLevel(NoiseGenerator* generator, int level, double x, double y, double z);
|
||||||
|
double noiseGet3DTotal(NoiseGenerator* generator, double x, double y, double z);
|
||||||
|
double noiseGet3DDetail(NoiseGenerator* generator, double x, double y, double z, double detail);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -108,16 +108,21 @@ void renderSetSize(int width, int height)
|
||||||
_cb_preview_clear(background_color);
|
_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
19
lib_paysages/renderer.c
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include "renderer.h"
|
||||||
|
#include "shared/constants.h"
|
||||||
|
|
||||||
|
static Color _fakeFilterLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light)
|
||||||
|
{
|
||||||
|
return light_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer rendererGetFake()
|
||||||
|
{
|
||||||
|
Renderer result;
|
||||||
|
|
||||||
|
result.render_quality = 5;
|
||||||
|
result.camera_location = VECTOR_ZERO;
|
||||||
|
|
||||||
|
result.filterLight = _fakeFilterLight;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
31
lib_paysages/renderer.h
Normal file
31
lib_paysages/renderer.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef _PAYSAGES_RENDERER_H_
|
||||||
|
#define _PAYSAGES_RENDERER_H_
|
||||||
|
|
||||||
|
#include "shared/types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct Renderer Renderer;
|
||||||
|
|
||||||
|
struct Renderer
|
||||||
|
{
|
||||||
|
/* Quality configuration */
|
||||||
|
int render_quality;
|
||||||
|
Vector3 camera_location;
|
||||||
|
|
||||||
|
/* Lighting related */
|
||||||
|
Color (*filterLight)(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light);
|
||||||
|
|
||||||
|
/* Custom data */
|
||||||
|
void* customData[10];
|
||||||
|
};
|
||||||
|
|
||||||
|
Renderer rendererGetFake();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
197
lib_paysages/scenery.c
Normal file
197
lib_paysages/scenery.c
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
#include "scenery.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
CameraDefinition _camera;
|
||||||
|
CloudsDefinition _clouds;
|
||||||
|
LightingDefinition _lighting;
|
||||||
|
SkyDefinition _sky;
|
||||||
|
TerrainDefinition _terrain;
|
||||||
|
TexturesDefinition _textures;
|
||||||
|
WaterDefinition _water;
|
||||||
|
|
||||||
|
static Color _filterLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light)
|
||||||
|
{
|
||||||
|
Color result;
|
||||||
|
|
||||||
|
result = waterLightFilter(&_water, renderer, light_color, at_location, light_location, direction_to_light);
|
||||||
|
result = terrainLightFilter(&_terrain, renderer, result, at_location, light_location, direction_to_light);
|
||||||
|
// TODO atmosphere filter
|
||||||
|
// TODO clouds filter
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RayCastingResult _reflectionFunction(Vector3 start, Vector3 direction)
|
||||||
|
{
|
||||||
|
RayCastingResult result;
|
||||||
|
|
||||||
|
if (!terrainProjectRay(start, direction, &result.hit_location, &result.hit_color))
|
||||||
|
{
|
||||||
|
result.hit_color = skyProjectRay(start, direction);
|
||||||
|
/* TODO hit_location */
|
||||||
|
}
|
||||||
|
|
||||||
|
result.hit = 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RayCastingResult _refractionFunction(Vector3 start, Vector3 direction)
|
||||||
|
{
|
||||||
|
RayCastingResult result;
|
||||||
|
|
||||||
|
result.hit = terrainProjectRay(start, direction, &result.hit_location, &result.hit_color);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sceneryInit()
|
||||||
|
{
|
||||||
|
cameraInit();
|
||||||
|
cloudsInit();
|
||||||
|
lightingInit();
|
||||||
|
skyInit();
|
||||||
|
terrainInit();
|
||||||
|
texturesInit();
|
||||||
|
waterInit();
|
||||||
|
|
||||||
|
_camera = cameraCreateDefinition();
|
||||||
|
_clouds = cloudsCreateDefinition();
|
||||||
|
_lighting = lightingCreateDefinition();
|
||||||
|
_sky = skyCreateDefinition();
|
||||||
|
_terrain = terrainCreateDefinition();
|
||||||
|
_textures = texturesCreateDefinition();
|
||||||
|
_water = waterCreateDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
void scenerySaveToFile(char* filepath)
|
||||||
|
{
|
||||||
|
FILE* f = fopen(filepath, "wb");
|
||||||
|
|
||||||
|
cameraSave(f, &_camera);
|
||||||
|
cloudsSave(f, &_clouds);
|
||||||
|
lightingSave(f, &_lighting);
|
||||||
|
skySave(f, &_sky);
|
||||||
|
terrainSave(f, &_terrain);
|
||||||
|
texturesSave(f, &_textures);
|
||||||
|
waterSave(f, &_water);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sceneryLoadFromFile(char* filepath)
|
||||||
|
{
|
||||||
|
FILE* f = fopen(filepath, "rb");
|
||||||
|
|
||||||
|
/* TODO Use intermediary definitions ? */
|
||||||
|
|
||||||
|
cameraLoad(f, &_camera);
|
||||||
|
cameraValidateDefinition(&_camera);
|
||||||
|
|
||||||
|
cloudsLoad(f, &_clouds);
|
||||||
|
cloudsValidateDefinition(&_clouds);
|
||||||
|
|
||||||
|
lightingLoad(f, &_lighting);
|
||||||
|
lightingValidateDefinition(&_lighting);
|
||||||
|
|
||||||
|
skyLoad(f, &_sky);
|
||||||
|
skyValidateDefinition(&_sky);
|
||||||
|
|
||||||
|
terrainLoad(f, &_terrain);
|
||||||
|
terrainValidateDefinition(&_terrain);
|
||||||
|
|
||||||
|
texturesLoad(f, &_textures);
|
||||||
|
texturesValidateDefinition(&_textures);
|
||||||
|
|
||||||
|
waterLoad(f, &_water);
|
||||||
|
waterValidateDefinition(&_water);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scenerySetCamera(CameraDefinition* camera)
|
||||||
|
{
|
||||||
|
cameraCopyDefinition(camera, &_camera);
|
||||||
|
cameraValidateDefinition(&_camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sceneryGetCamera(CameraDefinition* camera)
|
||||||
|
{
|
||||||
|
cameraCopyDefinition(&_camera, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scenerySetClouds(CloudsDefinition* clouds)
|
||||||
|
{
|
||||||
|
cloudsCopyDefinition(clouds, &_clouds);
|
||||||
|
cloudsValidateDefinition(&_clouds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sceneryGetClouds(CloudsDefinition* clouds)
|
||||||
|
{
|
||||||
|
cloudsCopyDefinition(_clouds, clouds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scenerySetLighting(LightingDefinition* lighting)
|
||||||
|
{
|
||||||
|
lightingCopyDefinition(lighting, &_lighting);
|
||||||
|
lightingValidateDefinition(&_lighting);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sceneryGetLighting(LightingDefinition* lighting)
|
||||||
|
{
|
||||||
|
lightingCopyDefinition(&_lighting, lighting);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scenerySetSky(SkyDefinition* sky)
|
||||||
|
{
|
||||||
|
skyCopyDefinition(sky, &_sky);
|
||||||
|
skyValidateDefinition(&_sky);
|
||||||
|
|
||||||
|
lightingValidateDefinition(&_lighting);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sceneryGetSky(SkyDefinition* sky)
|
||||||
|
{
|
||||||
|
skyCopyDefinition(&_sky, sky);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scenerySetTerrain(TerrainDefinition* terrain)
|
||||||
|
{
|
||||||
|
terrainCopyDefinition(terrain, &_terrain);
|
||||||
|
terrainValidateDefinition(&_terrain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sceneryGetTerrain(TerrainDefinition* terrain)
|
||||||
|
{
|
||||||
|
terrainCopyDefinition(&_terrain, terrain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scenerySetTextures(TexturesDefinition* textures)
|
||||||
|
{
|
||||||
|
texturesCopyDefinition(textures, &_textures);
|
||||||
|
texturesValidateDefinition(&_textures);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sceneryGetTextures(TexturesDefinition* textures)
|
||||||
|
{
|
||||||
|
texturesCopyDefinition(&_textures, textures);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scenerySetWater(WaterDefinition* water)
|
||||||
|
{
|
||||||
|
waterCopyDefinition(water, &_water);
|
||||||
|
waterValidateDefinition(&_water);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sceneryGetWater(WaterDefinition* water)
|
||||||
|
{
|
||||||
|
waterCopyDefinition(&_water, water);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer sceneryGetStandardRenderer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void sceneryRender()
|
||||||
|
{
|
||||||
|
}
|
57
lib_paysages/scenery.h
Normal file
57
lib_paysages/scenery.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#ifndef _PAYSAGES_SCENERY_H_
|
||||||
|
#define _PAYSAGES_SCENERY_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scenery management.
|
||||||
|
*
|
||||||
|
* This module handles all scenery components (terrain, water...) definitions and maintains
|
||||||
|
* a standard renderer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
|
#include "clouds.h"
|
||||||
|
#include "lighting.h"
|
||||||
|
#include "sky.h"
|
||||||
|
#include "terrain.h"
|
||||||
|
#include "textures.h"
|
||||||
|
#include "water.h"
|
||||||
|
|
||||||
|
#include "renderer.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void sceneryInit();
|
||||||
|
void scenerySaveToFile(char* filepath);
|
||||||
|
void sceneryLoadFromFile(char* filepath);
|
||||||
|
|
||||||
|
void scenerySetCamera(CameraDefinition* camera);
|
||||||
|
void sceneryGetCamera(CameraDefinition* camera);
|
||||||
|
|
||||||
|
void scenerySetClouds(CloudsDefinition* clouds);
|
||||||
|
void sceneryGetClouds(CloudsDefinition* clouds);
|
||||||
|
|
||||||
|
void scenerySetLighting(LightingDefinition* lighting);
|
||||||
|
void sceneryGetLighting(LightingDefinition* lighting);
|
||||||
|
|
||||||
|
void scenerySetSky(SkyDefinition* sky);
|
||||||
|
void sceneryGetSky(SkyDefinition* sky);
|
||||||
|
|
||||||
|
void scenerySetTerrain(TerrainDefinition* terrain);
|
||||||
|
void sceneryGetTerrain(TerrainDefinition* terrain);
|
||||||
|
|
||||||
|
void scenerySetTextures(TexturesDefinition* textures);
|
||||||
|
void sceneryGetTextures(TexturesDefinition* textures);
|
||||||
|
|
||||||
|
void scenerySetWater(WaterDefinition* water);
|
||||||
|
void sceneryGetWater(WaterDefinition* water);
|
||||||
|
|
||||||
|
Renderer sceneryGetStandardRenderer();
|
||||||
|
void sceneryRender();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -25,22 +25,10 @@ void arrayClear(Array* array);
|
||||||
void autoInit();
|
void 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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terrainValidateDefinition(destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
void terrainSetDefinition(TerrainDefinition definition)
|
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,27 +127,22 @@ 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)
|
||||||
|
{
|
||||||
|
memmove(definition->height_modifiers + modifier_position, definition->height_modifiers + modifier_position + 1, sizeof(HeightModifier*) * (definition->height_modifiers_count - modifier_position - 1));
|
||||||
|
}
|
||||||
|
definition->height_modifiers_count--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void terrainSetQuality(TerrainQuality quality)
|
|
||||||
{
|
|
||||||
_quality = quality;
|
|
||||||
}
|
|
||||||
|
|
||||||
TerrainQuality terrainGetQuality()
|
|
||||||
{
|
|
||||||
return _quality;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline double _getHeight(TerrainDefinition* definition, double x, double z, double detail)
|
static inline double _getHeight(TerrainDefinition* definition, double x, double z, double detail)
|
||||||
{
|
{
|
||||||
Vector3 location;
|
Vector3 location;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
int texturesGetLayerCount()
|
TexturesDefinition texturesCreateDefinition()
|
||||||
{
|
{
|
||||||
return _textures_count;
|
TexturesDefinition result;
|
||||||
|
|
||||||
|
result.nbtextures = 0;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int texturesAddLayer()
|
void texturesDeleteDefinition(TexturesDefinition* definition)
|
||||||
{
|
{
|
||||||
if (_textures_count < TEXTURES_MAX)
|
while (definition->nbtextures > 0)
|
||||||
{
|
{
|
||||||
_textures[_textures_count] = texturesCreateDefinition();
|
texturesDeleteLayer(definition, 0);
|
||||||
|
|
||||||
return _textures_count++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void texturesDeleteLayer(int layer)
|
void texturesCopyDefinition(TexturesDefinition* source, TexturesDefinition* destination)
|
||||||
{
|
{
|
||||||
if (layer >= 0 && layer < _textures_count)
|
TextureLayerDefinition* layer;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while (destination->nbtextures > 0)
|
||||||
{
|
{
|
||||||
zoneDelete(_textures[layer].zone);
|
texturesDeleteLayer(destination, 0);
|
||||||
noiseDeleteGenerator(_textures[layer].bump_noise);
|
}
|
||||||
if (_textures_count > 1 && layer < _textures_count - 1)
|
for (i = 0; i < source->nbtextures; i++)
|
||||||
{
|
{
|
||||||
memmove(_textures + layer, _textures + layer + 1, sizeof(TextureDefinition) * (_textures_count - layer - 1));
|
layer = texturesGetLayer(destination, texturesAddLayer(destination));
|
||||||
}
|
texturesLayerCopyDefinition(source->textures + i, layer);
|
||||||
_textures_count--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureDefinition texturesCreateDefinition()
|
void texturesValidateDefinition(TexturesDefinition* definition)
|
||||||
{
|
{
|
||||||
TextureDefinition result;
|
int i;
|
||||||
|
for (i = 0; i < definition->nbtextures; i++)
|
||||||
|
{
|
||||||
|
texturesLayerValidateDefinition(definition->textures + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureLayerDefinition texturesLayerCreateDefinition()
|
||||||
|
{
|
||||||
|
TextureLayerDefinition result;
|
||||||
|
|
||||||
result.zone = zoneCreate();
|
result.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)
|
||||||
|
{
|
||||||
|
return definition->nbtextures;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureLayerDefinition* texturesGetLayer(TexturesDefinition* definition, int layer)
|
||||||
|
{
|
||||||
|
if (layer >= 0 && layer < definition->nbtextures)
|
||||||
{
|
{
|
||||||
destination = _textures + layer;
|
return definition->textures + layer;
|
||||||
texturesCopyDefinition(definition, destination);
|
}
|
||||||
|
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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue