337 lines
9 KiB
C
337 lines
9 KiB
C
|
#include <unistd.h>
|
||
|
#include <math.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <time.h>
|
||
|
|
||
|
#include "shared/types.h"
|
||
|
#include "shared/functions.h"
|
||
|
#include "shared/constants.h"
|
||
|
#include "shared/globals.h"
|
||
|
#include "shared/system.h"
|
||
|
|
||
|
#include "water.h"
|
||
|
#include "clouds.h"
|
||
|
|
||
|
static int _cpu_count = 1;
|
||
|
static int _is_rendering = 0;
|
||
|
|
||
|
void autoInit()
|
||
|
{
|
||
|
_cpu_count = (int)sysconf(_SC_NPROCESSORS_ONLN);
|
||
|
renderSetBackgroundColor(&COLOR_BLACK);
|
||
|
|
||
|
terrainInit();
|
||
|
waterInit();
|
||
|
}
|
||
|
|
||
|
void autoSave(char* filepath)
|
||
|
{
|
||
|
FILE* f = fopen(filepath, "wb");
|
||
|
|
||
|
texturesSave(f);
|
||
|
|
||
|
cameraSave(f);
|
||
|
cloudsSave(f);
|
||
|
fogSave(f);
|
||
|
lightingSave(f);
|
||
|
renderSave(f);
|
||
|
skySave(f);
|
||
|
terrainSave(f);
|
||
|
waterSave(f);
|
||
|
|
||
|
fclose(f);
|
||
|
}
|
||
|
|
||
|
void autoLoad(char* filepath)
|
||
|
{
|
||
|
FILE* f = fopen(filepath, "rb");
|
||
|
|
||
|
texturesLoad(f);
|
||
|
|
||
|
cameraLoad(f);
|
||
|
cloudsLoad(f);
|
||
|
fogLoad(f);
|
||
|
lightingLoad(f);
|
||
|
renderLoad(f);
|
||
|
skyLoad(f);
|
||
|
terrainLoad(f);
|
||
|
waterLoad(f);
|
||
|
|
||
|
fclose(f);
|
||
|
}
|
||
|
|
||
|
void autoSetDaytime(int hour, int minute)
|
||
|
{
|
||
|
autoSetDaytimeFraction((double)hour / 24.0 + (double)minute / 1440.0);
|
||
|
}
|
||
|
|
||
|
void autoSetDaytimeFraction(double daytime)
|
||
|
{
|
||
|
daytime = fmod(daytime, 1.0);
|
||
|
if (daytime < 0.0)
|
||
|
{
|
||
|
daytime += 1.0;
|
||
|
}
|
||
|
|
||
|
ColorGradation grad_zenith, grad_haze, grad_sky, grad_sun;
|
||
|
Color sun, zenith, haze;
|
||
|
|
||
|
lightingSetSunAngle(0.0, (daytime + 0.25) * M_PI * 2.0);
|
||
|
|
||
|
grad_sun = colorGradationCreate();
|
||
|
colorGradationAddRgba(&grad_sun, 0.2, 0.1, 0.1, 0.1, 1.0);
|
||
|
colorGradationAddRgba(&grad_sun, 0.25, 0.9, 0.5, 0.5, 1.0);
|
||
|
colorGradationAddRgba(&grad_sun, 0.3, 0.8, 0.8, 0.8, 1.0);
|
||
|
colorGradationAddRgba(&grad_sun, 0.5, 1.0, 1.0, 1.0, 1.0);
|
||
|
colorGradationAddRgba(&grad_sun, 0.7, 0.8, 0.8, 0.8, 1.0);
|
||
|
colorGradationAddRgba(&grad_sun, 0.75, 0.7, 0.6, 0.5, 1.0);
|
||
|
colorGradationAddRgba(&grad_sun, 0.8, 0.1, 0.1, 0.1, 1.0);
|
||
|
sun = colorGradationGet(&grad_sun, daytime);
|
||
|
lightingSetSunColor(sun);
|
||
|
|
||
|
grad_zenith = colorGradationCreate();
|
||
|
colorGradationAddRgba(&grad_zenith, 0.2, 0.03, 0.03, 0.05, 1.0);
|
||
|
colorGradationAddRgba(&grad_zenith, 0.25, 0.25, 0.33, 0.37, 1.0);
|
||
|
colorGradationAddRgba(&grad_zenith, 0.35, 0.52, 0.63, 0.8, 1.0);
|
||
|
colorGradationAddRgba(&grad_zenith, 0.65, 0.52, 0.63, 0.8, 1.0);
|
||
|
colorGradationAddRgba(&grad_zenith, 0.75, 0.25, 0.33, 0.37, 1.0);
|
||
|
colorGradationAddRgba(&grad_zenith, 0.8, 0.03, 0.03, 0.05, 1.0);
|
||
|
zenith = colorGradationGet(&grad_zenith, daytime);
|
||
|
|
||
|
grad_haze = colorGradationCreate();
|
||
|
colorGradationAddRgba(&grad_haze, 0.2, 0.05, 0.05, 0.08, 1.0);
|
||
|
colorGradationAddRgba(&grad_haze, 0.25, 0.55, 0.42, 0.42, 1.0);
|
||
|
colorGradationAddRgba(&grad_haze, 0.3, 0.6, 0.6, 0.6, 1.0);
|
||
|
colorGradationAddRgba(&grad_haze, 0.4, 0.92, 0.93, 1.0, 1.0);
|
||
|
colorGradationAddRgba(&grad_haze, 0.6, 0.92, 0.93, 1.0, 1.0);
|
||
|
colorGradationAddRgba(&grad_haze, 0.7, 0.6, 0.6, 0.8, 1.0);
|
||
|
colorGradationAddRgba(&grad_haze, 0.75, 0.62, 0.50, 0.42, 1.0);
|
||
|
colorGradationAddRgba(&grad_haze, 0.8, 0.05, 0.05, 0.08, 1.0);
|
||
|
haze = colorGradationGet(&grad_haze, daytime);
|
||
|
|
||
|
grad_sky = colorGradationCreate();
|
||
|
colorGradationAdd(&grad_sky, 0.0, &haze);
|
||
|
colorGradationAdd(&grad_sky, 0.45, &haze);
|
||
|
colorGradationAdd(&grad_sky, 0.75, &zenith);
|
||
|
colorGradationAdd(&grad_sky, 1.0, &zenith);
|
||
|
skySetGradation(grad_sky);
|
||
|
|
||
|
fogSetColor(haze);
|
||
|
}
|
||
|
|
||
|
void autoSetRenderQuality(int quality)
|
||
|
{
|
||
|
WaterQuality water;
|
||
|
CloudsQuality clouds;
|
||
|
|
||
|
if (quality < 1)
|
||
|
{
|
||
|
quality = 1;
|
||
|
}
|
||
|
if (quality > 10)
|
||
|
{
|
||
|
quality = 10;
|
||
|
}
|
||
|
|
||
|
renderSetQuality(quality);
|
||
|
|
||
|
terrainSetChunkSize(0.1 / (double)render_quality, 0.05 / (double)render_quality);
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
Texture* tex;
|
||
|
WaterDefinition water;
|
||
|
CloudsDefinition cloud;
|
||
|
int layer;
|
||
|
HeightModifier* mod;
|
||
|
Zone* zone;
|
||
|
NoiseGenerator* noise;
|
||
|
|
||
|
if (!seed)
|
||
|
{
|
||
|
seed = time(NULL);
|
||
|
}
|
||
|
srand(seed);
|
||
|
|
||
|
/* Cloud layer */
|
||
|
cloud = cloudsCreateDefinition();
|
||
|
cloud.ymin = 10.0;
|
||
|
cloud.ycenter = 40.0;
|
||
|
cloud.ymax = 100.0;
|
||
|
cloud.color = COLOR_WHITE;
|
||
|
cloud.color.a = 0.1;
|
||
|
cloud.scaling = 50.0;
|
||
|
cloud.coverage = 0.5;
|
||
|
noiseGenerateBaseNoise(cloud.noise, 262144);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0, 0.3);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 2.0, 0.2);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 4.0, 0.1);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 10.0, 0.05);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 20.0, 0.03);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 40.0, 0.02);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 60.0, 0.01);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 80.0, 0.005);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 100.0, 0.02);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 150.0, 0.005);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 200.0, 0.003);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 400.0, 0.008);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 800.0, 0.001);
|
||
|
noiseAddLevelSimple(cloud.noise, 50.0 / 1000.0, 0.0005);
|
||
|
layer = cloudsAddLayer();
|
||
|
cloudsSetDefinition(layer, cloud);
|
||
|
|
||
|
/* Water */
|
||
|
water.height = 0.0;
|
||
|
water.transparency = 0.4;
|
||
|
water.reflection = 0.5;
|
||
|
water.main_color.r = 0.1;
|
||
|
water.main_color.g = 0.3;
|
||
|
water.main_color.b = 0.4;
|
||
|
water.main_color.a = 1.0;
|
||
|
water.height_noise = noiseCreateGenerator();
|
||
|
noiseGenerateBaseNoise(water.height_noise, 262144);
|
||
|
noiseAddLevelsSimple(water.height_noise, 2, 0.2, 0.015);
|
||
|
noiseAddLevelsSimple(water.height_noise, 3, 0.03, 0.003);
|
||
|
waterSetDefinition(water);
|
||
|
noiseDeleteGenerator(water.height_noise);
|
||
|
|
||
|
noise = noiseCreateGenerator();
|
||
|
noiseGenerateBaseNoise(noise, 1048576);
|
||
|
noiseAddLevelsSimple(noise, 10, 10.0, 1.0);
|
||
|
noiseNormalizeHeight(noise, -12.0, 12.0, 0);
|
||
|
terrainSetNoiseGenerator(noise);
|
||
|
noiseDeleteGenerator(noise);
|
||
|
|
||
|
tex = textureCreateFromFile("./data/textures/rock3.jpg");
|
||
|
tex->scaling_x = 0.003;
|
||
|
tex->scaling_y = 0.003;
|
||
|
tex->scaling_z = 0.003;
|
||
|
zone = zoneCreate(1.0);
|
||
|
terrainAddTexture(tex, 0.05, zone, 1.0);
|
||
|
|
||
|
tex = textureCreateFromFile("./data/textures/grass1.jpg");
|
||
|
tex->scaling_x = 0.0004;
|
||
|
tex->scaling_y = 0.0004;
|
||
|
tex->scaling_z = 0.0004;
|
||
|
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);
|
||
|
|
||
|
/*tex = textureCreateFromFile("./data/textures/snow1.jpg");
|
||
|
tex->scaling_x = 0.001;
|
||
|
tex->scaling_y = 0.001;
|
||
|
tex->scaling_z = 0.001;
|
||
|
zone = zoneCreate(0.0);
|
||
|
zoneAddHeightRange(zone, 1.0, 3.0, 4.0, 100.0, 100.0);
|
||
|
terrainAddTexture(tex, 0.5, zone, 0.1);*/
|
||
|
|
||
|
/* DEBUG */
|
||
|
mod = modifierCreate();
|
||
|
zone = modifierGetZone(mod);
|
||
|
zoneIncludeCircleArea(zone, 0.4, 0.0, 0.0, 8.0, 20.0);
|
||
|
modifierActionFixValue(mod, -2.0);
|
||
|
terrainAddModifier(mod);
|
||
|
mod = modifierCreate();
|
||
|
zone = modifierGetZone(mod);
|
||
|
zoneIncludeCircleArea(zone, 1.0, 0.0, 0.0, 0.3, 8.0);
|
||
|
modifierActionAddValue(mod, 8.0);
|
||
|
terrainAddModifier(mod);
|
||
|
mod = modifierCreate();
|
||
|
zone = modifierGetZone(mod);
|
||
|
zoneIncludeCircleArea(zone, 0.8, 0.0, 0.0, 0.3, 4.0);
|
||
|
modifierActionFixValue(mod, -8.0);
|
||
|
terrainAddModifier(mod);
|
||
|
|
||
|
fogSetDistance(20.0, 100.0);
|
||
|
}
|
||
|
|
||
|
void* _renderFirstPass(void* data)
|
||
|
{
|
||
|
if (!renderSetNextProgressStep(0.0, 0.1))
|
||
|
{
|
||
|
_is_rendering = 0;
|
||
|
return NULL;
|
||
|
}
|
||
|
skyRender(renderTellProgress);
|
||
|
if (!renderSetNextProgressStep(0.1, 0.3))
|
||
|
{
|
||
|
_is_rendering = 0;
|
||
|
return NULL;
|
||
|
}
|
||
|
terrainRender(renderTellProgress);
|
||
|
if (!renderSetNextProgressStep(0.3, 0.4))
|
||
|
{
|
||
|
_is_rendering = 0;
|
||
|
return NULL;
|
||
|
}
|
||
|
waterRender(renderTellProgress);
|
||
|
_is_rendering = 0;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
void autoRenderSceneTwoPass(int postonly)
|
||
|
{
|
||
|
Thread* thread;
|
||
|
int loops;
|
||
|
|
||
|
if (!postonly)
|
||
|
{
|
||
|
renderClear();
|
||
|
|
||
|
_is_rendering = 1;
|
||
|
thread = threadCreate(_renderFirstPass, NULL);
|
||
|
loops = 0;
|
||
|
|
||
|
while (_is_rendering)
|
||
|
{
|
||
|
timeSleepMs(100);
|
||
|
|
||
|
if (++loops >= 10)
|
||
|
{
|
||
|
renderUpdate();
|
||
|
loops = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
threadJoin(thread);
|
||
|
}
|
||
|
if (renderSetNextProgressStep(0.4, 1.0))
|
||
|
{
|
||
|
renderPostProcess(_cpu_count);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int _postProcessRayTracingOverlay(RenderFragment* fragment)
|
||
|
{
|
||
|
Vector3 terrain_hit, look;
|
||
|
|
||
|
look = v3Sub(fragment->vertex.location, camera_location);
|
||
|
if (!terrainProjectRay(camera_location, look, &terrain_hit, &fragment->vertex.color))
|
||
|
{
|
||
|
fragment->vertex.color = skyProjectRay(camera_location, look);
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void autoRenderSceneRayTracing()
|
||
|
{
|
||
|
renderClear();
|
||
|
cameraPushOverlay(COLOR_RED, _postProcessRayTracingOverlay);
|
||
|
renderUpdate();
|
||
|
|
||
|
if (renderSetNextProgressStep(0.0, 1.0))
|
||
|
{
|
||
|
renderPostProcess(_cpu_count);
|
||
|
}
|
||
|
}
|