paysages : Added auto presets (cirrus, stratus, cumulus, stratocumulus) for clouds + lake and sea presets for water.
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@465 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
a95c07623c
commit
b9ccbe7685
9 changed files with 174 additions and 50 deletions
1
TODO
1
TODO
|
@ -10,7 +10,6 @@ Technology Preview 2 :
|
||||||
=> Apply model to atmosphere (aerial perspective)
|
=> Apply model to atmosphere (aerial perspective)
|
||||||
=> Find a proper model for night sky (maybe Shirley)
|
=> Find a proper model for night sky (maybe Shirley)
|
||||||
- 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 (with several auto presets).
|
|
||||||
- Clouds should keep distance to ground.
|
- Clouds should keep distance to ground.
|
||||||
- Rethink the quality settings and detail smoothing in the distance.
|
- Rethink the quality settings and detail smoothing in the distance.
|
||||||
=> When quality setting is set to 10, add boost options
|
=> When quality setting is set to 10, add boost options
|
||||||
|
|
|
@ -131,9 +131,13 @@ private:
|
||||||
{
|
{
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
else if (dist < layer->thickness * 0.4)
|
||||||
|
{
|
||||||
|
return coverage;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double density = 1.0 - dist / (layer->thickness * 0.5);
|
double density = 1.0 - (dist - (layer->thickness * 0.4)) / (layer->thickness * 0.1);
|
||||||
return (density < coverage) ? density : coverage;
|
return (density < coverage) ? density : coverage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,6 +157,11 @@ private:
|
||||||
FormClouds::FormClouds(QWidget *parent):
|
FormClouds::FormClouds(QWidget *parent):
|
||||||
BaseFormLayer(parent)
|
BaseFormLayer(parent)
|
||||||
{
|
{
|
||||||
|
addAutoPreset(tr("Stratocumulus"));
|
||||||
|
addAutoPreset(tr("Cumulus"));
|
||||||
|
addAutoPreset(tr("Cirrus"));
|
||||||
|
addAutoPreset(tr("Stratus"));
|
||||||
|
|
||||||
_definition = cloudsCreateDefinition();
|
_definition = cloudsCreateDefinition();
|
||||||
_layer = cloudsLayerCreateDefinition();
|
_layer = cloudsLayerCreateDefinition();
|
||||||
|
|
||||||
|
@ -168,7 +177,7 @@ FormClouds::FormClouds(QWidget *parent):
|
||||||
addInputNoise(tr("Shape noise"), _layer->shape_noise);
|
addInputNoise(tr("Shape noise"), _layer->shape_noise);
|
||||||
addInputDouble(tr("Shape scaling"), &_layer->shape_scaling, 3.0, 30.0, 0.3, 3.0);
|
addInputDouble(tr("Shape scaling"), &_layer->shape_scaling, 3.0, 30.0, 0.3, 3.0);
|
||||||
addInputNoise(tr("Edge noise"), _layer->edge_noise);
|
addInputNoise(tr("Edge noise"), _layer->edge_noise);
|
||||||
addInputDouble(tr("Edge scaling"), &_layer->edge_scaling, 0.06, 1.5, 0.03, 0.3);
|
addInputDouble(tr("Edge scaling"), &_layer->edge_scaling, 0.5, 5.0, 0.05, 0.5);
|
||||||
addInputDouble(tr("Edge length"), &_layer->edge_length, 0.0, 1.0, 0.01, 0.1);
|
addInputDouble(tr("Edge length"), &_layer->edge_length, 0.0, 1.0, 0.01, 0.1);
|
||||||
addInputMaterial(tr("Material"), &_layer->material);
|
addInputMaterial(tr("Material"), &_layer->material);
|
||||||
addInputDouble(tr("Hardness to light"), &_layer->hardness, 0.0, 1.0, 0.01, 0.1);
|
addInputDouble(tr("Hardness to light"), &_layer->hardness, 0.0, 1.0, 0.01, 0.1);
|
||||||
|
@ -200,3 +209,10 @@ void FormClouds::layerApply(void* layer_definition)
|
||||||
{
|
{
|
||||||
cloudsLayerCopyDefinition(_layer, (CloudsLayerDefinition*)layer_definition);
|
cloudsLayerCopyDefinition(_layer, (CloudsLayerDefinition*)layer_definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FormClouds::autoPresetSelected(int preset)
|
||||||
|
{
|
||||||
|
cloudsLayerAutoPreset(_layer, (CloudsPreset)preset);
|
||||||
|
BaseForm::autoPresetSelected(preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ public slots:
|
||||||
protected:
|
protected:
|
||||||
virtual void layerGetCopy(void* layer_definition);
|
virtual void layerGetCopy(void* layer_definition);
|
||||||
virtual void layerApply(void* layer_definition);
|
virtual void layerApply(void* layer_definition);
|
||||||
|
virtual void autoPresetSelected(int preset);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CloudsDefinition _definition;
|
CloudsDefinition _definition;
|
||||||
|
|
|
@ -206,7 +206,8 @@ private:
|
||||||
FormWater::FormWater(QWidget *parent):
|
FormWater::FormWater(QWidget *parent):
|
||||||
BaseForm(parent)
|
BaseForm(parent)
|
||||||
{
|
{
|
||||||
addAutoPreset(tr("Standard water"));
|
addAutoPreset(tr("Lake surface"));
|
||||||
|
addAutoPreset(tr("Standard sea"));
|
||||||
|
|
||||||
_definition = waterCreateDefinition();
|
_definition = waterCreateDefinition();
|
||||||
|
|
||||||
|
@ -252,10 +253,7 @@ void FormWater::configChangeEvent()
|
||||||
|
|
||||||
void FormWater::autoPresetSelected(int preset)
|
void FormWater::autoPresetSelected(int preset)
|
||||||
{
|
{
|
||||||
if (preset == (int)WATER_PRESET_STD)
|
waterAutoPreset(&_definition, (WaterPreset)preset);
|
||||||
{
|
|
||||||
waterAutoPreset(&_definition, WATER_PRESET_STD);
|
|
||||||
}
|
|
||||||
BaseForm::autoPresetSelected(preset);
|
BaseForm::autoPresetSelected(preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ void autoGenRealisticLandscape(int seed)
|
||||||
|
|
||||||
/* Water */
|
/* Water */
|
||||||
water = waterCreateDefinition();
|
water = waterCreateDefinition();
|
||||||
waterAutoPreset(&water, WATER_PRESET_STD);
|
waterAutoPreset(&water, WATER_PRESET_LAKE);
|
||||||
scenerySetWater(&water);
|
scenerySetWater(&water);
|
||||||
waterDeleteDefinition(&water);
|
waterDeleteDefinition(&water);
|
||||||
|
|
||||||
|
|
|
@ -70,36 +70,13 @@ CloudsLayerDefinition* cloudsLayerCreateDefinition()
|
||||||
CloudsLayerDefinition* result;
|
CloudsLayerDefinition* result;
|
||||||
|
|
||||||
result = malloc(sizeof(CloudsLayerDefinition));
|
result = malloc(sizeof(CloudsLayerDefinition));
|
||||||
|
|
||||||
result->lower_altitude = 4.0;
|
|
||||||
result->thickness = 6.0;
|
|
||||||
result->coverage_by_altitude = curveCreate();
|
result->coverage_by_altitude = curveCreate();
|
||||||
curveQuickAddPoint(result->coverage_by_altitude, 0.0, 0.0);
|
|
||||||
curveQuickAddPoint(result->coverage_by_altitude, 0.3, 1.0);
|
|
||||||
curveQuickAddPoint(result->coverage_by_altitude, 0.5, 1.0);
|
|
||||||
curveQuickAddPoint(result->coverage_by_altitude, 1.0, 0.0);
|
|
||||||
result->material.base.r = 0.7;
|
|
||||||
result->material.base.g = 0.7;
|
|
||||||
result->material.base.b = 0.7;
|
|
||||||
result->material.base.a = 1.0;
|
|
||||||
result->material.reflection = 0.3;
|
|
||||||
result->material.shininess = 0.8;
|
|
||||||
result->hardness = 0.25;
|
|
||||||
result->transparencydepth = 1.5;
|
|
||||||
result->lighttraversal = 7.0;
|
|
||||||
result->minimumlight = 0.4;
|
|
||||||
result->shape_scaling = 10.0;
|
|
||||||
result->edge_scaling = 0.8;
|
|
||||||
result->edge_length = 0.3;
|
|
||||||
result->base_coverage = 0.4;
|
|
||||||
result->shape_noise = noiseCreateGenerator();
|
result->shape_noise = noiseCreateGenerator();
|
||||||
noiseAddLevelsSimple(result->shape_noise, 2, 1.0, 1.0);
|
|
||||||
noiseSetFunctionParams(result->shape_noise, NOISE_FUNCTION_SIMPLEX, 0.3);
|
|
||||||
result->edge_noise = noiseCreateGenerator();
|
result->edge_noise = noiseCreateGenerator();
|
||||||
noiseAddLevelsSimple(result->edge_noise, 8, 1.0, 1.0);
|
|
||||||
noiseSetFunctionParams(result->edge_noise, NOISE_FUNCTION_SIMPLEX, 0.5);
|
|
||||||
|
|
||||||
result->_custom_coverage = _standardCoverageFunc;
|
result->_custom_coverage = _standardCoverageFunc;
|
||||||
|
|
||||||
|
cloudsLayerAutoPreset(result, CLOUDS_PRESET_STRATOCUMULUS);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +89,110 @@ void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition)
|
||||||
free(definition);
|
free(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cloudsLayerAutoPreset(CloudsLayerDefinition* definition, CloudsPreset preset)
|
||||||
|
{
|
||||||
|
curveClear(definition->coverage_by_altitude);
|
||||||
|
noiseClearLevels(definition->shape_noise);
|
||||||
|
noiseClearLevels(definition->edge_noise);
|
||||||
|
definition->material.base.r = 0.7;
|
||||||
|
definition->material.base.g = 0.7;
|
||||||
|
definition->material.base.b = 0.7;
|
||||||
|
definition->material.base.a = 1.0;
|
||||||
|
|
||||||
|
if (preset == CLOUDS_PRESET_STRATOCUMULUS)
|
||||||
|
{
|
||||||
|
definition->lower_altitude = 5.0;
|
||||||
|
definition->thickness = 6.0;
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.0, 0.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.2, 1.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.5, 1.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 1.0, 0.0);
|
||||||
|
definition->material.reflection = 0.3;
|
||||||
|
definition->material.shininess = 0.8;
|
||||||
|
definition->hardness = 0.25;
|
||||||
|
definition->transparencydepth = 1.5;
|
||||||
|
definition->lighttraversal = 7.0;
|
||||||
|
definition->minimumlight = 0.4;
|
||||||
|
definition->shape_scaling = 10.0;
|
||||||
|
definition->edge_scaling = 0.8;
|
||||||
|
definition->edge_length = 0.3;
|
||||||
|
definition->base_coverage = 0.4;
|
||||||
|
noiseAddLevelsSimple(definition->shape_noise, 2, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->shape_noise, NOISE_FUNCTION_SIMPLEX, 0.3);
|
||||||
|
noiseAddLevelsSimple(definition->edge_noise, 8, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->edge_noise, NOISE_FUNCTION_SIMPLEX, 0.5);
|
||||||
|
}
|
||||||
|
else if (preset == CLOUDS_PRESET_CUMULUS)
|
||||||
|
{
|
||||||
|
definition->lower_altitude = 15.0;
|
||||||
|
definition->thickness = 15.0;
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.0, 0.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.1, 1.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.4, 0.8);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.7, 1.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 1.0, 0.0);
|
||||||
|
definition->material.reflection = 0.5;
|
||||||
|
definition->material.shininess = 1.2;
|
||||||
|
definition->hardness = 0.25;
|
||||||
|
definition->transparencydepth = 1.5;
|
||||||
|
definition->lighttraversal = 8.0;
|
||||||
|
definition->minimumlight = 0.4;
|
||||||
|
definition->shape_scaling = 20.0;
|
||||||
|
definition->edge_scaling = 2.0;
|
||||||
|
definition->edge_length = 0.0;
|
||||||
|
definition->base_coverage = 0.7;
|
||||||
|
noiseAddLevelsSimple(definition->shape_noise, 7, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->shape_noise, NOISE_FUNCTION_SIMPLEX, 0.4);
|
||||||
|
}
|
||||||
|
else if (preset == CLOUDS_PRESET_CIRRUS)
|
||||||
|
{
|
||||||
|
definition->lower_altitude = 25.0;
|
||||||
|
definition->thickness = 2.0;
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.0, 0.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.5, 1.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 1.0, 0.0);
|
||||||
|
definition->material.reflection = 0.4;
|
||||||
|
definition->material.shininess = 0.5;
|
||||||
|
definition->hardness = 0.0;
|
||||||
|
definition->transparencydepth = 3.0;
|
||||||
|
definition->lighttraversal = 10.0;
|
||||||
|
definition->minimumlight = 0.6;
|
||||||
|
definition->shape_scaling = 8.0;
|
||||||
|
definition->edge_scaling = 2.0;
|
||||||
|
definition->edge_length = 0.8;
|
||||||
|
definition->base_coverage = 0.6;
|
||||||
|
noiseAddLevelsSimple(definition->shape_noise, 3, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->shape_noise, NOISE_FUNCTION_SIMPLEX, 0.0);
|
||||||
|
noiseAddLevelsSimple(definition->edge_noise, 4, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->edge_noise, NOISE_FUNCTION_SIMPLEX, -0.2);
|
||||||
|
}
|
||||||
|
else if (preset == CLOUDS_PRESET_STRATUS)
|
||||||
|
{
|
||||||
|
definition->lower_altitude = 3.0;
|
||||||
|
definition->thickness = 4.0;
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.0, 0.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.2, 1.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 0.8, 1.0);
|
||||||
|
curveQuickAddPoint(definition->coverage_by_altitude, 1.0, 0.0);
|
||||||
|
definition->material.reflection = 0.1;
|
||||||
|
definition->material.shininess = 0.8;
|
||||||
|
definition->hardness = 0.1;
|
||||||
|
definition->transparencydepth = 3.0;
|
||||||
|
definition->lighttraversal = 10.0;
|
||||||
|
definition->minimumlight = 0.6;
|
||||||
|
definition->shape_scaling = 8.0;
|
||||||
|
definition->edge_scaling = 2.0;
|
||||||
|
definition->edge_length = 1.0;
|
||||||
|
definition->base_coverage = 0.4;
|
||||||
|
noiseAddLevelsSimple(definition->shape_noise, 3, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->shape_noise, NOISE_FUNCTION_SIMPLEX, -0.3);
|
||||||
|
noiseAddLevelsSimple(definition->edge_noise, 4, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->edge_noise, NOISE_FUNCTION_SIMPLEX, -0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
cloudsLayerValidateDefinition(definition);
|
||||||
|
}
|
||||||
|
|
||||||
void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination)
|
void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination)
|
||||||
{
|
{
|
||||||
CloudsLayerDefinition temp;
|
CloudsLayerDefinition temp;
|
||||||
|
|
|
@ -10,6 +10,14 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CLOUDS_PRESET_STRATOCUMULUS,
|
||||||
|
CLOUDS_PRESET_CUMULUS,
|
||||||
|
CLOUDS_PRESET_CIRRUS,
|
||||||
|
CLOUDS_PRESET_STRATUS
|
||||||
|
} CloudsPreset;
|
||||||
|
|
||||||
typedef struct CloudsLayerDefinition CloudsLayerDefinition;
|
typedef struct CloudsLayerDefinition CloudsLayerDefinition;
|
||||||
|
|
||||||
typedef double (*CloudCoverageFunc)(CloudsLayerDefinition* definition, Vector3 position);
|
typedef double (*CloudCoverageFunc)(CloudsLayerDefinition* definition, Vector3 position);
|
||||||
|
@ -47,6 +55,7 @@ void cloudsLoad(PackStream* stream, CloudsDefinition* definition);
|
||||||
|
|
||||||
CloudsLayerDefinition* cloudsLayerCreateDefinition();
|
CloudsLayerDefinition* cloudsLayerCreateDefinition();
|
||||||
void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition);
|
void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition);
|
||||||
|
void cloudsLayerAutoPreset(CloudsLayerDefinition* definition, CloudsPreset preset);
|
||||||
void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination);
|
void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination);
|
||||||
void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition);
|
void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition);
|
||||||
void cloudsLayerSetName(CloudsLayerDefinition* definition, const char* name);
|
void cloudsLayerSetName(CloudsLayerDefinition* definition, const char* name);
|
||||||
|
|
|
@ -71,33 +71,52 @@ void waterDeleteDefinition(WaterDefinition* definition)
|
||||||
|
|
||||||
void waterAutoPreset(WaterDefinition* definition, WaterPreset preset)
|
void waterAutoPreset(WaterDefinition* definition, WaterPreset preset)
|
||||||
{
|
{
|
||||||
if (preset == WATER_PRESET_STD)
|
if (preset == WATER_PRESET_LAKE)
|
||||||
{
|
{
|
||||||
definition->transparency = 0.5;
|
definition->transparency = 0.5;
|
||||||
definition->reflection = 0.4;
|
definition->reflection = 0.4;
|
||||||
definition->transparency_depth = 6.0;
|
definition->transparency_depth = 4.0;
|
||||||
definition->material.base.r = 0.05;
|
definition->material.base.r = 0.08;
|
||||||
definition->material.base.g = 0.15;
|
definition->material.base.g = 0.15;
|
||||||
definition->material.base.b = 0.2;
|
definition->material.base.b = 0.2;
|
||||||
definition->material.base.a = 1.0;
|
|
||||||
definition->material.reflection = 1.0;
|
|
||||||
definition->material.shininess = 16.0;
|
|
||||||
definition->depth_color.r = 0.0;
|
definition->depth_color.r = 0.0;
|
||||||
definition->depth_color.g = 0.1;
|
definition->depth_color.g = 0.1;
|
||||||
definition->depth_color.b = 0.1;
|
definition->depth_color.b = 0.1;
|
||||||
definition->depth_color.a = 1.0;
|
definition->lighting_depth = 6.0;
|
||||||
definition->lighting_depth = 3.0;
|
|
||||||
definition->scaling = 1.0;
|
definition->scaling = 1.0;
|
||||||
definition->waves_height = 1.0;
|
definition->waves_height = 0.8;
|
||||||
definition->detail_height = 0.05;
|
definition->detail_height = 0.05;
|
||||||
|
definition->turbulence = 0.1;
|
||||||
|
definition->foam_coverage = 0.15;
|
||||||
|
}
|
||||||
|
else if (preset == WATER_PRESET_SEA)
|
||||||
|
{
|
||||||
|
definition->transparency = 0.4;
|
||||||
|
definition->reflection = 0.35;
|
||||||
|
definition->transparency_depth = 3.0;
|
||||||
|
definition->material.base.r = 0.05;
|
||||||
|
definition->material.base.g = 0.18;
|
||||||
|
definition->material.base.b = 0.2;
|
||||||
|
definition->depth_color.r = 0.0;
|
||||||
|
definition->depth_color.g = 0.18;
|
||||||
|
definition->depth_color.b = 0.15;
|
||||||
|
definition->lighting_depth = 4.0;
|
||||||
|
definition->scaling = 1.5;
|
||||||
|
definition->waves_height = 1.0;
|
||||||
|
definition->detail_height = 0.06;
|
||||||
definition->turbulence = 0.3;
|
definition->turbulence = 0.3;
|
||||||
definition->foam_coverage = 0.4;
|
definition->foam_coverage = 0.4;
|
||||||
definition->foam_material.base.r = 0.8;
|
|
||||||
definition->foam_material.base.g = 0.8;
|
|
||||||
definition->foam_material.base.b = 0.8;
|
|
||||||
definition->foam_material.reflection = 0.2;
|
|
||||||
definition->foam_material.shininess = 1.5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
definition->depth_color.a = 1.0;
|
||||||
|
definition->material.base.a = 1.0;
|
||||||
|
definition->material.reflection = 1.0;
|
||||||
|
definition->material.shininess = 16.0;
|
||||||
|
definition->foam_material.base.r = 0.8;
|
||||||
|
definition->foam_material.base.g = 0.8;
|
||||||
|
definition->foam_material.base.b = 0.8;
|
||||||
|
definition->foam_material.reflection = 0.4;
|
||||||
|
definition->foam_material.shininess = 1.5;
|
||||||
|
|
||||||
waterValidateDefinition(definition);
|
waterValidateDefinition(definition);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ extern "C" {
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
WATER_PRESET_STD
|
WATER_PRESET_LAKE,
|
||||||
|
WATER_PRESET_SEA
|
||||||
} WaterPreset;
|
} WaterPreset;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
Loading…
Reference in a new issue