#include #include #define MAX_RANGES 20 #define MAX_CIRCLES 20 typedef struct { double value; double hardmin; double softmin; double softmax; double hardmax; } Range; typedef struct { double value; double centerx; double centerz; double softradius; double hardradius; } Circle; struct Zone { Range height_ranges[MAX_RANGES]; int height_ranges_count; Range steepness_ranges[MAX_RANGES]; int steepness_ranges_count; Circle circles_included[MAX_CIRCLES]; int circles_included_count; Circle circles_excluded[MAX_CIRCLES]; int circles_excluded_count; }; #include "shared/types.h" #include "shared/functions.h" void zoneSave(Zone* zone, FILE* f) { } void zoneLoad(Zone* zone, FILE* f) { } Zone* zoneCreate() { Zone* result; result = (Zone*)malloc(sizeof(Zone)); result->height_ranges_count = 0; result->steepness_ranges_count = 0; result->circles_included_count = 0; result->circles_excluded_count = 0; return result; } void zoneDelete(Zone* zone) { free(zone); } 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 */ } void zoneAddHeightRange(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax) { Range range = {value, hardmin, softmin, softmax, hardmax}; if (zone->height_ranges_count < MAX_RANGES) { zone->height_ranges[zone->height_ranges_count++] = range; } } void zoneAddSteepnessRange(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax) { Range range = {value, hardmin, softmin, softmax, hardmax}; if (zone->steepness_ranges_count < MAX_RANGES) { zone->steepness_ranges[zone->steepness_ranges_count++] = range; } } static inline double _getRangeInfluence(Range range, double position) { 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; dx = position.x - circle.centerx; dz = position.z - circle.centerz; radius = sqrt(dx * dx + dz * dz); 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; 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; } if (zone->steepness_ranges_count > 0) { value_steepness = 0.0; for (i = 0; i < zone->steepness_ranges_count; i++) { value = _getRangeInfluence(zone->steepness_ranges[i], (1.0 - normal.y)); 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; } } }