2012-01-29 17:39:56 +00:00
|
|
|
#include "textures.h"
|
|
|
|
|
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/constants.h"
|
|
|
|
#include "shared/globals.h"
|
2012-01-29 17:39:56 +00:00
|
|
|
#include "color.h"
|
|
|
|
#include "euclid.h"
|
2012-01-22 22:06:11 +00:00
|
|
|
#include "lighting.h"
|
2012-01-29 17:39:56 +00:00
|
|
|
#include "terrain.h"
|
|
|
|
#include "tools.h"
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
static TextureLayerDefinition _NULL_LAYER;
|
2012-01-03 15:40:50 +00:00
|
|
|
|
|
|
|
void texturesInit()
|
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
_NULL_LAYER = texturesLayerCreateDefinition();
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void texturesSave(FILE* f, TexturesDefinition* definition)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-03 15:40:50 +00:00
|
|
|
int i;
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsSaveInt(f, &definition->nbtextures);
|
2012-01-23 23:45:33 +00:00
|
|
|
for (i = 0; i < definition->nbtextures; i++)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-01-29 17:39:56 +00:00
|
|
|
zoneSave(f, definition->textures[i].zone);
|
|
|
|
noiseSave(f, definition->textures[i].bump_noise);
|
|
|
|
colorSave(f, &definition->textures[i].color);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void texturesLoad(FILE* f, TexturesDefinition* definition)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
TextureLayerDefinition* layer;
|
2012-01-18 18:47:46 +00:00
|
|
|
int i, n;
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
while (definition->nbtextures > 0)
|
2012-01-18 18:47:46 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
texturesDeleteLayer(definition, 0);
|
2012-01-18 18:47:46 +00:00
|
|
|
}
|
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsLoadInt(f, &n);
|
2012-01-18 18:47:46 +00:00
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
2012-01-24 13:16:20 +00:00
|
|
|
layer = definition->textures + texturesAddLayer(definition);
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
zoneLoad(f, layer->zone);
|
|
|
|
noiseLoad(f, layer->bump_noise);
|
|
|
|
colorLoad(f, &layer->color);
|
2012-01-18 18:47:46 +00:00
|
|
|
}
|
2012-01-23 23:45:33 +00:00
|
|
|
|
|
|
|
texturesValidateDefinition(definition);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
TexturesDefinition texturesCreateDefinition()
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
TexturesDefinition result;
|
|
|
|
|
|
|
|
result.nbtextures = 0;
|
|
|
|
|
|
|
|
return result;
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void texturesDeleteDefinition(TexturesDefinition* definition)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
while (definition->nbtextures > 0)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
texturesDeleteLayer(definition, 0);
|
|
|
|
}
|
|
|
|
}
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void texturesCopyDefinition(TexturesDefinition* source, TexturesDefinition* destination)
|
|
|
|
{
|
|
|
|
TextureLayerDefinition* layer;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
while (destination->nbtextures > 0)
|
|
|
|
{
|
|
|
|
texturesDeleteLayer(destination, 0);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
2012-01-23 23:45:33 +00:00
|
|
|
for (i = 0; i < source->nbtextures; i++)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
layer = texturesGetLayer(destination, texturesAddLayer(destination));
|
|
|
|
texturesLayerCopyDefinition(source->textures + i, layer);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void texturesValidateDefinition(TexturesDefinition* definition)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < definition->nbtextures; i++)
|
2012-01-18 18:47:46 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
texturesLayerValidateDefinition(definition->textures + i);
|
2012-01-18 18:47:46 +00:00
|
|
|
}
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
TextureLayerDefinition texturesLayerCreateDefinition()
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
TextureLayerDefinition 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-23 23:45:33 +00:00
|
|
|
void texturesLayerDeleteDefinition(TextureLayerDefinition* definition)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-24 13:16:20 +00:00
|
|
|
zoneDelete(definition->zone);
|
|
|
|
noiseDeleteGenerator(definition->bump_noise);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void texturesLayerCopyDefinition(TextureLayerDefinition* source, TextureLayerDefinition* destination)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-01-24 13:16:20 +00:00
|
|
|
destination->color = source->color;
|
|
|
|
noiseCopy(source->bump_noise, destination->bump_noise);
|
|
|
|
zoneCopy(source->zone, destination->zone);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void texturesLayerValidateDefinition(TextureLayerDefinition* definition)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
int texturesGetLayerCount(TexturesDefinition* definition)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
return definition->nbtextures;
|
|
|
|
}
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
TextureLayerDefinition* texturesGetLayer(TexturesDefinition* definition, int layer)
|
|
|
|
{
|
|
|
|
if (layer >= 0 && layer < definition->nbtextures)
|
|
|
|
{
|
|
|
|
return definition->textures + layer;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return &_NULL_LAYER;
|
|
|
|
}
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
int texturesAddLayer(TexturesDefinition* definition)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
if (definition->nbtextures < TEXTURES_MAX_LAYERS)
|
|
|
|
{
|
2012-01-24 13:16:20 +00:00
|
|
|
definition->textures[definition->nbtextures] = texturesLayerCreateDefinition();
|
2012-01-23 23:45:33 +00:00
|
|
|
|
|
|
|
return definition->nbtextures++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void texturesDeleteLayer(TexturesDefinition* definition, int layer)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
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--;
|
|
|
|
}
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
|
|
|
|
2012-01-24 13:16:20 +00:00
|
|
|
static inline Vector3 _getNormal(TextureLayerDefinition* definition, Renderer* renderer, Vector3 point, double scale)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
|
|
|
Vector3 dpoint, ref, normal;
|
|
|
|
|
|
|
|
ref.x = 0.0;
|
|
|
|
ref.y = 0.0;
|
2012-01-24 13:16:20 +00:00
|
|
|
point.y = renderer->getTerrainHeight(renderer, 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;
|
2012-01-24 13:16:20 +00:00
|
|
|
dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x, dpoint.z);
|
2012-01-03 15:40:50 +00:00
|
|
|
ref.z = -1.0;
|
|
|
|
normal = v3Normalize(v3Cross(ref, v3Sub(dpoint, point)));
|
|
|
|
|
|
|
|
dpoint.x = point.x + scale;
|
|
|
|
dpoint.z = point.z;
|
2012-01-24 13:16:20 +00:00
|
|
|
dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x, dpoint.z);
|
2012-01-03 15:40:50 +00:00
|
|
|
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;
|
2012-01-24 13:16:20 +00:00
|
|
|
dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x, dpoint.z);
|
2012-01-03 15:40:50 +00:00
|
|
|
ref.x = 1.0;
|
|
|
|
normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point))));
|
|
|
|
|
|
|
|
dpoint.x = point.x;
|
|
|
|
dpoint.z = point.z + scale;
|
2012-01-24 13:16:20 +00:00
|
|
|
dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x, dpoint.z);
|
2012-01-03 15:40:50 +00:00
|
|
|
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-23 23:45:33 +00:00
|
|
|
Color texturesGetLayerColor(TextureLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
Color result;
|
2012-01-03 15:40:50 +00:00
|
|
|
Vector3 normal;
|
|
|
|
double coverage;
|
2012-01-23 23:45:33 +00:00
|
|
|
SurfaceMaterial material;
|
2012-01-18 18:47:46 +00:00
|
|
|
|
2012-01-22 22:06:11 +00:00
|
|
|
result = COLOR_TRANSPARENT;
|
2012-01-26 22:30:20 +00:00
|
|
|
normal = _getNormal(definition, renderer, location, detail);
|
2012-01-03 15:40:50 +00:00
|
|
|
|
|
|
|
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;
|
2012-01-26 18:20:19 +00:00
|
|
|
material.shininess = 4.0;
|
2012-01-22 22:06:11 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
result = renderer->applyLightingToSurface(renderer, location, normal, material);
|
2012-01-03 15:40:50 +00:00
|
|
|
result.a = coverage;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-01-24 13:16:20 +00:00
|
|
|
Color texturesGetColor(TexturesDefinition* definition, Renderer* renderer, Vector3 location, double detail)
|
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-03 15:40:50 +00:00
|
|
|
result = COLOR_GREEN;
|
2012-01-23 23:45:33 +00:00
|
|
|
for (i = 0; i < definition->nbtextures; i++)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
|
|
|
/* TODO Do not compute layers fully covered */
|
2012-01-28 11:04:27 +00:00
|
|
|
/* TODO Optimize : each layer computes the same shadows */
|
2012-01-24 13:16:20 +00:00
|
|
|
tex_color = texturesGetLayerColor(definition->textures + i, renderer, location, detail);
|
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;
|
|
|
|
}
|