paysages: Textures form (with ranges).

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@288 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-04-05 20:09:39 +00:00 committed by ThunderK
parent d71c09e0d2
commit ae30098277
6 changed files with 278 additions and 79 deletions

View file

@ -7,6 +7,19 @@
static TexturesDefinition _definition; static TexturesDefinition _definition;
static TextureLayerDefinition _layer; static TextureLayerDefinition _layer;
typedef struct
{
double height_soft_min;
double height_hard_min;
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;
static TextureSupp _supp;
/**************** Previews ****************/ /**************** Previews ****************/
class PreviewTexturesCoverage:public BasePreview class PreviewTexturesCoverage:public BasePreview
{ {
@ -119,6 +132,15 @@ FormTextures::FormTextures(QWidget *parent):
addInputDouble(tr("Light reflection"), &_layer.material.reflection, 0.0, 1.0, 0.01, 0.1); addInputDouble(tr("Light reflection"), &_layer.material.reflection, 0.0, 1.0, 0.01, 0.1);
addInputDouble(tr("Light reflection shininess"), &_layer.material.shininess, 0.0, 20.0, 0.1, 1.0); addInputDouble(tr("Light reflection shininess"), &_layer.material.shininess, 0.0, 20.0, 0.1, 1.0);
addInputDouble(tr("Hard minimal height"), &_supp.height_hard_min, -20.0, 20.0, 0.1, 1.0);
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();
} }
@ -137,7 +159,29 @@ 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)
{
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();
} }
@ -159,7 +203,29 @@ 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)
{
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

@ -10,7 +10,7 @@ InputDouble::InputDouble(QWidget* form, QString label, double* value, double min
slider = new QSlider(form); slider = new QSlider(form);
slider->setOrientation(Qt::Horizontal); slider->setOrientation(Qt::Horizontal);
slider->setMinimumWidth(150); slider->setMinimumWidth(200);
slider->setMaximumWidth(400); slider->setMaximumWidth(400);
slider->setMinimum(0); slider->setMinimum(0);

View file

@ -477,7 +477,7 @@ Maintenir Ctrl : Plus rapide</translation>
<context> <context>
<name>FormTextures</name> <name>FormTextures</name>
<message> <message>
<location filename="../gui_qt/formtextures.cpp" line="112"/> <location filename="../gui_qt/formtextures.cpp" line="125"/>
<source>Coverage preview</source> <source>Coverage preview</source>
<translation>Aperçu de la couverture</translation> <translation>Aperçu de la couverture</translation>
</message> </message>
@ -486,40 +486,80 @@ Maintenir Ctrl : Plus rapide</translation>
<translation type="obsolete">Rendu en couleur</translation> <translation type="obsolete">Rendu en couleur</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formtextures.cpp" line="113"/> <location filename="../gui_qt/formtextures.cpp" line="126"/>
<source>Lighted sample</source> <source>Lighted sample</source>
<translation>Echantillon éclairé</translation> <translation>Echantillon éclairé</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formtextures.cpp" line="115"/> <location filename="../gui_qt/formtextures.cpp" line="128"/>
<source>Surface noise</source> <source>Surface noise</source>
<translation>Bruit de surface</translation> <translation>Bruit de surface</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formtextures.cpp" line="116"/> <location filename="../gui_qt/formtextures.cpp" line="129"/>
<source>Surface noise height</source> <source>Surface noise height</source>
<translation>Hauteur du bruit</translation> <translation>Hauteur du bruit</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formtextures.cpp" line="117"/> <location filename="../gui_qt/formtextures.cpp" line="130"/>
<source>Surface noise scaling</source> <source>Surface noise scaling</source>
<translation>Echelle du bruit</translation> <translation>Echelle du bruit</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formtextures.cpp" line="118"/> <location filename="../gui_qt/formtextures.cpp" line="131"/>
<source>Base color</source> <source>Base color</source>
<translation>Couleur de base</translation> <translation>Couleur de base</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formtextures.cpp" line="119"/> <location filename="../gui_qt/formtextures.cpp" line="132"/>
<source>Light reflection</source> <source>Light reflection</source>
<translation>Réflexion de lumière</translation> <translation>Réflexion de lumière</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formtextures.cpp" line="120"/> <location filename="../gui_qt/formtextures.cpp" line="133"/>
<source>Light reflection shininess</source> <source>Light reflection shininess</source>
<translation>Concentration de la réflexion de lumière</translation> <translation>Concentration de la réflexion de lumière</translation>
</message> </message>
<message>
<location filename="../gui_qt/formtextures.cpp" line="136"/>
<source>Soft minimal height</source>
<translation>Altitude minimal (adoucie)</translation>
</message>
<message>
<location filename="../gui_qt/formtextures.cpp" line="135"/>
<source>Hard minimal height</source>
<translation>Altitude minimale</translation>
</message>
<message>
<location filename="../gui_qt/formtextures.cpp" line="138"/>
<source>Hard maximal height</source>
<translation>Altitude maximale</translation>
</message>
<message>
<location filename="../gui_qt/formtextures.cpp" line="137"/>
<source>Soft maximal height</source>
<translation>Altitude maximale (adoucie)</translation>
</message>
<message>
<location filename="../gui_qt/formtextures.cpp" line="140"/>
<source>Soft minimal slope</source>
<translation>Pente minimale (adoucie)</translation>
</message>
<message>
<location filename="../gui_qt/formtextures.cpp" line="139"/>
<source>Hard minimal slope</source>
<translation>Pente minimale</translation>
</message>
<message>
<location filename="../gui_qt/formtextures.cpp" line="142"/>
<source>Hard maximal slope</source>
<translation>Pente maximale</translation>
</message>
<message>
<location filename="../gui_qt/formtextures.cpp" line="141"/>
<source>Soft maximal slope</source>
<translation>Pente maximale (adoucie)</translation>
</message>
</context> </context>
<context> <context>
<name>FormWater</name> <name>FormWater</name>
@ -761,7 +801,7 @@ Maintenir Ctrl : Plus rapide</translation>
Credits : Credits :
Programming - Michael Lemaire</source> Programming - Michael Lemaire</source>
<translation type="unfinished">Un logiciel d&apos;édition et rendu de décors naturels en 3D <translation>Un logiciel d&apos;édition et rendu de décors naturels en 3D
Crédits : Crédits :
Développement - Michaël LEMAIRE</translation> Développement - Michaël LEMAIRE</translation>

View file

@ -66,8 +66,6 @@ void autoGenRealisticLandscape(int seed)
TexturesDefinition textures; TexturesDefinition textures;
TextureLayerDefinition* texture; TextureLayerDefinition* texture;
LightingDefinition lighting; LightingDefinition lighting;
HeightModifier* mod;
Zone* zone;
if (!seed) if (!seed)
{ {
@ -144,32 +142,14 @@ void autoGenRealisticLandscape(int seed)
noiseAddLevelsSimple(terrain.height_noise, 10, 1.0, 1.0); noiseAddLevelsSimple(terrain.height_noise, 10, 1.0, 1.0);
terrain.height_factor = 12.0 / noiseGetMaxValue(terrain.height_noise); terrain.height_factor = 12.0 / noiseGetMaxValue(terrain.height_noise);
terrain.scaling = 10.0; terrain.scaling = 10.0;
/* DEBUG */
mod = modifierCreate();
zone = modifierGetZone(mod);
zoneIncludeCircleArea(zone, 0.4, 0.0, 0.0, 8.0, 20.0);
modifierActionFixValue(mod, -2.0);
terrainAddModifier(&terrain, mod);
modifierDelete(mod);
mod = modifierCreate();
zone = modifierGetZone(mod);
zoneIncludeCircleArea(zone, 1.0, 0.0, 0.0, 0.3, 8.0);
modifierActionAddValue(mod, 8.0);
terrainAddModifier(&terrain, mod);
modifierDelete(mod);
mod = modifierCreate();
zone = modifierGetZone(mod);
zoneIncludeCircleArea(zone, 0.8, 0.0, 0.0, 0.3, 4.0);
modifierActionFixValue(mod, -8.0);
terrainAddModifier(&terrain, mod);
modifierDelete(mod);
/* DEBUG */
scenerySetTerrain(&terrain); scenerySetTerrain(&terrain);
terrainDeleteDefinition(&terrain); terrainDeleteDefinition(&terrain);
/* 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);
noiseAddLevelsSimple(texture->bump_noise, 6, 1.0, 1.0); noiseAddLevelsSimple(texture->bump_noise, 6, 1.0, 1.0);
texture->bump_height = 0.1; texture->bump_height = 0.1;
@ -180,8 +160,8 @@ void autoGenRealisticLandscape(int seed)
texture->material.reflection = 0.2; texture->material.reflection = 0.2;
texture->material.shininess = 3.0; texture->material.shininess = 3.0;
texture = texturesGetLayer(&textures, texturesAddLayer(&textures)); texture = texturesGetLayer(&textures, texturesAddLayer(&textures));
zoneAddHeightRange(texture->zone, 1.0, -1.0, 0.0, 3.0, 15.0); zoneAddHeightRangeQuick(texture->zone, 1.0, -1.0, 0.0, 3.0, 15.0);
zoneAddSteepnessRange(texture->zone, 1.0, 0.0, 0.0, 0.2, 0.3); zoneAddSlopeRangeQuick(texture->zone, 1.0, 0.0, 0.0, 0.2, 0.3);
noiseGenerateBaseNoise(texture->bump_noise, 102400); noiseGenerateBaseNoise(texture->bump_noise, 102400);
noiseAddLevelsSimple(texture->bump_noise, 6, 1.0, 0.4); noiseAddLevelsSimple(texture->bump_noise, 6, 1.0, 0.4);
texture->bump_height = 0.02; texture->bump_height = 0.02;

View file

@ -7,15 +7,6 @@
#define MAX_RANGES 20 #define MAX_RANGES 20
#define MAX_CIRCLES 20 #define MAX_CIRCLES 20
typedef struct
{
double value;
double hardmin;
double softmin;
double softmax;
double hardmax;
} Range;
typedef struct typedef struct
{ {
double value; double value;
@ -26,11 +17,11 @@ typedef struct
} Circle; } Circle;
struct Zone { struct Zone {
Range height_ranges[MAX_RANGES]; ZoneRangeCondition height_ranges[MAX_RANGES];
int height_ranges_count; int height_ranges_count;
Range steepness_ranges[MAX_RANGES]; ZoneRangeCondition slope_ranges[MAX_RANGES];
int steepness_ranges_count; int slope_ranges_count;
Circle circles_included[MAX_CIRCLES]; Circle circles_included[MAX_CIRCLES];
int circles_included_count; int circles_included_count;
@ -45,7 +36,7 @@ Zone* zoneCreate()
result = (Zone*)malloc(sizeof(Zone)); result = (Zone*)malloc(sizeof(Zone));
result->height_ranges_count = 0; result->height_ranges_count = 0;
result->steepness_ranges_count = 0; result->slope_ranges_count = 0;
result->circles_included_count = 0; result->circles_included_count = 0;
result->circles_excluded_count = 0; result->circles_excluded_count = 0;
@ -71,14 +62,14 @@ void zoneSave(FILE* f, Zone* zone)
toolsSaveDouble(f, &zone->height_ranges[i].hardmax); toolsSaveDouble(f, &zone->height_ranges[i].hardmax);
} }
toolsSaveInt(f, &zone->steepness_ranges_count); toolsSaveInt(f, &zone->slope_ranges_count);
for (i = 0; i < zone->steepness_ranges_count; i++) for (i = 0; i < zone->slope_ranges_count; i++)
{ {
toolsSaveDouble(f, &zone->steepness_ranges[i].value); toolsSaveDouble(f, &zone->slope_ranges[i].value);
toolsSaveDouble(f, &zone->steepness_ranges[i].hardmin); toolsSaveDouble(f, &zone->slope_ranges[i].hardmin);
toolsSaveDouble(f, &zone->steepness_ranges[i].softmin); toolsSaveDouble(f, &zone->slope_ranges[i].softmin);
toolsSaveDouble(f, &zone->steepness_ranges[i].softmax); toolsSaveDouble(f, &zone->slope_ranges[i].softmax);
toolsSaveDouble(f, &zone->steepness_ranges[i].hardmax); toolsSaveDouble(f, &zone->slope_ranges[i].hardmax);
} }
toolsSaveInt(f, &zone->circles_included_count); toolsSaveInt(f, &zone->circles_included_count);
@ -116,14 +107,14 @@ void zoneLoad(FILE* f, Zone* zone)
toolsLoadDouble(f, &zone->height_ranges[i].hardmax); toolsLoadDouble(f, &zone->height_ranges[i].hardmax);
} }
toolsLoadInt(f, &zone->steepness_ranges_count); toolsLoadInt(f, &zone->slope_ranges_count);
for (i = 0; i < zone->steepness_ranges_count; i++) for (i = 0; i < zone->slope_ranges_count; i++)
{ {
toolsLoadDouble(f, &zone->steepness_ranges[i].value); toolsLoadDouble(f, &zone->slope_ranges[i].value);
toolsLoadDouble(f, &zone->steepness_ranges[i].hardmin); toolsLoadDouble(f, &zone->slope_ranges[i].hardmin);
toolsLoadDouble(f, &zone->steepness_ranges[i].softmin); toolsLoadDouble(f, &zone->slope_ranges[i].softmin);
toolsLoadDouble(f, &zone->steepness_ranges[i].softmax); toolsLoadDouble(f, &zone->slope_ranges[i].softmax);
toolsLoadDouble(f, &zone->steepness_ranges[i].hardmax); toolsLoadDouble(f, &zone->slope_ranges[i].hardmax);
} }
toolsLoadInt(f, &zone->circles_included_count); toolsLoadInt(f, &zone->circles_included_count);
@ -167,27 +158,129 @@ void zoneExcludeCircleArea(Zone* zone, double centerx, double centerz, double so
/* TODO */ /* TODO */
} }
void zoneAddHeightRange(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax) int zoneAddHeightRange(Zone* zone)
{ {
Range range = {value, hardmin, softmin, softmax, hardmax};
if (zone->height_ranges_count < MAX_RANGES) if (zone->height_ranges_count < MAX_RANGES)
{ {
zone->height_ranges[zone->height_ranges_count++] = range; 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
void zoneAddSteepnessRange(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax)
{ {
Range range = {value, hardmin, softmin, softmax, hardmax}; return -1;
}
}
if (zone->steepness_ranges_count < MAX_RANGES) int zoneGetHeightRangeCount(Zone* zone)
{ {
zone->steepness_ranges[zone->steepness_ranges_count++] = range; 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;
} }
} }
static inline double _getRangeInfluence(Range range, double position) 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);
}
return position;
}
int zoneAddSlopeRange(Zone* zone)
{
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;
}
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.hardmin && position <= range.hardmax)
{ {
@ -271,12 +364,12 @@ double zoneGetValue(Zone* zone, Vector3 location, Vector3 normal)
value_height = 1.0; value_height = 1.0;
} }
if (zone->steepness_ranges_count > 0) if (zone->slope_ranges_count > 0)
{ {
value_steepness = 0.0; value_steepness = 0.0;
for (i = 0; i < zone->steepness_ranges_count; i++) for (i = 0; i < zone->slope_ranges_count; i++)
{ {
value = _getRangeInfluence(zone->steepness_ranges[i], (1.0 - normal.y)); value = _getRangeInfluence(zone->slope_ranges[i], (1.0 - normal.y));
if (value > value_steepness) if (value > value_steepness)
{ {
value_steepness = value; value_steepness = value;

View file

@ -7,6 +7,15 @@
extern "C" { extern "C" {
#endif #endif
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(FILE* f, Zone* zone); void zoneSave(FILE* f, Zone* zone);
@ -14,8 +23,19 @@ void zoneLoad(FILE* f, Zone* zone);
void zoneCopy(Zone* source, Zone* destination); 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);
void zoneAddHeightRange(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax);
void zoneAddSteepnessRange(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax); int zoneAddHeightRange(Zone* zone);
int zoneGetHeightRangeCount(Zone* zone);
int zoneGetHeightRange(Zone* zone, int position, ZoneRangeCondition* range);
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);
int zoneGetSlopeRangeCount(Zone* zone);
int zoneGetSlopeRange(Zone* zone, int position, ZoneRangeCondition* range);
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);
#ifdef __cplusplus #ifdef __cplusplus