2012-01-29 17:39:56 +00:00
|
|
|
#include "zone.h"
|
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <math.h>
|
2012-01-29 17:39:56 +00:00
|
|
|
#include "tools.h"
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
#define MAX_RANGES 20
|
|
|
|
#define MAX_CIRCLES 20
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
double value;
|
|
|
|
double centerx;
|
|
|
|
double centerz;
|
|
|
|
double softradius;
|
|
|
|
double hardradius;
|
|
|
|
} Circle;
|
|
|
|
|
|
|
|
struct Zone {
|
2012-04-05 20:09:39 +00:00
|
|
|
ZoneRangeCondition height_ranges[MAX_RANGES];
|
2011-12-10 13:25:22 +00:00
|
|
|
int height_ranges_count;
|
|
|
|
|
2012-04-05 20:09:39 +00:00
|
|
|
ZoneRangeCondition slope_ranges[MAX_RANGES];
|
|
|
|
int slope_ranges_count;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
Circle circles_included[MAX_CIRCLES];
|
|
|
|
int circles_included_count;
|
|
|
|
|
|
|
|
Circle circles_excluded[MAX_CIRCLES];
|
|
|
|
int circles_excluded_count;
|
|
|
|
};
|
|
|
|
|
|
|
|
Zone* zoneCreate()
|
|
|
|
{
|
|
|
|
Zone* result;
|
|
|
|
|
|
|
|
result = (Zone*)malloc(sizeof(Zone));
|
|
|
|
result->height_ranges_count = 0;
|
2012-04-05 20:09:39 +00:00
|
|
|
result->slope_ranges_count = 0;
|
2011-12-10 13:25:22 +00:00
|
|
|
result->circles_included_count = 0;
|
|
|
|
result->circles_excluded_count = 0;
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void zoneDelete(Zone* zone)
|
|
|
|
{
|
|
|
|
free(zone);
|
|
|
|
}
|
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
void zoneSave(FILE* f, Zone* zone)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
|
|
|
int i;
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsSaveInt(f, &zone->height_ranges_count);
|
2012-01-03 15:40:50 +00:00
|
|
|
for (i = 0; i < zone->height_ranges_count; i++)
|
|
|
|
{
|
2012-01-29 17:39:56 +00:00
|
|
|
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);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2012-04-05 20:09:39 +00:00
|
|
|
toolsSaveInt(f, &zone->slope_ranges_count);
|
|
|
|
for (i = 0; i < zone->slope_ranges_count; i++)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-04-05 20:09:39 +00:00
|
|
|
toolsSaveDouble(f, &zone->slope_ranges[i].value);
|
|
|
|
toolsSaveDouble(f, &zone->slope_ranges[i].hardmin);
|
|
|
|
toolsSaveDouble(f, &zone->slope_ranges[i].softmin);
|
|
|
|
toolsSaveDouble(f, &zone->slope_ranges[i].softmax);
|
|
|
|
toolsSaveDouble(f, &zone->slope_ranges[i].hardmax);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsSaveInt(f, &zone->circles_included_count);
|
2012-01-03 15:40:50 +00:00
|
|
|
for (i = 0; i < zone->circles_included_count; i++)
|
|
|
|
{
|
2012-01-29 17:39:56 +00:00
|
|
|
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);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsSaveInt(f, &zone->circles_excluded_count);
|
2012-01-03 15:40:50 +00:00
|
|
|
for (i = 0; i < zone->circles_excluded_count; i++)
|
|
|
|
{
|
2012-01-29 17:39:56 +00:00
|
|
|
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);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
void zoneLoad(FILE* f, Zone* zone)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
|
|
|
int i;
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsLoadInt(f, &zone->height_ranges_count);
|
2012-01-03 15:40:50 +00:00
|
|
|
for (i = 0; i < zone->height_ranges_count; i++)
|
|
|
|
{
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsLoadDouble(f, &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);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2012-04-05 20:09:39 +00:00
|
|
|
toolsLoadInt(f, &zone->slope_ranges_count);
|
|
|
|
for (i = 0; i < zone->slope_ranges_count; i++)
|
2012-01-03 15:40:50 +00:00
|
|
|
{
|
2012-04-05 20:09:39 +00:00
|
|
|
toolsLoadDouble(f, &zone->slope_ranges[i].value);
|
|
|
|
toolsLoadDouble(f, &zone->slope_ranges[i].hardmin);
|
|
|
|
toolsLoadDouble(f, &zone->slope_ranges[i].softmin);
|
|
|
|
toolsLoadDouble(f, &zone->slope_ranges[i].softmax);
|
|
|
|
toolsLoadDouble(f, &zone->slope_ranges[i].hardmax);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsLoadInt(f, &zone->circles_included_count);
|
2012-01-03 15:40:50 +00:00
|
|
|
for (i = 0; i < zone->circles_included_count; i++)
|
|
|
|
{
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsLoadDouble(f, &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);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsLoadInt(f, &zone->circles_excluded_count);
|
2012-01-03 15:40:50 +00:00
|
|
|
for (i = 0; i < zone->circles_excluded_count; i++)
|
|
|
|
{
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsLoadDouble(f, &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);
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void zoneCopy(Zone* source, Zone* destination)
|
|
|
|
{
|
2012-01-03 17:43:01 +00:00
|
|
|
*destination = *source;
|
2012-01-03 15:40:50 +00:00
|
|
|
}
|
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius)
|
|
|
|
{
|
|
|
|
Circle circle = {value, centerx, centerz, softradius, hardradius};
|
|
|
|
|
|
|
|
if (zone->circles_included_count < MAX_CIRCLES)
|
|
|
|
{
|
|
|
|
zone->circles_included[zone->circles_included_count++] = circle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void zoneExcludeCircleArea(Zone* zone, double centerx, double centerz, double softradius, double hardradius)
|
|
|
|
{
|
|
|
|
/* TODO */
|
|
|
|
}
|
|
|
|
|
2012-04-05 20:09:39 +00:00
|
|
|
int zoneAddHeightRange(Zone* zone)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
if (zone->height_ranges_count < MAX_RANGES)
|
|
|
|
{
|
2012-04-05 20:09:39 +00:00
|
|
|
zone->height_ranges[zone->height_ranges_count].value = 0.0;
|
|
|
|
zone->height_ranges[zone->height_ranges_count].softmin = 0.0;
|
|
|
|
zone->height_ranges[zone->height_ranges_count].hardmin = 0.0;
|
|
|
|
zone->height_ranges[zone->height_ranges_count].hardmax = 0.0;
|
|
|
|
zone->height_ranges[zone->height_ranges_count].softmax = 0.0;
|
|
|
|
return zone->height_ranges_count++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int zoneGetHeightRangeCount(Zone* zone)
|
|
|
|
{
|
|
|
|
return zone->height_ranges_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
int zoneGetHeightRange(Zone* zone, int position, ZoneRangeCondition* range)
|
|
|
|
{
|
|
|
|
if (position >= 0 && position < zone->height_ranges_count)
|
|
|
|
{
|
|
|
|
*range = zone->height_ranges[position];
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int zoneSetHeightRange(Zone* zone, int position, ZoneRangeCondition* range)
|
|
|
|
{
|
|
|
|
if (position >= 0 && position < zone->height_ranges_count)
|
|
|
|
{
|
|
|
|
zone->height_ranges[position] = *range;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int zoneAddHeightRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax)
|
|
|
|
{
|
|
|
|
ZoneRangeCondition range = {value, hardmin, softmin, softmax, hardmax};
|
|
|
|
int position;
|
|
|
|
|
|
|
|
position = zoneAddHeightRange(zone);
|
|
|
|
if (position >= 0)
|
|
|
|
{
|
|
|
|
zoneSetHeightRange(zone, position, &range);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
2012-04-05 20:09:39 +00:00
|
|
|
return position;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-04-05 20:09:39 +00:00
|
|
|
int zoneAddSlopeRange(Zone* zone)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-04-05 20:09:39 +00:00
|
|
|
if (zone->slope_ranges_count < MAX_RANGES)
|
|
|
|
{
|
|
|
|
zone->slope_ranges[zone->slope_ranges_count].value = 0.0;
|
|
|
|
zone->slope_ranges[zone->slope_ranges_count].softmin = 0.0;
|
|
|
|
zone->slope_ranges[zone->slope_ranges_count].hardmin = 0.0;
|
|
|
|
zone->slope_ranges[zone->slope_ranges_count].hardmax = 0.0;
|
|
|
|
zone->slope_ranges[zone->slope_ranges_count].softmax = 0.0;
|
|
|
|
return zone->slope_ranges_count++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int zoneGetSlopeRangeCount(Zone* zone)
|
|
|
|
{
|
|
|
|
return zone->slope_ranges_count;
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-04-05 20:09:39 +00:00
|
|
|
int zoneGetSlopeRange(Zone* zone, int position, ZoneRangeCondition* range)
|
|
|
|
{
|
|
|
|
if (position >= 0 && position < zone->slope_ranges_count)
|
|
|
|
{
|
|
|
|
*range = zone->slope_ranges[position];
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int zoneSetSlopeRange(Zone* zone, int position, ZoneRangeCondition* range)
|
|
|
|
{
|
|
|
|
if (position >= 0 && position < zone->slope_ranges_count)
|
|
|
|
{
|
|
|
|
zone->slope_ranges[position] = *range;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int zoneAddSlopeRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax)
|
|
|
|
{
|
|
|
|
ZoneRangeCondition range = {value, hardmin, softmin, softmax, hardmax};
|
|
|
|
int position;
|
|
|
|
|
|
|
|
position = zoneAddSlopeRange(zone);
|
|
|
|
if (position >= 0)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-04-05 20:09:39 +00:00
|
|
|
zoneSetSlopeRange(zone, position, &range);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
2012-04-05 20:09:39 +00:00
|
|
|
return position;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-04-05 20:09:39 +00:00
|
|
|
static inline double _getRangeInfluence(ZoneRangeCondition range, double position)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
if (position >= range.hardmin && position <= range.hardmax)
|
|
|
|
{
|
|
|
|
if (position < range.softmin)
|
|
|
|
{
|
|
|
|
return range.value * (position - range.hardmin) / (range.softmin - range.hardmin);
|
|
|
|
}
|
|
|
|
else if (position > range.softmax)
|
|
|
|
{
|
|
|
|
return range.value * (range.hardmax - position) / (range.hardmax - range.softmax);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return range.value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline double _getCircleInfluence(Circle circle, Vector3 position)
|
|
|
|
{
|
|
|
|
double radius, dx, dz;
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
dx = position.x - circle.centerx;
|
|
|
|
dz = position.z - circle.centerz;
|
|
|
|
radius = sqrt(dx * dx + dz * dz);
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
if (radius > circle.hardradius)
|
|
|
|
{
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
else if (radius < circle.softradius)
|
|
|
|
{
|
|
|
|
return circle.value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return circle.value * (circle.hardradius - radius) / (circle.hardradius - circle.softradius);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
double zoneGetValue(Zone* zone, Vector3 location, Vector3 normal)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
double value, value_height, value_steepness, value_circle;
|
2012-01-03 17:43:01 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
if (zone->circles_included_count > 0)
|
|
|
|
{
|
|
|
|
value_circle = 0.0;
|
|
|
|
for (i = 0; i < zone->circles_included_count; i++)
|
|
|
|
{
|
|
|
|
value = _getCircleInfluence(zone->circles_included[i], location);
|
|
|
|
if (value > value_circle)
|
|
|
|
{
|
|
|
|
value_circle = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value_circle = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zone->height_ranges_count > 0)
|
|
|
|
{
|
|
|
|
value_height = 0.0;
|
|
|
|
for (i = 0; i < zone->height_ranges_count; i++)
|
|
|
|
{
|
|
|
|
value = _getRangeInfluence(zone->height_ranges[i], location.y);
|
|
|
|
if (value > value_height)
|
|
|
|
{
|
|
|
|
value_height = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value_height = 1.0;
|
|
|
|
}
|
|
|
|
|
2012-04-05 20:09:39 +00:00
|
|
|
if (zone->slope_ranges_count > 0)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
value_steepness = 0.0;
|
2012-04-05 20:09:39 +00:00
|
|
|
for (i = 0; i < zone->slope_ranges_count; i++)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-04-05 20:09:39 +00:00
|
|
|
value = _getRangeInfluence(zone->slope_ranges[i], (1.0 - normal.y));
|
2011-12-10 13:25:22 +00:00
|
|
|
if (value > value_steepness)
|
|
|
|
{
|
|
|
|
value_steepness = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value_steepness = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value_steepness < value_height)
|
|
|
|
{
|
|
|
|
if (value_circle < value_steepness)
|
|
|
|
{
|
|
|
|
return value_circle;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return value_steepness;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (value_circle < value_height)
|
|
|
|
{
|
|
|
|
return value_circle;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return value_height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|