2011-12-10 13:25:22 +00:00
|
|
|
#include <math.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2012-01-03 15:40:50 +00:00
|
|
|
#include <assert.h>
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
#include "shared/types.h"
|
|
|
|
#include "shared/functions.h"
|
|
|
|
#include "shared/constants.h"
|
|
|
|
#include "shared/globals.h"
|
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
#include "textures.h"
|
|
|
|
#include "terrain.h"
|
2012-01-22 22:06:11 +00:00
|
|
|
#include "lighting.h"
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
#define TEXTURES_MAX 50
|
2012-01-03 15:40:50 +00:00
|
|
|
static TextureQuality _quality;
|
|
|
|
static TextureEnvironment _environment;
|
2011-12-10 13:25:22 +00:00
|
|
|
static int _textures_count = 0;
|
2012-01-03 15:40:50 +00:00
|
|
|
static TextureDefinition _textures[TEXTURES_MAX];
|
|
|
|
|
|
|
|
void texturesInit()
|
|
|
|
{
|
|
|
|
_textures_count = 0;
|
2012-01-22 22:06:11 +00:00
|
|
|
|
|
|
|
_environment.lighting_definition = NULL;
|
|
|
|
_environment.lighting_environment = NULL;
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
void texturesSave(FILE* f)
|
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
int i;
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
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);
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void texturesLoad(FILE* f)
|
|
|
|
{
|
2012-01-18 18:47:46 +00:00
|
|
|
int i, n;
|
|
|
|
TextureDefinition* texture;
|
|
|
|
|
|
|
|
while (_textures_count > 0)
|
|
|
|
{
|
|
|
|
texturesDeleteLayer(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
n = toolsLoadInt(f);
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
texture = _textures + texturesAddLayer();
|
|
|
|
|
|
|
|
zoneLoad(texture->zone, f);
|
|
|
|
noiseLoad(texture->bump_noise, f);
|
|
|
|
texture->color = colorLoad(f);
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
int texturesGetLayerCount()
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
return _textures_count;
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
int texturesAddLayer()
|
|
|
|
{
|
|
|
|
if (_textures_count < TEXTURES_MAX)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
_textures[_textures_count] = texturesCreateDefinition();
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
return _textures_count++;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
void texturesDeleteLayer(int layer)
|
|
|
|
{
|
2012-01-18 18:47:46 +00:00
|
|
|
if (layer >= 0 && layer < _textures_count)
|
|
|
|
{
|
|
|
|
zoneDelete(_textures[layer].zone);
|
|
|
|
noiseDeleteGenerator(_textures[layer].bump_noise);
|
|
|
|
if (_textures_count > 1 && layer < _textures_count - 1)
|
|
|
|
{
|
|
|
|
memmove(_textures + layer, _textures + layer + 1, sizeof(TextureDefinition) * (_textures_count - layer - 1));
|
|
|
|
}
|
|
|
|
_textures_count--;
|
|
|
|
}
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
TextureDefinition texturesCreateDefinition()
|
|
|
|
{
|
|
|
|
TextureDefinition result;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
result.zone = zoneCreate();
|
|
|
|
result.bump_noise = noiseCreateGenerator();
|
|
|
|
result.color = COLOR_GREEN;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
return result;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
void texturesDeleteDefinition(TextureDefinition definition)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
zoneDelete(definition.zone);
|
|
|
|
noiseDeleteGenerator(definition.bump_noise);
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
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)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
destination = _textures + layer;
|
|
|
|
texturesCopyDefinition(definition, destination);
|
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-01-03 15:40:50 +00:00
|
|
|
TextureDefinition texturesGetDefinition(int layer)
|
|
|
|
{
|
|
|
|
assert(layer >= 0);
|
|
|
|
assert(layer < _textures_count);
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
return _textures[layer];
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
void texturesSetQuality(TextureQuality quality)
|
|
|
|
{
|
|
|
|
_quality = quality;
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
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;
|
2012-01-03 16:05:08 +00:00
|
|
|
point.y = terrainGetHeight(point.x, point.z) + noiseGet2DTotal(definition->bump_noise, point.x, point.z);
|
2012-01-03 15:40:50 +00:00
|
|
|
|
|
|
|
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);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-22 22:06:11 +00:00
|
|
|
Color texturesGetLayerColorCustom(Vector3 location, double detail, TextureDefinition* definition, TextureQuality* quality, TextureEnvironment* environment)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
Color result;
|
2012-01-03 15:40:50 +00:00
|
|
|
Vector3 normal;
|
|
|
|
double coverage;
|
2012-01-22 22:06:11 +00:00
|
|
|
ReceiverMaterial material;
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2012-01-22 22:06:11 +00:00
|
|
|
result = COLOR_TRANSPARENT;
|
2012-01-03 15:40:50 +00:00
|
|
|
normal = _getNormal(definition, location, detail * 0.3);
|
|
|
|
|
|
|
|
coverage = zoneGetValue(definition->zone, location, normal);
|
|
|
|
if (coverage > 0.0)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-22 22:06:11 +00:00
|
|
|
material.base = definition->color;
|
|
|
|
material.reflection = 0.1;
|
|
|
|
material.shininess = 0.1;
|
|
|
|
|
|
|
|
result = lightingApplyCustom(location, normal, material, environment->lighting_definition, NULL, environment->lighting_environment);
|
2012-01-03 15:40:50 +00:00
|
|
|
result.a = coverage;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-01-22 22:06:11 +00:00
|
|
|
Color texturesGetColorCustom(Vector3 location, double detail, TextureQuality* quality, TextureEnvironment* environment)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
Color result, tex_color;
|
|
|
|
int i;
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2012-01-22 22:06:11 +00:00
|
|
|
/*if (!quality)
|
|
|
|
{
|
|
|
|
quality = &_quality;
|
|
|
|
}
|
|
|
|
if (!environment)
|
|
|
|
{
|
|
|
|
environment = &_environment;
|
|
|
|
}*/
|
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
result = COLOR_GREEN;
|
|
|
|
for (i = 0; i < _textures_count; i++)
|
|
|
|
{
|
|
|
|
/* TODO Do not compute layers fully covered */
|
2012-01-22 22:06:11 +00:00
|
|
|
tex_color = texturesGetLayerColorCustom(location, detail, _textures + i, quality, environment);
|
2012-01-03 15:40:50 +00:00
|
|
|
if (tex_color.a > 0.0001)
|
|
|
|
{
|
|
|
|
colorMask(&result, &tex_color);
|
|
|
|
}
|
|
|
|
}
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-01-03 15:40:50 +00:00
|
|
|
Color texturesGetColor(Vector3 location)
|
|
|
|
{
|
2012-01-22 22:06:11 +00:00
|
|
|
return texturesGetColorCustom(location, renderGetPrecision(location), &_quality, &_environment);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|