paysages : Refactoring terrain and textures - WIP.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@206 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-01-03 15:40:50 +00:00 committed by ThunderK
parent 73f15a44f7
commit 9a580dcf7d
24 changed files with 486 additions and 303 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 716 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 728 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 B

View file

@ -2,8 +2,11 @@
#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)
{
@ -12,19 +15,24 @@ static Color _cbPreviewRenderPixel(SmallPreview* preview, double x, double y, do
result.r = result.g = result.b = terrainGetHeightNormalized(x, y);
result.a = 1.0;
/* TEMP */
//result = terrainGetColor(x, y, 0.01);
return result;
}
static void _cbEditNoiseDone(NoiseGenerator* generator)
{
terrainSetNoiseGenerator(generator);
noiseCopy(generator, _definition.height_noise);
terrainSetDefinition(_definition);
/* TODO Redraw only affected by terrain */
guiPreviewRedrawAll();
}
static void _cbEditNoise(GtkWidget* widget, gpointer data)
{
guiNoiseEdit(terrainGetNoiseGenerator(), _cbEditNoiseDone);
guiNoiseEdit(texturesGetDefinition(0).bump_noise, _cbEditNoiseDone);
}
void guiTerrainInit()

View file

@ -4,6 +4,7 @@
#include <QColor>
#include <math.h>
#include "../lib_paysages/terrain.h"
#include "../lib_paysages/water.h"
#include "../lib_paysages/shared/functions.h"
#include "../lib_paysages/shared/constants.h"

View file

@ -82,7 +82,7 @@
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value>
<value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/michael/coding/paysages/gui_qt</value>
<value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/michael/workspace/paysages/gui_qt</value>
<value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">3</value>
<value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-32bit.</value>
<value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">false</value>
@ -133,9 +133,7 @@
<value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">paysages-qt.pro</value>
<value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value>
<value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value>
<valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList">
<value type="QString">LD_LIBRARY_PATH=../lib_paysages</value>
</valuelist>
<valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
<value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value>
<value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value>
<value key="RunConfiguration.UseCppDebugger" type="bool">true</value>
@ -150,7 +148,7 @@
</data>
<data>
<variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
<value type="QString">{8abe6662-5ded-4243-9d4d-dbf8a3c19b83}</value>
<value type="QString">{d5145163-5b06-43da-aefd-e689d7a52ef8}</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>

View file

@ -12,6 +12,8 @@
#include "water.h"
#include "clouds.h"
#include "sky.h"
#include "terrain.h"
#include "textures.h"
static int _cpu_count = 1;
static int _is_rendering = 0;
@ -100,6 +102,7 @@ void autoSetDaytimeFraction(double daytime)
void autoSetRenderQuality(int quality)
{
TerrainQuality terrain;
WaterQuality water;
CloudsQuality clouds;
@ -114,7 +117,9 @@ void autoSetRenderQuality(int quality)
renderSetQuality(quality);
terrainSetChunkSize(0.1 / (double)render_quality, 0.05 / (double)render_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;
@ -126,14 +131,14 @@ void autoSetRenderQuality(int quality)
void autoGenRealisticLandscape(int seed)
{
Texture* tex;
TerrainDefinition terrain;
WaterDefinition water;
CloudsDefinition cloud;
SkyDefinition sky;
TextureDefinition texture;
int layer;
HeightModifier* mod;
Zone* zone;
NoiseGenerator* noise;
if (!seed)
{
@ -166,7 +171,7 @@ void autoGenRealisticLandscape(int seed)
noiseAddLevelSimple(cloud.noise, 50.0 / 800.0, 0.001);
noiseAddLevelSimple(cloud.noise, 50.0 / 1000.0, 0.0005);
layer = cloudsAddLayer();
cloudsSetDefinition(layer, cloud);
//cloudsSetDefinition(layer, cloud);
/* Water */
water.height = 0.0;
@ -215,14 +220,22 @@ void autoGenRealisticLandscape(int seed)
sky.sun_radius = 0.02;
skySetDefinition(sky);
noise = noiseCreateGenerator();
noiseGenerateBaseNoise(noise, 1048576);
noiseAddLevelsSimple(noise, 10, 10.0, 1.0);
noiseNormalizeHeight(noise, -12.0, 12.0, 0);
terrainSetNoiseGenerator(noise);
noiseDeleteGenerator(noise);
terrain = terrainCreateDefinition();
noiseGenerateBaseNoise(terrain.height_noise, 1048576);
noiseAddLevelsSimple(terrain.height_noise, 8, 10.0, 1.0);
noiseNormalizeHeight(terrain.height_noise, -12.0, 12.0, 0);
terrainSetDefinition(terrain);
terrainDeleteDefinition(terrain);
tex = textureCreateFromFile("./data/textures/rock3.jpg");
layer = texturesAddLayer();
texture = texturesCreateDefinition();
noiseGenerateBaseNoise(texture.bump_noise, 102400);
noiseAddLevelsSimple(texture.bump_noise, 6, 0.01, 0.01);
texture.color = COLOR_WHITE;
texturesSetDefinition(layer, texture);
texturesDeleteDefinition(texture);
/*tex = textureCreateFromFile("./data/textures/rock3.jpg");
tex->scaling_x = 0.003;
tex->scaling_y = 0.003;
tex->scaling_z = 0.003;
@ -236,7 +249,7 @@ void autoGenRealisticLandscape(int seed)
zone = zoneCreate(0.0);
zoneAddHeightRange(zone, 1.0, -1.0, 0.0, 3.0, 15.0);
zoneAddSteepnessRange(zone, 1.0, 0.0, 0.0, 0.3, 0.4);
terrainAddTexture(tex, 0.15, zone, 0.05);
terrainAddTexture(tex, 0.15, zone, 0.05);*/
/*tex = textureCreateFromFile("./data/textures/snow1.jpg");
tex->scaling_x = 0.001;
@ -247,7 +260,7 @@ void autoGenRealisticLandscape(int seed)
terrainAddTexture(tex, 0.5, zone, 0.1);*/
/* DEBUG */
mod = modifierCreate();
/*mod = modifierCreate();
zone = modifierGetZone(mod);
zoneIncludeCircleArea(zone, 0.4, 0.0, 0.0, 8.0, 20.0);
modifierActionFixValue(mod, -2.0);
@ -261,7 +274,7 @@ void autoGenRealisticLandscape(int seed)
zone = modifierGetZone(mod);
zoneIncludeCircleArea(zone, 0.8, 0.0, 0.0, 0.3, 4.0);
modifierActionFixValue(mod, -8.0);
terrainAddModifier(mod);
terrainAddModifier(mod);*/
fogSetDistance(20.0, 100.0);
}

View file

@ -51,6 +51,8 @@ void cloudsLoad(FILE* f)
int i;
CloudsDefinition* layer;
/* FIXME Delete unused noise generators and add missing ones */
_layers_count = toolsLoadInt(f);
for (i = 0; i < _layers_count; i++)
{

View file

@ -11,6 +11,7 @@
#include "shared/constants.h"
#include "shared/functions.h"
#include "shared/globals.h"
#include "terrain.h"
void paysagesInit()
{
@ -25,4 +26,17 @@ void paysagesInit()
autoSetRenderQuality(5);
autoGenRealisticLandscape(0);
autoSetDaytime(8, 30);
// DEBUG
double last_height, height, x;
last_height = height = 0.0;
x = 0.0;
while (height <= 1.0 || height >= last_height || last_height < 0.1)
{
last_height = height;
height = terrainGetHeight(x, 0.0);
x += 0.1;
}
cameraSetLocation(x - 2.0, height, 0.0);
cameraSetTarget(x - 1.0, height, 0.0);
}

View file

@ -172,28 +172,6 @@ Color skyProjectRay(Vector3 start, Vector3 direction);
void skySetGradation(ColorGradation grad);
void skyRender(RenderProgressCallback callback);
/* terrain.c */
void terrainSave(FILE* f);
void terrainLoad(FILE* f);
void terrainInit();
NoiseGenerator* terrainGetNoiseGenerator();
void terrainSetNoiseGenerator(NoiseGenerator* generator);
void terrainAddTexture(Texture* tex, double subsurf_scale, Zone* zone, double border_scaling);
void terrainAddModifier(HeightModifier* modifier);
double terrainGetHeight(double x, double z);
double terrainGetHeightNormalized(double x, double z);
Color terrainGetColor(double x, double z, double precision);
double terrainGetShadow(Vector3 start, Vector3 direction);
int terrainProjectRay(Vector3 start, Vector3 direction, Vector3* hit_point, Color* hit_color);
void terrainSetChunkSize(double min_size, double visible_size);
void terrainRender(RenderProgressCallback callback);
/* textures.c */
void texturesSave(FILE* f);
void texturesLoad(FILE* f);
Texture* textureCreateFromFile(const char* filename);
Color textureApply(Texture* tex, Vector3 location, Vector3 normal);
/* tools.c */
double toolsRandom();
double toolsBicubicInterpolate(double stencil[16], double x, double y);
@ -209,6 +187,7 @@ Zone* zoneCreate();
void zoneDelete(Zone* zone);
void zoneSave(Zone* zone, FILE* f);
void zoneLoad(Zone* zone, FILE* f);
void zoneCopy(Zone* source, Zone* destination);
void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius);
void zoneExcludeCircleArea(Zone* zone, double centerx, double centerz, double softradius, double hardradius);
void zoneAddHeightRange(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax);

View file

@ -87,16 +87,6 @@ typedef struct
void* data;
} Array;
typedef struct {
void* pixels;
int bytes_per_pixel;
int picture_width;
int picture_height;
double scaling_x;
double scaling_y;
double scaling_z;
} Texture;
struct NoiseLevel
{
double scaling;

View file

@ -6,118 +6,103 @@
#include "shared/globals.h"
#include "shared/constants.h"
#include "textures.h"
#include "water.h"
#include "terrain.h"
#define MAX_TEXTURES 10
#define MAX_MODIFIERS 50
typedef struct {
Texture* tex;
double subsurf_scale;
Zone* zone;
double border_scaling;
} TerrainTexture;
static NoiseGenerator* _noise_height;
static NoiseGenerator* _noise_texture_borders;
static TerrainDefinition _definition;
static TerrainQuality _quality;
static TerrainEnvironment _environment;
static double _max_height = 1.0;
static double _base_chunk_size = 1.0, _visible_chunk_size = 1.0;
static int _texture_count = 0;
static TerrainTexture _textures[MAX_TEXTURES];
static int _modifiers_count = 0;
static HeightModifier* _modifiers[MAX_MODIFIERS];
void terrainInit()
{
_definition = terrainCreateDefinition();
_max_height = noiseGetMaxValue(_definition.height_noise);
}
void terrainSave(FILE* f)
{
noiseSave(_noise_height, f);
noiseSave(_noise_texture_borders, f);
noiseSave(_definition.height_noise, f);
toolsSaveDouble(f, _max_height);
toolsSaveDouble(f, _base_chunk_size);
toolsSaveDouble(f, _visible_chunk_size);
/* TODO Textures */
/* TODO Modifiers */
}
void terrainLoad(FILE* f)
{
noiseLoad(_noise_height, f);
noiseLoad(_noise_texture_borders, f);
_max_height = toolsLoadDouble(f);
_base_chunk_size = toolsLoadDouble(f);
_visible_chunk_size = toolsLoadDouble(f);
noiseLoad(_definition.height_noise, f);
_max_height = noiseGetMaxValue(_definition.height_noise);
}
void terrainInit()
TerrainDefinition terrainCreateDefinition()
{
_noise_height = noiseCreateGenerator();
_max_height = noiseGetMaxValue(_noise_height);
TerrainDefinition definition;
_noise_texture_borders = noiseCreateGenerator();
noiseGenerateBaseNoise(_noise_texture_borders, 100);
noiseAddLevelsSimple(_noise_texture_borders, 10, 1.0, 1.0);
noiseNormalizeHeight(_noise_texture_borders, 0.0, 1.0, 0);
definition.height_noise = noiseCreateGenerator();
return definition;
}
NoiseGenerator* terrainGetNoiseGenerator()
void terrainDeleteDefinition(TerrainDefinition definition)
{
return _noise_height;
noiseDeleteGenerator(definition.height_noise);
}
void terrainSetNoiseGenerator(NoiseGenerator* generator)
void terrainCopyDefinition(TerrainDefinition source, TerrainDefinition* destination)
{
noiseCopy(generator, _noise_height);
_max_height = noiseGetMaxValue(_noise_height);
/* FIXME Max height depends on modifiers*/
noiseCopy(source.height_noise, destination->height_noise);
}
void terrainAddTexture(Texture* tex, double subsurf_scale, Zone* zone, double border_scaling)
void terrainSetDefinition(TerrainDefinition definition)
{
TerrainTexture ttex;
if (_texture_count < MAX_TEXTURES)
{
ttex.tex = tex;
ttex.subsurf_scale = subsurf_scale;
ttex.zone = zone;
ttex.border_scaling = border_scaling;
_textures[_texture_count++] = ttex;
}
terrainCopyDefinition(definition, &_definition);
_max_height = noiseGetMaxValue(_definition.height_noise);
/* FIXME _max_height depends on modifiers */
}
void terrainAddModifier(HeightModifier* modifier)
TerrainDefinition terrainGetDefinition()
{
if (_modifiers_count < MAX_MODIFIERS)
{
_modifiers[_modifiers_count++] = modifier;
}
return _definition;
}
static inline double _getHeight(double x, double z, double precision)
void terrainSetQuality(TerrainQuality quality)
{
_quality = quality;
}
TerrainQuality terrainGetQuality()
{
return _quality;
}
static inline double _getHeight(TerrainDefinition* definition, double x, double z, double detail)
{
Vector3 location;
int i;
/*int i;*/
location.x = x;
location.y = noiseGet2DDetail(_noise_height, x, z, precision);
location.y = noiseGet2DDetail(definition->height_noise, x, z, detail);
location.z = z;
for (i = 0; i < _modifiers_count; i++)
/*for (i = 0; i < _modifiers_count; i++)
{
location = modifierApply(_modifiers[i], location);
}
}*/
return location.y;
}
static inline Vector3 _getPoint(double x, double z, double precision)
static inline Vector3 _getPoint(TerrainDefinition* definition, double x, double z, double detail)
{
Vector3 result;
result.x = x;
result.y = _getHeight(x, z, precision);
result.y = _getHeight(definition, x, z, detail);
result.z = z;
return result;
@ -143,7 +128,7 @@ double terrainGetShadow(Vector3 start, Vector3 direction)
inc_vector = v3Scale(direction, inc_value);
length += v3Norm(inc_vector);
start = v3Add(start, inc_vector);
height = _getHeight(start.x, start.z, inc_value);
height = _getHeight(&_definition, start.x, start.z, inc_value);
diff = start.y - height;
if (diff < 0.0)
{
@ -175,78 +160,12 @@ double terrainGetShadow(Vector3 start, Vector3 direction)
}
}
static inline Vector3 _getNormal(Vector3 point, double scale)
static Color _getColor(TerrainDefinition* definition, Vector3 point, double precision)
{
Vector3 dpoint, ref, normal;
ref.x = 0.0;
ref.y = 0.0;
dpoint = _getPoint(point.x - scale, point.z, scale * 0.3);
ref.z = -1.0;
normal = v3Normalize(v3Cross(ref, v3Sub(dpoint, point)));
dpoint = _getPoint(point.x + scale, point.z, scale * 0.3);
ref.z = 1.0;
normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point))));
ref.z = 0.0;
dpoint = _getPoint(point.x, point.z - scale, scale * 0.3);
ref.x = 1.0;
normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point))));
dpoint = _getPoint(point.x, point.z + scale, scale * 0.3);
ref.x = -1.0;
normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point))));
return v3Normalize(normal);
}
static Color _getColor(Vector3 point, double precision)
{
Vector3 normal;
Color color, tex_color;
int i;
double shadowed, coverage, value;
shadowed = terrainGetShadow(point, sun_direction_inv);
/* Apply textures and subsurface lighting */
color = COLOR_GREEN;
for (i = 0; i < _texture_count; i++)
{
/* TODO Don't recalculate normals for same precision */
/* TODO Don't compute textures that will be totally covered */
normal = _getNormal(point, precision * _textures[i].subsurf_scale);
coverage = zoneGetValue(_textures[i].zone, point, normal);
if (coverage > 0.0)
{
if (coverage < 1.0)
{
value = noiseGet2DTotal(_noise_texture_borders, point.x / _textures[i].border_scaling, point.z / _textures[i].border_scaling);
if (value < coverage)
{
/* TODO Make smoothness precision-dependant */
value = (coverage - value) / 0.1;
coverage = (value > 1.0) ? 1.0 : value;
}
else
{
coverage = 0.0;
}
}
if (coverage > 0.0)
{
tex_color = textureApply(_textures[i].tex, point, normal);
tex_color = lightingApply(point, normal, shadowed, tex_color, 0.1, 0.1);
tex_color.a = coverage;
colorMask(&color, &tex_color);
}
}
}
Color color;
/* FIXME Environment for textures should be customized */
color = texturesGetColor(point);
color = fogApplyToLocation(point, color);
//color = cloudsApplySegmentResult(color, camera_location, point);
@ -269,13 +188,13 @@ int terrainProjectRay(Vector3 start, Vector3 direction, Vector3* hit_point, Colo
inc_vector = v3Scale(direction, inc_value);
length += v3Norm(inc_vector);
start = v3Add(start, inc_vector);
height = _getHeight(start.x, start.z, inc_value);
height = _getHeight(&_definition, start.x, start.z, inc_value);
diff = start.y - height;
if (diff < 0.0)
{
start.y = height;
*hit_point = start;
*hit_color = _getColor(start, inc_value);
*hit_color = _getColor(&_definition, start, inc_value);
return 1;
}
@ -304,19 +223,19 @@ static int _postProcessFragment(RenderFragment* fragment)
point = fragment->vertex.location;
precision = renderGetPrecision(point);
point = _getPoint(point.x, point.z, precision);
point = _getPoint(&_definition, point.x, point.z, precision);
fragment->vertex.color = _getColor(point, precision);
fragment->vertex.color = _getColor(&_definition, point, precision);
return 1;
}
static Vertex _getFirstPassVertex(double x, double z, double precision)
static Vertex _getFirstPassVertex(double x, double z, double detail)
{
Vertex result;
double value;
result.location = _getPoint(x, z, 0.0);
result.location = _getPoint(&_definition, x, z, 0.0);
value = sin(x) * sin(x) * cos(z) * cos(z);
result.color.r = value;
result.color.g = value;
@ -341,23 +260,22 @@ static void _renderQuad(double x, double z, double size)
double terrainGetHeight(double x, double z)
{
return _getHeight(x, z, 0.01 / (double)render_quality);
return _getHeight(&_definition, x, z, 0.01 / (double)render_quality);
}
double terrainGetHeightNormalized(double x, double z)
{
return 0.5 + _getHeight(x, z, 0.01 / (double)render_quality) / (_max_height * 2.0);
return 0.5 + _getHeight(&_definition, x, z, 0.01 / (double)render_quality) / (_max_height * 2.0);
}
Color terrainGetColor(double x, double z, double precision)
Color terrainGetColorCustom(double x, double z, double detail, TerrainDefinition* definition, TerrainQuality* quality, TerrainEnvironment* environment)
{
return _getColor(_getPoint(x, z, precision), precision);
return _getColor(definition, _getPoint(definition, x, z, detail), detail);
}
void terrainSetChunkSize(double min_size, double visible_size)
Color terrainGetColor(double x, double z, double detail)
{
_base_chunk_size = min_size;
_visible_chunk_size = visible_size;
return terrainGetColorCustom(x, z, detail, &_definition, &_quality, &_environment);
}
void terrainRender(RenderProgressCallback callback)
@ -370,8 +288,8 @@ void terrainRender(RenderProgressCallback callback)
chunk_factor = 1;
chunk_count = 2;
radius_int = 0.0;
radius_ext = _base_chunk_size;
chunk_size = _base_chunk_size;
radius_ext = _quality.min_chunk_size;
chunk_size = _quality.min_chunk_size;
while (radius_ext < 1000.0)
{
@ -388,14 +306,14 @@ void terrainRender(RenderProgressCallback callback)
_renderQuad(cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size);
}
if (chunk_count % 64 == 0 && chunk_size / radius_int < _visible_chunk_size)
if (chunk_count % 64 == 0 && chunk_size / radius_int < _quality.visible_chunk_size)
{
chunk_count /= 2;
chunk_factor *= 2;
/* TODO Fill in gaps with triangles */
}
chunk_count += 2;
chunk_size = _base_chunk_size * chunk_factor;
chunk_size = _quality.min_chunk_size * chunk_factor;
radius_int = radius_ext;
radius_ext += chunk_size;
}

54
lib_paysages/terrain.h Normal file
View file

@ -0,0 +1,54 @@
#ifndef _PAYSAGES_TERRAIN_H_
#define _PAYSAGES_TERRAIN_H_
#include "shared/types.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
NoiseGenerator* height_noise;
} TerrainDefinition;
typedef struct
{
double min_chunk_size;
double visible_chunk_size;
} TerrainQuality;
typedef struct
{
int unused;
} TerrainEnvironment;
void terrainInit();
void terrainSave(FILE* f);
void terrainLoad(FILE* f);
TerrainDefinition terrainCreateDefinition();
void terrainDeleteDefinition(TerrainDefinition definition);
void terrainCopyDefinition(TerrainDefinition source, TerrainDefinition* destination);
void terrainSetDefinition(TerrainDefinition definition);
TerrainDefinition terrainGetDefinition();
void terrainSetQuality(TerrainQuality quality);
TerrainQuality terrainGetQuality();
double terrainGetShadow(Vector3 start, Vector3 direction);
int terrainProjectRay(Vector3 start, Vector3 direction, Vector3* hit_point, Color* hit_color);
double terrainGetHeightCustom(double x, double z, TerrainDefinition* definition);
double terrainGetHeight(double x, double z);
double terrainGetHeightNormalizedCustom(double x, double z, TerrainDefinition* definition);
double terrainGetHeightNormalized(double x, double z);
Color terrainGetColorCustom(double x, double z, double detail, TerrainDefinition* definition, TerrainQuality* quality, TerrainEnvironment* environment);
Color terrainGetColor(double x, double z, double detail);
void terrainRender(RenderProgressCallback callback);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,137 +1,201 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "shared/types.h"
#include "shared/functions.h"
#include "shared/constants.h"
#include "shared/globals.h"
#include "IL/il.h"
#include "IL/ilu.h"
#include "textures.h"
#include "terrain.h"
#define TEXTURES_MAX 50
static TextureQuality _quality;
static TextureEnvironment _environment;
static int _textures_count = 0;
static Texture _textures[TEXTURES_MAX];
static TextureDefinition _textures[TEXTURES_MAX];
void texturesInit()
{
_textures_count = 0;
}
void texturesSave(FILE* f)
{
int i;
toolsSaveInt(f, _textures_count);
for (i = 0; i < _textures_count; i++)
{
zoneSave(_textures[i].zone, f);
noiseSave(_textures[i].bump_noise, f);
colorSave(_textures[i].color, f);
}
}
void texturesLoad(FILE* f)
{
// TODO
}
Texture* textureCreateFromFile(const char* filename)
int texturesGetLayerCount()
{
Texture* result;
ILuint imageid;
return _textures_count;
}
if (_textures_count >= TEXTURES_MAX)
int texturesAddLayer()
{
if (_textures_count < TEXTURES_MAX)
{
return _textures + (TEXTURES_MAX - 1);
_textures[_textures_count] = texturesCreateDefinition();
return _textures_count++;
}
else
{
result = _textures + _textures_count;
_textures_count++;
ilGenImages(1, &imageid);
ilBindImage(imageid);
ilLoadImage(filename);
result->bytes_per_pixel = ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL);
result->picture_width = ilGetInteger(IL_IMAGE_WIDTH);
result->picture_height = ilGetInteger(IL_IMAGE_HEIGHT);
result->pixels = malloc(result->bytes_per_pixel * result->picture_width * result->picture_height);
memcpy(result->pixels, ilGetData(), result->bytes_per_pixel * result->picture_width * result->picture_height);
result->scaling_x = 1.0;
result->scaling_y = 1.0;
result->scaling_z = 1.0;
ilDeleteImages(1, &imageid);
return result;
return -1;
}
}
static inline Color _getRawValue(Texture* tex, int x, int y)
void texturesDeleteLayer(int layer)
{
// TODO
}
TextureDefinition texturesCreateDefinition()
{
TextureDefinition result;
result.zone = zoneCreate();
result.bump_noise = noiseCreateGenerator();
result.color = COLOR_GREEN;
return result;
}
void texturesDeleteDefinition(TextureDefinition definition)
{
zoneDelete(definition.zone);
noiseDeleteGenerator(definition.bump_noise);
}
void texturesCopyDefinition(TextureDefinition source, TextureDefinition* destination)
{
destination->color = source.color;
noiseCopy(source.bump_noise, destination->bump_noise);
zoneCopy(source.zone, destination->zone);
}
void texturesSetDefinition(int layer, TextureDefinition definition)
{
TextureDefinition* destination;
if (layer >= 0 && layer < _textures_count)
{
destination = _textures + layer;
texturesCopyDefinition(definition, destination);
}
}
TextureDefinition texturesGetDefinition(int layer)
{
assert(layer >= 0);
assert(layer < _textures_count);
return _textures[layer];
}
void texturesSetQuality(TextureQuality quality)
{
_quality = quality;
}
TextureQuality texturesGetQuality()
{
return _quality;
}
static inline Vector3 _getNormal(TextureDefinition* definition, Vector3 point, double scale)
{
Vector3 dpoint, ref, normal;
ref.x = 0.0;
ref.y = 0.0;
dpoint.x = point.x - scale;
dpoint.z = point.z;
dpoint.y = terrainGetHeight(dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x, dpoint.z);
ref.z = -1.0;
normal = v3Normalize(v3Cross(ref, v3Sub(dpoint, point)));
dpoint.x = point.x + scale;
dpoint.z = point.z;
dpoint.y = terrainGetHeight(dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x, dpoint.z);
ref.z = 1.0;
normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point))));
ref.z = 0.0;
dpoint.x = point.x;
dpoint.z = point.z - scale;
dpoint.y = terrainGetHeight(dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x, dpoint.z);
ref.x = 1.0;
normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point))));
dpoint.x = point.x;
dpoint.z = point.z + scale;
dpoint.y = terrainGetHeight(dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x, dpoint.z);
ref.x = -1.0;
normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point))));
return v3Normalize(normal);
}
Color texturesGetLayerColorCustom(Vector3 location, double shadowing, double detail, TextureDefinition* definition, TextureQuality* quality, TextureEnvironment* environment)
{
Color result;
void* texdata;
Vector3 normal;
double coverage;
x = x % tex->picture_width;
if (x < 0)
result.a = 0.0;
normal = _getNormal(definition, location, detail * 0.3);
coverage = zoneGetValue(definition->zone, location, normal);
if (coverage > 0.0)
{
x += tex->picture_width;
result = lightingApply(location, normal, shadowing, definition->color, 0.1, 0.1);
result.a = coverage;
}
y = y % tex->picture_height;
if (y < 0)
{
y += tex->picture_height;
}
texdata = tex->pixels + (y * tex->picture_width + x) * tex->bytes_per_pixel;
result.r = ((double)(unsigned int)*((unsigned char*)texdata)) / 255.0;
result.g = ((double)(unsigned int)*((unsigned char*)(texdata + 1))) / 255.0;
result.b = ((double)(unsigned int)*((unsigned char*)(texdata + 2))) / 255.0;
return result;
}
static inline Color _getInterpolatedValue(Texture* tex, double fx, double fy)
Color texturesGetColorCustom(Vector3 location, double shadowing, double detail, TextureQuality* quality, TextureEnvironment* environment)
{
Color result;
double r[16];
double g[16];
double b[16];
int ix, iy;
int sx, sy;
Color result, tex_color;
int i;
ix = (int)floor(fx);
iy = (int)floor(fy);
fx -= (double)ix;
fy -= (double)iy;
for (sy = 0; sy < 4; sy++)
result = COLOR_GREEN;
for (i = 0; i < _textures_count; i++)
{
for (sx = 0; sx < 4; sx++)
/* TODO Do not compute layers fully covered */
tex_color = texturesGetLayerColorCustom(location, shadowing, detail, _textures + i, quality, environment);
if (tex_color.a > 0.0001)
{
result = _getRawValue(tex, ix + sx - 1, iy + sy - 1);
r[sy * 4 + sx] = result.r;
g[sy * 4 + sx] = result.g;
b[sy * 4 + sx] = result.b;
colorMask(&result, &tex_color);
}
}
result.r = toolsBicubicInterpolate(r, fx, fy);
result.g = toolsBicubicInterpolate(g, fx, fy);
result.b = toolsBicubicInterpolate(b, fx, fy);
result.a = 1.0;
return result;
}
Color textureApply(Texture* tex, Vector3 location, Vector3 normal)
Color texturesGetColor(Vector3 location)
{
Color col_x, col_y, col_z, result;
double x, y, z;
double distance;
double shadowing;
distance = v3Norm(v3Sub(camera_location, location)) / 10.0;
/* TODO Use environment to get lights to apply */
shadowing = terrainGetShadow(location, sun_direction_inv);
x = location.x / (tex->scaling_x * distance);
y = location.y / (tex->scaling_y * distance);
z = location.z / (tex->scaling_z * distance);
col_x = _getInterpolatedValue(tex, y, z);
col_y = _getInterpolatedValue(tex, x, z);
col_z = _getInterpolatedValue(tex, x, y);
result.r = (col_x.r + col_y.r + col_z.r) / 3.0;
result.g = (col_x.g + col_y.g + col_z.g) / 3.0;
result.b = (col_x.b + col_y.b + col_z.b) / 3.0;
result.a = (col_x.a + col_y.a + col_z.a) / 3.0;
return result;
return texturesGetColorCustom(location, shadowing, renderGetPrecision(location), &_quality, &_environment);
}

