paysages : Texture ranges replaced with curves.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@370 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-07-02 15:35:10 +00:00 committed by ThunderK
parent 2579d17f4a
commit b15b6c7d80
9 changed files with 82 additions and 289 deletions

View file

@ -15,6 +15,7 @@ Scenery :
* New cloud model with 2 noises : one for the global shape and one for edges. * New cloud model with 2 noises : one for the global shape and one for edges.
* Terrain shadows have been improved and are now configurable. * Terrain shadows have been improved and are now configurable.
* New sky model (based on Preetham's work). * New sky model (based on Preetham's work).
* Textures ranges are now using curves.
Rendering : Rendering :
* New texture model (perpendicular displacement and thickness). * New texture model (perpendicular displacement and thickness).

1
TODO
View file

@ -6,7 +6,6 @@ Technology Preview 2 :
- InputInt doesn't honor small_step. - InputInt doesn't honor small_step.
- Keep skydome lights in cache for a render. - Keep skydome lights in cache for a render.
- Add buttons to restore "auto" default values in tabs and dialogs. - Add buttons to restore "auto" default values in tabs and dialogs.
- Replace zone ranges with curves (with curve input and curve dialog).
- Interface for textures thickness, slope_range and thickness_transparency (and correct slider ranges). - Interface for textures thickness, slope_range and thickness_transparency (and correct slider ranges).
- Add "hardness to light" and shadow control ("minimum lighting") to material. - Add "hardness to light" and shadow control ("minimum lighting") to material.
- Add layer sorting/naming. - Add layer sorting/naming.

View file

