Vassilii KHACHATUROV: rain fix, cleanup, read formerly hard-coded values
from provided node "* minor redundant gl call in DrawCone2 optimized away (twice per frame) * corrected the glRotatef() order in drawRain even further (a less obvious mistake than before, which is noticed by looking skywards and wiggling the mouse in the view direction change mode) * all the "magic numbers" used in the rain rendering code have been provided a default (based on the old hardcoded value) in a form of a define, and a meaningfully named static member in SGEnviro"
This commit is contained in:
parent
31d0779377
commit
b05e98b1b6
@ -34,6 +34,7 @@
|
||||
#include <simgear/sound/soundmgr_openal.hxx>
|
||||
#include <simgear/scene/sky/cloudfield.hxx>
|
||||
#include <simgear/scene/sky/newcloud.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include "visual_enviro.hxx"
|
||||
|
||||
#include <vector>
|
||||
@ -51,6 +52,85 @@ typedef struct {
|
||||
static float rainpos[MAX_RAIN_SLICE];
|
||||
#define MAX_LT_TREE_SEG 400
|
||||
|
||||
#define DFL_MIN_LIGHT 0.35
|
||||
sgVec3 SGEnviro::min_light = {DFL_MIN_LIGHT, DFL_MIN_LIGHT, DFL_MIN_LIGHT};
|
||||
#define DFL_STREAK_BRIGHT_NEARMOST_LAYER 0.9
|
||||
SGfloat SGEnviro::streak_bright_nearmost_layer = DFL_STREAK_BRIGHT_NEARMOST_LAYER;
|
||||
#define DFL_STREAK_BRIGHT_FARMOST_LAYER 0.5
|
||||
SGfloat SGEnviro::streak_bright_farmost_layer = DFL_STREAK_BRIGHT_FARMOST_LAYER;
|
||||
#define DFL_STREAK_PERIOD_MAX 2.5
|
||||
SGfloat SGEnviro::streak_period_max = DFL_STREAK_PERIOD_MAX;
|
||||
#define DFL_STREAK_PERIOD_CHANGE_PER_KT 0.005
|
||||
SGfloat SGEnviro::streak_period_change_per_kt = DFL_STREAK_PERIOD_CHANGE_PER_KT;
|
||||
#define DFL_STREAK_PERIOD_MIN 1.0
|
||||
SGfloat SGEnviro::streak_period_min = DFL_STREAK_PERIOD_MIN;
|
||||
#define DFL_STREAK_LENGTH_MIN 0.03
|
||||
SGfloat SGEnviro::streak_length_min = DFL_STREAK_LENGTH_MIN;
|
||||
#define DFL_STREAK_LENGTH_CHANGE_PER_KT 0.0005
|
||||
SGfloat SGEnviro::streak_length_change_per_kt = DFL_STREAK_LENGTH_CHANGE_PER_KT;
|
||||
#define DFL_STREAK_LENGTH_MAX 0.1
|
||||
SGfloat SGEnviro::streak_length_max = DFL_STREAK_LENGTH_MAX;
|
||||
#define DFL_STREAK_COUNT_MIN 40
|
||||
int SGEnviro::streak_count_min = DFL_STREAK_COUNT_MIN;
|
||||
#define DFL_STREAK_COUNT_MAX 190
|
||||
#if (DFL_STREAK_COUNT_MAX > MAX_RAIN_SLICE)
|
||||
#error "Bad default!"
|
||||
#endif
|
||||
int SGEnviro::streak_count_max = DFL_STREAK_COUNT_MAX;
|
||||
#define DFL_CONE_BASE_RADIUS 15.0
|
||||
SGfloat SGEnviro::cone_base_radius = DFL_CONE_BASE_RADIUS;
|
||||
#define DFL_CONE_HEIGHT 30.0
|
||||
SGfloat SGEnviro::cone_height = DFL_CONE_HEIGHT;
|
||||
|
||||
|
||||
void SGEnviro::config(const SGPropertyNode* n)
|
||||
{
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
const float ml = n->getFloatValue("min-light", DFL_MIN_LIGHT);
|
||||
sgSetVec3(min_light, ml, ml, ml);
|
||||
|
||||
streak_bright_nearmost_layer = n->getFloatValue(
|
||||
"streak-brightness-nearmost-layer",
|
||||
DFL_STREAK_BRIGHT_NEARMOST_LAYER);
|
||||
streak_bright_farmost_layer = n->getFloatValue(
|
||||
"streak-brightness-farmost-layer",
|
||||
DFL_STREAK_BRIGHT_FARMOST_LAYER);
|
||||
|
||||
streak_period_max = n->getFloatValue(
|
||||
"streak-period-max",
|
||||
DFL_STREAK_PERIOD_MAX);
|
||||
streak_period_min = n->getFloatValue(
|
||||
"streak-period-min",
|
||||
DFL_STREAK_PERIOD_MIN);
|
||||
streak_period_change_per_kt = n->getFloatValue(
|
||||
"streak-period-change-per-kt",
|
||||
DFL_STREAK_PERIOD_CHANGE_PER_KT);
|
||||
|
||||
streak_length_max = n->getFloatValue(
|
||||
"streak-length-max",
|
||||
DFL_STREAK_LENGTH_MAX);
|
||||
streak_length_min = n->getFloatValue(
|
||||
"streak-length-min",
|
||||
DFL_STREAK_LENGTH_MIN);
|
||||
streak_length_change_per_kt = n->getFloatValue(
|
||||
"streak-length-change-per-kt",
|
||||
DFL_STREAK_LENGTH_CHANGE_PER_KT);
|
||||
|
||||
streak_count_min = n->getIntValue(
|
||||
"streak-count-min", DFL_STREAK_COUNT_MIN);
|
||||
streak_count_max = n->getIntValue(
|
||||
"streak-count-max", DFL_STREAK_COUNT_MAX);
|
||||
if (streak_count_max > MAX_RAIN_SLICE)
|
||||
streak_count_max = MAX_RAIN_SLICE;
|
||||
|
||||
cone_base_radius = n->getFloatValue(
|
||||
"cone-base-radius", DFL_CONE_BASE_RADIUS);
|
||||
cone_height = n->getFloatValue("cone_height", DFL_CONE_HEIGHT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A class to render lightnings.
|
||||
*/
|
||||
@ -362,24 +442,24 @@ list_of_SGWxRadarEcho *SGEnviro::get_radar_echo(void) {
|
||||
// precipitation rendering code
|
||||
void SGEnviro::DrawCone2(float baseRadius, float height, int slices, bool down, double rain_norm, double speed) {
|
||||
sgVec3 light;
|
||||
sgVec3 min_light = {0.35, 0.35, 0.35};
|
||||
sgAddVec3( light, fog_color, min_light );
|
||||
float da = SG_PI * 2.0f / (float) slices;
|
||||
// low number = faster
|
||||
float speedf = 2.5f - speed / 200.0;
|
||||
if( speedf < 1.0f )
|
||||
speedf = 1.0f;
|
||||
float lenf = 0.03f + speed / 2000.0;
|
||||
if( lenf > 0.10f )
|
||||
lenf = 0.10f;
|
||||
float speedf = streak_period_max - speed * streak_period_change_per_kt;
|
||||
if( speedf < streak_period_min )
|
||||
speedf = streak_period_min;
|
||||
float lenf = streak_length_min + speed * streak_length_change_per_kt;
|
||||
if( lenf > streak_length_max )
|
||||
lenf = streak_length_max;
|
||||
float t = fmod((float) elapsed_time, speedf) / speedf;
|
||||
// t = 0.1f;
|
||||
if( !down )
|
||||
t = 1.0f - t;
|
||||
float angle = 0.0f;
|
||||
glColor4f(1.0f, 0.7f, 0.7f, 0.9f);
|
||||
//glColor4f(1.0f, 0.7f, 0.7f, 0.9f); // XXX unneeded? overriden below
|
||||
glBegin(GL_LINES);
|
||||
int rainpos_indice = 0;
|
||||
if (slices > MAX_RAIN_SLICE)
|
||||
slices = MAX_RAIN_SLICE; // should never happen
|
||||
for( int i = 0 ; i < slices ; i++ ) {
|
||||
float x = cos(angle) * baseRadius;
|
||||
float y = sin(angle) * baseRadius;
|
||||
@ -387,12 +467,14 @@ void SGEnviro::DrawCone2(float baseRadius, float height, int slices, bool down,
|
||||
sgVec3 dir = {x, -height, y};
|
||||
|
||||
// rain drops at 2 different speed to simulate depth
|
||||
float t1 = (i & 1 ? t : t + t) + rainpos[rainpos_indice];
|
||||
float t1 = (i & 1 ? t : t + t) + rainpos[i];
|
||||
if(t1 > 1.0f) t1 -= 1.0f;
|
||||
if(t1 > 1.0f) t1 -= 1.0f;
|
||||
|
||||
// distant raindrops are more transparent
|
||||
float c = (i & 1 ? t1 * 0.5f : t1 * 0.9f);
|
||||
float c = t1 * (i & 1 ?
|
||||
streak_bright_farmost_layer
|
||||
: streak_bright_nearmost_layer);
|
||||
glColor4f(c * light[0], c * light[1], c * light[2], c);
|
||||
sgVec3 p1, p2;
|
||||
sgScaleVec3(p1, dir, t1);
|
||||
@ -402,8 +484,6 @@ void SGEnviro::DrawCone2(float baseRadius, float height, int slices, bool down,
|
||||
|
||||
glVertex3f(p1[0], p1[1] + height, p1[2]);
|
||||
glVertex3f(p2[0], p2[1] + height, p2[2]);
|
||||
if( ++rainpos_indice >= MAX_RAIN_SLICE )
|
||||
rainpos_indice = 0;
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
@ -414,13 +494,13 @@ void SGEnviro::drawRain(double pitch, double roll, double heading, double hspeed
|
||||
static int debug_period = 0;
|
||||
if (debug_period++ == 50) {
|
||||
debug_period = 0;
|
||||
cout << "drawRain("
|
||||
<< pitch << ", "
|
||||
<< roll << ", "
|
||||
<< heading << ", "
|
||||
<< hspeed << ", "
|
||||
cout << "drawRain("
|
||||
<< pitch << ", "
|
||||
<< roll << ", "
|
||||
<< heading << ", "
|
||||
<< hspeed << ", "
|
||||
<< rain_norm << ");"
|
||||
//" angle = " << angle
|
||||
//" angle = " << angle
|
||||
//<< " raindrop(KTS) = " << raindrop_speed_kts
|
||||
<< endl;
|
||||
}
|
||||
@ -437,14 +517,15 @@ void SGEnviro::drawRain(double pitch, double roll, double heading, double hspeed
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
int slice_count = static_cast<int>(
|
||||
(40.0 + rain_norm*150.0)* precipitation_density / 100.0);
|
||||
(streak_count_min + rain_norm*(streak_count_max-streak_count_min))
|
||||
* precipitation_density / 100.0);
|
||||
|
||||
// www.wonderquest.com/falling-raindrops.htm says that
|
||||
// Raindrop terminal velocity is 5 to 20mph
|
||||
// Rather than model it accurately (temp, pressure, diameter), and make it
|
||||
// smaller than terminal when closer to the precipitation cloud base,
|
||||
// we interpolate in the 5-20mph range according to rain_norm.
|
||||
double raindrop_speed_kts
|
||||
double raindrop_speed_kts
|
||||
= (5.0 + rain_norm*15.0) * SG_MPH_TO_MPS * SG_MPS_TO_KT;
|
||||
|
||||
float angle = atanf(hspeed / raindrop_speed_kts) * SG_RADIANS_TO_DEGREES;
|
||||
@ -456,10 +537,12 @@ void SGEnviro::drawRain(double pitch, double roll, double heading, double hspeed
|
||||
glRotatef(angle, 1.0, 0.0, 0.0);
|
||||
|
||||
// up cone
|
||||
DrawCone2(15.0, 30.0, slice_count, true, rain_norm, hspeed);
|
||||
DrawCone2(cone_base_radius, cone_height,
|
||||
slice_count, true, rain_norm, hspeed);
|
||||
// down cone (usually not visible)
|
||||
if(angle > 0.0 || heading != 0.0)
|
||||
DrawCone2(15.0, -30.0, slice_count, false, rain_norm, hspeed);
|
||||
DrawCone2(cone_base_radius, -cone_height,
|
||||
slice_count, false, rain_norm, hspeed);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
|
@ -90,11 +90,31 @@ private:
|
||||
|
||||
/** a list of all the radar echo. */
|
||||
list_of_SGWxRadarEcho radarEcho;
|
||||
static sgVec3 min_light;
|
||||
static SGfloat streak_bright_nearmost_layer,
|
||||
streak_bright_farmost_layer,
|
||||
streak_period_max,
|
||||
streak_period_change_per_kt,
|
||||
streak_period_min,
|
||||
streak_length_min,
|
||||
streak_length_change_per_kt,
|
||||
streak_length_max;
|
||||
static int streak_count_min, streak_count_max;
|
||||
static SGfloat cone_base_radius,
|
||||
cone_height;
|
||||
|
||||
public:
|
||||
SGEnviro();
|
||||
~SGEnviro();
|
||||
|
||||
/** Read the config from the precipitation rendering config properties.
|
||||
* @param precip_rendering_cfgNode "/sim/rendering/precipitation" in fg
|
||||
* Set from whatever info present in the
|
||||
* subnodes passed, substituting hardwired defaults for missing fields.
|
||||
* If NULL is given, do nothing.
|
||||
*/
|
||||
void config(const class SGPropertyNode* precip_rendering_cfgNode);
|
||||
|
||||
/**
|
||||
* Forward a few states used for renderings.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user