53
lib_paysages/textures.h Normal file
View file

@ -0,0 +1,53 @@
#ifndef _PAYSAGES_TEXTURES_H_
#define _PAYSAGES_TEXTURES_H_
#include "shared/types.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
Zone* zone;
NoiseGenerator* bump_noise;
Color color;
} TextureDefinition;
typedef struct
{
int unused;
} TextureQuality;
typedef struct
{
int unused;
} TextureEnvironment;
void texturesInit();
void texturesSave(FILE* f);
void texturesLoad(FILE* f);
int texturesGetLayerCount();
int texturesAddLayer();
void texturesDeleteLayer(int layer);
TextureDefinition texturesCreateDefinition();
void texturesDeleteDefinition(TextureDefinition definition);
void texturesCopyDefinition(TextureDefinition source, TextureDefinition* destination);
void texturesSetDefinition(int layer, TextureDefinition definition);
TextureDefinition texturesGetDefinition(int layer);
void texturesSetQuality(TextureQuality quality);
TextureQuality texturesGetQuality();
Color texturesGetLayerColorCustom(Vector3 location, double shadowing, double detail, TextureDefinition* definition, TextureQuality* quality, TextureEnvironment* environment);
Color texturesGetColorCustom(Vector3 location, double shadowing, double detail, TextureQuality* quality, TextureEnvironment* environment);
Color texturesGetColor(Vector3 location);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -2,7 +2,9 @@
#include "shared/functions.h"
#include "shared/constants.h"
#include "shared/globals.h"
#include "water.h"
#include "terrain.h"
#include <math.h>