@ -9,14 +9,8 @@ static TextureLayerDefinition _layer;
typedef struct typedef struct
{ {
double height_soft_min; Curve* height_curve;
double height_hard_min; Curve* slope_curve;
double height_hard_max;
double height_soft_max;
double slope_soft_min;
double slope_hard_min;
double slope_hard_max;
double slope_soft_max;
} TextureSupp; } TextureSupp;
static TextureSupp _supp; static TextureSupp _supp;
@ -133,6 +127,8 @@ FormTextures::FormTextures(QWidget *parent):
{ {
_definition = texturesCreateDefinition(); _definition = texturesCreateDefinition();
_layer = texturesLayerCreateDefinition(); _layer = texturesLayerCreateDefinition();
_supp.height_curve = curveCreate();
_supp.slope_curve = curveCreate();
previewCoverage = new PreviewTexturesCoverage(this); previewCoverage = new PreviewTexturesCoverage(this);
previewColor = new PreviewTexturesColor(this); previewColor = new PreviewTexturesColor(this);
@ -143,19 +139,20 @@ FormTextures::FormTextures(QWidget *parent):
addInputDouble(tr("Surface noise height"), &_layer.bump_height, 0.0, 0.5, 0.001, 0.05); addInputDouble(tr("Surface noise height"), &_layer.bump_height, 0.0, 0.5, 0.001, 0.05);
addInputDouble(tr("Surface noise scaling"), &_layer.bump_scaling, 0.01, 1.0, 0.01, 0.1); addInputDouble(tr("Surface noise scaling"), &_layer.bump_scaling, 0.01, 1.0, 0.01, 0.1);
addInputMaterial(tr("Material"), &_layer.material); addInputMaterial(tr("Material"), &_layer.material);
addInputCurve(tr("Coverage by altitude"), _supp.height_curve, -20.0, 20.0, 0.0, 1.0, tr("Terrain altitude"), tr("Texture coverage"));
addInputDouble(tr("Hard minimal height"), &_supp.height_hard_min, -20.0, 20.0, 0.1, 1.0); addInputCurve(tr("Coverage by slope"), _supp.slope_curve, 0.0, 5.0, 0.0, 1.0, tr("Terrain slope"), tr("Texture coverage"));
addInputDouble(tr("Soft minimal height"), &_supp.height_soft_min, -20.0, 20.0, 0.1, 1.0);
addInputDouble(tr("Soft maximal height"), &_supp.height_soft_max, -20.0, 20.0, 0.1, 1.0);
addInputDouble(tr("Hard maximal height"), &_supp.height_hard_max, -20.0, 20.0, 0.1, 1.0);
addInputDouble(tr("Hard minimal slope"), &_supp.slope_hard_min, 0.0, 5.0, 0.05, 0.5);
addInputDouble(tr("Soft minimal slope"), &_supp.slope_soft_min, 0.0, 5.0, 0.05, 0.5);
addInputDouble(tr("Soft maximal slope"), &_supp.slope_soft_max, 0.0, 5.0, 0.05, 0.5);
addInputDouble(tr("Hard maximal slope"), &_supp.slope_hard_max, 0.0, 5.0, 0.05, 0.5);
revertConfig(); revertConfig();
} }
FormTextures::~FormTextures()
{
texturesDeleteDefinition(&_definition);
texturesLayerDeleteDefinition(&_layer);
curveDelete(_supp.height_curve);
curveDelete(_supp.slope_curve);
}
void FormTextures::revertConfig() void FormTextures::revertConfig()
{ {
sceneryGetTextures(&_definition); sceneryGetTextures(&_definition);
@ -171,28 +168,10 @@ void FormTextures::applyConfig()
void FormTextures::configChangeEvent() void FormTextures::configChangeEvent()
{ {
ZoneRangeCondition range;
texturesLayerCopyDefinition(&_layer, texturesGetLayer(&_definition, currentLayer())); texturesLayerCopyDefinition(&_layer, texturesGetLayer(&_definition, currentLayer()));
if (zoneGetHeightRangeCount(_layer.zone) > 0) zoneSetHeightCurve(_layer.zone, _supp.height_curve);
{ zoneSetSlopeCurve(_layer.zone, _supp.slope_curve);
range.value = 1.0;
range.softmin = _supp.height_soft_min;
range.hardmin = _supp.height_hard_min;
range.hardmax = _supp.height_hard_max;
range.softmax = _supp.height_soft_max;
zoneSetHeightRange(_layer.zone, 0, &range);
}
if (zoneGetSlopeRangeCount(_layer.zone) > 0)
{
range.value = 1.0;
range.softmin = _supp.slope_soft_min;
range.hardmin = _supp.slope_hard_min;
range.hardmax = _supp.slope_hard_max;
range.softmax = _supp.slope_soft_max;
zoneSetSlopeRange(_layer.zone, 0, &range);
}
texturesValidateDefinition(&_definition); texturesValidateDefinition(&_definition);
BaseForm::configChangeEvent(); BaseForm::configChangeEvent();
@ -215,29 +194,10 @@ void FormTextures::layerDeletedEvent(int layer)
void FormTextures::layerSelectedEvent(int layer) void FormTextures::layerSelectedEvent(int layer)
{ {
ZoneRangeCondition range;
texturesLayerCopyDefinition(texturesGetLayer(&_definition, layer), &_layer); texturesLayerCopyDefinition(texturesGetLayer(&_definition, layer), &_layer);
if (zoneGetHeightRangeCount(_layer.zone) == 0) zoneGetHeightCurve(_layer.zone, _supp.height_curve);
{ zoneGetSlopeCurve(_layer.zone, _supp.slope_curve);
zoneAddHeightRange(_layer.zone);
}
zoneGetHeightRange(_layer.zone, 0, &range);
_supp.height_soft_min = range.softmin;
_supp.height_hard_min = range.hardmin;
_supp.height_hard_max = range.hardmax;
_supp.height_soft_max = range.softmax;
if (zoneGetSlopeRangeCount(_layer.zone) == 0)
{
zoneAddSlopeRange(_layer.zone);
}
zoneGetSlopeRange(_layer.zone, 0, &range);
_supp.slope_soft_min = range.softmin;
_supp.slope_hard_min = range.hardmin;
_supp.slope_hard_max = range.hardmax;
_supp.slope_soft_max = range.softmax;
BaseForm::layerSelectedEvent(layer); BaseForm::layerSelectedEvent(layer);
} }

View file

@ -11,6 +11,7 @@ class FormTextures : public BaseForm
public: public:
explicit FormTextures(QWidget *parent = 0); explicit FormTextures(QWidget *parent = 0);
~FormTextures();
protected: protected:
virtual void layerAddedEvent(); virtual void layerAddedEvent();

View file

@ -147,8 +147,6 @@ void autoGenRealisticLandscape(int seed)
/* Textures */ /* Textures */
textures = texturesCreateDefinition(); textures = texturesCreateDefinition();
texture = texturesGetLayer(&textures, texturesAddLayer(&textures)); texture = texturesGetLayer(&textures, texturesAddLayer(&textures));
zoneAddHeightRangeQuick(texture->zone, 1.0, -20.0, -20.0, 20.0, 20.0);
zoneAddSlopeRangeQuick(texture->zone, 1.0, 0.0, 0.0, 5.0, 5.0);
noiseGenerateBaseNoise(texture->bump_noise, 102400); noiseGenerateBaseNoise(texture->bump_noise, 102400);
noiseClearLevels(texture->bump_noise); noiseClearLevels(texture->bump_noise);
noiseAddLevelsSimple(texture->bump_noise, 8, 1.0, 1.0); noiseAddLevelsSimple(texture->bump_noise, 8, 1.0, 1.0);

View file

@ -8,6 +8,7 @@
struct Curve struct Curve
{ {
double default_value;
int nbpoints; int nbpoints;
CurvePoint points[MAX_NB_POINTS]; CurvePoint points[MAX_NB_POINTS];
}; };
@ -18,6 +19,7 @@ Curve* curveCreate()
result = malloc(sizeof(Curve)); result = malloc(sizeof(Curve));
result->nbpoints = 0; result->nbpoints = 0;
result->default_value = 0.0;
return result; return result;
} }
@ -36,6 +38,7 @@ void curveSave(PackStream* stream, Curve* curve)
{ {
int i; int i;
packWriteDouble(stream, &curve->default_value);
packWriteInt(stream, &curve->nbpoints); packWriteInt(stream, &curve->nbpoints);
for (i = 0; i < curve->nbpoints; i++) for (i = 0; i < curve->nbpoints; i++)
{ {
@ -48,6 +51,7 @@ void curveLoad(PackStream* stream, Curve* curve)
{ {
int i; int i;
packReadDouble(stream, &curve->default_value);
packReadInt(stream, &curve->nbpoints); packReadInt(stream, &curve->nbpoints);
for (i = 0; i < curve->nbpoints; i++) for (i = 0; i < curve->nbpoints; i++)
{ {
@ -61,6 +65,11 @@ void curveClear(Curve* curve)
curve->nbpoints = 0; curve->nbpoints = 0;
} }
void curveSetDefault(Curve* curve, double value)
{
curve->default_value = value;
}
int curveAddPoint(Curve* curve, CurvePoint* point) int curveAddPoint(Curve* curve, CurvePoint* point)
{ {
if (curve->nbpoints < MAX_NB_POINTS) if (curve->nbpoints < MAX_NB_POINTS)
@ -144,7 +153,7 @@ double curveGetValue(Curve* curve, double position)
if (curve->nbpoints == 0) if (curve->nbpoints == 0)
{ {
return 0.0; return curve->default_value;
} }
else if (curve->nbpoints == 1 || position <= curve->points[0].position) else if (curve->nbpoints == 1 || position <= curve->points[0].position)
{ {

View file

@ -21,6 +21,7 @@ void curveSave(PackStream* stream, Curve* curve);
void curveLoad(PackStream* stream, Curve* curve); void curveLoad(PackStream* stream, Curve* curve);
void curveClear(Curve* curve); void curveClear(Curve* curve);
void curveSetDefault(Curve* curve, double value);
int curveAddPoint(Curve* curve, CurvePoint* point); int curveAddPoint(Curve* curve, CurvePoint* point);
int curveQuickAddPoint(Curve* curve, double position, double value); int curveQuickAddPoint(Curve* curve, double position, double value);
int curveGetPointCount(Curve* curve); int curveGetPointCount(Curve* curve);

View file

@ -1,10 +1,12 @@
#include "zone.h" #include "zone.h"
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include "tools.h" #include "tools.h"
#define MAX_RANGES 20
#define MAX_CIRCLES 20 #define MAX_CIRCLES 20
typedef struct typedef struct
@ -17,11 +19,8 @@ typedef struct
} Circle; } Circle;
struct Zone { struct Zone {
ZoneRangeCondition height_ranges[MAX_RANGES]; Curve* value_by_height;
int height_ranges_count; Curve* value_by_slope;
ZoneRangeCondition slope_ranges[MAX_RANGES];
int slope_ranges_count;
Circle circles_included[MAX_CIRCLES]; Circle circles_included[MAX_CIRCLES];
int circles_included_count; int circles_included_count;
@ -35,8 +34,10 @@ Zone* zoneCreate()
Zone* result; Zone* result;
result = (Zone*)malloc(sizeof(Zone)); result = (Zone*)malloc(sizeof(Zone));
result->height_ranges_count = 0; result->value_by_height = curveCreate();
result->slope_ranges_count = 0; curveSetDefault(result->value_by_height, 1.0);
result->value_by_slope = curveCreate();
curveSetDefault(result->value_by_slope, 1.0);
result->circles_included_count = 0; result->circles_included_count = 0;
result->circles_excluded_count = 0; result->circles_excluded_count = 0;
@ -45,6 +46,8 @@ Zone* zoneCreate()
void zoneDelete(Zone* zone) void zoneDelete(Zone* zone)
{ {
curveDelete(zone->value_by_height);
curveDelete(zone->value_by_slope);
free(zone); free(zone);
} }
@ -52,25 +55,8 @@ void zoneSave(PackStream* stream, Zone* zone)
{ {
int i; int i;
packWriteInt(stream, &zone->height_ranges_count); curveSave(stream, zone->value_by_height);
for (i = 0; i < zone->height_ranges_count; i++) curveSave(stream, zone->value_by_slope);
{
packWriteDouble(stream, &zone->height_ranges[i].value);
packWriteDouble(stream, &zone->height_ranges[i].hardmin);
packWriteDouble(stream, &zone->height_ranges[i].softmin);
packWriteDouble(stream, &zone->height_ranges[i].softmax);
packWriteDouble(stream, &zone->height_ranges[i].hardmax);
}
packWriteInt(stream, &zone->slope_ranges_count);
for (i = 0; i < zone->slope_ranges_count; i++)
{
packWriteDouble(stream, &zone->slope_ranges[i].value);
packWriteDouble(stream, &zone->slope_ranges[i].hardmin);
packWriteDouble(stream, &zone->slope_ranges[i].softmin);
packWriteDouble(stream, &zone->slope_ranges[i].softmax);
packWriteDouble(stream, &zone->slope_ranges[i].hardmax);
}
packWriteInt(stream, &zone->circles_included_count); packWriteInt(stream, &zone->circles_included_count);
for (i = 0; i < zone->circles_included_count; i++) for (i = 0; i < zone->circles_included_count; i++)
@ -97,25 +83,8 @@ void zoneLoad(PackStream* stream, Zone* zone)
{ {
int i; int i;
packReadInt(stream, &zone->height_ranges_count); curveLoad(stream, zone->value_by_height);
for (i = 0; i < zone->height_ranges_count; i++) curveLoad(stream, zone->value_by_slope);
{
packReadDouble(stream, &zone->height_ranges[i].value);
packReadDouble(stream, &zone->height_ranges[i].hardmin);
packReadDouble(stream, &zone->height_ranges[i].softmin);
packReadDouble(stream, &zone->height_ranges[i].softmax);
packReadDouble(stream, &zone->height_ranges[i].hardmax);
}
packReadInt(stream, &zone->slope_ranges_count);
for (i = 0; i < zone->slope_ranges_count; i++)
{
packReadDouble(stream, &zone->slope_ranges[i].value);
packReadDouble(stream, &zone->slope_ranges[i].hardmin);
packReadDouble(stream, &zone->slope_ranges[i].softmin);
packReadDouble(stream, &zone->slope_ranges[i].softmax);
packReadDouble(stream, &zone->slope_ranges[i].hardmax);
}
packReadInt(stream, &zone->circles_included_count); packReadInt(stream, &zone->circles_included_count);
for (i = 0; i < zone->circles_included_count; i++) for (i = 0; i < zone->circles_included_count; i++)
@ -140,7 +109,14 @@ void zoneLoad(PackStream* stream, Zone* zone)
void zoneCopy(Zone* source, Zone* destination) void zoneCopy(Zone* source, Zone* destination)
{ {
*destination = *source; curveCopy(source->value_by_height, destination->value_by_height);
curveCopy(source->value_by_slope, destination->value_by_slope);
memcpy(destination->circles_included, source->circles_included, sizeof(Circle) * source->circles_included_count);
destination->circles_included_count = source->circles_included_count;
memcpy(destination->circles_excluded, source->circles_excluded, sizeof(Circle) * source->circles_excluded_count);
destination->circles_excluded_count = source->circles_excluded_count;
} }
void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius) void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius)
@ -158,149 +134,40 @@ void zoneExcludeCircleArea(Zone* zone, double centerx, double centerz, double so
/* TODO */ /* TODO */
} }
int zoneAddHeightRange(Zone* zone) void zoneGetHeightCurve(Zone* zone, Curve* curve)
{ {
if (zone->height_ranges_count < MAX_RANGES) curveCopy(zone->value_by_height, curve);
{
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) void zoneSetHeightCurve(Zone* zone, Curve* curve)
{ {
return zone->height_ranges_count; curveCopy(curve, zone->value_by_height);
} }
int zoneGetHeightRange(Zone* zone, int position, ZoneRangeCondition* range) void zoneAddHeightRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax)
{ {
if (position >= 0 && position < zone->height_ranges_count) curveQuickAddPoint(zone->value_by_height, hardmin, 0.0);
{ curveQuickAddPoint(zone->value_by_height, softmin, value);
*range = zone->height_ranges[position]; curveQuickAddPoint(zone->value_by_height, softmax, value);
return 1; curveQuickAddPoint(zone->value_by_height, hardmax, 0.0);
}
else
{
return 0;
}
} }
int zoneSetHeightRange(Zone* zone, int position, ZoneRangeCondition* range) void zoneGetSlopeCurve(Zone* zone, Curve* curve)
{ {
if (position >= 0 && position < zone->height_ranges_count) curveCopy(zone->value_by_slope, curve);
{
zone->height_ranges[position] = *range;
return 1;
}
else
{
return 0;
}
} }
int zoneAddHeightRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax) void zoneSetSlopeCurve(Zone* zone, Curve* curve)
{ {
ZoneRangeCondition range = {value, hardmin, softmin, softmax, hardmax}; curveCopy(curve, zone->value_by_slope);
int position;
position = zoneAddHeightRange(zone);
if (position >= 0)
{
zoneSetHeightRange(zone, position, &range);
}
return position;
} }
int zoneAddSlopeRange(Zone* zone) void zoneAddSlopeRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax)
{ {
if (zone->slope_ranges_count < MAX_RANGES) curveQuickAddPoint(zone->value_by_slope, hardmin, 0.0);
{ curveQuickAddPoint(zone->value_by_slope, softmin, value);
zone->slope_ranges[zone->slope_ranges_count].value = 0.0; curveQuickAddPoint(zone->value_by_slope, softmax, value);
zone->slope_ranges[zone->slope_ranges_count].softmin = 0.0; curveQuickAddPoint(zone->value_by_slope, hardmax, 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;
}
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)
{
zoneSetSlopeRange(zone, position, &range);
}
return position;
}
static inline double _getRangeInfluence(ZoneRangeCondition 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) static inline double _getCircleInfluence(Circle circle, Vector3 position)
@ -347,39 +214,8 @@ double zoneGetValue(Zone* zone, Vector3 location, Vector3 normal)
value_circle = 1.0; value_circle = 1.0;
} }
if (zone->height_ranges_count > 0) value_height = curveGetValue(zone->value_by_height, location.y);
{ value_steepness = curveGetValue(zone->value_by_slope, (1.0 - normal.y));
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->slope_ranges_count > 0)
{
value_steepness = 0.0;
for (i = 0; i < zone->slope_ranges_count; i++)
{
value = _getRangeInfluence(zone->slope_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_steepness < value_height)
{ {

View file

@ -2,6 +2,7 @@
#define _PAYSAGES_ZONE_H_ #define _PAYSAGES_ZONE_H_
#include "shared/types.h" #include "shared/types.h"
#include "curve.h"
#include "pack.h" #include "pack.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -10,15 +11,6 @@ extern "C" {
typedef struct Zone Zone; typedef struct Zone Zone;
typedef struct
{
double value;
double hardmin;
double softmin;
double softmax;
double hardmax;
} ZoneRangeCondition;
Zone* zoneCreate(); Zone* zoneCreate();
void zoneDelete(Zone* zone); void zoneDelete(Zone* zone);
void zoneSave(PackStream* stream, Zone* zone); void zoneSave(PackStream* stream, Zone* zone);
@ -27,17 +19,13 @@ void zoneCopy(Zone* source, Zone* destination);
void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius); void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius);
void zoneExcludeCircleArea(Zone* zone, double centerx, double centerz, double softradius, double hardradius); void zoneExcludeCircleArea(Zone* zone, double centerx, double centerz, double softradius, double hardradius);
int zoneAddHeightRange(Zone* zone); void zoneGetHeightCurve(Zone* zone, Curve* curve);
int zoneGetHeightRangeCount(Zone* zone); void zoneSetHeightCurve(Zone* zone, Curve* curve);
int zoneGetHeightRange(Zone* zone, int position, ZoneRangeCondition* range); void zoneAddHeightRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax);
int zoneSetHeightRange(Zone* zone, int position, ZoneRangeCondition* range);
int zoneAddHeightRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax);
int zoneAddSlopeRange(Zone* zone); void zoneGetSlopeCurve(Zone* zone, Curve* curve);
int zoneGetSlopeRangeCount(Zone* zone); void zoneSetSlopeCurve(Zone* zone, Curve* curve);
int zoneGetSlopeRange(Zone* zone, int position, ZoneRangeCondition* range); void zoneAddSlopeRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax);
int zoneSetSlopeRange(Zone* zone, int position, ZoneRangeCondition* range);
int zoneAddSlopeRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax);
double zoneGetValue(Zone* zone, Vector3 location, Vector3 normal); double zoneGetValue(Zone* zone, Vector3 location, Vector3 normal);