2012-01-23 23:45:33 +00:00
|
|
|
#include "terrain.h"
|
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <math.h>
|
2012-01-05 11:32:14 +00:00
|
|
|
#include <string.h>
|
2012-01-23 23:45:33 +00:00
|
|
|
#include <assert.h>
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
#include "shared/types.h"
|
|
|
|
#include "shared/constants.h"
|
2012-01-29 17:39:56 +00:00
|
|
|
#include "euclid.h"
|
2012-01-24 13:16:20 +00:00
|
|
|
#include "render.h"
|
2012-01-03 15:40:50 +00:00
|
|
|
#include "textures.h"
|
2011-12-10 13:25:22 +00:00
|
|
|
#include "water.h"
|
2012-01-29 17:39:56 +00:00
|
|
|
#include "tools.h"
|
2012-01-03 15:40:50 +00:00
|
|
|
|
|
|
|
void terrainInit()
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-02-12 16:57:29 +00:00
|
|
|
void terrainQuit()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void terrainSave(FILE* f, TerrainDefinition* definition)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-01-05 11:32:14 +00:00
|
|
|
int i;
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2012-02-27 15:25:12 +00:00
|
|
|
noiseSaveGenerator(f, definition->height_noise);
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsSaveDouble(f, &definition->height_factor);
|
|
|
|
toolsSaveDouble(f, &definition->scaling);
|
2012-01-23 23:45:33 +00:00
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsSaveInt(f, &definition->height_modifiers_count);
|
2012-01-23 23:45:33 +00:00
|
|
|
for (i = 0; i < definition->height_modifiers_count; i++)
|
2012-01-05 11:32:14 +00:00
|
|
|
{
|
2012-01-29 17:39:56 +00:00
|
|
|
modifierSave(f, definition->height_modifiers[i]);
|
2012-01-05 11:32:14 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void terrainLoad(FILE* f, TerrainDefinition* definition)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
int i, n;
|
|
|
|
HeightModifier* modifier;
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2012-02-27 15:25:12 +00:00
|
|
|
noiseLoadGenerator(f, definition->height_noise);
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsLoadDouble(f, &definition->height_factor);
|
|
|
|
toolsLoadDouble(f, &definition->scaling);
|
2012-01-05 11:32:14 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
while (definition->height_modifiers_count > 0)
|
2012-01-05 11:32:14 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
terrainDelModifier(definition, 0);
|
2012-01-05 11:32:14 +00:00
|
|
|
}
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsLoadInt(f, &n);
|
2012-01-23 23:45:33 +00:00
|
|
|
for (i = 0; i < n; i++)
|
2012-01-05 11:32:14 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
modifier = modifierCreate();
|
2012-01-29 17:39:56 +00:00
|
|
|
modifierLoad(f, modifier);
|
2012-01-24 13:16:20 +00:00
|
|
|
terrainAddModifier(definition, modifier);
|
2012-01-23 23:45:33 +00:00
|
|
|
modifierDelete(modifier);
|
2012-01-05 11:32:14 +00:00
|
|
|
}
|
2012-01-23 23:45:33 +00:00
|
|
|
|
|
|
|
terrainValidateDefinition(definition);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
TerrainDefinition terrainCreateDefinition()
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
TerrainDefinition definition;
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
definition.height_noise = noiseCreateGenerator();
|
2012-01-23 23:45:33 +00:00
|
|
|
definition.height_factor = 0.0;
|
|
|
|
definition.scaling = 1.0;
|
2012-01-05 11:32:14 +00:00
|
|
|
definition.height_modifiers_count = 0;
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
terrainValidateDefinition(&definition);
|
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
return definition;
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void terrainDeleteDefinition(TerrainDefinition* definition)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-01-05 11:32:14 +00:00
|
|
|
int i;
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
noiseDeleteGenerator(definition->height_noise);
|
|
|
|
for (i = 0; i < definition->height_modifiers_count; i++)
|
2012-01-05 11:32:14 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
modifierDelete(definition->height_modifiers[i]);
|
2012-01-05 11:32:14 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void terrainCopyDefinition(TerrainDefinition* source, TerrainDefinition* destination)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-05 11:32:14 +00:00
|
|
|
int i;
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2012-01-24 13:16:20 +00:00
|
|
|
noiseCopy(source->height_noise, destination->height_noise);
|
2012-01-23 23:45:33 +00:00
|
|
|
destination->height_factor = source->height_factor;
|
|
|
|
destination->scaling = source->scaling;
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2012-01-05 11:32:14 +00:00
|
|
|
for (i = 0; i < destination->height_modifiers_count; i++)
|
|
|
|
{
|
|
|
|
modifierDelete(destination->height_modifiers[i]);
|
|
|
|
}
|
2012-01-23 23:45:33 +00:00
|
|
|
destination->height_modifiers_count = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < source->height_modifiers_count; i++)
|
2012-01-05 11:32:14 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
terrainAddModifier(destination, source->height_modifiers[i]);
|
2012-01-05 11:32:14 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
terrainValidateDefinition(destination);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void terrainValidateDefinition(TerrainDefinition* definition)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
definition->_max_height = noiseGetMaxValue(definition->height_noise) * definition->height_factor;
|
|
|
|
/* FIXME _max_height depends on modifiers */
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-05 11:32:14 +00:00
|
|
|
int terrainAddModifier(TerrainDefinition* definition, HeightModifier* modifier)
|
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
if (definition->height_modifiers_count < TERRAIN_MAX_MODIFIERS)
|
2012-01-05 11:32:14 +00:00
|
|
|
{
|
|
|
|
definition->height_modifiers[definition->height_modifiers_count] = modifierCreateCopy(modifier);
|
|
|
|
return definition->height_modifiers_count++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void terrainDelModifier(TerrainDefinition* definition, int modifier_position)
|
|
|
|
{
|
|
|
|
if (modifier_position >= 0 && modifier_position < definition->height_modifiers_count)
|
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
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--;
|
2012-01-05 11:32:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-28 11:04:27 +00:00
|
|
|
static inline double _getHeight(TerrainDefinition* definition, double x, double z)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
Vector3 location;
|
2012-01-05 11:32:14 +00:00
|
|
|
int i;
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
location.x = x;
|
2012-01-28 11:04:27 +00:00
|
|
|
location.y = noiseGet2DTotal(definition->height_noise, x / definition->scaling, z / definition->scaling) * definition->height_factor;
|
2011-12-10 13:25:22 +00:00
|
|
|
location.z = z;
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2012-01-05 11:32:14 +00:00
|
|
|
for (i = 0; i < definition->height_modifiers_count; i++)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-05 11:32:14 +00:00
|
|
|
location = modifierApply(definition->height_modifiers[i], location);
|
|
|
|
}
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
return location.y;
|
|
|
|
}
|
|
|
|
|
2012-01-28 11:04:27 +00:00
|
|
|
static inline Vector3 _getPoint(TerrainDefinition* definition, double x, double z)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
Vector3 result;
|
|
|
|
|
|
|
|
result.x = x;
|
2012-01-28 11:04:27 +00:00
|
|
|
result.y = _getHeight(definition, x, z);
|
2011-12-10 13:25:22 +00:00
|
|
|
result.z = z;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
Color terrainLightFilter(TerrainDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
Vector3 inc_vector;
|
2012-01-22 22:06:11 +00:00
|
|
|
double inc_value, inc_base, inc_factor, height, diff, light_factor, smoothing, length;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-22 22:06:11 +00:00
|
|
|
direction_to_light = v3Normalize(direction_to_light);
|
2012-01-25 17:31:36 +00:00
|
|
|
if (fabs(direction_to_light.x) < 0.0001 && fabs(direction_to_light.z) < 0.0001)
|
|
|
|
{
|
|
|
|
return light;
|
|
|
|
}
|
2012-01-31 09:48:38 +00:00
|
|
|
else if (direction_to_light.y < 0.05)
|
|
|
|
{
|
|
|
|
return COLOR_BLACK;
|
|
|
|
}
|
|
|
|
else if (direction_to_light.y < 0.0000)
|
|
|
|
{
|
|
|
|
light.r *= (0.05 + direction_to_light.y) / 0.05;
|
|
|
|
light.g *= (0.05 + direction_to_light.y) / 0.05;
|
|
|
|
light.b *= (0.05 + direction_to_light.y) / 0.05;
|
|
|
|
}
|
2012-01-28 11:04:27 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
inc_factor = (double)renderer->render_quality;
|
2011-12-10 13:25:22 +00:00
|
|
|
inc_base = 1.0;
|
|
|
|
inc_value = inc_base / inc_factor;
|
2012-01-23 23:45:33 +00:00
|
|
|
smoothing = 0.03 * inc_factor;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-22 22:06:11 +00:00
|
|
|
light_factor = 1.0;
|
2011-12-10 13:25:22 +00:00
|
|
|
length = 0.0;
|
|
|
|
do
|
|
|
|
{
|
2012-01-22 22:06:11 +00:00
|
|
|
inc_vector = v3Scale(direction_to_light, inc_value);
|
2011-12-10 13:25:22 +00:00
|
|
|
length += v3Norm(inc_vector);
|
2012-01-22 22:06:11 +00:00
|
|
|
location = v3Add(location, inc_vector);
|
2012-01-28 11:04:27 +00:00
|
|
|
height = _getHeight(definition, location.x, location.z);
|
2012-01-22 22:06:11 +00:00
|
|
|
diff = location.y - height;
|
2011-12-10 13:25:22 +00:00
|
|
|
if (diff < 0.0)
|
|
|
|
{
|
2012-01-22 22:06:11 +00:00
|
|
|
light_factor += diff / smoothing;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (diff < inc_base / inc_factor)
|
|
|
|
{
|
|
|
|
inc_value = inc_base / inc_factor;
|
|
|
|
}
|
|
|
|
else if (diff > inc_base)
|
|
|
|
{
|
|
|
|
inc_value = inc_base;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
inc_value = diff;
|
|
|
|
}
|
2012-01-24 13:16:20 +00:00
|
|
|
} while (light_factor > 0.0 && length < 50.0 && location.y <= definition->_max_height);
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-22 22:06:11 +00:00
|
|
|
if (light_factor <= 0.0)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-22 22:06:11 +00:00
|
|
|
return COLOR_BLACK;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-22 22:06:11 +00:00
|
|
|
light.r *= light_factor;
|
|
|
|
light.g *= light_factor;
|
|
|
|
light.b *= light_factor;
|
|
|
|
|
|
|
|
return light;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
static Color _getColor(TerrainDefinition* definition, Renderer* renderer, Vector3 point, double precision)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
Color color;
|
2012-01-22 22:06:11 +00:00
|
|
|
|
2012-01-24 13:16:20 +00:00
|
|
|
color = renderer->applyTextures(renderer, point, precision);
|
|
|
|
color = renderer->applyAtmosphere(renderer, point, color);
|
2012-01-31 09:48:38 +00:00
|
|
|
color = renderer->applyClouds(renderer, color, renderer->camera_location, point);
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
return color;
|
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
int terrainProjectRay(TerrainDefinition* definition, Renderer* renderer, Vector3 start, Vector3 direction, Vector3* hit_point, Color* hit_color)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
Vector3 inc_vector;
|
|
|
|
double inc_value, inc_base, inc_factor, height, diff, length;
|
|
|
|
|
|
|
|
direction = v3Normalize(direction);
|
2012-01-23 23:45:33 +00:00
|
|
|
inc_factor = (double)renderer->render_quality;
|
2011-12-10 13:25:22 +00:00
|
|
|
inc_base = 1.0;
|
|
|
|
inc_value = inc_base / inc_factor;
|
|
|
|
|
|
|
|
length = 0.0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
inc_vector = v3Scale(direction, inc_value);
|
|
|
|
length += v3Norm(inc_vector);
|
|
|
|
start = v3Add(start, inc_vector);
|
2012-01-28 11:04:27 +00:00
|
|
|
height = _getHeight(definition, start.x, start.z);
|
2011-12-10 13:25:22 +00:00
|
|
|
diff = start.y - height;
|
|
|
|
if (diff < 0.0)
|
|
|
|
{
|
|
|
|
start.y = height;
|
|
|
|
*hit_point = start;
|
2012-01-28 11:04:27 +00:00
|
|
|
*hit_color = _getColor(definition, renderer, start, renderer->getPrecision(renderer, start));
|
2011-12-10 13:25:22 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (diff < inc_base / inc_factor)
|
|
|
|
{
|
|
|
|
inc_value = inc_base / inc_factor;
|
|
|
|
}
|
|
|
|
else if (diff > inc_base)
|
|
|
|
{
|
|
|
|
inc_value = inc_base;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
inc_value = diff;
|
|
|
|
}
|
2012-01-24 13:16:20 +00:00
|
|
|
} while (length < 50.0 && start.y <= definition->_max_height);
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-01-24 13:16:20 +00:00
|
|
|
static int _postProcessFragment(RenderFragment* fragment, Renderer* renderer, void* data)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-24 13:16:20 +00:00
|
|
|
Vector3 point;
|
2011-12-10 13:25:22 +00:00
|
|
|
double precision;
|
2012-01-24 13:16:20 +00:00
|
|
|
TerrainDefinition* definition;
|
|
|
|
|
|
|
|
definition = (TerrainDefinition*)data;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
point = fragment->vertex.location;
|
2012-01-28 11:04:27 +00:00
|
|
|
point = _getPoint(definition, point.x, point.z);
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-28 11:04:27 +00:00
|
|
|
precision = renderer->getPrecision(renderer, point);
|
2012-01-24 13:16:20 +00:00
|
|
|
fragment->vertex.color = _getColor(definition, renderer, point, precision);
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
static Vertex _getFirstPassVertex(TerrainDefinition* definition, double x, double z, double detail)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
Vertex result;
|
|
|
|
double value;
|
|
|
|
|
2012-01-28 11:04:27 +00:00
|
|
|
result.location = _getPoint(definition, x, z);
|
2011-12-10 13:25:22 +00:00
|
|
|
value = sin(x) * sin(x) * cos(z) * cos(z);
|
|
|
|
result.color.r = value;
|
|
|
|
result.color.g = value;
|
|
|
|
result.color.b = value;
|
|
|
|
result.color.a = 1.0;
|
|
|
|
result.normal.x = result.normal.y = result.normal.z = 0.0;
|
|
|
|
result.callback = _postProcessFragment;
|
2012-01-24 13:16:20 +00:00
|
|
|
result.callback_data = definition;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-01-29 17:53:12 +00:00
|
|
|
static void _renderQuad(TerrainDefinition* definition, Renderer* renderer, double x, double z, double size, double water_height)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
Vertex v1, v2, v3, v4;
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
v1 = _getFirstPassVertex(definition, x, z, size);
|
|
|
|
v2 = _getFirstPassVertex(definition, x, z + size, size);
|
|
|
|
v3 = _getFirstPassVertex(definition, x + size, z + size, size);
|
|
|
|
v4 = _getFirstPassVertex(definition, x + size, z, size);
|
2012-01-29 17:53:12 +00:00
|
|
|
|
|
|
|
if (v1.location.y > water_height || v2.location.y > water_height || v3.location.y > water_height || v4.location.y > water_height)
|
|
|
|
{
|
2012-01-29 21:45:58 +00:00
|
|
|
renderer->pushQuad(renderer, &v1, &v2, &v3, &v4);
|
2012-01-29 17:53:12 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
double terrainGetHeight(TerrainDefinition* definition, double x, double z)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-28 11:04:27 +00:00
|
|
|
return _getHeight(definition, x, z);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
double terrainGetHeightNormalized(TerrainDefinition* definition, double x, double z)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-24 13:16:20 +00:00
|
|
|
if (definition->_max_height == 0.0)
|
|
|
|
{
|
|
|
|
return 0.5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-28 11:04:27 +00:00
|
|
|
return 0.5 + _getHeight(definition, x, z) / (definition->_max_height * 2.0);
|
2012-01-24 13:16:20 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double x, double z, double detail)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-28 11:04:27 +00:00
|
|
|
Vector3 point = _getPoint(definition, x, z);
|
2012-01-23 23:45:33 +00:00
|
|
|
return _getColor(definition, renderer, point, detail);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-29 21:45:58 +00:00
|
|
|
void terrainRender(TerrainDefinition* definition, Renderer* renderer)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
int chunk_factor, chunk_count, i;
|
2012-01-23 23:45:33 +00:00
|
|
|
double cx = renderer->camera_location.x;
|
|
|
|
double cz = renderer->camera_location.z;
|
|
|
|
double min_chunk_size, visible_chunk_size;
|
2011-12-10 13:25:22 +00:00
|
|
|
double radius_int, radius_ext, chunk_size;
|
2012-01-29 17:53:12 +00:00
|
|
|
double water_height;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
min_chunk_size = 0.1 / (double)renderer->render_quality;
|
|
|
|
visible_chunk_size = 0.05 / (double)renderer->render_quality;
|
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
chunk_factor = 1;
|
|
|
|
chunk_count = 2;
|
|
|
|
radius_int = 0.0;
|
2012-01-23 23:45:33 +00:00
|
|
|
radius_ext = min_chunk_size;
|
|
|
|
chunk_size = min_chunk_size;
|
2012-01-29 17:53:12 +00:00
|
|
|
|
|
|
|
water_height = renderer->getWaterHeightInfo(renderer).max_height;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
while (radius_ext < 1000.0)
|
|
|
|
{
|
2012-01-29 21:45:58 +00:00
|
|
|
if (!renderer->addRenderProgress(renderer, 0.0))
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2012-01-22 18:39:42 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
for (i = 0; i < chunk_count - 1; i++)
|
|
|
|
{
|
2012-01-29 17:53:12 +00:00
|
|
|
_renderQuad(definition, renderer, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size, water_height);
|
|
|
|
_renderQuad(definition, renderer, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size, water_height);
|
|
|
|
_renderQuad(definition, renderer, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size, water_height);
|
|
|
|
_renderQuad(definition, renderer, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size, water_height);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
if (chunk_count % 64 == 0 && chunk_size / radius_int < visible_chunk_size)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
chunk_count /= 2;
|
|
|
|
chunk_factor *= 2;
|
|
|
|
/* TODO Fill in gaps with triangles */
|
|
|
|
}
|
|
|
|
chunk_count += 2;
|
2012-01-23 23:45:33 +00:00
|
|
|
chunk_size = min_chunk_size * chunk_factor;
|
2011-12-10 13:25:22 +00:00
|
|
|
radius_int = radius_ext;
|
|
|
|
radius_ext += chunk_size;
|
|
|
|
}
|
|
|
|
}
|