View file

@ -39,14 +39,6 @@ struct Zone {
#include "shared/types.h"
#include "shared/functions.h"
void zoneSave(Zone* zone, FILE* f)
{
}
void zoneLoad(Zone* zone, FILE* f)
{
}
Zone* zoneCreate()
{
Zone* result;
@ -65,6 +57,101 @@ void zoneDelete(Zone* zone)
free(zone);
}
void zoneSave(Zone* zone, FILE* f)
{
int i;
toolsSaveInt(f, zone->height_ranges_count);
for (i = 0; i < zone->height_ranges_count; i++)
{
toolsSaveDouble(f, zone->height_ranges[i].value);
toolsSaveDouble(f, zone->height_ranges[i].hardmin);
toolsSaveDouble(f, zone->height_ranges[i].softmin);
toolsSaveDouble(f, zone->height_ranges[i].softmax);
toolsSaveDouble(f, zone->height_ranges[i].hardmax);
}
toolsSaveInt(f, zone->steepness_ranges_count);
for (i = 0; i < zone->steepness_ranges_count; i++)
{
toolsSaveDouble(f, zone->steepness_ranges[i].value);
toolsSaveDouble(f, zone->steepness_ranges[i].hardmin);
toolsSaveDouble(f, zone->steepness_ranges[i].softmin);
toolsSaveDouble(f, zone->steepness_ranges[i].softmax);
toolsSaveDouble(f, zone->steepness_ranges[i].hardmax);
}
toolsSaveInt(f, zone->circles_included_count);
for (i = 0; i < zone->circles_included_count; i++)
{
toolsSaveDouble(f, zone->circles_included[i].value);
toolsSaveDouble(f, zone->circles_included[i].centerx);
toolsSaveDouble(f, zone->circles_included[i].centerz);
toolsSaveDouble(f, zone->circles_included[i].softradius);
toolsSaveDouble(f, zone->circles_included[i].hardradius);
}
toolsSaveInt(f, zone->circles_excluded_count);
for (i = 0; i < zone->circles_excluded_count; i++)
{
toolsSaveDouble(f, zone->circles_excluded[i].value);
toolsSaveDouble(f, zone->circles_excluded[i].centerx);
toolsSaveDouble(f, zone->circles_excluded[i].centerz);
toolsSaveDouble(f, zone->circles_excluded[i].softradius);
toolsSaveDouble(f, zone->circles_excluded[i].hardradius);
}
}
void zoneLoad(Zone* zone, FILE* f)
{
int i;
zone->height_ranges_count = toolsLoadInt(f);
for (i = 0; i < zone->height_ranges_count; i++)
{
zone->height_ranges[i].value = toolsLoadDouble(f);
zone->height_ranges[i].hardmin = toolsLoadDouble(f);
zone->height_ranges[i].softmin = toolsLoadDouble(f);
zone->height_ranges[i].softmax = toolsLoadDouble(f);
zone->height_ranges[i].hardmax = toolsLoadDouble(f);
}
zone->steepness_ranges_count = toolsLoadInt(f);
for (i = 0; i < zone->steepness_ranges_count; i++)
{
zone->steepness_ranges[i].value = toolsLoadDouble(f);
zone->steepness_ranges[i].hardmin = toolsLoadDouble(f);
zone->steepness_ranges[i].softmin = toolsLoadDouble(f);
zone->steepness_ranges[i].softmax = toolsLoadDouble(f);
zone->steepness_ranges[i].hardmax = toolsLoadDouble(f);
}
zone->circles_included_count = toolsLoadInt(f);
for (i = 0; i < zone->circles_included_count; i++)
{
zone->circles_included[i].value = toolsLoadDouble(f);
zone->circles_included[i].centerx = toolsLoadDouble(f);
zone->circles_included[i].centerz = toolsLoadDouble(f);
zone->circles_included[i].softradius = toolsLoadDouble(f);
zone->circles_included[i].hardradius = toolsLoadDouble(f);
}
zone->circles_excluded_count = toolsLoadInt(f);
for (i = 0; i < zone->circles_excluded_count; i++)
{
zone->circles_excluded[i].value = toolsLoadDouble(f);
zone->circles_excluded[i].centerx = toolsLoadDouble(f);
zone->circles_excluded[i].centerz = toolsLoadDouble(f);
zone->circles_excluded[i].softradius = toolsLoadDouble(f);
zone->circles_excluded[i].hardradius = toolsLoadDouble(f);
}
}
void zoneCopy(Zone* source, Zone* destination)
{
*source = *destination;
}
void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius)
{
Circle circle = {value, centerx, centerz, softradius, hardradius};