1
0
Fork 0

Merge branch 'master' of git://gitorious.org/fg/fgdata

This commit is contained in:
Alexis Bory 2010-11-02 23:14:37 +01:00
commit b4667447c7
75 changed files with 4228 additions and 3427 deletions

View file

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<PropertyList>
<sim>
<model>
<formation>
<variant type="string">Echelon Stbd</variant>
<index type="int">2</index>
<position>
<x-offset>-75</x-offset>
<y-offset>75</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-150</x-offset>
<y-offset>150</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-75</x-offset>
<y-offset>75</y-offset>
<z-offset>0</z-offset>
</position>
</formation>
</model>
</sim>
</PropertyList>

View file

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<PropertyList>
<sim>
<model>
<formation>
<variant type="string">Echelon Port</variant>
<index type="int">3</index>
<position>
<x-offset>-75</x-offset>
<y-offset>-75</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-150</x-offset>
<y-offset>-150</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-75</x-offset>
<y-offset>-75</y-offset>
<z-offset>0</z-offset>
</position>
</formation>
</model>
</sim>
</PropertyList>

View file

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<PropertyList>
<sim>
<model>
<formation>
<variant type="string">Diamond</variant>
<index type="int">4</index>
<position>
<x-offset>-75</x-offset>
<y-offset>-75</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-75</x-offset>
<y-offset>75</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-75</x-offset>
<y-offset>-75</y-offset>
<z-offset>0</z-offset>
</position>
</formation>
</model>
</sim>
</PropertyList>

View file

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<PropertyList>
<sim>
<model>
<formation>
<variant type="string">Finger</variant>
<index type="int">5</index>
<position>
<x-offset>-100</x-offset>
<y-offset>-100</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-100</x-offset>
<y-offset>100</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-100</x-offset>
<y-offset>100</y-offset>
<z-offset>0</z-offset>
</position>
</formation>
</model>
</sim>
</PropertyList>

View file

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<PropertyList>
<sim>
<model>
<formation>
<variant type="string">Echelon Stbd Step Up</variant>
<index type="int">6</index>
<position>
<x-offset>-75</x-offset>
<y-offset>75</y-offset>
<z-offset>30</z-offset>
</position>
<position>
<x-offset>-150</x-offset>
<y-offset>150</y-offset>
<z-offset>60</z-offset>
</position>
<position>
<x-offset>-75</x-offset>
<y-offset>75</y-offset>
<z-offset>30</z-offset>
</position>
</formation>
</model>
</sim>
</PropertyList>

View file

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<PropertyList>
<sim>
<model>
<formation>
<variant type="string">Take Off</variant>
<index type="int">7</index>
<position>
<x-offset>-50</x-offset>
<y-offset>-50</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-300</x-offset>
<y-offset>0</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-50</x-offset>
<y-offset>-50</y-offset>
<z-offset>0</z-offset>
</position>
</formation>
</model>
</sim>
</PropertyList>

View file

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<PropertyList>
<sim>
<model>
<formation>
<variant type="string">Carrier Launch</variant>
<index type="int">1</index>
<position>
<x-offset>-15</x-offset>
<y-offset>-65</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-200</x-offset>
<y-offset>0</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-15</x-offset>
<y-offset>-63</y-offset>
<z-offset>0</z-offset>
</position>
</formation>
</model>
</sim>
</PropertyList>

View file

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<PropertyList>
<sim>
<model>
<formation>
<variant type="string">Swan</variant>
<index type="int">6</index>
<position>
<x-offset>-225</x-offset>
<y-offset>-75</y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-150</x-offset>
<y-offset></y-offset>
<z-offset>0</z-offset>
</position>
<position>
<x-offset>-75</x-offset>
<y-offset>75</y-offset>
<z-offset>0</z-offset>
</position>
</formation>
</model>
</sim>
</PropertyList>

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View file

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<PropertyList>
<sim>
<model>
<logo>
<name type="string">Pumpkin</name>
<texture>../../Generic/Logos/pumpkin.png</texture>
</logo>
</model>
</sim>
</PropertyList>

View file

@ -0,0 +1,198 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Walk view module for FlightGear.
Copyright (C) 2010 Anders Gidenstam (anders(at)gidenstam.org)
This file is licensed under the GPL license v2 or later.
-->
<PropertyList>
<!--
This module can be used to add suitable key bindings for walk views
to any aircraft.
Usage example:
Include it in the keybord section of the aircraft's -set file.
<keyboard include="../Generic/WalkView/walk-view-keys.xml">
Note: If the aircraft use other custom key bindings for the same keys
the walk view bindings should be merged into the aircraft specific
bindings. The walk view API commands return false if not currently
in a walk view so the other alternative action can be put in an
if statement. E.g.
if (!walkview.forward(4.0)) {
# Perform the non-walk view action of this key.
}
-->
<!-- Keyboard commands -->
<key n="87">
<name>W</name>
<desc>Walk view: Run forward.</desc>
<binding>
<command>nasal</command>
<script>
if (!walkview.forward(4.0)) {
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
walkview.forward(0);
</script>
</binding>
</mod-up>
</key>
<key n="119">
<name>w</name>
<desc>Walk view: Walk forward.</desc>
<binding>
<command>nasal</command>
<script>
if (!walkview.forward(1.0)) {
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
walkview.forward(0);
</script>
</binding>
</mod-up>
</key>
<key n="100">
<name>d</name>
<desc>Walk view: Side step right.</desc>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>
if (!walkview.side_step(0.5)) {
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
walkview.side_step(0);
</script>
</binding>
</mod-up>
</key>
<key n="68">
<name>D</name>
<desc>Walk view: Fast side step right.</desc>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>
if (!walkview.side_step(1.0)) {
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
walkview.side_step(0);
</script>
</binding>
</mod-up>
</key>
<key n="97">
<name>a</name>
<desc>Walk view: Side step left.</desc>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>
if (!walkview.side_step(-0.5)) {
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
walkview.side_step(0);
</script>
</binding>
</mod-up>
</key>
<key n="65">
<name>A</name>
<desc>Walk view: Fast side step left.</desc>
<repeatable type="bool">true</repeatable>
<binding>
<command>nasal</command>
<script>
if (!walkview.side_step(-1.0)) {
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
walkview.side_step(0);
</script>
</binding>
</mod-up>
</key>
<key n="115">
<name>s</name>
<desc>Walk view: Walk backwards.</desc>
<binding>
<command>nasal</command>
<script>
if (!walkview.forward(-1.0)) {
controls.startEngine(1);
}
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
walkview.forward(0);
controls.startEngine(0);
</script>
</binding>
</mod-up>
</key>
<!-- Remove this if you for some reason have 2d panels and want the default
Swap panels function on 'S'.
-->
<!-- key n="83">
<name>S</name>
<desc>Walk view: Walk backwards.</desc>
<binding>
<command>nasal</command>
<script>
walkview.forward(-1.0);
</script>
</binding>
<mod-up>
<binding>
<command>nasal</command>
<script>
walkview.forward(0);
</script>
</binding>
</mod-up>
</key -->
</PropertyList>

View file

@ -83,7 +83,8 @@ var active_walker = func {
# speed ... speed in m/sec : double # speed ... speed in m/sec : double
# #
# set_pos(pos) # set_pos(pos)
# get_pos() : position # pos ... position in meter : [double, double, double]
# get_pos() : position ([meter, meter, meter])
# #
# set_eye_height(h) # set_eye_height(h)
# get_eye_height() : int (meter) # get_eye_height() : int (meter)
@ -97,13 +98,15 @@ var active_walker = func {
# [19.5, 0.3, -8.85]); # [19.5, 0.3, -8.85]);
# var walker = walkview.walker.new("Passenger View", constraint); # var walker = walkview.walker.new("Passenger View", constraint);
# #
# See Aircraft/Nordstern, Aircraft/Short_Empire and Aircraft/ZLT-NT
# for working examples of walk views.
#
# NOTES: # NOTES:
# Currently there can only be one view manager per view so the # Currently there can only be one view manager per view so the
# walk view should not have any other view manager. # walk view should not have any other view manager.
# var Walker = {
var walker = {
new : func (view_name, constraints = nil, managers = nil) { new : func (view_name, constraints = nil, managers = nil) {
var obj = { parents : [walker] }; var obj = { parents : [Walker] };
obj.view = view.views[view.indexof(view_name)]; obj.view = view.views[view.indexof(view_name)];
obj.constraints = constraints; obj.constraints = constraints;
obj.managers = managers; obj.managers = managers;
@ -124,7 +127,7 @@ var walker = {
view.manager.register(view_name, obj); view.manager.register(view_name, obj);
walkers[obj.view.getPath()] = obj; walkers[obj.view.getPath()] = obj;
debug.dump(obj); #debug.dump(obj);
return obj; return obj;
}, },
active : func { active : func {
@ -216,13 +219,52 @@ var walker = {
############################################################################### ###############################################################################
# Constraint classes. Determines where the view can walk. # Constraint classes. Determines where the view can walk.
#
# Convenience functions.
# Build a UnionConstraint hierarchy from a list of constraints.
# cs - list of constraints : [constraint]
var makeUnionConstraint = func (cs) {
if (size(cs) < 2) return cs[0];
var ret = cs[0];
for (var i = 1; i < size(cs); i += 1) {
ret = UnionConstraint.new(ret, cs[i]);
}
return ret;
}
# Build a UnionConstraint hierachy that represents a polyline path
# with a certain width. Each internal point gets a circular surface.
# points - list of points : [position] ([[meter, meter, meter]])
# width - width of the path : length (meter)
# round_ends - put a circle also on the first and last points : bool
var makePolylinePath = func (points, width, round_ends = 0) {
if (size(points) < 2) return nil;
var ret = LinePlane.new(points[0], points[1], width);
if (round_ends) {
ret = UnionConstraint.new(line,
CircularXYSurface.new(points[0], width/2));
}
for (var i = 2; i < size(points); i += 1) {
var line = LinePlane.new(points[i-1], points[i], width);
if (i + 1 < size(points) or round_ends) {
line = UnionConstraint.new
(line,
CircularXYSurface.new(points[i], width/2));
}
ret = UnionConstraint.new(line, ret);
}
return ret;
}
# The union of two constraints. # The union of two constraints.
# c1, c2 - the constraints : constraint # c1, c2 - the constraints : constraint
# NOTE: Assumes that the constraints are convex. # NOTE: Assumes that the constraints are convex.
var unionConstraint = { var UnionConstraint = {
new : func (c1, c2) { new : func (c1, c2) {
var obj = { parents : [unionConstraint] }; var obj = { parents : [UnionConstraint] };
obj.c1 = c1; obj.c1 = c1;
obj.c2 = c2; obj.c2 = c2;
return obj; return obj;
@ -244,40 +286,82 @@ var unionConstraint = {
} }
}; };
# Build a unionConstraint hierarchy from a list of constraints. # Rectangular plane defined by a straight line and a width.
# cs - list of constraints : [constraint] # The line is extruded horizontally on each side by width/2 into a
var makeUnionConstraint = func (cs) { # planar surface.
if (size(cs) < 2) return cs[0]; # p1, p2 - the line endpoints. : position ([meter, meter, meter])
# width - total width of the plane. : length (meter)
var ret = cs[0]; var LinePlane = {
for (var i = 1; i < size(cs); i += 1) { new : func (p1, p2, width) {
ret = unionConstraint.new(ret, cs[i]); var obj = { parents : [LinePlane] };
} obj.p1 = p1;
return ret; obj.p2 = p2;
} obj.halfwidth = width/2;
obj.length = vec2.length(vec2.sub(p2, p1));
obj.e1 = vec2.normalize(vec2.sub(p2, p1));
obj.e2 = [obj.e1[1], -obj.e1[0]];
obj.k = (p2[2] - p1[2]) / obj.length;
# Mostly aligned plane sloping along the X axis.
# minp - the X,Y minimum point : position (meter)
# maxp - the X,Y maximum point : position (meter)
var slopingYAlignedPlane = {
new : func (minp, maxp) {
var obj = { parents : [slopingYAlignedPlane] };
obj.minp = minp;
obj.maxp = maxp;
obj.kxz = (maxp[2] - minp[2])/(maxp[0] - minp[0]);
return obj; return obj;
}, },
constrain : func (pos) { constrain : func (pos) {
var p = [pos[0], pos[1], pos[2]]; var p = [pos[0], pos[1], pos[2]];
if (pos[0] < me.minp[0]) p[0] = me.minp[0]; var pXY = vec2.sub(pos, me.p1);
if (pos[0] > me.maxp[0]) p[0] = me.maxp[0]; var along = vec2.dot(pXY, me.e1);
if (pos[1] < me.minp[1]) p[1] = me.minp[1]; var across = vec2.dot(pXY, me.e2);
if (pos[1] > me.maxp[1]) p[1] = me.maxp[1];
p[2] = me.minp[2] + me.kxz * (pos[0] - me.minp[0]); var along2 = max(0, min(along, me.length));
var across2 = max(-me.halfwidth, min(across, me.halfwidth));
if (along2 != along or across2 != across) {
# Compute new XY position.
var t = vec2.add(vec2.mul(along2, me.e1), vec2.mul(across2, me.e2));
p[0] = me.p1[0] + t[0];
p[1] = me.p1[1] + t[1];
}
# Compute Z positition.
p[2] = me.p1[2] + me.k * along2;
return p;
}
};
# Circular surface aligned with the XY plane
# center - the center point : position ([meter, meter, meter])
# radius - radius in the XY plane : length (meter)
var CircularXYSurface = {
new : func (center, radius) {
var obj = { parents : [CircularXYSurface] };
obj.center = center;
obj.radius = radius;
return obj;
},
constrain : func (pos) {
var p = [pos[0], pos[1], me.center[2]];
var pXY = vec2.sub(pos, me.center);
var lXY = vec2.length(pXY);
if (lXY > me.radius) {
var t = vec2.add(me.center, vec2.mul(me.radius/lXY, pXY));
p[0] = t[0];
p[1] = t[1];
}
return p; return p;
}, },
}; };
# Mostly aligned plane sloping along the X axis.
# NOTE: Obsolete. Use linePlane instead.
# minp - the X,Y minimum point : position ([meter, meter, meter])
# maxp - the X,Y maximum point : position ([meter, meter, meter])
var SlopingYAlignedPlane = {
new : func (minp, maxp) {
return LinePlane.new([minp[0], (minp[1] + maxp[1])/2, minp[2]],
[maxp[0], (minp[1] + maxp[1])/2, maxp[2]],
(maxp[1] - minp[1]));
}
};
# Action constraint # Action constraint
# Triggers an action when entering or exiting the constraint. # Triggers an action when entering or exiting the constraint.
# constraint - the area in question : constraint # constraint - the area in question : constraint
@ -285,9 +369,9 @@ var slopingYAlignedPlane = {
# on_exit(x, y) - function that is called when the walker leaves the area. # on_exit(x, y) - function that is called when the walker leaves the area.
# x and y are <0, 0 or >0 depending on in which direction(s) # x and y are <0, 0 or >0 depending on in which direction(s)
# the walker left the constraint. # the walker left the constraint.
var actionConstraint = { var ActionConstraint = {
new : func (constraint, on_enter = nil, on_exit = nil) { new : func (constraint, on_enter = nil, on_exit = nil) {
var obj = { parents : [actionConstraint] }; var obj = { parents : [ActionConstraint] };
obj.constraint = constraint; obj.constraint = constraint;
obj.on_enter = on_enter; obj.on_enter = on_enter;
obj.on_exit = on_exit; obj.on_exit = on_exit;
@ -366,3 +450,33 @@ var closerXY = func (pos, p1, p2) {
var l2 = [p2[0] - pos[0], p2[1] - pos[1]]; var l2 = [p2[0] - pos[0], p2[1] - pos[1]];
return (l1[0]*l1[0] + l1[1]*l1[1]) - (l2[0]*l2[0] + l2[1]*l2[1]); return (l1[0]*l1[0] + l1[1]*l1[1]) - (l2[0]*l2[0] + l2[1]*l2[1]);
} }
var max = func (a, b) {
return b > a ? b : a;
}
var min = func (a, b) {
return a > b ? b : a;
}
# 2D vector math.
var vec2 = {
add : func (a, b) {
return [a[0] + b[0], a[1] + b[1]];
},
sub : func (a, b) {
return [a[0] - b[0], a[1] - b[1]];
},
mul : func (k, a) {
return [k * a[0], k * a[1]];
},
length : func (a) {
return math.sqrt(a[0]*a[0] + a[1]*a[1]);
},
dot : func (a, b) {
return a[0]*b[0] + a[1]*b[1];
},
normalize : func (a) {
var s = 1/vec2.length(a);
return [s * a[0], s * a[1]];
}
}

View file

@ -0,0 +1,96 @@
#####################################################################################
# #
# this script runs the foramation selection utility #
# #
#####################################################################################
# ================================ Initalize ======================================
# Make sure all needed properties are present and accounted
# for, and that they have sane default values.
for(var i = 0; i < 3; i = i + 1){
setprop("/sim/model/formation/position[" ~ i ~ "]/x-offset", 0);
setprop("/sim/model/formation/position[" ~ i ~ "]/y-offset", 0);
setprop("/sim/model/formation/position[" ~ i ~ "]/z-offset", 0);
}
formation_variant_Node = props.globals.getNode("sim/formation/variant", 1);
formation_variant_Node.setIntValue(0);
formation_index_Node = props.globals.getNode("sim/formation/index", 1);
formation_index_Node.setIntValue(0);
tgt_x_offset_Node = props.globals.getNode("ai/models/wingman/position/tgt-x-offset",1);
tgt_y_offset_Node = props.globals.getNode("ai/models/wingman/position/tgt-y-offset",1);
tgt_z_offset_Node = props.globals.getNode("ai/models/wingman/position/tgt-z-offset",1);
tgt_x_offset_1_Node = props.globals.getNode("ai/models/wingman[1]/position/tgt-x-offset",1);
tgt_y_offset_1_Node = props.globals.getNode("ai/models/wingman[1]/position/tgt-y-offset",1);
tgt_z_offset_1_Node = props.globals.getNode("ai/models/wingman[1]/position/tgt-z-offset",1);
tgt_x_offset_2_Node = props.globals.getNode("ai/models/wingman[2]/position/tgt-x-offset",1);
tgt_y_offset_2_Node = props.globals.getNode("ai/models/wingman[2]/position/tgt-y-offset",1);
tgt_z_offset_2_Node = props.globals.getNode("ai/models/wingman[2]/position/tgt-z-offset",1);
props.globals.getNode("/sim/model/formation/position/x-offset",1);
var formation_dialog = nil;
initialize = func {
print("Initializing formation ...");
# initialise dialogs
aircraft.data.add("sim/model/formation/variant");
formation_dialog = gui.OverlaySelector.new("Select Formation",
"Aircraft/Generic/Formations",
"sim/model/formation/variant", nil, func(no) {
formation_variant_Node.setIntValue(no);
tgt_x_offset_Node.setDoubleValue(getprop("/sim/model/formation/position/x-offset"));
tgt_y_offset_Node.setDoubleValue(getprop("/sim/model/formation/position/y-offset"));
tgt_z_offset_Node.setDoubleValue(getprop("/sim/model/formation/position/z-offset"));
tgt_x_offset_1_Node.setDoubleValue(getprop("/sim/model/formation/position[1]/x-offset"));
tgt_y_offset_1_Node.setDoubleValue(getprop("/sim/model/formation/position[1]/y-offset"));
tgt_z_offset_1_Node.setDoubleValue(getprop("/sim/model/formation/position[1]/z-offset"));
tgt_x_offset_2_Node.setDoubleValue(getprop("/sim/model/formation/position[2]/x-offset"));
tgt_y_offset_2_Node.setDoubleValue(getprop("/sim/model/formation/position[2]/y-offset"));
tgt_z_offset_2_Node.setDoubleValue(getprop("/sim/model/formation/position[2]/z-offset"));
}
);
#set listeners
setlistener("/sim/model/formation/variant", func {
print("formation listener: ", getprop("/sim/model/formation/position/x-offset"));
if (tgt_x_offset_Node != nil){
print("formation listener getting", getprop("/sim/model/formation/position/x-offset"));
tgt_x_offset_Node.setDoubleValue(getprop("/sim/model/formation/position/x-offset"));
tgt_y_offset_Node.setDoubleValue(getprop("/sim/model/formation/position/y-offset"));
tgt_z_offset_Node.setDoubleValue(getprop("/sim/model/formation/position/z-offset"));
}
if (tgt_x_offset_1_Node != nil){
tgt_x_offset_1_Node.setDoubleValue(getprop("/sim/model/formation/position[1]/x-offset"));
tgt_y_offset_1_Node.setDoubleValue(getprop("/sim/model/formation/position[1]/y-offset"));
tgt_z_offset_1_Node.setDoubleValue(getprop("/sim/model/formation/position[1]/z-offset"));
}
if (tgt_x_offset_2_Node != nil){
tgt_x_offset_2_Node.setDoubleValue(getprop("/sim/model/formation/position[2]/x-offset"));
tgt_y_offset_2_Node.setDoubleValue(getprop("/sim/model/formation/position[2]/y-offset"));
tgt_z_offset_2_Node.setDoubleValue(getprop("/sim/model/formation/position[2]/z-offset"));
}
},
0,
1);
} # end func
###
# ====================== end Initialization ========================================
###
# Fire it up
setlistener("sim/signals/fdm-initialized", initialize);
# end

View file

@ -7,7 +7,7 @@
<body> <body>
<h1>Local Weather Package - v0.85</h1> <h1>Local Weather Package - v0.9</h1>
<h2>1. Introduction</h2> <h2>1. Introduction</h2>
@ -15,7 +15,7 @@ The aim of a local weather system is to simulate weather phenomena tied to speci
This is in contrast to the current (v.2.0.0) weather system of Flightgear where weather changes affect the weather everywhere in the simulated world and are (with few exceptions) not tied to specific locations. In such a system, it is impossible to observe e.g. the approach of a rainfront while flying in sunshine.<p> This is in contrast to the current (v.2.0.0) weather system of Flightgear where weather changes affect the weather everywhere in the simulated world and are (with few exceptions) not tied to specific locations. In such a system, it is impossible to observe e.g. the approach of a rainfront while flying in sunshine.<p>
The local weather package ultimately aims to provide the functionality to simulate such local phenomena. In version 0.85, the package supplies various cloud placement algorithms, as well as local control over most major weather parameters (wind, visibility, pressure, temperature, rain, snow, thermal lift, turbulence...) through interpolation routines and event volumes. The dynamics of the different systems is tied together - clouds and weather effects drift in the specified wind field. The package also contains a fairly detailed algorithm to generate convective clouds and thermals with a realistic distribution. Unfortunately, as of v0.85, there is no interaction yet between the windfield and the cloud-generating algorithms, i.e. while the placement algorithms create a realistic configuration of thermals and convective clouds, the wind will simply move this configuration, not create, destroy or move clouds in altitude dynamically (which would be realistic). <p> The local weather package ultimately aims to provide the functionality to simulate such local phenomena. In version 0.9, the package supplies various cloud placement algorithms, as well as local control over most major weather parameters (wind, visibility, pressure, temperature, rain, snow, thermal lift, turbulence...) through interpolation routines and effect volumes. The dynamics of the different systems is tied together - clouds and weather effects drift in the specified wind field. The package also contains a fairly detailed algorithm to generate convective clouds and thermals with a realistic distribution. In addition, there is a simulation of realistic interaction of the convective cloud system with the terrain as a function of time. Clouds drifting in the wind flow over obstacles, i.e. they change their altitude dynamically. Convection is implemented with a life cycle model of clouds - they are generated, evolve for a given lifetime dependent on the underlying terrain and decay at the end of their life cycle. Thermals associated with the clouds follow the same pattern. In particular, in the presence of wind favourable spots for convection generate 'alleys' of dense cloud cover downwind, or thermals and clouds generated over land decay rapidly once they reach open water.<p>
For long-range flights, the system automatically provides transitions between different weather patterns like fronts and low and high pressure areas. However, basically all features currently present can and will eventually be improved.<p> For long-range flights, the system automatically provides transitions between different weather patterns like fronts and low and high pressure areas. However, basically all features currently present can and will eventually be improved.<p>
@ -24,13 +24,18 @@ For long-range flights, the system automatically provides transitions between di
The package needs to be unpacked in the Flightgear root directory. It writes content into the <i>Nasal/, gui/, gui/dialogs/, Shaders, Effects/, Docs/</i>, and <i>Models/Weather/</i> subdirectories. The installation does not overwrite any of the default Flightgear files, but to be accessible from the menu, one must copy <i>gui/menubar.xml.alt</i> to the default <i>menubar.xml</i> or copy the last two lines of the environemnt menu calling <i>local_weather</i> and <i>local_weather_tiles</i> into the default file.<p> The package needs to be unpacked in the Flightgear root directory. It writes content into the <i>Nasal/, gui/, gui/dialogs/, Shaders, Effects/, Docs/</i>, and <i>Models/Weather/</i> subdirectories. The installation does not overwrite any of the default Flightgear files, but to be accessible from the menu, one must copy <i>gui/menubar.xml.alt</i> to the default <i>menubar.xml</i> or copy the last two lines of the environemnt menu calling <i>local_weather</i> and <i>local_weather_tiles</i> into the default file.<p>
This adds the items <i>Local Weather</i>, <i>Local Weather Tiles</i> and <i>Local Weather Settings</i> to the <i>Environment</i> menu when Flightgear is up. Most of the basic functionality is contained in <i>local_weather.nas</i> which is loaded at startup and identifies itself with a message, but does not start any functions unless called from the GUI.<p> This adds the items <i>Local Weather</i>, <i>Local Weather Tiles</i> and <i>Local Weather Settings</i> to the <i>Environment</i> menu when Flightgear is up. Most of the basic functionality is contained in <i>local_weather.nas</i> which is loaded at startup and identifies itself with a message.<p>
Unless asked to do so from the menu, local weather does <b>not</b> run any process in the background. Upon loading, the package does not set any properties already existing, but only generates properties necessary for the menu entries in its own subdirectory <i>/local-weather/</i> in the tree. The package also does a features check on startup if particular functions are available in hard-coded form. If the features are not present, the package will still function properly using slower Nasal fallbacks.<p>
<h2>3. Functionality</h2> <h2>3. Functionality</h2>
The general rule is that the gui is not hardened against problematic user input, for example it will not reject meaningless input like negative windspeeds or unphysical windshear. It is recommended to watch the console, because some level of warnings and errors are passed to the console. Placement calls may sometimes take a significant time to execute especially for large numbers of clouds tied in a complicated way to the terrain. Placing 500 barrier clouds against a small barrier may take a minute to compute. During this time, a reduced framerate is to be expected<p> The general rule is that the gui is not hardened against problematic user input, for example it will not reject meaningless input like negative windspeeds or unphysical windshear. It is recommended to watch the console, because some level of warnings and errors are passed to the console if the log options is on. Crucial warnings are also printed on-screen.<p>
The first menu contains the low level cloud placement functions. Its purpose is mainly for developing cloud patterns without having to resort to re-type the underlying Nasal code every time. Currently five options are supported: <i>Place a single cloud</i>, <i>Place a cloud streak</i>, <i>Start the convective system</i>, <i>Create barrier clouds</i> and <i>Place a cloud layer</i>.<p> Placement calls may sometimes take a significant time to execute especially for large numbers of clouds tied in a complicated way to the terrain. Placing 500 barrier clouds against a small barrier may take a minute to compute. During this time, a reduced framerate is to be expected<p>
The first menu <b>Local Weather</b> contains the low level cloud placement functions. Its purpose is mainly for developing cloud patterns without having to resort to re-type the underlying Nasal code every time. Currently five options are supported: <i>Place a single cloud</i>, <i>Place a cloud streak</i>, <i>Start the convective system</i>, <i>Create barrier clouds</i> , <i>Place a cloud layer</i> and <i>Make a cloudbox</i>.<p>
<center> <center>
<img src="menu1.jpg"> <img src="menu1.jpg">
@ -93,26 +98,45 @@ The second menu is used to place complete weather tiles based on low-level calls
<img src="menu2.jpg"> <img src="menu2.jpg">
</center><p> </center><p>
Weather is created in a series of 40x40 km squares, called tiles. Tiles are classified by airmass, such that the sequence of tiles can describe for example the transition from a high pressure area to a low pressure area. The dropdown menu is used to select the type of weather tile to build initially. The menu contains two groups of tiles - the first are classified by airmass, whereas the last two are scenarios intended for soaring. <p> Weather is created in a series of 40x40 km squares, called tiles. Tiles are classified by airmass, such that the sequence of tiles can describe for example the transition from a high pressure area to a low pressure area. The dropdown menu is used to select the type of weather tile to build initially. <p>
Below are entries for three parameters. The first two are the simplified version of wind direction and speed for the user who is not interested in specifying many different wind interpolation points. Below are entries for three parameters. The first two are the simplified version of wind direction and speed for the user who is not interested in specifying many different wind interpolation points.
The third parameter, the altitude offset, is to manually adjust the altitude level of clouds in the absence of terrain presampling. Cloud layer placement calls are then specified for absolute altitudes and calibrated at sea level. As a result, layers are placed too low in mountainous terrain, hence the need for an offset. The offset may at present also be useful for dynamical weather, as convective clouds with terrain presampling follow terrain altitude, which looks strange when the clouds are allowed to drift in the wind without altitude correction. <p> The third parameter, the altitude offset, is to manually adjust the altitude level of clouds in the absence of terrain presampling. Cloud layer placement calls are then specified for absolute altitudes and calibrated at sea level. As a result, layers are placed too low in mountainous terrain, hence the need for an offset. <p>
The dropdown menu for the wind contains various models for how the windfield is specified which require a different amount of user-specified input. The options are described further down when the windfield modelling is described in more detail.<p> The dropdown menu for the wind contains various models for how the windfield is specified which require a different amount of user-specified input. The options are described further down when the windfield modelling is described in more detail.<p>
The dropdown menu for the tile selection mode controls the long-range behaviour of weather. It specifies according to what rules tiles are automatically generated once the aircraft reaches the border of the original tile. The option 'single tile' creates a single weather tile as specified without automatic generation of further tiles. The option 'repeat tile' creates new tiles of the same type as the originally selected tile. This does not mean that weather will be unchanged during flight, as both parameters like pressure, temperature and visibility as well as the positioning of cloud banks are randomized to some degree. In addition, each tile typically contains 2-5 different cloud scenarios, so five repeated generations of 'low-pressure-border' tiles may never result in the same arrangement of cloud layers. Necertheless, the option will keep weather conditions roughly the same. This is different with the (somewhat optimistically named) 'realistic weather'. This option allows transitions between different airmasses, thus one may select 'low-pressure-core' initially, but as the flight goes on, eventually a region of high pressure and clear skies may be reached. Currently this change between airmasses does not include transitions across fronts. Moreover, it does not cover transitions to arctic or tropical weather conditions - those will be covered in a future release. Note that 'realistic weather' does not work for the two soaring scenarios, 'repeat tile' does not work for any tile which is part of a front.<p> The dropdown menu for the tile selection mode controls the long-range behaviour of weather. It specifies according to what rules tiles are automatically generated once the aircraft reaches the border of the original tile. The option 'single tile' creates a single weather tile as specified without automatic generation of further tiles. The option 'repeat tile' creates new tiles of the same type as the originally selected tile. This does not mean that weather will be unchanged during flight, as both parameters like pressure, temperature and visibility as well as the positioning of cloud banks are randomized to some degree. In addition, each tile typically contains 2-5 different cloud scenarios, so five repeated generations of 'low-pressure-border' tiles may never result in the same arrangement of cloud layers. Necertheless, the option will keep weather conditions roughly the same. This is different with the (somewhat optimistically named) 'realistic weather'. This option allows transitions between different airmasses, thus one may select 'low-pressure-core' initially, but as the flight goes on, eventually a region of high pressure and clear skies may be reached. Moreover, it does not cover transitions to arctic or tropical weather conditions - those will be covered in a future release. 'repeat tile' does not work for any tile which is part of a front.<p>
The final option, 'METAR', generates weather according to parsed METAR information. This information must be made available in the property tree. Currently this is <b>not</b> done automatically and the METAR system does <b>not</b> work with real-weather-fetch, this needs some work on the Flightgear core.<p> The final option, 'METAR', generates weather according to parsed METAR information. This information must be made available in the property tree. Currently this is <b>not</b> done automatically and the METAR system does <b>not</b> work with real-weather-fetch, this needs some work on the Flightgear core. Future versions will be able to use parsed METAR to generate weather tiles.<p>
Below the menu are five tickboxes. 'Terrain presampling' finds the distribution of altitude in the terrain before placing a cloud layer. As a result, the layers or clouds are automatically placed at the correct altitude above ground in level terrain. In mountain regions, cloud placement is fairly tricky, and the algorithm analyzes quantities like the median altitude to determine what to do. The appendix contains a detailed description of the algorithm. If the box is ticked, the altitude offset specified above is not parsed.<p> Below the menu are six tickboxes. 'Terrain presampling' finds the distribution of altitude in the terrain before placing a cloud layer. As a result, the layers or clouds are automatically placed at the correct altitude above ground in level terrain. In mountain regions, cloud placement is fairly tricky, and the algorithm analyzes quantities like the median altitude to determine what to do. The appendix contains a detailed description of the algorithm. If the box is ticked, the altitude offset specified above is not parsed.<p>
'generate thermals' is an option intended primarily for soaring. It determines if thermals will be placed whenever a convective clouds is generated. Since managing a large number of thermals costs some amount of resources, it is recommended to generate thermals only if they are needed, i.e. definitely for soaring, possibly for added realism in small aircraft.<p>
'Worker threads' is an option to distribute the work flow. Usually, the local weather package will compute a task till it is done before starting the next. Thus, creating a new weather tile may lead to a few seconds freeze, before Flightgear continues normally. With 'worker threads' selected, computations will be split across several frames. The advantage is that Flightgear stays responsive during loading and unloading of weather tiles, and in general the flight continues smoothly, albeit with reduced framerate. However, selecting this option does not guarantee that an operation is finished by the time another is beginning - thus there may be situations in which the loading of a new tile blocks unloading of an old one and so on, in essence leading to processes competing for access to the weather array, resulting in an extended period of very low framerates. Dependent on system performance, this may or may not be acceptable to the user. 'asymmetric range' is an experimental performance-improving option (see below). Finally, 'detailed clouds' will change the technique for generating Cumulus clouds from a multilayer model to multiple cloudlets filling a box. This improves the visual appearance of the clouds significantly, albeit at the expense of a (significant) loss of framerate. Rendering multiple tiles of dense Cumulus development with detailed clouds will quite possibly freeze even a powerful system. <p> 'debug output' determines if the system writes status messages to the console. Unselecting the option suppresses normal status messages (warnings and errors will still be written). However, in many cases the log of status messages is needed to trace bugs, so if you switch it off and experience a problem, it is likely that the problem cannot be traced.<p>
The option 'dynamical weather' ties all clouds and weather effects to the windfield. If that option is not chosen, the wind is still generated according to the chosen model, but only felt by the aircraft. This makes e.g. soaring unrealistic, as the aircraft continuously drifts out of a static thermal below a static cap cloud. When 'dynamical weather' is selected, aircraft, cloud and thermal are all displaced by the wind.<p> 'detailed clouds' will change the technique for generating Cumulus clouds from a multilayer model to multiple cloudlets filling a box. This improves the visual appearance of the clouds significantly, albeit at the expense of some loss of framerate. Rendering multiple tiles of dense Cumulus development with detailed clouds will quite possibly slow down even a powerful system. <p>
The option 'dynamical weather' ties all clouds and weather effects to the windfield. If that option is not chosen, the wind is still generated according to the chosen model, but only felt by the aircraft. This makes e.g. soaring unrealistic, as the aircraft continuously drifts out of a static thermal below a static cap cloud. When 'dynamical weather' is selected, aircraft, cloud and thermal are all displaced by the wind and follow elevation changes to some degree.<p>
The final option 'dynamical convection' requires both 'terrain presamling' and 'dynamical weather' to be on (if not, a warning is given and the system aborts). If this option is chosen, all convective clouds and thermals have a life cycle - clouds are continually spawned and decay after a while. This preserves realistic cloud configurations over islands even with wind drift on and improves the realism of the soaring experience as the thermals change over time, but again uses somewhat more performance - switch it on if you need it, for fast planes the visual gain is almost non-existent.<p>
The slider 'Thermal properties' is mainly relevant for soaring scenarios. It governs the rato of maximum lift to radius of a thermal. A setting close to 'low convection' creates large thermals with relatively small lift and virtually no turbulence, a setting close to 'rough day' creates very narrow, turbulent thermals with large lift. However, it also affects the Cumulus textures to be used. 'low convection' creates well-formed, smooth Cumuli whereas 'rough day' biases the texture selection towards more rugged and diffuse clouds.<p> The slider 'Thermal properties' is mainly relevant for soaring scenarios. It governs the rato of maximum lift to radius of a thermal. A setting close to 'low convection' creates large thermals with relatively small lift and virtually no turbulence, a setting close to 'rough day' creates very narrow, turbulent thermals with large lift. However, it also affects the Cumulus textures to be used. 'low convection' creates well-formed, smooth Cumuli whereas 'rough day' biases the texture selection towards more rugged and diffuse clouds.<p>
The difference is apparent from the following pictures: Smooth and well-formed clouds characteristic of a calm day:<p>
<center>
<img src="detailed_clouds04.jpg">
</center><p>
Rough clouds characteristic of windshear and more turbulent conditions:<p>
<center>
<img src="detailed_clouds05.jpg">
</center><p>
As for the buttons, 'Ok' starts the local weather system with the selected options (note that all options in this menu are startup-time options, they are read once and changing them without restarting the system will not affect the behaviour of the system). 'Clear/End' clears all clouds and ends all local weather functionality - the button brings the system back into the state before it was started. No loops or other subroutines are executed after the button is pressed. 'Close' closes the dialog without starting the system.<p>
The button 'Show winds' brings up the detailed wind menu which is needed for the wind models 'aloft interpolated' and 'aloft waypoints':<p> The button 'Show winds' brings up the detailed wind menu which is needed for the wind models 'aloft interpolated' and 'aloft waypoints':<p>
<center> <center>
@ -125,14 +149,14 @@ In principle, the waypoint information inserted so far can be seen using the pro
The following pictures show the results of tile setups 'Low-pressure-border' and 'High-pressure-border':<p> The following pictures show possible results of tile setups 'High-pressure-border' and 'Low-pressure':<p>
<center> <center>
<img src="carrier-ops08.jpg"> <img src="high_pressure_border.jpg">
</center><p> </center><p>
<center> <center>
<img src="clouds-lpb01.jpg"> <img src="low_pressure.jpg">
</center><p> </center><p>
<h3>Performance settings</h3> <h3>Performance settings</h3>
@ -162,11 +186,20 @@ All performance setting menu-options work at runtime, but are processed over tim
The package contains a number of different cloud models, both static ones for Cirrus and Cirrocumulus clouds as well as rotated ones for Altocumulus, Cirrostratus, Cumulus, Cumulonimbus, Stratus and Nimbostratus cloudlet models. Neither the cloud textures, nor the models nor the transformations are perfected, and any aspect can be improved.<p> The package contains a number of different cloud models, both static ones for Cirrus and Cirrocumulus clouds as well as rotated ones for Altocumulus, Cirrostratus, Cumulus, Cumulonimbus, Stratus and Nimbostratus cloudlet models. Neither the cloud textures, nor the models nor the transformations are perfected, and any aspect can be improved.<p>
Static clouds project textures onto curved sheets into the sky. The advantage of the technique is that cloud layers consisting of thousands of cloudlets with different sizes can be modelled. However, the sheets do not look equally well from all perspectives and somewhat unrealistic from close up.<p>
<center>
<img src="clouds-static.jpg">
</center><p>
Rotated cloud models have the advantage that they look much better from close up and hardly unrealistic from any perspective, but the size distribution of cloudlets is somewhat restricted and they use a lot more performance than static clouds.<p>
<center> <center>
<img src="clouds-detailed01.jpg"> <img src="clouds-detailed01.jpg">
</center><p> </center><p>
These are rendered by a different technique: While the default Cumulus models consist of multiple layers rotated around the center of the model, the detailed Cumulus clouds consist of multiple (up to 24) individual cloudlets, rotating each around its own center, randomly distributed into a box. This not only improves the visual appearance, but also leads to a more realistic distribution of cloud sizes and shapes in the sky. In addition, when circling below the cloud (as done when soaring) the effect of the cloudlet rotation is less pronounced. The price to pay is that rendering detailed clouds costs about a factor 4 more performance, so they may not be suitable for all systems.<p> These are rendered by different techniques. While the default Cumulus models consist of multiple layers rotated around the center of the model, the detailed Cumulus clouds consist of multiple (up to 24) individual cloudlets, rotating each around its own center, randomly distributed into a box with different texture types used for the cloud bottom. This not only improves the visual appearance, but also leads to a more realistic distribution of cloud sizes and shapes in the sky. In addition, when circling below the cloud (as done when soaring) the effect of the cloudlet rotation is less pronounced. The price to pay is that rendering detailed clouds costs more performance, so they may not be suitable for all systems.<p>
More complex clouds are rendered in sandwitched layers of several different textures. An example are Cumulonimbus towers, which use diffuse textures on the bottom, changing to more structured textures in the upper part of the cloud. With up to 2000 cloudlets, skies with multiple thunderstorms may not render with sufficient framerates on every system.<p> More complex clouds are rendered in sandwitched layers of several different textures. An example are Cumulonimbus towers, which use diffuse textures on the bottom, changing to more structured textures in the upper part of the cloud. With up to 2000 cloudlets, skies with multiple thunderstorms may not render with sufficient framerates on every system.<p>
@ -178,7 +211,7 @@ The general problem is finding a good balance between spending a lot of CPU time
Currently all clouds which need to be rotated are treated in the Shaders using a view-axis based rotation by two angles. This generally looks okay from a normal flight position, but rapid change of the view axis (looking around), especially straight up or down, causes unrealistic cloud movement. Any static picture of clouds however is (almost) guaranteed to look fine. This means that shader effects need to be 'on' in order to see most of the clouds.<p> Currently all clouds which need to be rotated are treated in the shaders using a view-axis based rotation by two angles. This generally looks okay from a normal flight position, but rapid change of the view axis (looking around), especially straight up or down, causes unrealistic cloud movement. Any static picture of clouds however is (almost) guaranteed to look fine. This means that shader effects need to be 'on' in order to see most of the clouds.<p>
<h2>5. Local weather parameters</h2> <h2>5. Local weather parameters</h2>
@ -208,11 +241,11 @@ Volumes 2 and 3 are nested inside volume 1, therefore all settings of 2 overwrit
Effect volumes are always specified between a minimum and a maximum altitude, and they can have a circular, elliptical and rectangular share (the last two rotated by an angle phi). Since it is quite difficult to set up event volumes without visual reference and also not realistic to use them without the context of a cloud or precipitation model, there is no low-level setup call available in the menu. Effect volumes can be created with a Nasal call <p> Effect volumes are always specified between a minimum and a maximum altitude, and they can have a circular, elliptical and rectangular share (the last two rotated by an angle phi). Since it is quite difficult to set up event volumes without visual reference and also not realistic to use them without the context of a cloud or precipitation model, there is no low-level setup call available in the menu. Effect volumes can be created with a Nasal call <p>
<i>create_effect_volume(geometry, lat, lon, r1, r2, phi, alt_low, alt_high, vis, rain, snow, turb, lift, lift_flag);</i><p> <i>create_effect_volume(geometry, lat, lon, r1, r2, phi, alt_low, alt_high, vis, rain, snow, turb, lift, lift_flag, sat);</i><p>
where <i>geometry</i> is a flag (1: circular, 2: elliptical and 3: rectangular), <i>lat</i> and <i>lon</i> are the latitude and longitude, <i>r1</i> and <i>r2</i> are the two size parameters for the elliptic or rectangular shape (for the circular shape, only the first is used), <i>phi</i> is the rotation angle of the shape (not used for circular shape), <i>alt_low</i> and <i>alt_high</i> are the altitude boundaries, <i>vis, rain, snow, turb</i> and <i>lift</i> are weather parameters which are either set to the value they should assume, or to -1 if they are not to be used, or to -2 if a function instead of a parameter is to be used. Since thermal lift can be set to negative values in a sink, a separate flag is provided in this case.<p> where <i>geometry</i> is a flag (1: circular, 2: elliptical and 3: rectangular), <i>lat</i> and <i>lon</i> are the latitude and longitude, <i>r1</i> and <i>r2</i> are the two size parameters for the elliptic or rectangular shape (for the circular shape, only the first is used), <i>phi</i> is the rotation angle of the shape (not used for circular shape), <i>alt_low</i> and <i>alt_high</i> are the altitude boundaries, <i>vis, rain, snow, turb</i> and <i>lift</i> are weather parameters which are either set to the value they should assume, or to -1 if they are not to be used, or to -2 if a function instead of a parameter is to be used and -3 if a function for wave lift is used. Since thermal lift can be set to negative values in a sink, a separate flag is provided in this case. <i>sat</i> finally determines the light saturation - it can be used to dim the light beneath cloud layers (which is not done automatically as objects don't cast shades in Flightgear, and given that most cloud models are rotated, their shade would look rather odd on any case).<p>
In version 0.85, thermal lift is implemented by function. There is no easy way to implement any weather parameter by function in an effect volume, as this requires some amount of Nasal coding. In version 0.9, thermal lift and wave lift are implemented by function (wave lift is not yet automatically placed, but can be easily from Nasal). There is no easy way to implement any weather parameter by function in an effect volume, as this requires some amount of Nasal coding.
<h2>6. Wind models and dynamical weather</h2> <h2>6. Wind models and dynamical weather</h2>
@ -245,9 +278,9 @@ The internal state of the local weather system is found in the property tree und
The <i>local-weather</i> folder contains various subdirectories. <i>clouds/</i> contains the record of all visible weather phenomena (clouds, precipitation layers, lightning...) in a subdirectory <i>tile[j]/cloud[i]/</i>. The total number of all models placed is accessible as <i>local-weather/clouds/cloud-number</i>. Inside each <i>cloud/</i> subdirectory, there is a string <i>type</i> specifying the type of object and subdirectories <i>position/</i> and <i>orientation</i> which contain the position and spatial orientation of the model inside the scenery. Note that the orientation property is obsolete for clouds which are rotated by the shader.<p> The <i>local-weather</i> folder contains various subdirectories. <i>clouds/</i> contains the record of all visible weather phenomena (clouds, precipitation layers, lightning...) in a subdirectory <i>tile[j]/cloud[i]/</i>. The total number of all models placed is accessible as <i>local-weather/clouds/cloud-number</i>. Inside each <i>cloud/</i> subdirectory, there is a string <i>type</i> specifying the type of object and subdirectories <i>position/</i> and <i>orientation</i> which contain the position and spatial orientation of the model inside the scenery. Note that the orientation property is obsolete for clouds which are rotated by the shader.<p>
The <i>local-weather/effect-volumes/</i> subfolder contains the management of the effect volumes. It has the total count of specified effect volumes, along with the count of currently active volumes for each property. If volumes are defined, their properties are stored under <i>local-weather/effect-volumes/effect-volume[i]/</i>. In each folder, there are <i>position/</i> and <i>volume/</i> storing the spatial position and extent of the volume, as well as the <i>active-flag</i> which is set to 1 if the airplane is in the volume and the <i>geometry</i> flag which determines if the volume has circular, elliptical or rectangular shape. Finally, the <i>effects/</i> subfolder holds flags determining of a property is to be set when the volume is active and the corresponding values. On entry, the effect volumes also create a subfolder <i>restore/</i> in which the conditions as they were when the volume was entered are saved.<p> The <i>local-weather/effect-volumes/</i> subfolder contains the management of the effect volumes. It has the total count of specified effect volumes, along with the count of currently active volumes for each property.<p>
<i>local-weather/interpolation/</i> holds all properties which are set by the interpolation system, as well as subfolders <i>station[i]/</i> in which the weather station information for the interpolation are found and subfolders <i>wind[i]</i> where wind information in the case of 'aloft interpolated' or 'aloft waypoints' is stored. Basically, here is the state of the weather as it is outside of effect volumes. Since parameters may be set to different values in effect volumes, the folder <i>local-weather/current/</i> contains the weather as the local weather system currently thinks it should be. Currently, weather is actually passed to the Flightgear environment system through several workarounds. In a clean C++ supported version, the parameters should be read from here.<p> <i>local-weather/interpolation/</i> holds all properties which are set by the interpolation system. Basically, here is the state of the weather as it is outside of effect volumes. Since parameters may be set to different values in effect volumes, the folder <i>local-weather/current/</i> contains the weather as the local weather system currently thinks it should be. Currently, weather may be passed to the Flightgear environment system through several workarounds, dependent on the Flightgear core version.<p>
<i>local-weather/tiles</i> stores the information of the 9 managed weather tiles (the one the airplane is currently in, and the 8 surrounding it). By default each directory contains the tile center coordinates and a flag if it has been generated. Tiles are not generated unless a minimum distance to the tile center has been reached. Once this happens, the tile type is written as a code, and the cloud, interpolation and effect volume information corresponding to the tile is generated. <p> <i>local-weather/tiles</i> stores the information of the 9 managed weather tiles (the one the airplane is currently in, and the 8 surrounding it). By default each directory contains the tile center coordinates and a flag if it has been generated. Tiles are not generated unless a minimum distance to the tile center has been reached. Once this happens, the tile type is written as a code, and the cloud, interpolation and effect volume information corresponding to the tile is generated. <p>
@ -261,7 +294,7 @@ The first important call sets up the conditions to be interpolated:<p>
<i>set_weather_station(latitude, longitude, visibility-m, temperature-degc, dewpoint-degc, pressure-sea-level-inhg);</i><p> <i>set_weather_station(latitude, longitude, visibility-m, temperature-degc, dewpoint-degc, pressure-sea-level-inhg);</i><p>
The cloud placement calls should be reasonably familiar, as they closely resemble the structure by which they are accessible from the menu. Note that for (rather stupid reasons) currently a <i>randomize_pos</i> call <b>must</b> follow a <i>create_streak</i> call.<p> The cloud placement calls should be reasonably familiar, as they closely resemble the structure by which they are accessible from the 'Local Weather' menu.<p>
If the cloud layer has an orientation, then all placement coordinates should be rotated accordingly. Similarly, each placement call should include the altitude offset. Take care to nest effect volumes properly where possible, otherwise undesired effects might occur...<p> If the cloud layer has an orientation, then all placement coordinates should be rotated accordingly. Similarly, each placement call should include the altitude offset. Take care to nest effect volumes properly where possible, otherwise undesired effects might occur...<p>
@ -281,7 +314,8 @@ With default settings, the local weather package generates a 40x40 km weather ti
<li> if this does not help, try avoiding scenarios with large cloud count. As a rule, low pressure areas have high cloud count, high pressure areas have a low cloud count. Do not use 'detailed clouds', which tend to generate large cloud counts.<p> <li> if this does not help, try avoiding scenarios with large cloud count. As a rule, low pressure areas have high cloud count, high pressure areas have a low cloud count. Do not use 'detailed clouds', which tend to generate large cloud counts.<p>
<li> a different issue is a characteristic small pause every second. This is caused by the interpolation loop resetting the weather parameters. Currently, a computationally expensive workaround is needed to do so, causing the problem. Work on a better environment controller is on the way, however until that modification to the core Flightgear code is implemented, the best solution is to set the loop time in <i>Nasal/local-weather.nas</i> to a larger value. <p> <li> a different issue is a characteristic small pause every second. This may be caused by the interpolation loop resetting the weather parameters or by the altitude correction of convective clouds when cloud count is high and wind drift is on. The first issue only occurs when the system did not find hard coded support. There is no easy fix for the second problem, except to avoid dynamical weather in situations with large cloud counts.
<p>
<li> dynamical weather uses a lot of performance. If framerate is low and you don't need it, don't use it! From fast planes, cloud drift is almost impossible to see against the relative motion of cloud and airplane anyway.<p> <li> dynamical weather uses a lot of performance. If framerate is low and you don't need it, don't use it! From fast planes, cloud drift is almost impossible to see against the relative motion of cloud and airplane anyway.<p>
@ -297,7 +331,7 @@ With default settings, the local weather package generates a 40x40 km weather ti
<li> Rain and snow may not start properly. For me, rain is only generated when I switch 'Shader effects' on and off in the menu on startup, otherwise neither moving the menu slider nor entering an effect volume generate rain. This seems to be a bug of some Flightgear versions, not of the local weather system.<p> <li> Rain and snow may not start properly. For me, rain is only generated when I switch 'Shader effects' on and off in the menu on startup, otherwise neither moving the menu slider nor entering an effect volume generate rain. This seems to be a bug of some Flightgear versions, not of the local weather system.<p>
<li> Especially with multiple overcast layers and weather fronts, loading and unloading weather tiles may take a long time / cause severe drops in framerate. Please refer to performance tuning to solve such problems. In general, overcast layers and tropical weather tiles do require a system on the high end of the performance scale to render properly.<p> <li> Especially with multiple overcast layers and weather fronts, loading and unloading weather tiles may take a long time / cause severe drops in framerate. The problem is much worse in GIT than in 2.0.0. Please refer to performance tuning to solve such problems. In general, overcast layers and tropical weather tiles do require a system on the high end of the performance scale to render properly.<p>
<li> The local weather package is able to occasionally trigger errors like 'Warning:: Picked up error in TriangleIntersect'. These seem to be a problem in the core Flightgear code - the package does nothing but placing normal (rather simple) AC3D models into the scenery.<p> <li> The local weather package is able to occasionally trigger errors like 'Warning:: Picked up error in TriangleIntersect'. These seem to be a problem in the core Flightgear code - the package does nothing but placing normal (rather simple) AC3D models into the scenery.<p>
@ -307,6 +341,8 @@ With default settings, the local weather package generates a 40x40 km weather ti
<li> Large tile creation distances can cause problems in low visibility weather, because Flightgear loads terrain only if it is within visual range. Thus, trying to sample the terrain for a tile 55 km away in 8 km visibility doesn't work because the terrain elevation and altitude is not known. This may cause improper placement of clouds - chiefly convective clouds, but also layered clouds may not appear on the proper altitude. Currently, there is a limit which restricts tile loading range to 3 times the visibility, but presumably a better solution can be found.<p> <li> Large tile creation distances can cause problems in low visibility weather, because Flightgear loads terrain only if it is within visual range. Thus, trying to sample the terrain for a tile 55 km away in 8 km visibility doesn't work because the terrain elevation and altitude is not known. This may cause improper placement of clouds - chiefly convective clouds, but also layered clouds may not appear on the proper altitude. Currently, there is a limit which restricts tile loading range to 3 times the visibility, but presumably a better solution can be found.<p>
<li> Using the 'aloft interpolated' wind option, it is possible to turn the wind direction sharply over a small distance (for example, one may turn the wind by 90 degrees from one tile to the next). Such sharp wind changes are (in most situations) unphysical, and they may cause problems for local weather because they rotate the coordinate system to a degree that the neighbouring tile may not be identified correctly. In essence, the system may not generate new tiles because the nearest tile is still the last generated one. There will be a future fix to address the problem, for the moment just avoid rotating the wind strongly.<p>
<li> The thermals in the soaring scenarios need GIT to work.<p> <li> The thermals in the soaring scenarios need GIT to work.<p>
</ul> </ul>
@ -314,9 +350,9 @@ With default settings, the local weather package generates a 40x40 km weather ti
This section describes the more complicated cloud placement algorithms in some detail. It is intended for readers who are interested in understanding (and possibly modifying) what creates the weather they get to see. This section describes the more complicated cloud placement algorithms in some detail. It is intended for readers who are interested in understanding (and possibly modifying) what creates the weather they get to see.
<h3>The convective algorithm and the properties of thermals</h3> <h3>The convective startup algorithm and the properties of thermals</h3>
The convective algorithm is used to place Cumulus clouds as well as thermals. Thermals are by default not placed to save CPU time unless a tile designed for soaring is selected, but they can be generated for any weather tile by setting <i>local-weather/tmp/generate-thermal-lift-flag</i> to either 1 (constant-strength thermals) or 2 (detailed thermal model).<p> The convective startup algorithm is used to place Cumulus clouds as well as thermals. Thermals are by default not placed to save CPU time unless the flag is set in the menu.<p>
At the core of the convective algorithm is the concept of locally available thermal energy. The source of this energy is solar radiation. The flux of solar energy depends on the angle of incident sunlight with the terrain surface. It is possibly (though computationally very expensive) to compute this quantity, but the algorithm uses a proxy instead. The daily angle of the sun at the equator assuming flat terrain is modelled as <i>0.5 * (1.0-cos(t/24.0*2pi))</i> with t expressed in hours, a function that varies between zero at midnight and 1 at noon. There is a geographical correction to this formula which goes with <i>cos(latitude)</i>, taking care of the fact that the sun does not reach the zenith at higher latitudes. Both the yearly summer/winter variation of the solar position in the sky and the terrain slope are neglected.<p> At the core of the convective algorithm is the concept of locally available thermal energy. The source of this energy is solar radiation. The flux of solar energy depends on the angle of incident sunlight with the terrain surface. It is possibly (though computationally very expensive) to compute this quantity, but the algorithm uses a proxy instead. The daily angle of the sun at the equator assuming flat terrain is modelled as <i>0.5 * (1.0-cos(t/24.0*2pi))</i> with t expressed in hours, a function that varies between zero at midnight and 1 at noon. There is a geographical correction to this formula which goes with <i>cos(latitude)</i>, taking care of the fact that the sun does not reach the zenith at higher latitudes. Both the yearly summer/winter variation of the solar position in the sky and the terrain slope are neglected.<p>
@ -368,6 +404,32 @@ At sunset around 19:00 pm, the number of clouds decreases quickly, but there is
While not accurate in every respect, the model works fairly well to reproduce the actual time dependence of convective clouds and thermal lift during the day.<p> While not accurate in every respect, the model works fairly well to reproduce the actual time dependence of convective clouds and thermal lift during the day.<p>
<h3>The convective dynamics algorithm</h3>
The convective dynamics algorithm is responsible for modelling the life cycle of convective clouds, dependent on the terrain type underneath. It meshes well with the convective startup algorithm, and its long-term zero wind limit is just the situation set up by the initial convective placement.<p>
At its heart is the idea of fractional cloud lifetime. A cloud is born with fractional lifetime zero, and it decays once its fractional lifetime reaces 1. The translation of real time to fractional lifetime is given by <i>sqrt(p)</i> where <i>p</i> is the landcover dependent probability defined above. A cloud over landcover with maximum <i>p</i> of 0.35 has a lifetime of 30 minutes, so if a cloud spends 10 minutes over this terrain type, its fractional lifetime is increased by 1/3. If the landcover is different, the lifetime is reduced according to <i>sqrt(p_1/p_max)</i>.<p>
A cloud field is initialized with fractional lifetimes randomly distributed between zero and 1. To compensate for the decay of clouds, clouds are periodically respawned as in the startup algorithm, but with placement probability <i>sqrt(p)</i> instead of <i>p</i>. In the limit of no wind, the cloud density over a terrain type is then given by placement probability times lifetime, i.e. <i>sqrt(p) * sqrt(p) = p</i> as it should be. The presence of a windfield distorts the cloud distribution, dense clouds are then found preferably downwind of suitable convection sources.<p>
<h3>The thermal lift model</h3>
The model of the distribution of lift inside a thermal is quite complex. <p>
<center>
<img src="thermal_lift.gif">
</center><p>
Vertically, is is characterized in addition to height and radius by two parameters, 'coning' and 'shaping', which make it cone-shaped and wasp-waisted. From zero to 200 m above ground, the lift is smoothly fading in, above the cloudbase it is smoothly faded out to zero at 10% above the nominal altitude. Horizontally, there is an outer ring where the air becomes turbulent, followed by a region of sink which in turn is followed by the inner core of lift.<p>
The distribution of lift and sink is time dependent.
<center>
<img src="thermal_lift_time.gif">
</center><p>
In a young thermal, lift starts to develop from the ground, sink is initially absent. When the lift reaches the cloudbase, sink starts to develop from the ground and rises up as well. Only in a mature thermal are sink and lift in equilibrium. When the thermal starts to decay, lift initially decays from the ground upward, till it reaches the cloudbase. At this time the cap cloud dissolves. For a time there is a residual distribution of sink decaying from bottom to top till the thermal evolution is over and the thermal (and the associate turbulence field) is removed.<p>
<h3>The terrain presampling and cloud altitude determination algorithm</h3> <h3>The terrain presampling and cloud altitude determination algorithm</h3>
While the meaning of a cloud layer altitude is rather obvious in level terrain, this quickly becomes a highly non-trivial question in mountaineous terrain where the elevation of the terrain is more difficult to define. Observation of weather patterns in mountain regions suggests that clouds follow changes in terrain elevation to some degree, but not all cloud types do to the same degree. While convective clouds follow a change in elevation more readily even on small distance scales, layered clouds don't do so. The purpose of the terrain presampling and cloud altitude determination algorithm is to capture this behaviour as closely as possible.<p> While the meaning of a cloud layer altitude is rather obvious in level terrain, this quickly becomes a highly non-trivial question in mountaineous terrain where the elevation of the terrain is more difficult to define. Observation of weather patterns in mountain regions suggests that clouds follow changes in terrain elevation to some degree, but not all cloud types do to the same degree. While convective clouds follow a change in elevation more readily even on small distance scales, layered clouds don't do so. The purpose of the terrain presampling and cloud altitude determination algorithm is to capture this behaviour as closely as possible.<p>
@ -434,10 +496,10 @@ Realistically, the boundary layer should also depend on terrain coverage. Due to
<h2>Credits</h2> <h2>Credits</h2>
The model of a thermal has been developed by Patrice Poly. The shader code used to transform clouds is heavily based on prior work by Stuart Buchanan.<p> The model of a thermal has been developed by Patrice Poly. The shader code used to transform clouds is heavily based on prior work by Stuart Buchanan. Hard-coding of some features by Torsten Dreyer is greatly appreciated.<p>
Thorsten Renk, June 2010 Thorsten Renk, October 2010
</body> </body>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 58 KiB

BIN
Docs/clouds-static.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
Docs/detailed_clouds04.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
Docs/detailed_clouds05.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
Docs/low_pressure.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

BIN
Docs/thermal_lift.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
Docs/thermal_lift_time.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -13,6 +13,149 @@
<tangent type="int">6</tangent> <tangent type="int">6</tangent>
<binormal type="int">7</binormal> <binormal type="int">7</binormal>
</generate> </generate>
<technique n="8">
<predicate>
<and>
<property>/sim/rendering/urban-shader</property>
<property>/sim/rendering/shader-effects</property>
<less-equal>
<value type="float">4.0</value>
<float-property>/sim/rendering/quality-level</float-property>
</less-equal>
<or>
<less-equal>
<value type="float">2.0</value>
<glversion/>
</less-equal>
<and>
<extension-supported>GL_ARB_shader_objects</extension-supported>
<extension-supported>GL_ARB_shading_language_100</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
</and>
</or>
</and>
</predicate>
<pass>
<lighting>true</lighting>
<material>
<ambient><use>material/ambient</use></ambient>
<diffuse><use>material/diffuse</use></diffuse>
<specular><use>material/specular</use></specular>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<blend><use>transparent</use></blend>
<alpha-test><use>transparent</use></alpha-test>
<shade-model>smooth</shade-model>
<cull-face>back</cull-face>
<render-bin>
<bin-number><use>render-bin/bin-number</use></bin-number>
<bin-name><use>render-bin/bin-name</use></bin-name>
</render-bin>
<texture-unit>
<unit>0</unit>
<image><use>texture[0]/image</use></image>
<filter><use>texture[0]/filter</use></filter>
<wrap-s><use>texture[0]/wrap-s</use></wrap-s>
<wrap-t><use>texture[0]/wrap-t</use></wrap-t>
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
</texture-unit>
<texture-unit>
<unit>1</unit>
<image><use>texture[2]/image</use></image>
<filter><use>texture[2]/filter</use></filter>
<wrap-s><use>texture[2]/wrap-s</use></wrap-s>
<wrap-t><use>texture[2]/wrap-t</use></wrap-t>
<internal-format><use>texture[2]/internal-format</use></internal-format>
</texture-unit>
<texture-unit>
<unit>2</unit>
<image><use>texture[2]/image</use></image>
<filter>nearest-mipmap-nearest</filter>
<wrap-s><use>texture[2]/wrap-s</use></wrap-s>
<wrap-t><use>texture[2]/wrap-t</use></wrap-t>
<internal-format><use>texture[2]/internal-format</use></internal-format>
<mipmap-control>
<function-r>average</function-r>
<function-g>average</function-g>
<function-b>average</function-b>
<function-a>min</function-a>
</mipmap-control>
</texture-unit>
<texture-unit>
<unit>3</unit>
<type>noise</type>
</texture-unit>
<program>
<vertex-shader>Shaders/urban.vert</vertex-shader>
<fragment-shader>Shaders/urban.frag</fragment-shader>
<attribute>
<name>tangent</name>
<index>6</index>
</attribute>
<attribute>
<name>binormal</name>
<index>7</index>
</attribute>
<attribute>
<name>normal</name>
<index>15</index>
</attribute>
</program>
<uniform>
<name>BaseTex</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>NormalTex</name>
<type>sampler-2d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>QDMTex</name>
<type>sampler-2d</type>
<value type="int">2</value>
</uniform>
<uniform>
<name>NoiseTex</name>
<type>sampler-3d</type>
<value type="int">3</value>
</uniform>
<uniform>
<name>depth_factor</name>
<type>float</type>
<value><use>depth-factor</use></value>
</uniform>
<uniform>
<name>tile_size</name>
<type>float</type>
<value><use>xsize</use></value>
</uniform>
<uniform>
<name>night_color</name>
<type>float-vec3</type>
<value><use>night-color</use></value>
</uniform>
<uniform>
<name>quality_level</name>
<type>float</type>
<value><use>quality-level</use></value>
</uniform>
<uniform>
<name>snowlevel</name>
<type>float</type>
<value><use>snow-level</use></value>
</uniform>
<uniform>
<name>max_lod_level</name>
<type>float</type>
<value><use>max-lod-level</use></value>
</uniform>
</pass>
</technique>
<technique n="9"> <technique n="9">
<predicate> <predicate>
<and> <and>

View file

@ -10,13 +10,6 @@
<wrap-t>repeat</wrap-t> <wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format> <internal-format>normalized</internal-format>
</texture> </texture>
<texture n="1">
<image>Textures/Water/water-refraction.png</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<texture n="2"> <texture n="2">
<image>Textures/Water/water-normalmap.png</image> <image>Textures/Water/water-normalmap.png</image>
<filter>linear-mipmap-linear</filter> <filter>linear-mipmap-linear</filter>
@ -84,16 +77,6 @@
<use>texture[0]/internal-format</use> <use>texture[0]/internal-format</use>
</internal-format> </internal-format>
</texture-unit> </texture-unit>
<texture-unit>
<unit>1</unit>
<image><use>texture[1]/image</use></image>
<filter><use>texture[1]/filter</use></filter>
<wrap-s><use>texture[1]/wrap-s</use></wrap-s>
<wrap-t><use>texture[1]/wrap-t</use></wrap-t>
<internal-format>
<use>texture[1]/internal-format</use>
</internal-format>
</texture-unit>
<texture-unit> <texture-unit>
<unit>2</unit> <unit>2</unit>
<image><use>texture[2]/image</use></image> <image><use>texture[2]/image</use></image>
@ -124,11 +107,6 @@
<value type="int">0</value> <value type="int">0</value>
</uniform> </uniform>
<uniform> <uniform>
<name>water_refraction</name>
<type>sampler-2d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>water_normalmap</name> <name>water_normalmap</name>
<type>sampler-2d</type> <type>sampler-2d</type>
<value type="int">2</value> <value type="int">2</value>

View file

@ -1,40 +0,0 @@
<?xml version="1.0"?>
<!--
Preliminary Default Hud.
November 2000
Neetha Girish <neetha@ada.ernet.in>
Based on Default Panel by David Megginson, david@megginson.com.
This is a Hud configuration file for the open-source flight
simulator FlightGear (www.flightgear.org). The file is an XML-encoded
FlightGear property list defining the Hud.
Each instrument is, itself, defined in an XML-encoded property list
in a separate file.
-->
<PropertyList>
<depreciated/>
<name>Fighter Hud</name>
<instruments>
<hudladder>
<path>Huds/Instruments/Custom/hudladder.xml</path>
</hudladder>
<hudcard>
<path>Huds/Instruments/Custom/hudcard.xml</path>
</hudcard>
<instrlabel>
<path>Huds/Instruments/Custom/instrlabel.xml</path>
</instrlabel>
</instruments>
</PropertyList>

View file

@ -1,56 +0,0 @@
<?xml version="1.0"?>
<!--
Preliminary Default Hud.
November 2000
Neetha Girish <neetha@ada.ernet.in>
Based on Default Panel by David Megginson, david@megginson.com.
This is a Hud configuration file for the open-source flight
simulator FlightGear (www.flightgear.org). The file is an XML-encoded
FlightGear property list defining the Hud.
Each instrument is, itself, defined in an XML-encoded property list
in a separate file.
-->
<PropertyList>
<depreciated/>
<name>Default Aircraft Hud</name>
<instruments>
<hudladder>
<path>Huds/Instruments/Default/hudladder.xml</path>
</hudladder>
<hudcard>
<path>Huds/Instruments/Default/hudcard.xml</path>
</hudcard>
<instrlabel>
<path>Huds/Instruments/Default/instrlabel.xml</path>
</instrlabel>
<fgTBI>
<path>Huds/Instruments/Default/fgtbi.xml</path>
</fgTBI>
<Gload>
<path>Huds/Instruments/Default/gload.xml</path>
</Gload>
<!-- disabled by default because the runway projection and selection has some
issues ...
<runwayhud>
<path>Huds/Instruments/Default/runwayinstr.xml</path>
</runwayhud>
-->
</instruments>
</PropertyList>

View file

@ -1,44 +0,0 @@
<?xml version="1.0"?>
<!--
Preliminary Default Hud.
November 2000
Neetha Girish <neetha@ada.ernet.in>
Based on Default Panel by David Megginson, david@megginson.com.
This is a Hud configuration file for the open-source flight
simulator FlightGear (www.flightgear.org). The file is an XML-encoded
FlightGear property list defining the Hud.
Each instrument is, itself, defined in an XML-encoded property list
in a separate file.
-->
<PropertyList>
<depreciated/>
<name>Default Aircraft Hud</name>
<instruments>
<hudladder>
<path>Huds/Instruments/Default/hudladder.xml</path>
</hudladder>
<hudcard>
<path>Huds/Instruments/Default/hudcard.xml</path>
</hudcard>
<instrlabel>
<path>Huds/Instruments/Engineering/instrlabel.xml</path>
</instrlabel>
<fgTBI>
<path>Huds/Instruments/Default/fgtbi.xml</path>
</fgTBI>
</instruments>
</PropertyList>

View file

@ -1,22 +0,0 @@
<PropertyList>
<tbis>
<f1>
<name>fgTBI_Instrument</name>
<x>290</x>
<y>200</y>
<width>60</width>
<height>10</height>
<maxBankAngle>45.0</maxBankAngle>
<maxSlipAngle>5.0</maxSlipAngle>
<gap_width>5</gap_width>
<working>true</working>
<tsi>true</tsi> <!-- suma -->
<rad>150.0</rad> <!-- suma -->
</f1>
</tbis>
</PropertyList>

View file

@ -1,183 +0,0 @@
<?xml version="1.0"?>
<!--
HudCards for ADA.
Started November 2000 by Neetha Girish, neetha@ada.ernet.in
Based on Panel Instruments by David Megginson, david@megginson.com.
This is an instrument configuration file for the open-source flight
simulator FlightGear (www.flightgear.org). The file is an XML-encoded
FlightGear property list defining the instrument's properties.
-->
<PropertyList>
<cards>
<c1>
<!-- changes made by suma this angle is to rotate thru the envt.-->
<!-- suma
To display the hud-card as a type of gauge, radius and number of divisions are included.
radius-> of the circle and divisions-> number of divisions in a circle. so it should be multiple of 4.
all the moved values are used when the type="tape". and when the type="gauge" radius and divisions are used.
-->
<!-- for a vertical scale the option value should be 6,10 or 14.
6 -> left side arrow
10 -> right side arrow
14 -> both sides arrow -->
<!-- for a horizontal scale the option value should be 6,10 or 14.
4 -> top facing arrow
8 -> bottom facing arrow
12 -> both sides arrow -->
<name>Gyrocompass</name>
<x>260</x> <!-- 260 -->
<y>248</y> <!-- 248 -->
<width>120</width>
<height>28</height>
<loadfn>heading</loadfn>
<options>4</options> <!-- Read ReadMe.xmlhud -->
<maxValue>360.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>0.1</disp_scaling> <!-- 0.1 -->
<major_divs>10</major_divs>
<minor_divs>5</minor_divs>
<modulator>360</modulator>
<value_span>60.0</value_span>
<type>tape</type> <!-- when the type is "gauge",only radius is needed. -->
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>10.0</marker_offset>
<enable_pointer>false</enable_pointer>
<pointer_type>fixed</pointer_type> <!-- this should be always fixed type for compass -->
<tick_type>line</tick_type>
<tick_length>variable</tick_length>
<working>true</working>
<radius>40.0</radius> <!-- for type=gauge -->
<divisions>12</divisions> <!-- it should be multiple of 4 -->
<zoom>0</zoom> <!-- for VSI -->
</c1>
<c2>
<name>AOA</name>
<x>180</x> <!-- 175 -->
<y>100</y>
<width>28</width>
<height>100</height>
<loadfn>aoa</loadfn>
<options>6</options>
<maxValue>20.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>4</major_divs>
<minor_divs>2</minor_divs>
<modulator>0</modulator>
<value_span>20.0</value_span>
<type>tape</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>10.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>moving</pointer_type>
<tick_type>circle</tick_type>
<tick_length>constant</tick_length>
<working>true</working>
<radius>30.0</radius> <!-- for type=gauge -->
<divisions>12</divisions> <!-- it should be multiple of 4 -->
<zoom>0</zoom> <!-- for VSI -->
</c2>
<c3>
<name>NormalAcceleration</name>
<x>140</x>
<y>110</y>
<width>18</width>
<height>100</height>
<loadfn>anzg</loadfn>
<options>6</options>
<maxValue>9.0</maxValue>
<minValue>-3.0</minValue>
<disp_scaling>1</disp_scaling>
<major_divs>2</major_divs>
<minor_divs>1</minor_divs>
<modulator>0</modulator>
<value_span>12.0</value_span>
<type>tape</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>10.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>moving</pointer_type>
<tick_type>line</tick_type>
<tick_length>variable</tick_length>
<working>false</working>
<radius>40.0</radius> <!-- for type=gauge -->
<divisions>12</divisions> <!-- it should be multiple of 4 -->
<zoom>0</zoom> <!-- for VSI -->
</c3>
<!-- for moving type pointer adjust the values of value_span, major_divs, minor_divs, disp_scaling -->
<c4>
<name>VSI</name>
<x>430</x> <!-- 445 -->
<y>50</y>
<width>28</width>
<height>150</height>
<loadfn>climb</loadfn>
<options>10</options>
<maxValue>1000.0</maxValue>
<minValue>-1000.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>200</major_divs>
<minor_divs>100</minor_divs>
<modulator>0</modulator>
<value_span>2000.0</value_span> <!-- set value_span = maxValue + minValue for moving type pointer -->
<type>tape</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>10.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>moving</pointer_type>
<tick_type>line</tick_type>
<tick_length>variable</tick_length>
<working>true</working>
<radius>40.0</radius> <!-- for type=gauge -->
<divisions>12</divisions> <!-- it should be multiple of 4 -->
<zoom>1</zoom> <!-- for VSI -->
</c4>
</cards>
</PropertyList>

View file

@ -1,53 +0,0 @@
<?xml version="1.0"?>
<!--
HudLadder for ADA.
Started November 2000 by Neetha Girish, neetha@ada.ernet.in
Based on Panel Instruments by David Megginson, david@megginson.com.
This is an instrument configuration file for the open-source flight
simulator FlightGear (www.flightgear.org). The file is an XML-encoded
FlightGear property list defining the instrument's properties.
-->
<PropertyList>
<ladders>
<l1>
<name>Climb/Dive Ladder</name>
<x>260</x>
<y>150</y> <!-- 150 -->
<width>120</width>
<height>180</height> <!-- 180 -->
<compression_factor>12.6316</compression_factor>
<loadfn>roll</loadfn>
<loadfn1>pitch</loadfn1>
<span_units>45</span_units>
<division_units>5.0</division_units>
<screen_hole>70</screen_hole>
<lbl_pos>0</lbl_pos>
<enable_frl>true</enable_frl>
<enable_target_spot>false</enable_target_spot>
<enable_velocity_vector>true</enable_velocity_vector>
<enable_drift_marker>true</enable_drift_marker>
<enable_alpha_bracket>true</enable_alpha_bracket>
<enable_energy_marker>true</enable_energy_marker>
<enable_climb_dive_marker>true</enable_climb_dive_marker>
<enable_glide_slope_marker>true</enable_glide_slope_marker>
<glide_slope>-4.0</glide_slope>
<enable_energy_worm>true</enable_energy_worm>
<enable_waypoint_marker>true</enable_waypoint_marker>
<working>true</working>
<zenith>1</zenith>
<nadir>1</nadir>
<hat>1</hat>
</l1>
</ladders>
</PropertyList>

View file

@ -1,209 +0,0 @@
<PropertyList>
<labels>
<i1>
<name>digitalkias</name>
<x>130</x>
<y>265</y>
<width>40</width> <!-- specify the width of the label box here according to label format-->
<height>30</height>
<data_source>speed</data_source>
<label_format>%5.0f</label_format>
<pre_label_string>NULL</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options> <!-- Read ReadMe.xmlhud -->
<justification>2</justification>
<blinking>0</blinking>
<latitude>false</latitude>
<longitude>false</longitude>
<label_box>false</label_box>
<working>true</working>
</i1>
<i2>
<name>machno</name>
<x>140</x>
<y>245</y>
<width>40</width>
<height>30</height>
<data_source>mach</data_source>
<label_format>%5.2f</label_format>
<pre_label_string>NULL</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>2</justification>
<blinking>0</blinking>
<latitude>false</latitude>
<longitude>false</longitude>
<label_box>false</label_box>
<working>true</working>
</i2>
<i3>
<name>pressurealtitude</name>
<x>430</x>
<y>265</y>
<width>40</width>
<height>30</height>
<data_source>altitude</data_source>
<label_format>%5.0f</label_format>
<pre_label_string>NULL</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<latitude>false</latitude>
<longitude>false</longitude>
<label_box>false</label_box>
<working>true</working>
<digits>1</digits>
</i3>
<i4>
<name>radioaltitude</name>
<x>430</x>
<y>245</y>
<width>40</width>
<height>30</height>
<data_source>agl</data_source>
<label_format>%5.0f</label_format>
<pre_label_string>NULL</pre_label_string>
<post_label_string> R</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<latitude>false</latitude>
<longitude>false</longitude>
<label_box>false</label_box>
<working>true</working>
</i4>
<i5>
<name>xposn</name>
<x>560</x>
<y>440</y>
<width>40</width>
<height>30</height>
<data_source>aux4</data_source>
<label_format>%5.0f</label_format>
<pre_label_string>NULL</pre_label_string>
<post_label_string> m</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<latitude>false</latitude>
<longitude>false</longitude>
<label_box>false</label_box>
<working>true</working>
</i5>
<i6>
<name>pla</name>
<x>560</x>
<y>430</y>
<width>40</width>
<height>30</height>
<data_source>throttleval</data_source>
<label_format>%5.0f</label_format>
<pre_label_string>NULL</pre_label_string>
<post_label_string> pla</post_label_string>
<scale_data>130.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<latitude>false</latitude>
<longitude>false</longitude>
<label_box>false</label_box>
<working>true</working>
</i6>
<i7>
<name>FrameRate</name>
<x>0</x>
<y>25</y>
<width>60</width>
<height>10</height>
<data_source>framerate</data_source>
<label_format>%3.1f</label_format>
<pre_label_string>NULL</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>1</justification>
<blinking>0</blinking>
<latitude>false</latitude>
<longitude>false</longitude>
<label_box>false</label_box>
<working>true</working>
</i7>
<i8>
<name>acceleration</name>
<x>140</x>
<y>90</y>
<width>20</width>
<height>30</height>
<data_source>anzg</data_source>
<label_format>%1.1f</label_format>
<pre_label_string>blank</pre_label_string>
<post_label_string>NULL</post_label_string>
<scale_data>1.0</scale_data>
<options>1</options>
<justification>0</justification>
<blinking>0</blinking>
<latitude>false</latitude>
<longitude>false</longitude>
<label_box>true</label_box>
<working>true</working>
</i8>
<lat>
<name>lattitude</name>
<x>40</x>
<y>40</y>
<width>1</width>
<height>10</height>
<data_source>latitude</data_source>
<label_format>%s%</label_format>
<pre_label_string>blank</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>1</justification>
<blinking>0</blinking>
<latitude>true</latitude>
<longitude>false</longitude>
<label_box>false</label_box>
<working>true</working>
</lat>
<lon>
<name>longitude</name>
<x>550</x>
<y>40</y>
<width>1</width>
<height>10</height>
<data_source>longitude</data_source>
<label_format>%s%</label_format>
<pre_label_string>blank</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>1</justification>
<blinking>0</blinking>
<latitude>false</latitude>
<longitude>true</longitude>
<working>true</working>
</lon>
</labels>
</PropertyList>

View file

@ -1,21 +0,0 @@
<PropertyList>
<tbis>
<f1>
<name>fgTBI_Instrument</name>
<x>290</x>
<y>45</y>
<width>60</width>
<height>10</height>
<loadfn>roll</loadfn>
<loadfn1>sideslip</loadfn1>
<maxBankAngle>45.0</maxBankAngle>
<maxSlipAngle>5.0</maxSlipAngle>
<gap_width>5</gap_width>
<working>true</working>
</f1>
</tbis>
</PropertyList>

View file

@ -1,34 +0,0 @@
<!--
# Gload.xml file
# Defines a control that displays gload on the HUD
# Created by Keerti Bhamidpati (bhamidip@uiuc.edu)
-->
<PropertyList>
<labels>
<i1>
<name>G Load</name>
<x>41</x>
<y>345</y>
<width>40</width>
<height>30</height>
<data_source>anzg</data_source> <!-- Name of the function to be called, here get_anzg() is called -->
<label_format>%4.2f</label_format> <!-- The Label Format -->
<pre_label_string>NULL</pre_label_string> <!-- String to be written Pre Label -->
<post_label_string> g</post_label_string> <!-- String to be written Post Label -->
<scale_data>1.0</scale_data>
<options>4</options> <!-- Read Tape options or Hud.hxx -->
<justification>0</justification> <!-- Justify the label, 0=LEFT_JUSTIFY, 1=CENTER_JUSTIFY, 2=RIGHT_JUSTIFY -->
<blinking>0</blinking> <!-- Yet to be implemented -->
<working>true</working>
<latitude>false</latitude> <!-- True if the label is to display Lattitude (special label, displays deg.min.sec)-->
<longitude>false</longitude> <!-- True if the label is to display Longitude (special label, displays deg.min.sec)-->
</i1>
</labels>
</PropertyList>

View file

@ -1,285 +0,0 @@
<PropertyList>
<cards>
<c1>
<name>Gyrocompass</name>
<x>220</x>
<y>430</y>
<width>200</width>
<height>28</height>
<loadfn>heading</loadfn>
<options>4</options> <!-- HUDS_TOP --> <!-- Read ReadMe.xmlhud for Values -->
<maxValue>360.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>5</major_divs>
<minor_divs>1</minor_divs>
<modulator>360</modulator>
<value_span>25.0</value_span>
<type>tape</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>true</tick_right>
<tick_left>true</tick_left>
<cap_bottom>true</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<tick_type>line</tick_type>
<tick_length>variable</tick_length>
<working>true</working>
</c1>
<c2>
<name>AMSL</name>
<x>565</x>
<y>140</y>
<width>35</width>
<height>200</height>
<loadfn>altitude</loadfn>
<options>6</options> <!-- HUDS_LEFT | HUDS_VERT -->
<maxValue>5000.0</maxValue>
<minValue>-1000.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>100</major_divs>
<minor_divs>25</minor_divs>
<modulator>0</modulator>
<value_span>250.0</value_span>
<type>tape</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>true</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<tick_type>line</tick_type>
<tick_length>variable</tick_length>
<working>true</working>
</c2>
<c3>
<name>RadioAltimeter</name>
<x>438</x>
<y>165</y>
<width>25</width>
<height>150</height>
<loadfn>agl</loadfn>
<options>6</options> <!-- HUDS_LEFT | HUDS_VERT -->
<maxValue>1000.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>25</major_divs>
<minor_divs>5</minor_divs>
<modulator>0</modulator>
<value_span>200.0</value_span>
<type>tape</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>true</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<tick_type>line</tick_type>
<tick_length>variable</tick_length>
<working>true</working>
</c3>
<c4>
<name>KIAS</name>
<x>40</x>
<y>140</y>
<width>28</width>
<height>200</height>
<loadfn>speed</loadfn>
<options>10</options> <!-- HUDS_RIGHT | HUDS_VERT -->
<maxValue>200.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>10</major_divs>
<minor_divs>5</minor_divs>
<modulator>0</modulator>
<value_span>50.0</value_span>
<type>tape</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>true</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<tick_type>line</tick_type>
<tick_length>variable</tick_length>
<working>true</working>
</c4>
<g1>
<name>Gauge1</name>
<x>270</x>
<y>310</y>
<width>100</width>
<height>20</height>
<loadfn>aileronval</loadfn>
<options>136</options> <!-- HUDS_BOTTOM | HUDS_NOTEXT -->
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<disp_scaling>100.0</disp_scaling>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span> <!-- (maxValue - minValue) -->
<type>gauge</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>true</tick_right>
<tick_left>true</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>true</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g1>
<g2>
<name>Gauge2</name>
<x>182</x>
<y>190</y>
<width>20</width>
<height>100</height>
<loadfn>elevatorval</loadfn>
<options>138</options> <!-- HUDS_RIGHT | HUDS_VERT | HUDS_NOTEXT -->
<disp_scaling>-100.0</disp_scaling>
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span> <!-- (maxValue - minValue) -->
<marker_offset>0.0</marker_offset>
<type>gauge</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>true</cap_left>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g2>
<g3>
<name>Gauge3</name>
<x>270</x>
<y>150</y>
<width>100</width>
<height>20</height>
<loadfn>rudderval</loadfn>
<options>132</options> <!-- HUDS_TOP | HUDS_NOTEXT -->
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<disp_scaling>100.0</disp_scaling>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span> <!-- (maxValue - minValue) -->
<type>gauge</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>true</tick_right>
<tick_left>true</tick_left>
<cap_bottom>true</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g3>
<g4>
<name>Gauge4</name>
<x>15</x>
<y>165</y>
<width>20</width>
<height>150</height>
<loadfn>throttleval</loadfn>
<options>134</options> <!-- HUDS_VERT | HUDS_LEFT | HUDS_NOTEXT -->
<maxValue>1.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>100.0</disp_scaling>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>1.0</value_span> <!-- (maxValue - minValue) -->
<type>gauge</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>true</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g4>
<g5>
<name>Gauge5</name>
<x>172</x>
<y>190</y>
<width>10</width>
<height>100</height>
<loadfn>elevatortrimval</loadfn>
<options>134</options> <!-- HUDS_LEFT | HUDS_VERT | HUDS_NOTEXT -->
<disp_scaling>-100.0</disp_scaling>
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span> <!-- (maxValue - minValue) -->
<marker_offset>0.0</marker_offset>
<type>gauge</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g5>
</cards>
</PropertyList>

View file

@ -1,34 +0,0 @@
<PropertyList>
<ladders>
<l1>
<name>Pitch Ladder</name>
<x>260</x>
<y>150</y>
<width>120</width>
<height>180</height>
<compression_factor>2.68</compression_factor>
<loadfn>roll</loadfn>
<loadfn1>pitch</loadfn1>
<span_units>45.0</span_units>
<division_units>10.0</division_units>
<screen_hole>70</screen_hole>
<lbl_pos>0</lbl_pos>
<enable_frl>false</enable_frl>
<enable_target_spot>true</enable_target_spot>
<enable_velocity_vector>false</enable_velocity_vector>
<enable_drift_marker>false</enable_drift_marker>
<enable_alpha_bracket>false</enable_alpha_bracket>
<enable_energy_marker>false</enable_energy_marker>
<enable_climb_dive_marker>false</enable_climb_dive_marker>
<enable_glide_slope_marker>false</enable_glide_slope_marker>
<glide_slope>0.0</glide_slope>
<enable_energy_worm>false</enable_energy_worm>
<enable_waypoint_marker>false</enable_waypoint_marker>
<working>true</working>
</l1>
</ladders>
</PropertyList>

View file

@ -1,45 +0,0 @@
<PropertyList>
<labels>
<lat>
<name>latitude</name>
<x>110</x>
<y>430</y>
<width>1</width>
<height>10</height>
<data_source>latitude</data_source>
<label_format>%s%</label_format>
<pre_label_string>blank</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>1</justification>
<blinking>0</blinking>
<working>true</working>
<latitude>true</latitude>
<longitude>false</longitude>
</lat>
<lon>
<name>longitude</name>
<x>530</x>
<y>430</y>
<width>1</width>
<height>10</height>
<data_source>longitude</data_source>
<label_format>%s%</label_format>
<pre_label_string>blank</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>1</justification>
<blinking>0</blinking>
<working>true</working>
<latitude>false</latitude>
<longitude>true</longitude>
</lon>
</labels>
</PropertyList>

View file

@ -1,19 +0,0 @@
<PropertyList>
<runways>
<runway>
<name>Runway Hud</name>
<x>0</x>
<y>0</y>
<width>480</width>
<height>360</height>
<working>true</working>
<scale_dist_nm>5</scale_dist_nm>
<line_scale>5.0</line_scale>
<arrow_always>false</arrow_always>
<arrow_scale>1.0</arrow_scale>
<arrow_radius>50.0</arrow_radius>
<outer_stipple>-1</outer_stipple>
<center_stipple>64250</center_stipple>
</runway>
</runways>
</PropertyList>

View file

@ -1,21 +0,0 @@
<PropertyList>
<tbis>
<f1>
<name>fgTBI_Instrument</name>
<x>290</x>
<y>45</y>
<width>60</width>
<height>10</height>
<loadfn>roll</loadfn>
<loadfn1>sideslip</loadfn1>
<maxBankAngle>45.0</maxBankAngle>
<maxSlipAngle>5.0</maxSlipAngle>
<gap_width>5</gap_width>
<working>true</working>
</f1>
</tbis>
</PropertyList>

View file

@ -1,247 +0,0 @@
<PropertyList>
<cards>
<c1>
<name>Gyrocompass</name>
<x>220</x>
<y>430</y>
<width>200</width>
<height>28</height>
<loadfn>heading</loadfn>
<options>4</options> <!-- Read ReadMe.xmlhud for Values -->
<maxValue>360.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>5</major_divs>
<minor_divs>1</minor_divs>
<modulator>360</modulator>
<value_span>25.0</value_span>
<type>tape</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>true</tick_right>
<tick_left>true</tick_left>
<cap_bottom>true</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</c1>
<c2>
<name>AMSL</name>
<x>565</x>
<y>140</y>
<width>35</width>
<height>200</height>
<loadfn>altitude</loadfn>
<options>6</options>
<maxValue>5000.0</maxValue>
<minValue>-1000.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>100</major_divs>
<minor_divs>25</minor_divs>
<modulator>0</modulator>
<value_span>250.0</value_span>
<type>tape</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>true</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</c2>
<c3>
<name>RadioAltimeter</name>
<x>438</x>
<y>165</y>
<width>25</width>
<height>150</height>
<loadfn>agl</loadfn>
<options>6</options>
<maxValue>1000.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>25</major_divs>
<minor_divs>5</minor_divs>
<modulator>0</modulator>
<value_span>200.0</value_span>
<type>tape</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>true</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</c3>
<c4>
<name>KIAS</name>
<x>40</x>
<y>140</y>
<width>28</width>
<height>200</height>
<loadfn>speed</loadfn>
<options>10</options>
<maxValue>200.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>10</major_divs>
<minor_divs>5</minor_divs>
<modulator>0</modulator>
<value_span>50.0</value_span>
<type>tape</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>true</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</c4>
<g1>
<name>Gauge1</name>
<x>270</x>
<y>310</y>
<width>100</width>
<height>20</height>
<loadfn>aileronval</loadfn>
<options>88</options>
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<disp_scaling>100.0</disp_scaling>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span> <!-- (maxValue - minValue) -->
<type>gauge</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>true</tick_right>
<tick_left>true</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>true</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g1>
<g2>
<name>Gauge2</name>
<x>182</x>
<y>190</y>
<width>20</width>
<height>100</height>
<loadfn>elevatorval</loadfn>
<options>90</options>
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<disp_scaling>-100.0</disp_scaling>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span> <!-- (maxValue - minValue) -->
<type>gauge</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>true</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g2>
<g3>
<name>Gauge3</name>
<x>270</x>
<y>150</y>
<width>100</width>
<height>20</height>
<loadfn>rudderval</loadfn>
<options>84</options>
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<disp_scaling>100.0</disp_scaling>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span> <!-- (maxValue - minValue) -->
<type>gauge</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>true</tick_right>
<tick_left>true</tick_left>
<cap_bottom>true</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g3>
<g4>
<name>Gauge4</name>
<x>15</x>
<y>165</y>
<width>20</width>
<height>150</height>
<loadfn>throttleval</loadfn>
<options>86</options>
<maxValue>1.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>100.0</disp_scaling>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>1.0</value_span> <!-- (maxValue - minValue) -->
<type>gauge</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>true</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g4>
</cards>
</PropertyList>

View file

@ -1,34 +0,0 @@
<PropertyList>
<ladders>
<l1>
<name>Pitch Ladder</name>
<x>260</x>
<y>150</y>
<width>120</width>
<height>180</height>
<compression_factor>2.68</compression_factor>
<loadfn>roll</loadfn>
<loadfn1>pitch</loadfn1>
<span_units>45.0</span_units>
<division_units>10.0</division_units>
<screen_hole>70</screen_hole>
<lbl_pos>0</lbl_pos>
<enable_frl>false</enable_frl>
<enable_target_spot>true</enable_target_spot>
<enable_velocity_vector>false</enable_velocity_vector>
<enable_drift_marker>false</enable_drift_marker>
<enable_alpha_bracket>false</enable_alpha_bracket>
<enable_energy_marker>false</enable_energy_marker>
<enable_climb_dive_marker>false</enable_climb_dive_marker>
<enable_glide_slope_marker>false</enable_glide_slope_marker>
<glide_slope>0.0</glide_slope>
<enable_energy_worm>false</enable_energy_worm>
<enable_waypoint_marker>false</enable_waypoint_marker>
<working>true</working>
</l1>
</ladders>
</PropertyList>

View file

@ -1,140 +0,0 @@
<PropertyList>
<labels>
<i1>
<name>machno</name>
<x>25</x>
<y>130</y>
<width>40</width>
<height>30</height>
<data_source>mach</data_source>
<label_format>%4.2f</label_format>
<pre_label_string>blank</pre_label_string>
<post_label_string>NULL</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>2</justification>
<blinking>0</blinking>
<working>true</working>
<latitude>false</latitude>
<longitude>false</longitude>
</i1>
<lat>
<name>lattitude</name>
<x>110</x>
<y>430</y>
<width>1</width>
<height>10</height>
<data_source>latitude</data_source>
<label_format>%s%</label_format>
<pre_label_string>blank</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>1</justification>
<blinking>0</blinking>
<working>true</working>
<latitude>true</latitude>
<longitude>false</longitude>
</lat>
<lon>
<name>longitude</name>
<x>530</x>
<y>430</y>
<width>1</width>
<height>10</height>
<data_source>longitude</data_source>
<label_format>%s%</label_format>
<pre_label_string>blank</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>1</justification>
<blinking>0</blinking>
<working>true</working>
<latitude>false</latitude>
<longitude>true</longitude>
</lon>
<alpha>
<name>alpha</name>
<x>530</x>
<y>70</y>
<width>1</width>
<height>10</height>
<data_source>aoa</data_source>
<label_format>%4.1f%</label_format>
<pre_label_string>alpha:</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
<latitude>false</latitude>
<longitude>false</longitude>
</alpha>
<beta>
<name>beta</name>
<x>530</x>
<y>55</y>
<width>1</width>
<height>10</height>
<data_source>sideslip</data_source>
<label_format>%4.1f%</label_format>
<pre_label_string>beta:</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
<latitude>false</latitude>
<longitude>false</longitude>
</beta>
<nlf>
<name>nlf</name>
<x>530</x>
<y>40</y>
<width>1</width>
<height>10</height>
<data_source>nlf</data_source>
<label_format>%4.1f%</label_format>
<pre_label_string>nlf:</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
<latitude>false</latitude>
<longitude>false</longitude>
</nlf>
<framerate>
<name>framerate</name>
<x>530</x>
<y>25</y>
<width>1</width>
<height>10</height>
<data_source>framerate</data_source>
<label_format>%5.1f%</label_format>
<pre_label_string>framerate:</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
<latitude>false</latitude>
<longitude>false</longitude>
</framerate>
</labels>
</PropertyList>

View file

@ -1,21 +0,0 @@
<PropertyList>
<tbis>
<f1>
<name>fgTBI_Instrument</name>
<x>290</x>
<y>55</y>
<width>60</width>
<height>10</height>
<loadfn>roll</loadfn>
<loadfn1>sideslip</loadfn1>
<maxBankAngle>45.0</maxBankAngle>
<maxSlipAngle>5.0</maxSlipAngle>
<gap_width>5</gap_width>
<working>true</working>
</f1>
</tbis>
</PropertyList>

View file

@ -1,34 +0,0 @@
<!--
# Gload.xml file
# Defines a control that displays gload on the HUD
# Created by Keerti Bhamidpati (bhamidip@uiuc.edu)
-->
<PropertyList>
<labels>
<i1>
<name>G Load</name>
<x>11</x>
<y>294</y>
<width>40</width>
<height>30</height>
<data_source>anzg</data_source> <!-- Name of the function to be called, here get_anzg() is called -->
<label_format>%4.2f</label_format> <!-- The Label Format -->
<pre_label_string>NULL</pre_label_string> <!-- String to be written Pre Label -->
<post_label_string> g</post_label_string> <!-- String to be written Post Label -->
<scale_data>1.0</scale_data>
<options>4</options> <!-- Read Tape options or Hud.hxx -->
<justification>0</justification> <!-- Justify the label, 0=LEFT_JUSTIFY, 1=CENTER_JUSTIFY, 2=RIGHT_JUSTIFY -->
<blinking>0</blinking> <!-- Yet to be implemented -->
<working>true</working>
<latitude>false</latitude> <!-- True if the label is to display Lattitude (special label, displays deg.min.sec)-->
<longitude>false</longitude> <!-- True if the label is to display Longitude (special label, displays deg.min.sec)-->
</i1>
</labels>
</PropertyList>

View file

@ -1,189 +0,0 @@
<PropertyList>
<cards>
<c1>
<name>Gyrocompass</name>
<x>220</x>
<y>430</y>
<width>200</width>
<height>28</height>
<loadfn>view_direction</loadfn>
<options>4</options> <!-- HUDS_TOP -->
<maxValue>360.0</maxValue>
<minValue>0.0</minValue>
<disp_scaling>1.0</disp_scaling>
<major_divs>5</major_divs>
<minor_divs>1</minor_divs>
<modulator>360</modulator>
<value_span>25.0</value_span>
<type>tape</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>true</tick_right>
<tick_left>true</tick_left>
<cap_bottom>true</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<tick_type>line</tick_type>
<tick_length>variable</tick_length>
<working>true</working>
</c1>
<g1>
<name>Gauge1</name>
<x>270</x>
<y>390</y>
<width>100</width>
<height>20</height>
<loadfn>aileronval</loadfn>
<options>136</options> <!-- HUDS_BOTTOM | HUDS_NOTEXT -->
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<disp_scaling>100.0</disp_scaling>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span>
<type>gauge</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>true</tick_right>
<tick_left>true</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>true</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g1>
<g2>
<name>Gauge2</name>
<x>20</x>
<y>190</y>
<width>20</width>
<height>100</height>
<loadfn>elevatorval</loadfn>
<options>138</options> <!-- HUDS_RIGHT | HUDS_VERT | HUDS_NOTEXT -->
<disp_scaling>-100.0</disp_scaling>
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span>
<type>gauge</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>true</cap_left>
<marker_offset>0.0</marker_offset>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g2>
<g3>
<name>Gauge3</name>
<x>270</x>
<y>25</y>
<width>100</width>
<height>20</height>
<loadfn>rudderval</loadfn>
<options>132</options> <!-- HUDS_TOP | HUDS_NOTEXT -->
<disp_scaling>100.0</disp_scaling>
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span>
<marker_offset>0.0</marker_offset>
<type>gauge</type>
<tick_bottom>false</tick_bottom>
<tick_top>false</tick_top>
<tick_right>true</tick_right>
<tick_left>true</tick_left>
<cap_bottom>true</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g3>
<g4>
<name>Gauge4</name>
<x>600</x>
<y>160</y>
<width>20</width>
<height>160</height>
<loadfn>throttleval</loadfn>
<options>134</options> <!-- HUDS_VERT | HUDS_LEFT | HUDS_NOTEXT -->
<disp_scaling>100.0</disp_scaling>
<maxValue>1.0</maxValue>
<minValue>0.0</minValue>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>1.0</value_span>
<marker_offset>0.0</marker_offset>
<type>gauge</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>true</cap_right>
<cap_left>false</cap_left>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g4>
<g5>
<name>Gauge5</name>
<x>10</x>
<y>190</y>
<width>10</width>
<height>100</height>
<loadfn>elevatortrimval</loadfn>
<options>134</options> <!-- HUDS_LEFT | HUDS_VERT | HUDS_NOTEXT -->
<disp_scaling>-100.0</disp_scaling>
<maxValue>+1.0</maxValue>
<minValue>-1.0</minValue>
<major_divs>50</major_divs>
<minor_divs>0</minor_divs>
<modulator>0</modulator>
<value_span>2.0</value_span> <!-- (maxValue - minValue) -->
<marker_offset>0.0</marker_offset>
<type>gauge</type>
<tick_bottom>true</tick_bottom>
<tick_top>true</tick_top>
<tick_right>false</tick_right>
<tick_left>false</tick_left>
<cap_bottom>false</cap_bottom>
<cap_top>false</cap_top>
<cap_right>false</cap_right>
<cap_left>false</cap_left>
<enable_pointer>true</enable_pointer>
<pointer_type>fixed</pointer_type>
<working>true</working>
</g5>
</cards>
</PropertyList>

View file

@ -1,35 +0,0 @@
<PropertyList>
<ladders>
<l1>
<name>artificialhorizon</name>
<x>260</x>
<y>150</y>
<width>120</width>
<height>180</height>
<compression_factor>2.68</compression_factor>
<loadfn>roll</loadfn>
<loadfn1>pitch</loadfn1>
<span_units>45.0</span_units>
<division_units>0.0</division_units>
<minor_division>0.0</minor_division>
<screen_hole>70</screen_hole>
<lbl_pos>0</lbl_pos>
<enable_frl>false</enable_frl>
<enable_target_spot>true</enable_target_spot>
<enable_velocity_vector>false</enable_velocity_vector>
<enable_drift_marker>false</enable_drift_marker>
<enable_alpha_bracket>false</enable_alpha_bracket>
<enable_energy_marker>false</enable_energy_marker>
<enable_climb_dive_marker>false</enable_climb_dive_marker>
<enable_glide_slope_marker>false</enable_glide_slope_marker>
<glide_slope>0.0</glide_slope>
<enable_energy_worm>false</enable_energy_worm>
<enable_waypoint_marker>false</enable_waypoint_marker>
<working>true</working>
</l1>
</ladders>
</PropertyList>

View file

@ -1,160 +0,0 @@
<PropertyList>
<labels>
<i1>
<name>Label1</name>
<x>40</x>
<y>25</y>
<width>60</width>
<height>10</height>
<data_source>framerate</data_source>
<label_format>%7.1f</label_format>
<pre_label_string>Frame rate =</pre_label_string>
<post_label_string>NULL</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
</i1>
<i2>
<name>Label2</name>
<x>40</x>
<y>40</y>
<width>90</width>
<height>10</height>
<data_source>fov</data_source>
<label_format>%7.1f</label_format>
<pre_label_string>FOV =</pre_label_string>
<post_label_string>NULL</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
</i2>
<i3>
<name>Label3</name>
<x>480</x>
<y>70</y>
<width>60</width>
<height>10</height>
<data_source>aoa</data_source>
<label_format>%7.2f</label_format>
<pre_label_string>AOA =</pre_label_string>
<post_label_string> Deg</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
</i3>
<i4>
<name>Label4</name>
<x>480</x>
<y>55</y>
<width>40</width>
<height>30</height>
<data_source>speed</data_source>
<label_format>%5.0f</label_format>
<pre_label_string>Airspeed </pre_label_string>
<post_label_string> Kts</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
</i4>
<i5>
<name>Label5</name>
<x>480</x>
<y>40</y>
<width>40</width>
<height>10</height>
<data_source>altitude</data_source>
<label_format>%5.0f</label_format>
<pre_label_string>Altitude </pre_label_string>
<post_label_string>units</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
</i5>
<i6>
<name>Label6</name>
<x>480</x>
<y>25</y>
<width>40</width>
<height>10</height>
<data_source>agl</data_source>
<label_format>%5.0f</label_format>
<pre_label_string>Elevation </pre_label_string>
<post_label_string>units</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
</i6>
<i7>
<name>Label7</name>
<x>480</x>
<y>10</y>
<width>60</width>
<height>10</height>
<data_source>heading</data_source>
<label_format>%5.1f</label_format>
<pre_label_string>Heading </pre_label_string>
<post_label_string> Deg</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>0</justification>
<blinking>0</blinking>
<working>true</working>
</i7>
<lat>
<name>lattitude</name>
<x>110</x>
<y>430</y>
<width>0</width>
<data_source>latitude</data_source>
<label_format>%s%</label_format>
<pre_label_string>blank</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>1</justification>
<blinking>0</blinking>
<working>true</working>
<latitude>true</latitude>
</lat>
<lon>
<name>longitude</name>
<x>530</x>
<y>430</y>
<width>1</width>
<data_source>longitude</data_source>
<label_format>%s%</label_format>
<pre_label_string>blank</pre_label_string>
<post_label_string>blank</post_label_string>
<scale_data>1.0</scale_data>
<options>4</options>
<justification>1</justification>
<blinking>0</blinking>
<working>true</working>
<longitude>true</longitude>
</lon>
</labels>
</PropertyList>

View file

@ -1,48 +0,0 @@
<?xml version="1.0"?>
<!--
Preliminary Default Hud.
November 2000
Neetha Girish <neetha@ada.ernet.in>
Based on Default Panel by David Megginson, david@megginson.com.
This is a Hud configuration file for the open-source flight
simulator FlightGear (www.flightgear.org). The file is an XML-encoded
FlightGear property list defining the Hud.
Each instrument is, itself, defined in an XML-encoded property list
in a separate file.
-->
<PropertyList>
<depreciated/>
<name>Minimal Aircraft Hud</name>
<instruments>
<hudladder>
<path>Huds/Instruments/Minimal/hudladder.xml</path>
</hudladder>
<hudcard>
<path>Huds/Instruments/Minimal/hudcard.xml</path>
</hudcard>
<instrlabel>
<path>Huds/Instruments/Minimal/instrlabel.xml</path>
</instrlabel>
<fgTBI>
<path>Huds/Instruments/Minimal/fgtbi.xml</path>
</fgTBI>
<Gload>
<path>Huds/Instruments/Minimal/gload.xml</path>
</Gload>
</instruments>
</PropertyList>

View file

@ -4,10 +4,26 @@
<!-- heading --> <!-- heading -->
<label>
<width>60</width>
<height>10</height>
<box>true</box>
<format>ROLL</format>
<halign>left</halign>
<condition>
<equals>
<property>/autopilot/locks/heading</property>
<value>wing-leveler</value>
</equals>
</condition>
</label>
<label> <label>
<width>2</width> <width>60</width>
<height>2</height> <height>10</height>
<format>hdg = %.1f</format> <box>true</box>
<format>HDG %03d</format>
<halign>left</halign> <halign>left</halign>
<input> <input>
<property>/autopilot/settings/heading-bug-deg</property> <property>/autopilot/settings/heading-bug-deg</property>
@ -21,9 +37,10 @@
</label> </label>
<label> <label>
<width>2</width> <width>60</width>
<height>2</height> <height>10</height>
<format>hdg = %.1f</format> <box>true</box>
<format>HDG %03d</format>
<halign>left</halign> <halign>left</halign>
<input> <input>
<property>/autopilot/settings/true-heading-deg</property> <property>/autopilot/settings/true-heading-deg</property>
@ -36,217 +53,15 @@
</condition> </condition>
</label> </label>
<!-- wp[0] -->
<label>
<x>0</x>
<y>-15</y>
<width>2</width>
<height>2</height>
<format>%5s</format>
<halign>left</halign>
<input>
<property>/autopilot/route-manager/wp[0]/id</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/heading</property>
<value>true-heading-hold</value>
</equals>
</condition>
</label>
<label>
<x>35</x>
<y>-15</y>
<width>2</width>
<height>2</height>
<format>%6.1fnm</format>
<halign>left</halign>
<input>
<property>/autopilot/route-manager/wp[0]/dist</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/heading</property>
<value>true-heading-hold</value>
</equals>
<not>
<equals>
<property>/autopilot/route-manager/wp[0]/id</property>
<value></value>
</equals>
</not>
</condition>
</label>
<label>
<x>82</x>
<y>-15</y>
<width>2</width>
<height>2</height>
<format>%s</format>
<halign>left</halign>
<input>
<property>/autopilot/route-manager/wp[0]/eta</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/heading</property>
<value>true-heading-hold</value>
</equals>
<not>
<equals>
<property>/autopilot/route-manager/wp[0]/id</property>
<value></value>
</equals>
</not>
</condition>
</label>
<!-- wp[1] -->
<label>
<x>0</x>
<y>-30</y>
<width>2</width>
<height>2</height>
<format>%5s</format>
<halign>left</halign>
<input>
<property>/autopilot/route-manager/wp[1]/id</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/heading</property>
<value>true-heading-hold</value>
</equals>
</condition>
</label>
<label>
<x>35</x>
<y>-30</y>
<width>2</width>
<height>2</height>
<format>%6.1fnm</format>
<halign>left</halign>
<input>
<property>/autopilot/route-manager/wp[1]/dist</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/heading</property>
<value>true-heading-hold</value>
</equals>
<not>
<equals>
<property>/autopilot/route-manager/wp[1]/id</property>
<value></value>
</equals>
</not>
</condition>
</label>
<label>
<x>82</x>
<y>-30</y>
<width>2</width>
<height>2</height>
<format>%s</format>
<halign>left</halign>
<input>
<property>/autopilot/route-manager/wp[1]/eta</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/heading</property>
<value>true-heading-hold</value>
</equals>
<not>
<equals>
<property>/autopilot/route-manager/wp[1]/id</property>
<value></value>
</equals>
</not>
</condition>
</label>
<!-- wp[2] -->
<label>
<x>0</x>
<y>-45</y>
<width>2</width>
<height>2</height>
<format>%5s</format>
<halign>left</halign>
<input>
<property>/autopilot/route-manager/wp[2]/id</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/heading</property>
<value>true-heading-hold</value>
</equals>
</condition>
</label>
<label>
<x>35</x>
<y>-45</y>
<width>2</width>
<height>2</height>
<format>%6.1fnm</format>
<halign>left</halign>
<input>
<property>/autopilot/route-manager/wp[2]/dist</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/heading</property>
<value>true-heading-hold</value>
</equals>
<not>
<equals>
<property>/autopilot/route-manager/wp[2]/id</property>
<value></value>
</equals>
</not>
</condition>
</label>
<label>
<x>82</x>
<y>-45</y>
<width>2</width>
<height>2</height>
<format>%s</format>
<halign>left</halign>
<input>
<property>/autopilot/route-manager/wp[2]/eta</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/heading</property>
<value>true-heading-hold</value>
</equals>
<not>
<equals>
<property>/autopilot/route-manager/wp[2]/id</property>
<value></value>
</equals>
</not>
</condition>
</label>
<!-- altitude --> <!-- altitude -->
<label> <label>
<y>-60</y> <x>60</x>
<width>2</width> <width>60</width>
<height>2</height> <height>10</height>
<format>alt = %.0f</format> <box>true</box>
<format>ALT %04d</format>
<halign>left</halign> <halign>left</halign>
<input> <input>
<property>/autopilot/settings/target-altitude-ft</property> <property>/autopilot/settings/target-altitude-ft</property>
@ -259,12 +74,47 @@
</condition> </condition>
</label> </label>
<label> <label>
<y>-60</y> <x>60</x>
<width>2</width> <width>60</width>
<height>2</height> <height>10</height>
<format>agl = %.0f</format> <box>true</box>
<format>PTCH</format>
<halign>left</halign> <halign>left</halign>
<condition>
<equals>
<property>/autopilot/locks/altitude</property>
<value>pitch-hold</value>
</equals>
</condition>
</label>
<label>
<x>60</x>
<width>60</width>
<height>10</height>
<box>true</box>
<format>V/S %d</format>
<halign>left</halign>
<input>
<property>/autopilot/settings/vertical-speed-fpm</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/altitude</property>
<value>vertical-speed-hold</value>
</equals>
</condition>
</label>
<label>
<x>60</x>
<width>60</width>
<height>10</height>
<format>AGL %04d</format>
<halign>left</halign>
<box>true</box>
<input> <input>
<property>/autopilot/settings/target-agl-ft</property> <property>/autopilot/settings/target-agl-ft</property>
</input> </input>
@ -276,4 +126,59 @@
</condition> </condition>
</label> </label>
<!-- speed -->
<label>
<x>120</x>
<width>60</width>
<height>10</height>
<format>IAS %3dkt</format>
<halign>left</halign>
<box>true</box>
<input>
<property>/autopilot/settings/target-speed-kt</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/speed</property>
<value>speed-with-throttle</value>
</equals>
</condition>
</label>
<label>
<x>120</x>
<width>60</width>
<height>10</height>
<format>MACH %1.2f</format>
<halign>left</halign>
<box>true</box>
<input>
<property>/autopilot/settings/target-speed-mach</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/speed</property>
<value>mach-with-throttle</value>
</equals>
</condition>
</label>
<label>
<x>120</x>
<width>60</width>
<height>10</height>
<format>PITCH %3dkt</format>
<halign>left</halign>
<box>true</box>
<input>
<property>/autopilot/settings/target-speed-mach</property>
</input>
<condition>
<equals>
<property>/autopilot/locks/speed</property>
<value>speed-with-pitch-trim</value>
</equals>
</condition>
</label>
</PropertyList> </PropertyList>

182
Huds/Sets/gps.xml Normal file
View file

@ -0,0 +1,182 @@
<?xml version="1.0"?>
<PropertyList>
<!-- GPS waypoint -->
<label>
<width>2</width>
<height>2</height>
<format>GPS OBS:%5s</format>
<halign>left</halign>
<input>
<property>/instrumentation/gps/wp/wp[1]/ID</property>
</input>
<condition>
<equals>
<property>/instrumentation/gps/mode</property>
<value>obs</value>
</equals>
</condition>
</label>
<label>
<width>2</width>
<height>2</height>
<x>80</x>
<format>(TO)</format>
<halign>left</halign>
<condition>
<and>
<equals>
<property>/instrumentation/gps/mode</property>
<value>obs</value>
</equals>
<not><property>/instrumentation/gps/from-flag</property></not>
</and>
</condition>
</label>
<label>
<width>2</width>
<height>2</height>
<x>80</x>
<format>(FROM)</format>
<halign>left</halign>
<condition>
<and>
<equals>
<property>/instrumentation/gps/mode</property>
<value>obs</value>
</equals>
<property>/instrumentation/gps/from-flag</property>
</and>
</condition>
</label>
<label>
<width>2</width>
<height>2</height>
<format>GPS DTO:%5s</format>
<halign>left</halign>
<input>
<property>/instrumentation/gps/wp/wp[1]/ID</property>
</input>
<condition>
<equals>
<property>/instrumentation/gps/mode</property>
<value>dto</value>
</equals>
</condition>
</label>
<label>
<width>2</width>
<height>2</height>
<format>GPS LEG:%5s</format>
<halign>left</halign>
<input>
<property>/instrumentation/gps/wp/wp[0]/ID</property>
</input>
<condition>
<equals>
<property>/instrumentation/gps/mode</property>
<value>leg</value>
</equals>
</condition>
</label>
<label>
<width>2</width>
<height>2</height>
<x>80</x>
<format>-&gt;%5s</format>
<halign>left</halign>
<input>
<property>/instrumentation/gps/wp/wp[1]/ID</property>
</input>
<condition>
<equals>
<property>/instrumentation/gps/mode</property>
<value>leg</value>
</equals>
</condition>
</label>
<label>
<width>2</width>
<height>2</height>
<y>-10</y>
<format>D: %4.1fnm</format>
<halign>left</halign>
<input>
<property>/instrumentation/gps/wp/wp[1]/distance-nm</property>
</input>
</label>
<label>
<width>2</width>
<height>2</height>
<x>60</x>
<y>-10</y>
<format>TTW:%s</format>
<halign>left</halign>
<input>
<property>/instrumentation/gps/wp/wp[1]/TTW</property>
</input>
</label>
<label>
<width>2</width>
<height>2</height>
<y>-20</y>
<format>BRG:%03d</format>
<halign>left</halign>
<input>
<property>/instrumentation/gps/wp/wp[1]/bearing-mag-deg</property>
</input>
</label>
<label>
<width>2</width>
<height>2</height>
<y>-20</y>
<x>60</x>
<format>XTK: %2.1fnm</format>
<halign>left</halign>
<input>
<property>/instrumentation/gps/wp/wp[1]/course-error-nm</property>
</input>
<condition>
<greater-than>
<expression>
<abs><property>/instrumentation/gps/wp/wp[1]/course-error-nm</property></abs>
</expression>
<value>0.1</value>
</greater-than>
</condition>
</label>
<label>
<width>2</width>
<height>2</height>
<y>-30</y>
<format>GS:%3dkts</format>
<halign>left</halign>
<input>
<property>/instrumentation/gps/indicated-ground-speed-kt</property>
</input>
</label>
</PropertyList>

View file

@ -29,7 +29,13 @@
<import> <import>
<path>Huds/Sets/autopilot.xml</path> <path>Huds/Sets/autopilot.xml</path>
<x-offset>-280</x-offset> <x-offset>-100</x-offset>
<y-offset>160</y-offset>
</import>
<import>
<path>Huds/Sets/gps.xml</path>
<x-offset>-300</x-offset>
<y-offset>160</y-offset> <y-offset>160</y-offset>
</import> </import>

View file

@ -1,9 +1,8 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="joystick.xsl"?> <?xml-stylesheet type="text/xsl" href="joystick.xsl"?>
<!-- $Id$ -->
<!-- Saitek AV8R/Aviator <!-- Saitek AV8R/Aviator
Copyright (C) 2007 - 2009 Anders Gidenstam (anders(at)gidenstam.org) Copyright (C) 2007 - 2010 Anders Gidenstam (anders(at)gidenstam.org)
This file is released under the GPL license v2 or later. This file is released under the GPL license v2 or later.
--> -->
<PropertyList> <PropertyList>
@ -21,18 +20,27 @@
# TM0: All selected; TM1: #1 & #2; TM2: #3 & #4 # TM0: All selected; TM1: #1 & #2; TM2: #3 & #4
var engine_axis_mode = 0; var engine_axis_mode = 0;
# Valid only in TM1 and TM2. # Valid only in TM1 and TM2.
# EA0: throttle, +mod: propeller # EA0: throttle
# EA1: propeller, +mod: throttle # EA1: mixture
# EA2: propeller
var quick_view_active = 0; var quick_view_active = 0;
var old_view = view.point.save(); var old_view = view.point.save();
var pressed = [0,0,0,0,0,0,0,0,0,0,0,0]; var pressed = [0,0,0,0,0,0,0,0,0,0,0,0];
# Map engines to throttles for TM1 (0, 1) and TM2 (2, 3)
var engine = [0, 1, 2, 3]; var engine = [0, 1, 2, 3];
# Do per-aircraft modifications # Do per-aircraft modifications
if (getprop("/sim/model/path") == if (contains({"Aircraft/Short_Empire/Models/Short_Empire-model.xml" : 0,
"Aircraft/Short_Empire/Models/Short_Empire-model.xml") { "Aircraft/Lockheed1049/Models/Lockheed1049_twa.xml" : 0},
getprop("/sim/model/path"))) {
# TM1: the outer engines, TM2: the inner engines
engine = [0, 3, 1, 2]; engine = [0, 3, 1, 2];
} }
if (contains({"Aircraft/DO-X/Models/dox.xml" : 0},
getprop("/sim/model/path"))) {
engine = [[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11],
[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]];
}
var goal_heading_offset = var goal_heading_offset =
@ -46,7 +54,7 @@
var kbdalt = props.globals.getNode("/devices/status/keyboard/alt", 1); var kbdalt = props.globals.getNode("/devices/status/keyboard/alt", 1);
var quick_view = func { var quick_view = func {
dir = arg[0]; var dir = arg[0];
if (dir == 0) { if (dir == 0) {
quick_view_active = 0; quick_view_active = 0;
view.point.move(old_view, 0.1); view.point.move(old_view, 0.1);
@ -99,7 +107,13 @@
</nasal> </nasal>
<!-- Analog axis 0. Aileron --> <!-- Analog axis 0. Aileron -->
<axis n="0"> <axis>
<name>Stick left/right</name>
<number>
<unix>0</unix>
<mac>0</mac>
<windows>0</windows>
</number>
<desc>aileron</desc> <desc>aileron</desc>
<binding> <binding>
<command>property-scale</command> <command>property-scale</command>
@ -111,7 +125,13 @@
</axis> </axis>
<!-- Analog axis 1. Elevator --> <!-- Analog axis 1. Elevator -->
<axis n="1"> <axis>
<name>Stick forward/back</name>
<number>
<unix>1</unix>
<mac>1</mac>
<windows>1</windows>
</number>
<desc>elevator</desc> <desc>elevator</desc>
<binding> <binding>
<command>property-scale</command> <command>property-scale</command>
@ -125,6 +145,7 @@
<!-- Analog axis 3. Rudder --> <!-- Analog axis 3. Rudder -->
<axis> <axis>
<name>Stick twist</name>
<number> <number>
<unix>3</unix> <unix>3</unix>
<mac>2</mac> <mac>2</mac>
@ -139,10 +160,18 @@
<factor type="double">1.0</factor> <factor type="double">1.0</factor>
<squared type="bool">true</squared> <squared type="bool">true</squared>
</binding> </binding>
<!-- binding>
<command>nasal</command>
<script>
setprop("sim/current-view/goal-heading-offset-deg",
-90.0*cmdarg().getNode("setting").getValue());
</script>
</binding -->
</axis> </axis>
<!-- Analog axis 2. Throttle 1 --> <!-- Analog axis 2. Throttle 1 -->
<axis> <axis>
<name>Left throttle</name>
<number> <number>
<unix>2</unix> <unix>2</unix>
<mac>3</mac> <mac>3</mac>
@ -155,43 +184,43 @@
if (engine_select_mode == 0) { if (engine_select_mode == 0) {
controls.throttleAxis(); controls.throttleAxis();
} else { } else {
var val = cmdarg().getNode("setting").getValue(); controls.perEngineSelectedAxisHandler(engine_axis_mode)
var ctrl_pp = ((engine_select_mode == 1) ? engine[0] : engine[2]);
"/controls/engines/engine[" ~
((engine_select_mode == 1) ? engine[0] : engine[2]) ~ "]/" ~
(engine_axis_mode ? "propeller-pitch" : "throttle");
setprop(ctrl_pp, (1 - val)/2);
} }
</script> </script>
</binding> </binding>
</axis> </axis>
<!-- Analog axis 4. Throttle 2 --> <!-- Analog axis 4. Throttle 2 -->
<axis n="4"> <axis>
<desc>TM0: mixture, +mod: propeller pitch, TM1: throttle/propeller 2, TM2: throttle/propeller 4</desc> <name>Right throttle</name>
<number>
<unix>4</unix>
<mac>4</mac>
<windows>4</windows>
</number>
<desc>TM0: mixture, TM1: throttle/propeller 2, TM2: throttle/propeller 4</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script> <script>
if (engine_select_mode == 0) { if (engine_select_mode == 0) {
if (!modifier) { controls.mixtureAxis();
controls.mixtureAxis();
} else {
controls.propellerAxis();
}
} else { } else {
var val = cmdarg().getNode("setting").getValue(); controls.perEngineSelectedAxisHandler(engine_axis_mode)
var ctrl_pp = ((engine_select_mode == 1) ? engine[1] : engine[3]);
"/controls/engines/engine[" ~
((engine_select_mode == 1) ? engine[1] : engine[3]) ~ "]/" ~
(engine_axis_mode ? "propeller-pitch" : "throttle");
setprop(ctrl_pp, (1 - val)/2);
} }
</script> </script>
</binding> </binding>
</axis> </axis>
<!-- Axis 5. Hat left/right --> <!-- Axis 5. Hat left/right -->
<axis n="5"> <axis>
<name>Hat left/right</name>
<number>
<unix>5</unix>
<mac>5</mac>
<windows>5</windows>
</number>
<desc>quick view left/right, +mod: horizontal view pan</desc> <desc>quick view left/right, +mod: horizontal view pan</desc>
<low> <low>
<repeatable type="bool">true</repeatable> <repeatable type="bool">true</repeatable>
@ -238,10 +267,12 @@
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script> <script>
<![CDATA[
trace("Axis 5, Hat: low released!"); trace("Axis 5, Hat: low released!");
if (!modifier) { if (!modifier) {
quick_view(0); quick_view(0);
} }
]]>
</script> </script>
</binding> </binding>
</mod-up> </mod-up>
@ -249,7 +280,13 @@
</axis> </axis>
<!-- Axis 6. Hat up/down --> <!-- Axis 6. Hat up/down -->
<axis n="6"> <axis>
<name>Hat up/down</name>
<number>
<unix>6</unix>
<mac>6</mac>
<windows>6</windows>
</number>
<desc>view reset/quick view front, +mod: vertical view pan</desc> <desc>view reset/quick view front, +mod: vertical view pan</desc>
<low> <low>
<repeatable type="bool">true</repeatable> <repeatable type="bool">true</repeatable>
@ -270,9 +307,11 @@
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script> <script>
<![CDATA[
if (!modifier) { if (!modifier) {
#quick_view(0); #quick_view(0);
} }
]]>
</script> </script>
</binding> </binding>
</mod-up> </mod-up>
@ -296,9 +335,11 @@
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script> <script>
<![CDATA[
if (!modifier) { if (!modifier) {
quick_view(0); quick_view(0);
} }
]]>
</script> </script>
</binding> </binding>
</mod-up> </mod-up>
@ -306,8 +347,13 @@
</axis> </axis>
<!-- Trigger Button --> <!-- Trigger Button -->
<button n="0"> <button>
<name>Trigger</name> <name>Trigger</name>
<number>
<unix>0</unix>
<mac>0</mac>
<windows>0</windows>
</number>
<desc>function modifier (mod)</desc> <desc>function modifier (mod)</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
@ -327,8 +373,13 @@
</button> </button>
<!-- Center Button --> <!-- Center Button -->
<button n="2"> <button>
<name>Center button</name> <name>Center button</name>
<number>
<unix>2</unix>
<mac>2</mac>
<windows>2</windows>
</number>
<desc>brakes, +mod: Toggle parking brake</desc> <desc>brakes, +mod: Toggle parking brake</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
@ -352,8 +403,13 @@
</button> </button>
<!-- Left Button --> <!-- Left Button -->
<button n="1"> <button>
<name>Left button</name> <name>Left button</name>
<number>
<unix>1</unix>
<mac>1</mac>
<windows>1</windows>
</number>
<desc>left brake, +mod: PTT</desc> <desc>left brake, +mod: PTT</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
@ -378,8 +434,13 @@
</button> </button>
<!-- Right Button --> <!-- Right Button -->
<button n="3"> <button>
<name>Right button</name> <name>Right button</name>
<number>
<unix>3</unix>
<mac>3</mac>
<windows>3</windows>
</number>
<desc>right brake, +mod: trigger</desc> <desc>right brake, +mod: trigger</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
@ -404,8 +465,13 @@
</button> </button>
<!-- Button: T1 --> <!-- Button: T1 -->
<button n="4"> <button>
<name>T1</name> <name>T1</name>
<number>
<unix>4</unix>
<mac>4</mac>
<windows>4</windows>
</number>
<desc>next view, +mod: zoom in +Shift: next weapon</desc> <desc>next view, +mod: zoom in +Shift: next weapon</desc>
<repeatable type="bool">true</repeatable> <repeatable type="bool">true</repeatable>
<binding> <binding>
@ -442,8 +508,13 @@
</button> </button>
<!-- Button: T2 --> <!-- Button: T2 -->
<button n="5"> <button>
<name>T2</name> <name>T2</name>
<number>
<unix>5</unix>
<mac>5</mac>
<windows>5</windows>
</number>
<desc>previous view, +mod: zoom out, +Shift: previous weapon</desc> <desc>previous view, +mod: zoom out, +Shift: previous weapon</desc>
<repeatable type="bool">true</repeatable> <repeatable type="bool">true</repeatable>
<binding> <binding>
@ -480,8 +551,13 @@
</button> </button>
<!-- Button: T3 --> <!-- Button: T3 -->
<button n="6"> <button>
<name>T3</name> <name>T3</name>
<number>
<unix>6</unix>
<mac>6</mac>
<windows>6</windows>
</number>
<desc>trim nose down, +mod: disarm speed brakes</desc> <desc>trim nose down, +mod: disarm speed brakes</desc>
<repeatable type="bool">true</repeatable> <repeatable type="bool">true</repeatable>
<binding> <binding>
@ -498,8 +574,13 @@
</button> </button>
<!-- Button: T4 --> <!-- Button: T4 -->
<button n="7"> <button>
<name>T4</name> <name>T4</name>
<number>
<unix>7</unix>
<mac>7</mac>
<windows>7</windows>
</number>
<desc>trim nose up, +mod: deploy speed brakes</desc> <desc>trim nose up, +mod: deploy speed brakes</desc>
<repeatable type="bool">true</repeatable> <repeatable type="bool">true</repeatable>
<binding> <binding>
@ -516,8 +597,13 @@
</button> </button>
<!-- Button: T5 --> <!-- Button: T5 -->
<button n="8"> <button>
<name>T5</name> <name>T5</name>
<number>
<unix>8</unix>
<mac>8</mac>
<windows>8</windows>
</number>
<desc>retract flaps one step, +mod: gear up</desc> <desc>retract flaps one step, +mod: gear up</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
@ -542,8 +628,13 @@
</button> </button>
<!-- Button: T6 --> <!-- Button: T6 -->
<button n="9"> <button>
<name>T6</name> <name>T6</name>
<number>
<unix>9</unix>
<mac>9</mac>
<windows>9</windows>
</number>
<desc>deploy flaps one step, +mod: gear down</desc> <desc>deploy flaps one step, +mod: gear down</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
@ -568,8 +659,13 @@
</button> </button>
<!-- Button: T7 --> <!-- Button: T7 -->
<button n="10"> <button>
<name>T7</name> <name>T7</name>
<number>
<unix>10</unix>
<mac>10</mac>
<windows>10</windows>
</number>
<desc>Increase magnetos, +mod: Engine throttle/propeller axis swap</desc> <desc>Increase magnetos, +mod: Engine throttle/propeller axis swap</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
@ -578,14 +674,19 @@
if (!modifier) { if (!modifier) {
controls.stepMagnetos(1); controls.stepMagnetos(1);
} else { } else {
engine_axis_mode = !engine_axis_mode; engine_axis_mode = 2*!engine_axis_mode;
} }
</script> </script>
</binding> </binding>
</button> </button>
<!-- Button: T8 --> <!-- Button: T8 -->
<button n="11"> <button>
<number>
<unix>11</unix>
<mac>11</mac>
<windows>11</windows>
</number>
<name>T8</name> <name>T8</name>
<desc>Decrease magnetos, +mod: Engine throttle/propeller axis swap</desc> <desc>Decrease magnetos, +mod: Engine throttle/propeller axis swap</desc>
<binding> <binding>
@ -595,15 +696,20 @@
if (!modifier) { if (!modifier) {
controls.stepMagnetos(-1); controls.stepMagnetos(-1);
} else { } else {
engine_axis_mode = !engine_axis_mode; engine_axis_mode = 2*!engine_axis_mode;
} }
</script> </script>
</binding> </binding>
</button> </button>
<!-- Button: 3-way Mode switch --> <!-- Button: 3-way Mode switch -->
<button n="12"> <button>
<name>Mode 1</name> <name>Mode 1</name>
<number>
<unix>12</unix>
<mac>12</mac>
<windows>12</windows>
</number>
<desc>Engine 0/1 throttle mode</desc> <desc>Engine 0/1 throttle mode</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
@ -622,7 +728,13 @@
</binding> </binding>
</mod-up> </mod-up>
</button> </button>
<button n="13"> <button>
<name>Mode 2</name>
<number>
<unix>13</unix>
<mac>13</mac>
<windows>13</windows>
</number>
<name>Mode 2</name> <name>Mode 2</name>
<desc>Engine 2/3 throttle mode</desc> <desc>Engine 2/3 throttle mode</desc>
<binding> <binding>

View file

@ -1,35 +1,122 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- Saitek Pro Flight Quadrant <!-- Saitek Pro Flight Quadrant
Copyright (C) 2008 Ronald Jensen (wino(at)jentronics.com) Copyright (C) 2008 Ronald Jensen (wino(at)jentronics.com)
This file is released under the GPL license. Copyright (C) 2009 - 2010 Anders Gidenstam (anders(at)gidenstam.org)
This file is released under the GPL license version 2.
--> -->
<PropertyList> <PropertyList>
<name>Saitek Saitek Pro Flight Quadrant</name> <name>Saitek Saitek Pro Flight Quadrant</name>
<name>Saitek Pro Flight Quadrant</name> <name>Saitek Pro Flight Quadrant</name>
<name>Saitek Pro Flight Throttle Quadrant</name> <name>Saitek Pro Flight Throttle Quadrant</name>
<axis n="0">
<desc>Throttle</desc> <nasal>
<script>
<![CDATA[
var self = cmdarg().getParent();
var data = self.getNode("data");
var engine_select_mode = 0;
# TM0: All selected; TM1: #1-#3; TM2: #3-#6
var engine_axis_mode = 0;
# Valid only in TM1 and TM2.
# EA0: throttle
# EA1: mixure
# EA2: propeller
var pressed = [0,0,0,0,0,0];
var engine = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
# Do per-aircraft modifications
if (contains({"Aircraft/Short_Empire/Models/Short_Empire-model.xml" : 0,
"Aircraft/Lockheed1049/Models/Lockheed1049_twa.xml" : 0},
getprop("/sim/model/path"))) {
# Map port outer to axis 0, starboard outer to axis 2 and
# the inner engines to axis 1.
engine = [0, [1, 2], 3];
}
if (contains({"Aircraft/DO-X/Models/dox.xml" : 0},
getprop("/sim/model/path"))) {
engine = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]];
}
if (contains({"Aircraft/Nordstern/Models/Nordstern.xml" : 0},
getprop("/sim/model/path"))) {
engine = [0, 1, [2, 3]];
}
var kbdctrl = props.globals.getNode("/devices/status/keyboard/ctrl", 1);
var kbdalt = props.globals.getNode("/devices/status/keyboard/alt", 1);
var axis_handler = func(axis) {
if (engine_select_mode == 0) {
if (axis == 0) {
controls.throttleAxis();
} elsif (axis == 1) {
controls.propellerAxis();
} elsif (axis == 2) {
controls.mixtureAxis();
}
} else {
controls.perEngineSelectedAxisHandler(engine_axis_mode)
(engine[axis + 3*(engine_select_mode - 1)]);
}
}
var trace = func(str) {
# Uncomment the line below to trace button presses.
#print("Pro-Flight-Quadrant.xml: " ~ str);
}
]]>
</script>
</nasal>
<!-- Levers left to right. -->
<axis>
<name>Left lever</name>
<number>
<unix>0</unix>
<mac>0</mac>
<windows>0</windows>
</number>
<desc>TM0: throttle, TM1: throttle/propeller 1, TM2: throttle/propeller 4</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script>controls.throttleAxis()</script> <script>axis_handler(0)</script>
</binding> </binding>
</axis> </axis>
<axis n="1"> <axis>
<desc>Prop Pitch</desc> <name>Middle lever</name>
<number>
<unix>1</unix>
<mac>1</mac>
<windows>1</windows>
</number>
<desc>TM0: propeller, TM1: throttle/propeller 2, TM2: throttle/propeller 5</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script>controls.propellerAxis()</script> <script>axis_handler(1)</script>
</binding> </binding>
</axis> </axis>
<axis n="2"> <axis>
<desc>Mixture </desc> <name>Right lever</name>
<number>
<unix>2</unix>
<mac>2</mac>
<windows>2</windows>
</number>
<desc>TM0: mixture, TM1: throttle/propeller 3, TM2: throttle/propeller 6</desc>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script>controls.mixtureAxis()</script> <script>axis_handler(2)</script>
</binding> </binding>
</axis> </axis>
<button n="0">
<!-- 2-way rocker switches. Left to right. -->
<button>
<name>Left button up</name>
<number>
<unix>0</unix>
<mac>0</mac>
<windows>0</windows>
</number>
<desc>Flaps up</desc> <desc>Flaps up</desc>
<repeatable>false</repeatable> <repeatable>false</repeatable>
<binding> <binding>
@ -42,14 +129,40 @@
<script>controls.flapsDown(0)</script> <script>controls.flapsDown(0)</script>
</binding> </binding>
</mod-up> </mod-up>
<mod-shift>
<binding>
<command>nasal</command>
<script>
trace("Button 0 + shift pressed!");
gui.popupTip("Saitek Quadrant: Throttle Mode 1");
engine_select_mode = 1;
</script>
</binding>
</mod-shift>
</button> </button>
<button n="1"> <button n="1">
<name>Left button down</name>
<number>
<unix>1</unix>
<mac>1</mac>
<windows>1</windows>
</number>
<desc>Flaps down</desc> <desc>Flaps down</desc>
<repeatable>false</repeatable> <repeatable>false</repeatable>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script>controls.flapsDown(1)</script> <script>controls.flapsDown(1)</script>
</binding> </binding>
<mod-shift>
<binding>
<command>nasal</command>
<script>
trace("Button 1 + shift pressed!");
gui.popupTip("Saitek Quadrant: Throttle Mode 0");
engine_select_mode = 0;
</script>
</binding>
</mod-shift>
<mod-up> <mod-up>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
@ -57,23 +170,64 @@
</binding> </binding>
</mod-up> </mod-up>
</button> </button>
<button n="2">
<button>
<name>Middle button up</name>
<number>
<unix>2</unix>
<mac>2</mac>
<windows>2</windows>
</number>
<desc>Elevator trim up</desc> <desc>Elevator trim up</desc>
<repeatable>true</repeatable> <repeatable>true</repeatable>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script>controls.elevatorTrim(-0.75)</script> <script>controls.elevatorTrim(-0.75)</script>
</binding> </binding>
<mod-shift>
<binding>
<command>nasal</command>
<script>
trace("Button 2 + shift pressed!");
if (engine_select_mode) gui.popupTip("Saitek Quadrant: Throttle control");
engine_axis_mode = 0;
</script>
</binding>
</mod-shift>
</button> </button>
<button n="3"> <button>
<name>Middle button down</name>
<number>
<unix>3</unix>
<mac>3</mac>
<windows>3</windows>
</number>
<desc>Elevator trim down</desc> <desc>Elevator trim down</desc>
<repeatable>true</repeatable> <repeatable>true</repeatable>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script>controls.elevatorTrim(0.75)</script> <script>controls.elevatorTrim(0.75)</script>
</binding> </binding>
<mod-shift>
<binding>
<command>nasal</command>
<script>
trace("Button 3 + shift pressed!");
if (engine_select_mode)
gui.popupTip("Saitek Quadrant: Propeller control");
engine_axis_mode = 2;
</script>
</binding>
</mod-shift>
</button> </button>
<button n="4">
<button>
<name>Right button up</name>
<number>
<unix>4</unix>
<mac>4</mac>
<windows>4</windows>
</number>
<desc>Gear up</desc> <desc>Gear up</desc>
<repeatable>false</repeatable> <repeatable>false</repeatable>
<binding> <binding>
@ -81,7 +235,13 @@
<script>controls.gearDown(-1)</script> <script>controls.gearDown(-1)</script>
</binding> </binding>
</button> </button>
<button n="5"> <button>
<name>Right button down</name>
<number>
<unix>5</unix>
<mac>5</mac>
<windows>5</windows>
</number>
<desc>Gear down</desc> <desc>Gear down</desc>
<repeatable>false</repeatable> <repeatable>false</repeatable>
<binding> <binding>
@ -89,4 +249,49 @@
<script>controls.gearDown(1)</script> <script>controls.gearDown(1)</script>
</binding> </binding>
</button> </button>
<!-- Axis reverse area switches. -->
<button>
<name>Left lever reverse</name>
<number>
<unix>6</unix>
<mac>6</mac>
<windows>6</windows>
</number>
<desc></desc>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script></script>
</binding>
</button>
<button>
<name>Middle lever reverse</name>
<number>
<unix>7</unix>
<mac>7</mac>
<windows>7</windows>
</number>
<desc></desc>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script></script>
</binding>
</button>
<button>
<name>Right lever reverse</name>
<number>
<unix>8</unix>
<mac>8</mac>
<windows>8</windows>
</number>
<desc></desc>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script></script>
</binding>
</button>
</PropertyList> </PropertyList>

View file

@ -954,12 +954,11 @@ var kias_to_ktas = func(kias, altitude) {
# #
var HUD = { var HUD = {
init: func { init: func {
me.vis0N = props.globals.getNode("/sim/hud/visibility[0]", 1);
me.vis1N = props.globals.getNode("/sim/hud/visibility[1]", 1); me.vis1N = props.globals.getNode("/sim/hud/visibility[1]", 1);
me.currcolN = props.globals.getNode("/sim/hud/current-color", 1); me.currcolN = props.globals.getNode("/sim/hud/current-color", 1);
me.paletteN = props.globals.getNode("/sim/hud/palette", 1); me.paletteN = props.globals.getNode("/sim/hud/palette", 1);
me.brightnessN = props.globals.getNode("/sim/hud/color/brightness", 1); me.brightnessN = props.globals.getNode("/sim/hud/color/brightness", 1);
me.currentN = me.vis0N; me.currentN = me.vis1N;
}, },
cycle_color: func { # h-key cycle_color: func { # h-key
if (!me.currentN.getBoolValue()) # if off, turn on if (!me.currentN.getBoolValue()) # if off, turn on
@ -979,34 +978,14 @@ var HUD = {
var br = me.brightnessN.getValue() - 0.2; var br = me.brightnessN.getValue() - 0.2;
me.brightnessN.setValue(br > 0.01 ? br : 1); me.brightnessN.setValue(br > 0.01 ? br : 1);
}, },
normal_type: func { # i-key normal_type: func { # i-key
me.is_active() or return;
me.oldinit1(); },
me.vis0N.setBoolValue(1); cycle_type: func { # I-key
me.vis1N.setBoolValue(0);
me.currentN = me.vis0N; },
},
cycle_type: func { # I-key
me.is_active() or return;
if (me.currentN == me.vis0N) {
me.vis0N.setBoolValue(0);
me.vis1N.setBoolValue(1);
me.currentN = me.vis1N;
} elsif (me.currentN == me.vis1N) {
me.vis0N.setBoolValue(1);
me.vis1N.setBoolValue(0);
me.oldinit2();
me.currentN = me.vis0N;
}
},
oldinit1: func {
fgcommand("hud-init");
},
oldinit2: func {
fgcommand("hud-init2");
},
is_active: func { is_active: func {
me.vis0N.getValue() or me.vis1N.getValue(); me.vis1N.getValue();
}, },
}; };

View file

@ -7,21 +7,19 @@
# function purpose # function purpose
# #
# setVisibility to set the visibility to a given value # setVisibility to set the visibility to a given value
# setLift to set lift to given value
# setRain to set rain to a given value # setRain to set rain to a given value
# setSnow to set snow to a given value # setSnow to set snow to a given value
# setTurbulence to set turbulence to a given value # setTurbulence to set turbulence to a given value
# setTemperature to set temperature to a given value # setTemperature to set temperature to a given value
# setPressure to set pressure to a given value # setPressure to set pressure to a given value
# setDewpoint to set the dewpoint to a given value # setDewpoint to set the dewpoint to a given value
# setLight to set light saturation to given value
# setWind to set wind # setWind to set wind
# setWindSmoothly to set the wind gradually across a second # setWindSmoothly to set the wind gradually across a second
# smooth_wind_loop helper function for setWindSmoothly # smooth_wind_loop (helper function for setWindSmoothly)
# create_cloud to place a single cloud into the scenery # create_cloud to place a single cloud into the scenery
# create_cloud_array to place clouds from storage arrays into the scenery # create_cloud_array to place clouds from storage arrays into the scenery
# move_cloud to move the cloud position
# remove_clouds to remove clouds by tile index
# waiting_loop to ensure tile removal calls do not overlap
# remove_tile_loop to remove a fixed number of clouds per frame
# get_elevation to get the terrain elevation at given coordinates # get_elevation to get the terrain elevation at given coordinates
# get_elevation_vector to get terrain elevation at given coordinate vector # get_elevation_vector to get terrain elevation at given coordinate vector
@ -68,72 +66,35 @@
# The compatibility layer is currently work in progress and will be extended as new Nasal # The compatibility layer is currently work in progress and will be extended as new Nasal
# APIs are being added to FlightGear. # APIs are being added to FlightGear.
###########################################
# header checking availability of functions
###########################################
var has_symbol = func(s) contains(globals,s);
var is_function = func(s) typeof(globals[s])=='func';
var has_function = func(f) has_symbol(f) and is_function(f);
# try to call a function with given parameters
# save exceptions to err vector
# returns 0 for no exceptions (exceptions vector is empty)
# returns >=1 for exception occurred (i.e. unsupported API call)
var try_call = func(f, params) {
var err=[];
call(globals[f], params, nil,nil,err); # see http://plausible.org/nasal/lib.html
return size(err);
};
var query = func(api,params) {
if ( has_function(api) ) {
return try_call(api, params );
}
return 1; # fail
}
var patches = { geodinfo: "http://flightgear.org/forums/viewtopic.php?f=5&t=7358&st=0&sk=t&sd=a&start=90#p82805", };
# query fgfs binary for required APIs and set values in this hash
var features = {};
#fixme: compare results from new and old API
var check_geodinfo_vec = func {
var err=[];
if ( query('geodinfo',[ [37.618,-122.374],1000])==0 ) {
printf("geodinfo found"); # now try to use it
var ksfo=[37.618, -122.374];
var alt=10000;
# see if it returns a vector or not
call( func { print (alt); (typeof(geodinfo(ksfo,alt))=='vector')?return:die(); }, [], caller()[0],nil,err);
print('-','geodinfo:', (size(err) >=1) ? "Vector support unavailable" : "Vector support available");
if(size(err) and contains(patches,'geodinfo')) print('---> A patch is available at ', patches['geodinfo']);
return size(err)?0:1;
}
return 0;
}
_setlistener("/sim/signals/nasal-dir-initialized", func { _setlistener("/sim/signals/nasal-dir-initialized", func {
print ("Compatibility layer: Checking available Nasal APIs:");
print ("(this may cause harmless error messages when hard-coded support is lacking)"); var result = "yes";
print ("##########################################");
features.geodinfo_supports_vectors= check_geodinfo_vec (); print("Compatibility layer: testing for hard coded support");
print("features.geodinfo_supports_vectors=", features.geodinfo_supports_vectors);
print ("##########################################"); if (props.globals.getNode("/rendering/scene/saturation", 0) == nil)
print("Compatibility checks done."); {result = "no"; features.can_set_light = 0;}
else
{result = "yes"; features.can_set_light = 1;}
print("* can set light saturation: "~result);
if (props.globals.getNode("/environment/terrain", 0) == nil)
{result = "no"; features.terrain_presampling = 0;}
else
{result = "yes"; features.terrain_presampling = 1;}
print("* hard coded terrain presampling: "~result);
if (props.globals.getNode("/environment/config/enabled", 0) == nil)
{result = "no"; features.can_disable_environment = 0;}
else
{result = "yes"; features.can_disable_environment = 1;}
print("* can disable global weather: "~result);
print("Compatibility layer: tests done.");
}); });
# this is now where we can simply refer to features.geodinfo_supports_vectors
# for checking if vector support is available or not - to use the most appropriate
# APIs
@ -143,20 +104,38 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
var setVisibility = func (vis) { var setVisibility = func (vis) {
# this is a rather dirty workaround till a better solution becomes available if (features.can_disable_environment == 1)
# essentially we update all entries in config and reinit environment {
setprop("/environment/visibility-m",vis);
}
else
{
# this is a workaround for systems which lack hard-coded support
# essentially we update all entries in config and reinit environment
var entries_aloft = props.globals.getNode("environment/config/aloft", 1).getChildren("entry"); var entries_aloft = props.globals.getNode("environment/config/aloft", 1).getChildren("entry");
foreach (var e; entries_aloft) { foreach (var e; entries_aloft) {
e.getNode("visibility-m",1).setValue(vis); e.getNode("visibility-m",1).setValue(vis);
} }
var entries_boundary = props.globals.getNode("environment/config/boundary", 1).getChildren("entry"); var entries_boundary = props.globals.getNode("environment/config/boundary", 1).getChildren("entry");
foreach (var e; entries_boundary) { foreach (var e; entries_boundary) {
e.getNode("visibility-m",1).setValue(vis); e.getNode("visibility-m",1).setValue(vis);
} }
fgcommand("reinit", props.Node.new({subsystem:"environment"})); fgcommand("reinit", props.Node.new({subsystem:"environment"}));
}
}
####################################
# set thermal lift to given value
####################################
var setLift = func (lift) {
if (features.can_disable_environment == 1)
{
setprop("/environment/wind-from-down-fps",lift);
}
} }
#################################### ####################################
@ -193,24 +172,36 @@ setprop("environment/metar/snow-norm",snow);
var setTurbulence = func (turbulence) { var setTurbulence = func (turbulence) {
# this is a rather dirty workaround till a better solution becomes available if (features.can_disable_environment == 1)
# essentially we update all entries in config and reinit environment {
setprop("/environment/turbulence/magnitude-norm",turbulence);
setprop("/environment/turbulence/rate-hz",3.0);
}
var entries_aloft = props.globals.getNode("environment/config/aloft", 1).getChildren("entry"); else
foreach (var e; entries_aloft) { {
e.getNode("turbulence/magnitude-norm",1).setValue(turbulence); # this is a workaround for systems which lack hard-coded support
} # essentially we update all entries in config and reinit environment
# turbulence is slightly reduced in boundary layers var entries_aloft = props.globals.getNode("environment/config/aloft", 1).getChildren("entry");
foreach (var e; entries_aloft) {
e.getNode("turbulence/magnitude-norm",1).setValue(turbulence);
e.getNode("turbulence/rate-hz",1).setValue(3.0);
e.getNode("turbulence/factor",1).setValue(1.0);
}
var entries_boundary = props.globals.getNode("environment/config/boundary", 1).getChildren("entry"); # turbulence is slightly reduced in boundary layers
var i = 1;
foreach (var e; entries_boundary) {
e.getNode("turbulence/magnitude-norm",1).setValue(turbulence * 0.25*i);
i = i + 1;
}
fgcommand("reinit", props.Node.new({subsystem:"environment"}));
var entries_boundary = props.globals.getNode("environment/config/boundary", 1).getChildren("entry");
var i = 1;
foreach (var e; entries_boundary) {
e.getNode("turbulence/magnitude-norm",1).setValue(turbulence * 0.25*i);
e.getNode("turbulence/rate-hz",1).setValue(5.0);
e.getNode("turbulence/factor",1).setValue(1.0);
i = i + 1;
}
fgcommand("reinit", props.Node.new({subsystem:"environment"}));
}
} }
@ -220,11 +211,18 @@ fgcommand("reinit", props.Node.new({subsystem:"environment"}));
var setTemperature = func (T) { var setTemperature = func (T) {
# this is a rather dirty workaround till a better solution becomes available if (features.can_disable_environment == 1)
# essentially we update the entry in config and reinit environment {
setprop("/environment/temperature-sea-level-degc",T);
setprop(ec~"boundary/entry[0]/temperature-degc",T); }
fgcommand("reinit", props.Node.new({subsystem:"environment"})); else
{
# this is a workaround for systems which lack hard-coded support
# essentially we update the entry in config and reinit environment
setprop(ec~"boundary/entry[0]/temperature-degc",T);
fgcommand("reinit", props.Node.new({subsystem:"environment"}));
}
} }
#################################### ####################################
@ -233,12 +231,19 @@ fgcommand("reinit", props.Node.new({subsystem:"environment"}));
var setPressure = func (p) { var setPressure = func (p) {
# this is a rather dirty workaround till a better solution becomes available if (features.can_disable_environment == 1)
# essentially we update the entry in config and reinit environment {
setprop("/environment/pressure-sea-level-inhg",p);
}
else
{
# this is a workaround for systems which lack hard-coded support
# essentially we update the entry in config and reinit environment
setprop(ec~"boundary/entry[0]/pressure-sea-level-inhg",p); setprop(ec~"boundary/entry[0]/pressure-sea-level-inhg",p);
setprop(ec~"aloft/entry[0]/pressure-sea-level-inhg",p); setprop(ec~"aloft/entry[0]/pressure-sea-level-inhg",p);
fgcommand("reinit", props.Node.new({subsystem:"environment"})); fgcommand("reinit", props.Node.new({subsystem:"environment"}));
}
} }
#################################### ####################################
@ -247,11 +252,30 @@ fgcommand("reinit", props.Node.new({subsystem:"environment"}));
var setDewpoint = func (D) { var setDewpoint = func (D) {
# this is a rather dirty workaround till a better solution becomes available if (features.can_disable_environment == 1)
# essentially we update the entry in config and reinit environment {
setprop("/environment/dewpoint-sea-level-degc",D);
}
else
{
# this is a workaround for systems which lack hard-coded support
# essentially we update the entry in config and reinit environment
setprop(ec~"boundary/entry[0]/dewpoint-degc",D); setprop(ec~"boundary/entry[0]/dewpoint-degc",D);
fgcommand("reinit", props.Node.new({subsystem:"environment"})); fgcommand("reinit", props.Node.new({subsystem:"environment"}));
}
}
####################################
# set light saturation to given value
####################################
var setLight = func (s) {
if (features.can_set_light == 1)
{
setprop("/rendering/scene/saturation",s);
}
} }
########################################################### ###########################################################
@ -261,23 +285,30 @@ fgcommand("reinit", props.Node.new({subsystem:"environment"}));
var setWind = func (dir, speed) { var setWind = func (dir, speed) {
# this is a rather dirty workaround till a better solution becomes available if (features.can_disable_environment == 1)
# essentially we update all entries in config and reinit environment {
setprop("/environment/wind-from-heading-deg",dir);
setprop("/environment/wind-speed-kt",speed);
}
else
{
# this is a workaround for systems which lack hard-coded support
# essentially we update all entries in config and reinit environment
var entries_aloft = props.globals.getNode("environment/config/aloft", 1).getChildren("entry");
foreach (var e; entries_aloft) {
e.getNode("wind-from-heading-deg",1).setValue(dir);
e.getNode("wind-speed-kt",1).setValue(speed);
}
var entries_aloft = props.globals.getNode("environment/config/aloft", 1).getChildren("entry"); var entries_boundary = props.globals.getNode("environment/config/boundary", 1).getChildren("entry");
foreach (var e; entries_aloft) { foreach (var e; entries_boundary) {
e.getNode("wind-from-heading-deg",1).setValue(dir); e.getNode("wind-from-heading-deg",1).setValue(dir);
e.getNode("wind-speed-kt",1).setValue(speed); e.getNode("wind-speed-kt",1).setValue(speed);
} }
var entries_boundary = props.globals.getNode("environment/config/boundary", 1).getChildren("entry");
foreach (var e; entries_boundary) {
e.getNode("wind-from-heading-deg",1).setValue(dir);
e.getNode("wind-speed-kt",1).setValue(speed);
}
fgcommand("reinit", props.Node.new({subsystem:"environment"}));
fgcommand("reinit", props.Node.new({subsystem:"environment"}));
}
} }
########################################################### ###########################################################
@ -288,21 +319,29 @@ fgcommand("reinit", props.Node.new({subsystem:"environment"}));
var setWindSmoothly = func (dir, speed) { var setWindSmoothly = func (dir, speed) {
var entries_aloft = props.globals.getNode("environment/config/aloft", 1).getChildren("entry"); if (features.can_disable_environment == 1)
{
setWind(dir, speed);
}
else
{
var dir_old = entries_aloft[0].getNode("wind-from-heading-deg",1).getValue(); var entries_aloft = props.globals.getNode("environment/config/aloft", 1).getChildren("entry");
var speed_old = entries_aloft[0].getNode("wind-speed-kt",1).getValue();
var dir = dir * math.pi/180.0; var dir_old = entries_aloft[0].getNode("wind-from-heading-deg",1).getValue();
var dir_old = dir_old * math.pi/180.0; var speed_old = entries_aloft[0].getNode("wind-speed-kt",1).getValue();
var vx = speed * math.sin(dir); var dir = dir * math.pi/180.0;
var vx_old = speed_old * math.sin(dir_old); var dir_old = dir_old * math.pi/180.0;
var vy = speed * math.cos(dir); var vx = speed * math.sin(dir);
var vy_old = speed_old * math.cos(dir_old); var vx_old = speed_old * math.sin(dir_old);
smooth_wind_loop(vx,vy,vx_old, vy_old, 4, 4); var vy = speed * math.cos(dir);
var vy_old = speed_old * math.cos(dir_old);
smooth_wind_loop(vx,vy,vx_old, vy_old, 4, 4);
}
} }
@ -335,10 +374,35 @@ var create_cloud = func(path, lat, long, alt, heading) {
var tile_counter = getprop(lw~"tiles/tile-counter"); var tile_counter = getprop(lw~"tiles/tile-counter");
var buffer_flag = getprop(lw~"config/buffer-flag"); var buffer_flag = getprop(lw~"config/buffer-flag");
var dynamics_flag = getprop(lw~"config/dynamics-flag");
var d_max = weather_tile_management.cloud_view_distance + 1000.0; var d_max = weather_tile_management.cloud_view_distance + 1000.0;
# check if we deal with a convective cloud
var convective_flag = 0;
if (find("cumulus",path) != -1)
{
if ((find("alto",path) != -1) or (find("cirro", path) != -1) or (find("strato", path) != -1))
{convective_flag = 0;}
else if ((find("small",path) != -1) or (find("whisp",path) != -1))
{convective_flag = 1;}
else if (find("bottom",path) != -1)
{convective_flag = 4;}
else
{convective_flag = 2;}
}
else if (find("congestus",path) != -1)
{
if (find("bottom",path) != -1)
{convective_flag = 5;}
else
{convective_flag = 3;}
}
#print("path: ", path, " flag: ", convective_flag);
# first check if the cloud should be stored in the buffer # first check if the cloud should be stored in the buffer
# we keep it if it is in visual range or at high altitude (where visual range is different) # we keep it if it is in visual range or at high altitude (where visual range is different)
@ -352,8 +416,17 @@ if (buffer_flag == 1)
if ((d > d_max) and (alt < 20000.0)) # we buffer the cloud if ((d > d_max) and (alt < 20000.0)) # we buffer the cloud
{ {
var b = weather_tile_management.cloudBuffer.new(lat, long, alt, path, heading, tile_counter); var b = weather_tile_management.cloudBuffer.new(lat, long, alt, path, heading, tile_counter, convective_flag);
if (dynamics_flag ==1) {b.timestamp = weather_dynamics.time_lw;} if (local_weather.dynamics_flag ==1)
{
b.timestamp = weather_dynamics.time_lw;
if (convective_flag !=0) # Cumulus clouds get some extra info
{
b.evolution_timestamp = cloud_evolution_timestamp;
b.flt = cloud_flt;
b.rel_alt = alt - cloud_mean_altitude;
}
}
append(weather_tile_management.cloudBufferArray,b); append(weather_tile_management.cloudBufferArray,b);
return; return;
} }
@ -364,10 +437,12 @@ if (buffer_flag == 1)
if (getprop(lw~"tmp/buffer-status") == "placing") if (getprop(lw~"tmp/buffer-status") == "placing")
{ {
tile_counter = getprop(lw~"tmp/buffer-tile-index"); #tile_counter = getprop(lw~"tmp/buffer-tile-index");
tile_counter = buffered_tile_index;
} }
# if the cloud is not buffered, get property tree nodes and write it # if the cloud is not buffered, get property tree nodes and write it
# into the scenery # into the scenery
@ -382,6 +457,7 @@ var cloud_number = n.getNode("placement-index").getValue();
cl = c.getChild("cloud", i, 1); cl = c.getChild("cloud", i, 1);
n.getNode("placement-index").setValue(i); n.getNode("placement-index").setValue(i);
var placement_index = i;
var model_number = n.getNode("model-placement-index").getValue(); var model_number = n.getNode("model-placement-index").getValue();
var m = props.globals.getNode("models", 1); var m = props.globals.getNode("models", 1);
@ -397,8 +473,6 @@ var latN = cl.getNode("position/latitude-deg", 1); latN.setValue(lat);
var lonN = cl.getNode("position/longitude-deg", 1); lonN.setValue(long); var lonN = cl.getNode("position/longitude-deg", 1); lonN.setValue(long);
var altN = cl.getNode("position/altitude-ft", 1); altN.setValue(alt); var altN = cl.getNode("position/altitude-ft", 1); altN.setValue(alt);
var hdgN = cl.getNode("orientation/true-heading-deg", 1); hdgN.setValue(heading); var hdgN = cl.getNode("orientation/true-heading-deg", 1); hdgN.setValue(heading);
#var pitchN = cl.getNode("orientation/pitch-deg", 1); pitchN.setValue(0.0);
#var rollN = cl.getNode("orientation/roll-deg", 1);rollN.setValue(0.0);
cl.getNode("tile-index",1).setValue(tile_counter); cl.getNode("tile-index",1).setValue(tile_counter);
@ -407,35 +481,57 @@ model.getNode("latitude-deg-prop", 1).setValue(latN.getPath());
model.getNode("longitude-deg-prop", 1).setValue(lonN.getPath()); model.getNode("longitude-deg-prop", 1).setValue(lonN.getPath());
model.getNode("elevation-ft-prop", 1).setValue(altN.getPath()); model.getNode("elevation-ft-prop", 1).setValue(altN.getPath());
model.getNode("heading-deg-prop", 1).setValue(hdgN.getPath()); model.getNode("heading-deg-prop", 1).setValue(hdgN.getPath());
#model.getNode("pitch-deg-prop", 1).setValue(pitchN.getPath());
#model.getNode("roll-deg-prop", 1).setValue(rollN.getPath());
model.getNode("tile-index",1).setValue(tile_counter); model.getNode("tile-index",1).setValue(tile_counter);
model.getNode("load", 1).remove(); model.getNode("load", 1).remove();
n.getNode("cloud-number").setValue(n.getNode("cloud-number").getValue()+1);
# sort the model node into a vector for easy deletion # sort the model node into a vector for easy deletion
# append(weather_tile_management.modelArrays[tile_counter-1],model); # append(weather_tile_management.modelArrays[tile_counter-1],model);
# sort the cloud into the cloud hash array # sort the cloud into the cloud hash array
if ((buffer_flag == 1) and (getprop(lw~"tmp/tile-management") != "single tile")) if (buffer_flag == 1)
{ {
var cs = weather_tile_management.cloudScenery.new(tile_counter, cl, model); var cs = weather_tile_management.cloudScenery.new(tile_counter, convective_flag, cl, model);
append(weather_tile_management.cloudSceneryArray,cs); append(weather_tile_management.cloudSceneryArray,cs);
} }
# if weather dynamics is on, also create a timestamp property and sort the cloud node into quadtree # if weather dynamics is on, also create a timestamp property and sort the cloud hash into quadtree
#if (getprop(lw~"config/dynamics-flag") == 1) if (local_weather.dynamics_flag == 1)
if (dynamics_flag == 1)
{ {
cl.getNode("timestamp-sec",1).setValue(weather_dynamics.time_lw); cs.timestamp = weather_dynamics.time_lw;
var blat = getprop(lw~"tiles/tmp/latitude-deg"); cs.write_index = placement_index;
var blon = getprop(lw~"tiles/tmp/longitude-deg");
var alpha = getprop(lw~"tmp/tile-orientation-deg"); if (convective_flag !=0) # Cumulus clouds get some extra info
weather_dynamics.sort_into_quadtree(blat, blon, alpha, lat, long, weather_dynamics.cloudQuadtrees[tile_counter-1], cl); {
cs.evolution_timestamp = cloud_evolution_timestamp;
cs.flt = cloud_flt;
cs.rel_alt = alt - cloud_mean_altitude;
cs.target_alt = alt;
}
if (getprop(lw~"tmp/buffer-status") == "placing")
{
var blat = buffered_tile_latitude;
var blon = buffered_tile_longitude;
var alpha = buffered_tile_alpha;
#var blat1 = getprop(lw~"tiles/tmp/latitude-deg");
#var blon1 = getprop(lw~"tiles/tmp/longitude-deg");
#var alpha1 = getprop(lw~"tmp/tile-orientation-deg");
#print("Lat: ", blat1, " ", blat);
#print("Lon: ", blon1, " ", blon);
#print("Alp: ", alpha1, " ", alpha);
}
else
{
var blat = getprop(lw~"tiles/tmp/latitude-deg");
var blon = getprop(lw~"tiles/tmp/longitude-deg");
var alpha = getprop(lw~"tmp/tile-orientation-deg");
}
weather_dynamics.sort_into_quadtree(blat, blon, alpha, lat, long, weather_dynamics.cloudQuadtrees[tile_counter-1], cs);
} }
} }
@ -451,12 +547,13 @@ if (getprop(lw~"tmp/thread-status") != "placing") {return;}
if (getprop(lw~"tmp/convective-status") != "idle") {return;} if (getprop(lw~"tmp/convective-status") != "idle") {return;}
if ((i < 0) or (i==0)) if ((i < 0) or (i==0))
{ {
print("Cloud placement from array finished!"); if (local_weather.debug_output_flag == 1)
{print("Cloud placement from array finished!"); }
setprop(lw~"tmp/thread-status", "idle"); setprop(lw~"tmp/thread-status", "idle");
# now set flag that tile has been completely processed # now set flag that tile has been completely processed
var dir_index = props.globals.getNode(lw~"tiles/tmp/dir-index").getValue(); var dir_index = props.globals.getNode(lw~"tiles/tmp/dir-index").getValue();
# print("dir_index: ",dir_index);
props.globals.getNode(lw~"tiles").getChild("tile",dir_index).getNode("generated-flag").setValue(2); props.globals.getNode(lw~"tiles").getChild("tile",dir_index).getNode("generated-flag").setValue(2);
return; return;
@ -470,6 +567,12 @@ if (s < k_max) {k_max = s;}
for (var k = 0; k < k_max; k = k+1) for (var k = 0; k < k_max; k = k+1)
{ {
if (getprop(lw~"config/dynamics-flag") ==1)
{
cloud_mean_altitude = local_weather.clouds_mean_alt[s-k-1];
cloud_flt = local_weather.clouds_flt[s-k-1];
cloud_evolution_timestamp = local_weather.clouds_evolution_timestamp[s-k-1];
}
create_cloud(clouds_path[s-k-1], clouds_lat[s-k-1], clouds_lon[s-k-1], clouds_alt[s-k-1], clouds_orientation[s-k-1]); create_cloud(clouds_path[s-k-1], clouds_lat[s-k-1], clouds_lon[s-k-1], clouds_alt[s-k-1], clouds_orientation[s-k-1]);
} }
@ -479,144 +582,19 @@ setsize(clouds_lon,s-k_max);
setsize(clouds_alt,s-k_max); setsize(clouds_alt,s-k_max);
setsize(clouds_orientation,s-k_max); setsize(clouds_orientation,s-k_max);
if (getprop(lw~"config/dynamics-flag") ==1)
{
setsize(local_weather.clouds_mean_alt,s-k_max);
setsize(local_weather.clouds_flt,s-k_max);
setsize(local_weather.clouds_evolution_timestamp,s-k_max);
}
settimer( func {create_cloud_array(i - k, clouds_path, clouds_lat, clouds_lon, clouds_alt, clouds_orientation ) }, 0 ); settimer( func {create_cloud_array(i - k, clouds_path, clouds_lat, clouds_lon, clouds_alt, clouds_orientation ) }, 0 );
}; };
####################################################
# move a cloud
####################################################
var move_cloud = func (c, tile_index) {
# get the old spacetime position of the cloud
var lat_old = c.getNode("position/latitude-deg").getValue();
var lon_old = c.getNode("position/longitude-deg").getValue();
var alt = c.getNode("position/altitude-ft").getValue();
var timestamp = c.getNode("timestamp-sec").getValue();
# get windfield and time since last update
var windfield = weather_dynamics.get_windfield(tile_index);
var dt = weather_dynamics.time_lw - timestamp;
#print(dt * windfield[1]);
# update the spacetime position of the cloud
c.getNode("position/latitude-deg",1).setValue(lat_old + windfield[1] * dt * local_weather.m_to_lat);
c.getNode("position/longitude-deg",1).setValue(lon_old + windfield[0] * dt * local_weather.m_to_lon);
c.getNode("timestamp-sec",1).setValue(weather_dynamics.time_lw);
}
####################################################
# remove clouds by tile index
####################################################
var remove_clouds = func (index) {
var n = size(props.globals.getNode("local-weather/clouds").getChild("tile",index,1).getChildren("cloud"));
props.globals.getNode("local-weather/clouds", 1).removeChild("tile",index);
setprop(lw~"clouds/cloud-number",getprop(lw~"clouds/cloud-number")-n);
if (getprop(lw~"tmp/thread-flag") == 1)
{settimer( func {waiting_loop(index); },0);}
else
{
var modelNode = props.globals.getNode("models", 1).getChildren("model");
foreach (var m; modelNode)
{
if (m.getNode("tile-index",1).getValue() == index) {m.remove();}
}
}
}
# this is to avoid two tile removal loops starting at the same time
var waiting_loop = func (index) {
var status = getprop(lw~"tmp/thread-status");
if (status == "idle") {remove_tile_loop(index);}
else {
print("Removal of ",index, " waiting for idle thread...");
settimer( func {waiting_loop(index); },1.0);
}
}
var remove_tile_loop = func (index) {
var n = 100;
var flag_mod = 0;
var status = getprop(lw~"tmp/thread-status");
if ((status == "computing") or (status == "placing")) # the array is blocked
{
settimer( func {remove_tile_loop(index); },0); # try again next frame
return;
}
else if (status == "idle") # we initialize the loop
{
mvec = weather_tile_management.modelArrays[index-1];
msize = size(mvec);
if (msize == 0)
{
print("Tile deletion loop finished!");
setprop(lw~"tmp/thread-status", "idle");
setprop(lw~"clouds/placement-index",0);
setprop(lw~"clouds/model-placement-index",0);
setsize(weather_tile_management.modelArrays[index-1],0);
return;
}
setprop(lw~"tmp/last-reading-pos-mod", msize);
setprop(lw~"tmp/thread-status", "removing");
}
var lastpos = getprop(lw~"tmp/last-reading-pos-mod");
if (lastpos < (msize-1)) {var istart = lastpos;} else {var istart = (msize-1);}
if (istart<0) {istart=0;}
var i_min = istart - n;
if (i_min < -1) {i_min =-1;}
for (var i = istart; i > i_min; i = i- 1)
{
m = mvec[i];
m.remove();
}
if (i<0) {flag_mod = 1;}
if (flag_mod == 0) {setprop(lw~"tmp/last-reading-pos-mod",i); }
if (flag_mod == 0) # we still have work to do
{settimer( func {remove_tile_loop(index); },0);}
else
{
print("Tile deletion loop finished!");
setprop(lw~"tmp/thread-status", "idle");
setprop(lw~"clouds/placement-index",0);
setprop(lw~"clouds/model-placement-index",0);
setsize(weather_tile_management.modelArrays[index-1],0);
}
}
@ -629,7 +607,8 @@ var get_elevation = func (lat, lon) {
var info = geodinfo(lat, lon); var info = geodinfo(lat, lon);
if (info != nil) {var elevation = info[0] * local_weather.m_to_ft;} if (info != nil) {var elevation = info[0] * local_weather.m_to_ft;}
else {var elevation = -1.0;} else {var elevation = -1.0; }
return elevation; return elevation;
} }
@ -643,17 +622,12 @@ var get_elevation_array = func (lat, lon) {
var elevation = []; var elevation = [];
var n = size(lat); var n = size(lat);
if (features.geodinfo_supports_vectors == 0)
for(var i = 0; i < n; i=i+1)
{ {
for(var i = 0; i < n; i=i+1) append(elevation, get_elevation(lat[i], lon[i]));
{
append(elevation, get_elevation(lat[i], lon[i]));
}
}
else
{
elevation = geodinfo(lat,10000);
} }
return elevation; return elevation;
} }
@ -673,3 +647,20 @@ var ec = "/environment/config/";
var mvec = []; var mvec = [];
var msize = 0; var msize = 0;
# available hard-coded support
var features = {};
# globals to transmit info if clouds are written from buffer
var buffered_tile_latitude = 0.0;
var buffered_tile_longitude = 0.0;
var buffered_tile_alpha = 0.0;
var buffered_tile_index = 0;
# globals to handle additional info for Cumulus cloud dynamics
var cloud_mean_altitude = 0.0;
var cloud_flt = 0.0;
var cloud_evolution_timestamp = 0.0;

View file

@ -26,8 +26,8 @@ updateContrail = func{
### Contrail ### Contrail
print ("init contrail");
_setlistener("/sim/signals/nasal-dir-initialized", func { _setlistener("/sim/signals/nasal-dir-initialized", func {
printlog ("debug", "init contrail");
props.globals.initNode("environment/pressure-inhg", 1, "DOUBLE"); props.globals.initNode("environment/pressure-inhg", 1, "DOUBLE");
props.globals.initNode("environment/temperature-degc", 1, "DOUBLE"); props.globals.initNode("environment/temperature-degc", 1, "DOUBLE");
props.globals.initNode("environment/contrail", 1, "BOOL"); props.globals.initNode("environment/contrail", 1, "BOOL");

View file

@ -74,6 +74,51 @@ var mixtureAxis = axisHandler("/controls/engines/engine[", "]/mixture");
var propellerAxis = axisHandler("/controls/engines/engine[", "]/propeller-pitch"); var propellerAxis = axisHandler("/controls/engines/engine[", "]/propeller-pitch");
var carbHeatAxis = axisHandler("/controls/anti-ice/engine[", "]/carb-heat"); var carbHeatAxis = axisHandler("/controls/anti-ice/engine[", "]/carb-heat");
# Joystick axis handler for controlling subsets of similar properties.
# Shouldn't be called from other contexts.
# The argument engine can be either an index number or a list of
# index numbers.
# Use only when perEngineSelectedAxisHandler() below will not do.
var perIndexAxisHandler = func(pre, post) {
return
func(index, invert = 0) {
var val = cmdarg().getNode("setting").getValue();
if(invert) val = -val;
if (typeof(index) == "scalar") {
setprop(pre ~ index ~ post, (1 - val) / 2);
} else {
foreach (var e; index) {
setprop(pre ~ e ~ post, (1 - val) / 2);
}
}
};
}
# Joystick axis handler for controlling a selected axis on specific engines.
# Shouldn't be called from other contexts.
# The argument mode can be
# 0 - throttle
# 1 - mixture
# 2 - propeller-pitch
# The argument engine to the returned function can be either an
# engine number or a list of engine numbers.
# Usage example (controlling the mixture of engines 1 and 2):
# <script>
# controls.perEngineSelectedAxisHandler(1)([1,2]);
# </script>
var _axisMode = {
0: perIndexAxisHandler("/controls/engines/engine[",
"]/throttle"),
1: perIndexAxisHandler("/controls/engines/engine[",
"]/mixture"),
2: perIndexAxisHandler("/controls/engines/engine[",
"]/propeller-pitch")
};
var perEngineSelectedAxisHandler = func(mode) {
return _axisMode[mode];
}
## ##
# Wrapper around stepProps() which emulates the "old" flap behavior for # Wrapper around stepProps() which emulates the "old" flap behavior for
# configurations that aren't using the new mechanism. # configurations that aren't using the new mechanism.

File diff suppressed because it is too large Load diff

View file

@ -178,6 +178,7 @@ var dialog = {
{ type: "checkbox", property: "controls/invisible", callback: "multiplayer.dialog.toggle_ignore", { type: "checkbox", property: "controls/invisible", callback: "multiplayer.dialog.toggle_ignore",
argprop: "callsign", label: "---------", halign: "right", font: font }, argprop: "callsign", label: "---------", halign: "right", font: font },
]; ];
me.cs_warnings = {};
me.name = "who-is-online"; me.name = "who-is-online";
me.dialog = nil; me.dialog = nil;
me.loopid = 0; me.loopid = 0;
@ -275,20 +276,29 @@ var dialog = {
var ac = geo.Coord.new().set_xyz(x, y, z); var ac = geo.Coord.new().set_xyz(x, y, z);
var distance = nil; var distance = nil;
call(func distance = self.distance_to(ac), nil, var err = []); call(func distance = self.distance_to(ac), nil, var err = []);
if (size(err)) { if ((size(err))or(distance==nil)) {
# debug.printerror(err); # Oops, have errors. Bogus position data (and distance==nil).
# debug.dump(self, ac, mp); if (me.cs_warnings[mp.callsign]!=1) {
# debug.tree(mp.node); # report each callsign once only (avoid cluttering)
me.cs_warnings[mp.callsign] = 1;
print("Received invalid position data: " ~ debug._error(mp.callsign));
}
# debug.printerror(err);
# debug.dump(self, ac, mp);
# debug.tree(mp.node);
}
else
{
# Node with valid position data (and "distance!=nil").
n.setValues({
"model-short": mp.available ? mp.model : "[" ~ mp.model ~ "]",
"bearing-to": self.course_to(ac),
"distance-to-km": distance / 1000.0,
"distance-to-nm": distance * M2NM,
"position/altitude-m": n.getNode("position/altitude-ft").getValue() * FT2M,
"controls/invisible": contains(ignore, mp.callsign),
});
} }
n.setValues({
"model-short": mp.available ? mp.model : "[" ~ mp.model ~ "]",
"bearing-to": self.course_to(ac),
"distance-to-km": distance / 1000.0,
"distance-to-nm": distance * M2NM,
"position/altitude-m": n.getNode("position/altitude-ft").getValue() * FT2M,
"controls/invisible": contains(ignore, mp.callsign),
});
} }
if (PILOTSDLG_RUNNING) if (PILOTSDLG_RUNNING)
settimer(func me.update(id), 1, 1); settimer(func me.update(id), 1, 1);

View file

@ -1,11 +1,13 @@
_setlistener("/sim/presets/latitude-deg", func { _setlistener("/sim/signals/nasal-dir-initialized", func {
print("*** NEW LOCATION ***"); _setlistener("/sim/presets/latitude-deg", func {
settimer(func { printlog("info", "*** NEW LOCATION ***");
var typ = getprop("/sim/type"); settimer(func {
var lat = getprop("/position/latitude-deg"); var typ = getprop("/sim/type");
var lon = getprop("/position/longitude-deg"); var lat = getprop("/position/latitude-deg");
var g = geodinfo(lat, lon); var lon = getprop("/position/longitude-deg");
if ((g != nil and g[1] != nil and g[1].solid) and (typ == "seaplane") ) var g = geodinfo(lat, lon);
fgcommand("dialog-show", props.Node.new({ "dialog-name": "seaport" })); if ((g != nil and g[1] != nil and g[1].solid) and (typ == "seaplane") )
}, 8); fgcommand("dialog-show", props.Node.new({ "dialog-name": "seaport" }));
}, 1); }, 8);
}, 1);
});

View file

@ -1,6 +1,6 @@
######################################################## ########################################################
# routines to simulate cloud wind drift and evolution # routines to simulate cloud wind drift and evolution
# Thorsten Renk, July 2010 # Thorsten Renk, October 2010
######################################################## ########################################################
# function purpose # function purpose
@ -9,18 +9,18 @@
# timing_loop to provide accurate timing information for wind drift calculations # timing_loop to provide accurate timing information for wind drift calculations
# quadtree_loop to manage drift of clouds in the field of view # quadtree_loop to manage drift of clouds in the field of view
# weather_dynamics_loop to manage drift of weather effects, tile centers and interpolation points # weather_dynamics_loop to manage drift of weather effects, tile centers and interpolation points
# convective_loop to regularly recreate convective clouds
# generate_quadtree_structure to generate a quadtree data structure used for managing the visual field # generate_quadtree_structure to generate a quadtree data structure used for managing the visual field
# sort_into_quadtree to sort objects into a quadtree structure # sort_into_quadtree to sort objects into a quadtree structure
# sorting_recursion to recursively sort into a quadree (helper)
# quadtree_recursion to search the quadtree for objects in the visual field # quadtree_recursion to search the quadtree for objects in the visual field
# check_visibility to check if a quadrant is currently visible # check_visibility to check if a quadrant is currently visible
# move_tile to move tile coordinates in the wind # move_tile to move tile coordinates in the wind
# move_effect_volume to move an effect volume in the wind
# move_weather_station to move a weather station in the wind
# get_cartesian to get local Cartesian coordinates out of coordinates # get_cartesian to get local Cartesian coordinates out of coordinates
#################################################### ####################################################
# get the windfield for a given locatio and altitude # get the windfield for a given location and altitude
# (currently constant, but supposed to be local later) # (currently constant, but supposed to be local later)
#################################################### ####################################################
@ -63,7 +63,8 @@ return windfield;
var timing_loop = func { var timing_loop = func {
time_lw = time_lw + getprop("/sim/time/delta-sec"); dt_lw = getprop("/sim/time/delta-sec");
time_lw = time_lw + dt_lw;
if (getprop(lw~"timing-loop-flag") ==1) {settimer(timing_loop, 0);} if (getprop(lw~"timing-loop-flag") ==1) {settimer(timing_loop, 0);}
@ -116,6 +117,8 @@ foreach (t; tiles)
cos_beta = math.cos(beta * math.pi/180.0); cos_beta = math.cos(beta * math.pi/180.0);
sin_beta = math.sin(beta * math.pi/180.0); sin_beta = math.sin(beta * math.pi/180.0);
plane_x = xy_vec[0]; plane_y = xy_vec[1]; plane_x = xy_vec[0]; plane_y = xy_vec[1];
windfield = get_windfield(index);
quadtree_recursion(cloudQuadtrees[index-1],0,1,0.0,0.0); quadtree_recursion(cloudQuadtrees[index-1],0,1,0.0,0.0);
} }
@ -156,34 +159,172 @@ if (getprop(lw~"dynamics-loop-flag") ==1) {settimer(quadtree_loop, 0);}
var weather_dynamics_loop = func (index) { var weather_dynamics_loop = func (index, cindex) {
var n = 20; var n = 20;
var nc = 1;
var csize = weather_tile_management.n_cloudSceneryArray;
var i_max = index + n; var i_max = index + n;
if (i_max > local_weather.n_effectVolumeArray) {i_max = local_weather.n_effectVolumeArray;} if (i_max > local_weather.n_effectVolumeArray) {i_max = local_weather.n_effectVolumeArray;}
var ecount = 0;
for (var i = index; i < i_max; i = i+1) for (var i = index; i < i_max; i = i+1)
{ {
move_effect_volume(local_weather.effectVolumeArray[i]); var ev = local_weather.effectVolumeArray[i];
if (ev.index !=0)
{ev.move();}
if ((ev.lift_flag == 2) and (rand() < 0.05) and (local_weather.presampling_flag == 1))
{
if (local_weather.dynamical_convection_flag ==1)
{
ev.correct_altitude_and_age();
if (ev.flt > 1.2) # beyond 1.0, sink is still active
{
local_weather.effectVolumeArray = weather_tile_management.delete_from_vector(local_weather.effectVolumeArray,i);
local_weather.n_effectVolumeArray = local_weather.n_effectVolumeArray - 1;
i = i-1; i_max = i_max -1; ecount = ecount + 1;
}
}
else
{ev.correct_altitude();}
}
} }
setprop(lw~"effect-volumes/number",getprop(lw~"effect-volumes/number")- ecount);
index = index + n; index = index + n;
if (i >= local_weather.n_effectVolumeArray) {index = 0;} if (i >= local_weather.n_effectVolumeArray) {index = 0;}
var stations = props.globals.getNode(lw~"interpolation").getChildren("station");
foreach (s; stations) var ccount = 0;
if (csize > 0)
{ {
move_weather_station(s);
var j_max = cindex + nc;
if (j_max > csize -1) {j_max = csize-1;}
for (var j = cindex; j < j_max; j = j+1)
{
var cs = weather_tile_management.cloudSceneryArray[j];
#cs.move();
if (cs.type !=0)
{
if ((rand() < 0.1) and (local_weather.presampling_flag == 1))
{
if (local_weather.dynamical_convection_flag ==1)
{
cs.correct_altitude_and_age();
if (cs.flt > 1.0) # the cloud has reached its maximum age and decays
{
cs.removeNodes();
weather_tile_management.cloudSceneryArray = weather_tile_management.delete_from_vector(weather_tile_management.cloudSceneryArray,j);
ccount = ccount + 1;
}
}
else
{
cs.correct_altitude();
}
}
}
}
cindex = cindex + nc;
if (j >= csize) {cindex = 0;}
} }
if (getprop(lw~"dynamics-loop-flag") ==1) {settimer( func {weather_dynamics_loop(index); },0);}
foreach (s; local_weather.weatherStationArray)
{
s.move();
}
if (getprop(lw~"dynamics-loop-flag") ==1) {settimer( func {weather_dynamics_loop(index, cindex); },0);}
} }
###########################################################
# convective evolution loop
###########################################################
var convective_loop = func {
# a 30 second loop needs a different strategy to end, otherwise there is trouble if it is restarted while still running
if (convective_loop_kill_flag == 1)
{convective_loop_kill_flag = 0; return;}
var cloud_respawning_interval_s = 30.0;
if (getprop(lw~"tmp/thread-status") == "placing")
{if (getprop(lw~"convective-loop-flag") ==1) {settimer( func {convective_loop()}, 5.0);} return;}
# open the system for write status
setprop(lw~"tmp/buffer-status","placing");
if (local_weather.debug_output_flag == 1)
{print("Respawning convective clouds...");}
for(var i = 0; i < 9; i = i + 1)
{
var index = getprop(lw~"tiles/tile["~i~"]/tile-index");
if ((index == -1) or (index == 0)) {continue;}
if (getprop(lw~"tiles/tile["~i~"]/generated-flag") != 2)
{continue;}
var strength = tile_convective_strength[index-1];
var alt = tile_convective_altitude[index-1];
var n = weather_tiles.get_n(strength);
if (local_weather.detailed_clouds_flag == 1)
{n = int(0.7 * n);}
n = n/cloud_convective_lifetime_s * cloud_respawning_interval_s * math.sqrt(0.35);
n_res = n - int(n);
n = int(n);
if (rand() < n_res) {n=n+1;}
if (local_weather.debug_output_flag == 1)
{print("Tile: ", index, " n: ", n);}
var lat = getprop(lw~"tiles/tile["~i~"]/latitude-deg");
var lon = getprop(lw~"tiles/tile["~i~"]/longitude-deg");
var alpha = getprop(lw~"tiles/tile["~i~"]/orientation-deg");
compat_layer.buffered_tile_latitude = lat;
compat_layer.buffered_tile_longitude = lon;
compat_layer.buffered_tile_alpha = alpha;
compat_layer.buffered_tile_index = index;
setprop(lw~"tmp/buffer-tile-index", index);
if (local_weather.presampling_flag == 1)
{var alt_offset = local_weather.alt_20_array[index -1];}
else
{var alt_offset = getprop(lw~"tmp/tile-alt-offset-ft");}
local_weather.recreate_cumulus(lat,lon, alt + alt_offset, alpha, n, 20000.0, index);
}
# close the write process
setprop(lw~"tmp/buffer-status","idle");
if (getprop(lw~"convective-loop-flag") ==1) {settimer(convective_loop, cloud_respawning_interval_s);}
}
########################################################### ###########################################################
# generate quadtree structure # generate quadtree structure
########################################################### ###########################################################
@ -266,7 +407,8 @@ if (depth == quadtree_depth +1)
{ {
foreach (var c; tree) foreach (var c; tree)
{ {
compat_layer.move_cloud(c, current_tile_index_wd); c.move();
c.to_target_alt();
cloud_counter = cloud_counter + 1; cloud_counter = cloud_counter + 1;
} }
return; return;
@ -396,59 +538,6 @@ t.getNode("timestamp-sec",1).setValue(weather_dynamics.time_lw);
} }
####################################################
# move an effect volume
####################################################
var move_effect_volume = func (e) {
# get the old spacetime position of the effect
var lat_old = e.getNode("position/latitude-deg").getValue();
var lon_old = e.getNode("position/longitude-deg").getValue();
var tile_index = e.getNode("tile-index").getValue();
var timestamp = e.getNode("timestamp-sec").getValue();
# get windfield and time since last update
var windfield = weather_dynamics.get_windfield(tile_index);
var dt = weather_dynamics.time_lw - timestamp;
# update the spacetime position of the effect
e.getNode("position/latitude-deg",1).setValue(lat_old + windfield[1] * dt * local_weather.m_to_lat);
e.getNode("position/longitude-deg",1).setValue(lon_old + windfield[0] * dt * local_weather.m_to_lon);
e.getNode("timestamp-sec",1).setValue(weather_dynamics.time_lw);
}
####################################################
# move a weather station
####################################################
var move_weather_station = func (s) {
# get the old spacetime position of the station
var lat_old = s.getNode("latitude-deg").getValue();
var lon_old = s.getNode("longitude-deg").getValue();
var tile_index = s.getNode("tile-index").getValue();
var timestamp = s.getNode("timestamp-sec").getValue();
# get windfield and time since last update
var windfield = weather_dynamics.get_windfield(tile_index);
var dt = weather_dynamics.time_lw - timestamp;
# update the spacetime position of the effect
s.getNode("latitude-deg",1).setValue(lat_old + windfield[1] * dt * local_weather.m_to_lat);
s.getNode("longitude-deg",1).setValue(lon_old + windfield[0] * dt * local_weather.m_to_lon);
s.getNode("timestamp-sec",1).setValue(weather_dynamics.time_lw);
}
########################################################### ###########################################################
# get local Cartesian coordinates # get local Cartesian coordinates
@ -504,7 +593,12 @@ var lw = "/local-weather/";
# globals # globals
var time_lw = 0.0; var time_lw = 0.0;
var dt_lw = 0.0;
var max_clouds_in_loop = 250; var max_clouds_in_loop = 250;
var cloud_max_vertical_speed_fts = 30.0;
var cloud_convective_lifetime_s = 1800.0; # max. lifetime of convective clouds
var convective_loop_kill_flag = 0;
# the quadtree structure # the quadtree structure
@ -516,6 +610,8 @@ var quadtree_depth = 3;
var tile_wind_direction = []; var tile_wind_direction = [];
var tile_wind_speed = []; var tile_wind_speed = [];
var tile_convective_altitude = [];
var tile_convective_strength = [];
# define these as global, as we need to evaluate them only once per frame # define these as global, as we need to evaluate them only once per frame
# but use them over and over # but use them over and over
@ -525,6 +621,7 @@ var cos_beta = 0;
var sin_beta = 0; var sin_beta = 0;
var plane_x = 0; var plane_x = 0;
var plane_y = 0; var plane_y = 0;
var windfield = [];
var current_tile_index_wd = 0; var current_tile_index_wd = 0;

View file

@ -1,6 +1,6 @@
######################################################## ########################################################
# routines to set up, transform and manage weather tiles # routines to set up, transform and manage weather tiles
# Thorsten Renk, July 2010 # Thorsten Renk, October 2010
######################################################## ########################################################
# function purpose # function purpose
@ -13,9 +13,17 @@
# create_neighbour to set up information for a new neighbouring tile # create_neighbour to set up information for a new neighbouring tile
# create_neighbours to initialize the 8 neighbours of the initial tile # create_neighbours to initialize the 8 neighbours of the initial tile
# buffer_loop to manage the buffering of faraway clouds in an array # buffer_loop to manage the buffering of faraway clouds in an array
# housekeeping_loop to shift clouds from the scenery into the buffer
# wathcdog loop (debug helping structure)
# calc_geo to get local Cartesian geometry for latitude conversion # calc_geo to get local Cartesian geometry for latitude conversion
# get_lat to get latitude from Cartesian coordinates # get_lat to get latitude from Cartesian coordinates
# get_lon to get longitude from Cartesian coordinates # get_lon to get longitude from Cartesian coordinates
# delete_from_vector to delete an element 'n' from a vector
# object purpose
#
# cloudBuffer to store a cloud in a Nasal buffer, to provide methods to move it
# cloudScenery to store info for clouds in scenery, to provide methods to move and evolve them
################################### ###################################
@ -38,11 +46,12 @@ var loading_flag = getprop(lw~"tmp/asymmetric-tile-loading-flag");
var this_frame_action_flag = 0; # use this flag to avoid overlapping tile operations var this_frame_action_flag = 0; # use this flag to avoid overlapping tile operations
setsize(active_tile_list,0); setsize(active_tile_list,0);
#append(active_tile_list,0); # tile zero formally containing static objects is always active
if (distance_to_load > 3.0 * current_visibility) if (distance_to_load > 3.0 * current_visibility)
{distance_to_load = 3.0 * current_visibility;} {distance_to_load = 3.0 * current_visibility;}
if (distance_to_load < 25000.0) if (distance_to_load < 29000.0)
{distance_to_load = 25000.0;} {distance_to_load = 29000.0;}
foreach (var t; tNode) { foreach (var t; tNode) {
@ -77,10 +86,11 @@ foreach (var t; tNode) {
{ {
this_frame_action_flag = 1; this_frame_action_flag = 1;
setprop(lw~"tiles/tile-counter",getprop(lw~"tiles/tile-counter")+1); setprop(lw~"tiles/tile-counter",getprop(lw~"tiles/tile-counter")+1);
print("Building tile unique index ",getprop(lw~"tiles/tile-counter"), " in direction ",i); if (local_weather.debug_output_flag == 1)
{print("Building tile unique index ",getprop(lw~"tiles/tile-counter"), " in direction ",i);}
append(active_tile_list,getprop(lw~"tiles/tile-counter")); append(active_tile_list,getprop(lw~"tiles/tile-counter"));
if (getprop(lw~"config/dynamics-flag") == 1) if (local_weather.dynamics_flag == 1)
{ {
var quadtree = []; var quadtree = [];
weather_dynamics.generate_quadtree_structure(0, quadtree); weather_dynamics.generate_quadtree_structure(0, quadtree);
@ -97,7 +107,8 @@ foreach (var t; tNode) {
if ((d > d_remove) and (flag == 2) and (this_frame_action_flag == 0)) # the tile needs to be deleted if it exists if ((d > d_remove) and (flag == 2) and (this_frame_action_flag == 0)) # the tile needs to be deleted if it exists
{ {
print("Removing tile, unique index ", t.getNode("tile-index").getValue()," direction ",i); if (local_weather.debug_output_flag == 1)
{print("Removing tile, unique index ", t.getNode("tile-index").getValue()," direction ",i);}
remove_tile(t.getNode("tile-index").getValue()); remove_tile(t.getNode("tile-index").getValue());
t.getNode("generated-flag").setValue(0); t.getNode("generated-flag").setValue(0);
this_frame_action_flag = 1; this_frame_action_flag = 1;
@ -132,7 +143,8 @@ foreach (var t; tNode) {
print("Flag: ",gen_flag); print("Flag: ",gen_flag);
} }
print("Changing active tile to direction ", i_min); if (local_weather.debug_output_flag == 1)
{print("Changing active tile to direction ", i_min);}
change_active_tile(i_min); change_active_tile(i_min);
} }
@ -169,28 +181,30 @@ setprop(lw~"tiles/tmp/dir-index",dir_index);
# do windspeed and orientation before presampling check, but test not to do it again # do windspeed and orientation before presampling check, but test not to do it again
if (((getprop(lw~"tmp/presampling-flag") == 1) and (getprop(lw~"tmp/presampling-status") == "idle")) or (getprop(lw~"tmp/presampling-flag") == 0)) if (((local_weather.presampling_flag == 1) and (getprop(lw~"tmp/presampling-status") == "idle")) or (local_weather.presampling_flag == 0))
{ {
var alpha = getprop(lw~"tmp/tile-orientation-deg"); var alpha = getprop(lw~"tmp/tile-orientation-deg");
if ((local_weather.wind_model_flag == 2) or (local_weather.wind_model_flag ==4)) if ((local_weather.wind_model_flag == 2) or (local_weather.wind_model_flag ==4))
{ {
alpha = alpha + 2.0 * (rand()-0.5) * 10.0; alpha = alpha + 2.0 * (rand()-0.5) * 10.0;
# account for the systematic spin of weather systems around a low pressure # account for the systematic spin of weather systems around a low pressure
# core dependent on hemisphere # core dependent on hemisphere
if (lat >0.0) {alpha = alpha -3.0;} if (lat >0.0) {alpha = alpha -3.0;}
else {alpha = alpha +3.0;} else {alpha = alpha +3.0;}
setprop(lw~"tmp/tile-orientation-deg",alpha); setprop(lw~"tmp/tile-orientation-deg",alpha);
# compute the new windspeed # compute the new windspeed
var windspeed = getprop(lw~"tmp/windspeed-kt"); var windspeed = getprop(lw~"tmp/windspeed-kt");
windspeed = windspeed + 2.0 * (rand()-0.5) * 2.0; windspeed = windspeed + 2.0 * (rand()-0.5) * 2.0;
if (windspeed < 0) {windspeed = rand();} if (windspeed < 0) {windspeed = rand();}
setprop(lw~"tmp/windspeed-kt", windspeed); setprop(lw~"tmp/windspeed-kt",windspeed);
# store the tile orientation and wind strength in an array for fast processing # store the tile orientation and wind strength in an array for fast processing
@ -204,7 +218,6 @@ if (((getprop(lw~"tmp/presampling-flag") == 1) and (getprop(lw~"tmp/presampling-
alpha = res[0]; alpha = res[0];
setprop(lw~"tmp/tile-orientation-deg",alpha); setprop(lw~"tmp/tile-orientation-deg",alpha);
var windspeed = res[1]; var windspeed = res[1];
setprop(lw~"tmp/windspeed-kt",windspeed); setprop(lw~"tmp/windspeed-kt",windspeed);
@ -219,16 +232,17 @@ if (((getprop(lw~"tmp/presampling-flag") == 1) and (getprop(lw~"tmp/presampling-
# now see if we need to presample the terrain # now see if we need to presample the terrain
if ((getprop(lw~"tmp/presampling-flag") == 1) and (getprop(lw~"tmp/presampling-status") == "idle")) if ((local_weather.presampling_flag == 1) and (getprop(lw~"tmp/presampling-status") == "idle"))
{ {
local_weather.terrain_presampling_start(lat, lon, 1000, 40000, getprop(lw~"tmp/tile-orientation-deg")); local_weather.terrain_presampling_start(lat, lon, 1000, 40000, getprop(lw~"tmp/tile-orientation-deg"));
return; return;
} }
print("Current tile type: ", code);
if (local_weather.debug_output_flag == 1)
{print("Current tile type: ", code);}
if (getprop(lw~"tmp/tile-management") == "repeat tile") if (getprop(lw~"tmp/tile-management") == "repeat tile")
{ {
@ -248,7 +262,11 @@ if (getprop(lw~"tmp/tile-management") == "repeat tile")
else if (code == "cold_sector") {weather_tiles.set_cold_sector_tile();} else if (code == "cold_sector") {weather_tiles.set_cold_sector_tile();}
else if (code == "warm_sector") {weather_tiles.set_warm_sector_tile();} else if (code == "warm_sector") {weather_tiles.set_warm_sector_tile();}
else if (code == "tropical_weather") {weather_tiles.set_tropical_weather_tile();} else if (code == "tropical_weather") {weather_tiles.set_tropical_weather_tile();}
else {print("Repeat tile not implemented with this tile type!");} else
{
print("Repeat tile not implemented with this tile type!");
setprop("/sim/messages/pilot", "Local weather: Repeat tile not implemented with this tile type!");
}
} }
else if (getprop(lw~"tmp/tile-management") == "realistic weather") else if (getprop(lw~"tmp/tile-management") == "realistic weather")
{ {
@ -370,6 +388,7 @@ else if (getprop(lw~"tmp/tile-management") == "realistic weather")
else else
{ {
print("Realistic weather not implemented with this tile type!"); print("Realistic weather not implemented with this tile type!");
setprop("/sim/messages/pilot", "Local weather: Realistic weather not implemented with this tile type!");
} }
} # end if mode == realistic weather } # end if mode == realistic weather
@ -397,21 +416,34 @@ for (var j = 0; j < s; j=j+1)
settimer( func { props.globals.getNode("local-weather/clouds", 1).removeChild("tile",index) },100); settimer( func { props.globals.getNode("local-weather/clouds", 1).removeChild("tile",index) },100);
#compat_layer.remove_clouds(index);
var effectNode = props.globals.getNode("local-weather/effect-volumes").getChildren("effect-volume"); var effectNode = props.globals.getNode("local-weather/effect-volumes").getChildren("effect-volume");
var ecount = 0; var ecount = 0;
foreach (var e; effectNode) for (var i = 0; i < local_weather.n_effectVolumeArray; i = i + 1)
{ {
if (e.getNode("tile-index").getValue() == index) ev = local_weather.effectVolumeArray[i];
{ if (ev.index == index)
e.remove(); {
local_weather.effectVolumeArray = delete_from_vector(local_weather.effectVolumeArray,i);
local_weather.n_effectVolumeArray = local_weather.n_effectVolumeArray - 1;
i = i - 1;
ecount = ecount + 1; ecount = ecount + 1;
} }
else if (ev.index == 0) # use the opportunity to check if static effects should also be removed
{
if (ev.get_distance() > 80000.0)
{
local_weather.effectVolumeArray = delete_from_vector(local_weather.effectVolumeArray,i);
local_weather.n_effectVolumeArray = local_weather.n_effectVolumeArray - 1;
i = i - 1;
ecount = ecount + 1;
}
}
} }
setprop(lw~"effect-volumes/number",getprop(lw~"effect-volumes/number")- ecount); setprop(lw~"effect-volumes/number",getprop(lw~"effect-volumes/number")- ecount);
# set placement indices to zero to reinitiate search for free positions # set placement indices to zero to reinitiate search for free positions
@ -422,7 +454,7 @@ setprop(lw~"effect-volumes/effect-placement-index",0);
# remove quadtree structures # remove quadtree structures
if (getprop(lw~"config/dynamics-flag") ==1) if (local_weather.dynamics_flag ==1)
{ {
settimer( func {setsize(weather_dynamics.cloudQuadtrees[index-1],0);},1.0); settimer( func {setsize(weather_dynamics.cloudQuadtrees[index-1],0);},1.0);
} }
@ -568,11 +600,6 @@ t.getNode("timestamp-sec").setValue(f.getNode("timestamp-sec").getValue());
t.getNode("orientation-deg").setValue(f.getNode("orientation-deg").getValue()); t.getNode("orientation-deg").setValue(f.getNode("orientation-deg").getValue());
t.getNode("code").setValue(f.getNode("code").getValue()); t.getNode("code").setValue(f.getNode("code").getValue());
#if (f.getNode("code").getValue() == "")
# {print("Empty tile code copying from ", from_index," to ", to_index, "!");}
#if (f.getNode("code").getValue() != "") # we don't copy an empty code, that can trigger errors
# {t.getNode("code").setValue(f.getNode("code").getValue());}
} }
@ -630,7 +657,7 @@ setprop(lw~"tiles/tile[0]/generated-flag",0);
setprop(lw~"tiles/tile[0]/tile-index",-1); setprop(lw~"tiles/tile[0]/tile-index",-1);
setprop(lw~"tiles/tile[0]/code",""); setprop(lw~"tiles/tile[0]/code","");
setprop(lw~"tiles/tile[0]/timestamp-sec",weather_dynamics.time_lw); setprop(lw~"tiles/tile[0]/timestamp-sec",weather_dynamics.time_lw);
setprop(lw~"tiles/tile[0]/orientation-deg",0.0); setprop(lw~"tiles/tile[0]/orientation-deg",alpha);
x = 0.0; y = 40000.0; x = 0.0; y = 40000.0;
setprop(lw~"tiles/tile[1]/latitude-deg",blat + get_lat(x,y,phi)); setprop(lw~"tiles/tile[1]/latitude-deg",blat + get_lat(x,y,phi));
@ -639,7 +666,7 @@ setprop(lw~"tiles/tile[1]/generated-flag",0);
setprop(lw~"tiles/tile[1]/tile-index",-1); setprop(lw~"tiles/tile[1]/tile-index",-1);
setprop(lw~"tiles/tile[1]/code",""); setprop(lw~"tiles/tile[1]/code","");
setprop(lw~"tiles/tile[1]/timestamp-sec",weather_dynamics.time_lw); setprop(lw~"tiles/tile[1]/timestamp-sec",weather_dynamics.time_lw);
setprop(lw~"tiles/tile[1]/orientation-deg",0.0); setprop(lw~"tiles/tile[1]/orientation-deg",alpha);
x = 40000.0; y = 40000.0; x = 40000.0; y = 40000.0;
setprop(lw~"tiles/tile[2]/latitude-deg",blat + get_lat(x,y,phi)); setprop(lw~"tiles/tile[2]/latitude-deg",blat + get_lat(x,y,phi));
@ -648,7 +675,7 @@ setprop(lw~"tiles/tile[2]/generated-flag",0);
setprop(lw~"tiles/tile[2]/tile-index",-1); setprop(lw~"tiles/tile[2]/tile-index",-1);
setprop(lw~"tiles/tile[2]/code",""); setprop(lw~"tiles/tile[2]/code","");
setprop(lw~"tiles/tile[2]/timestamp-sec",weather_dynamics.time_lw); setprop(lw~"tiles/tile[2]/timestamp-sec",weather_dynamics.time_lw);
setprop(lw~"tiles/tile[2]/orientation-deg",0.0); setprop(lw~"tiles/tile[2]/orientation-deg",alpha);
x = -40000.0; y = 0.0; x = -40000.0; y = 0.0;
setprop(lw~"tiles/tile[3]/latitude-deg",blat + get_lat(x,y,phi)); setprop(lw~"tiles/tile[3]/latitude-deg",blat + get_lat(x,y,phi));
@ -657,7 +684,7 @@ setprop(lw~"tiles/tile[3]/generated-flag",0);
setprop(lw~"tiles/tile[3]/tile-index",-1); setprop(lw~"tiles/tile[3]/tile-index",-1);
setprop(lw~"tiles/tile[3]/code",""); setprop(lw~"tiles/tile[3]/code","");
setprop(lw~"tiles/tile[3]/timestamp-sec",weather_dynamics.time_lw); setprop(lw~"tiles/tile[3]/timestamp-sec",weather_dynamics.time_lw);
setprop(lw~"tiles/tile[3]/orientation-deg",0.0); setprop(lw~"tiles/tile[3]/orientation-deg",alpha);
# this is the current tile # this is the current tile
x = 0.0; y = 0.0; x = 0.0; y = 0.0;
@ -677,7 +704,7 @@ setprop(lw~"tiles/tile[5]/generated-flag",0);
setprop(lw~"tiles/tile[5]/tile-index",-1); setprop(lw~"tiles/tile[5]/tile-index",-1);
setprop(lw~"tiles/tile[5]/code",""); setprop(lw~"tiles/tile[5]/code","");
setprop(lw~"tiles/tile[5]/timestamp-sec",weather_dynamics.time_lw); setprop(lw~"tiles/tile[5]/timestamp-sec",weather_dynamics.time_lw);
setprop(lw~"tiles/tile[5]/orientation-deg",0.0); setprop(lw~"tiles/tile[5]/orientation-deg",alpha);
x = -40000.0; y = -40000.0; x = -40000.0; y = -40000.0;
setprop(lw~"tiles/tile[6]/latitude-deg",blat + get_lat(x,y,phi)); setprop(lw~"tiles/tile[6]/latitude-deg",blat + get_lat(x,y,phi));
@ -686,7 +713,7 @@ setprop(lw~"tiles/tile[6]/generated-flag",0);
setprop(lw~"tiles/tile[6]/tile-index",-1); setprop(lw~"tiles/tile[6]/tile-index",-1);
setprop(lw~"tiles/tile[6]/code",""); setprop(lw~"tiles/tile[6]/code","");
setprop(lw~"tiles/tile[6]/timestamp-sec",weather_dynamics.time_lw); setprop(lw~"tiles/tile[6]/timestamp-sec",weather_dynamics.time_lw);
setprop(lw~"tiles/tile[6]/orientation-deg",0.0); setprop(lw~"tiles/tile[6]/orientation-deg",alpha);
x = 0.0; y = -40000.0; x = 0.0; y = -40000.0;
setprop(lw~"tiles/tile[7]/latitude-deg",blat + get_lat(x,y,phi)); setprop(lw~"tiles/tile[7]/latitude-deg",blat + get_lat(x,y,phi));
@ -695,7 +722,7 @@ setprop(lw~"tiles/tile[7]/generated-flag",0);
setprop(lw~"tiles/tile[7]/tile-index",-1); setprop(lw~"tiles/tile[7]/tile-index",-1);
setprop(lw~"tiles/tile[7]/code",""); setprop(lw~"tiles/tile[7]/code","");
setprop(lw~"tiles/tile[7]/timestamp-sec",weather_dynamics.time_lw); setprop(lw~"tiles/tile[7]/timestamp-sec",weather_dynamics.time_lw);
setprop(lw~"tiles/tile[7]/orientation-deg",0.0); setprop(lw~"tiles/tile[7]/orientation-deg",alpha);
x = 40000.0; y = -40000.0; x = 40000.0; y = -40000.0;
setprop(lw~"tiles/tile[8]/latitude-deg",blat + get_lat(x,y,phi)); setprop(lw~"tiles/tile[8]/latitude-deg",blat + get_lat(x,y,phi));
@ -704,7 +731,7 @@ setprop(lw~"tiles/tile[8]/generated-flag",0);
setprop(lw~"tiles/tile[8]/tile-index",-1); setprop(lw~"tiles/tile[8]/tile-index",-1);
setprop(lw~"tiles/tile[8]/code",""); setprop(lw~"tiles/tile[8]/code","");
setprop(lw~"tiles/tile[8]/timestamp-sec",weather_dynamics.time_lw); setprop(lw~"tiles/tile[8]/timestamp-sec",weather_dynamics.time_lw);
setprop(lw~"tiles/tile[8]/orientation-deg",0.0); setprop(lw~"tiles/tile[8]/orientation-deg",alpha);
} }
@ -772,7 +799,7 @@ for (var i = index; i < i_max; i = i+1)
# if wind drift is on, move the cloud # if wind drift is on, move the cloud
if (getprop(lw~"config/dynamics-flag") == 1) if (local_weather.dynamics_flag == 1)
{ {
c.move(); c.move();
} }
@ -797,8 +824,30 @@ for (var i = index; i < i_max; i = i+1)
if (d < d_comp) # insert the cloud into scenery and delete from buffer if (d < d_comp) # insert the cloud into scenery and delete from buffer
{ {
setprop(lw~"tmp/buffer-tile-index",c.index); compat_layer.buffered_tile_index = c.index;
if (local_weather.dynamics_flag == 1) # assemble the current tile coordinates for insertion into quadtree
{
for (var j = 0; j < 9; j=j+1)
{
if (getprop(lw~"tiles/tile["~j~"]/tile-index") == c.index)
{
compat_layer.buffered_tile_latitude = getprop(lw~"tiles/tile["~j~"]/latitude-deg");
compat_layer.buffered_tile_longitude = getprop(lw~"tiles/tile["~j~"]/longitude-deg");
compat_layer.buffered_tile_alpha=getprop(lw~"tiles/tile["~j~"]/orientation-deg");
break;
}
}
}
if ((c.type !=0) and (local_weather.dynamics_flag == 1)) # set additional info for Cumulus clouds
{
compat_layer.cloud_mean_altitude = c.alt - c.rel_alt;
compat_layer.cloud_flt = c.flt;
compat_layer.cloud_evolution_timestamp = c.evolution_timestamp;
}
compat_layer.create_cloud(c.path, c.lat, c.lon, c.alt, c.orientation); compat_layer.create_cloud(c.path, c.lat, c.lon, c.alt, c.orientation);
n_cloudSceneryArray = n_cloudSceneryArray +1;
cloudBufferArray = delete_from_vector(cloudBufferArray,i); cloudBufferArray = delete_from_vector(cloudBufferArray,i);
i = i -1; i_max = i_max - 1; n_max = n_max - 1; i = i -1; i_max = i_max - 1; n_max = n_max - 1;
deleted_flag = 1; deleted_flag = 1;
@ -826,6 +875,7 @@ var housekeeping_loop = func (index) {
var n = 5; var n = 5;
var n_max = size(cloudSceneryArray); var n_max = size(cloudSceneryArray);
n_cloudSceneryArray = n_max;
var s = size(active_tile_list); var s = size(active_tile_list);
setprop(lw~"clouds/cloud-scenery-count",n_max); setprop(lw~"clouds/cloud-scenery-count",n_max);
@ -869,6 +919,7 @@ for (var i = index; i < i_max; i = i+1)
c.removeNodes(); c.removeNodes();
cloudSceneryArray = delete_from_vector(cloudSceneryArray,i); cloudSceneryArray = delete_from_vector(cloudSceneryArray,i);
i = i -1; i_max = i_max - 1; n_max = n_max - 1; i = i -1; i_max = i_max - 1; n_max = n_max - 1;
n_cloudSceneryArray = n_cloudSceneryArray -1;
continue; continue;
} }
@ -893,6 +944,7 @@ for (var i = index; i < i_max; i = i+1)
append(cloudBufferArray,c.to_buffer()); append(cloudBufferArray,c.to_buffer());
cloudSceneryArray = delete_from_vector(cloudSceneryArray,i); cloudSceneryArray = delete_from_vector(cloudSceneryArray,i);
i = i -1; i_max = i_max - 1; n_max = n_max - 1; i = i -1; i_max = i_max - 1; n_max = n_max - 1;
n_cloudSceneryArray = n_cloudSceneryArray -1;
continue; continue;
} }
@ -921,11 +973,13 @@ foreach(t; tNode)
var code = t.getNode("code").getValue(); var code = t.getNode("code").getValue();
var index = t.getNode("tile-index").getValue(); var index = t.getNode("tile-index").getValue();
var flag = t.getNode("generated-flag").getValue(); var flag = t.getNode("generated-flag").getValue();
var alpha = t.getNode("orientation-deg").getValue();
print(i,": code: ", code, " unique id: ", index, " flag: ", flag); print(i,": code: ", code, " unique id: ", index, " flag: ", flag, " alpha: ",alpha);
i = i + 1; i = i + 1;
} }
print("alpha: ",getprop(lw~"tmp/tile-orientation-deg"));
print("===================="); print("====================");
@ -963,8 +1017,9 @@ var active_tile_list = [];
var cloudBufferArray = []; var cloudBufferArray = [];
var cloudBuffer = { var cloudBuffer = {
new: func(lat, lon, alt, path, orientation, index) { new: func(lat, lon, alt, path, orientation, index, type) {
var c = { parents: [cloudBuffer] }; var c = { parents: [cloudBuffer] };
c.lat = lat; c.lat = lat;
c.lon = lon; c.lon = lon;
@ -972,6 +1027,7 @@ var cloudBuffer = {
c.path = path; c.path = path;
c.orientation = orientation; c.orientation = orientation;
c.index = index; c.index = index;
c.type = type;
return c; return c;
}, },
get_distance: func { get_distance: func {
@ -1003,13 +1059,21 @@ var cloudBuffer = {
var cloudSceneryArray = []; var cloudSceneryArray = [];
var n_cloudSceneryArray = 0;
var cloudScenery = { var cloudScenery = {
new: func(index, cloudNode, modelNode) { new: func(index, type, cloudNode, modelNode) {
var c = { parents: [cloudScenery] }; var c = { parents: [cloudScenery] };
c.index = index; c.index = index;
c.type = type;
c.cloudNode = cloudNode; c.cloudNode = cloudNode;
c.modelNode = modelNode; c.modelNode = modelNode;
c.calt = cloudNode.getNode("position/altitude-ft");
c.clat = cloudNode.getNode("position/latitude-deg");
c.clon = cloudNode.getNode("position/longitude-deg");
c.alt = c.calt.getValue();
c.lat = c.clat.getValue();
c.lon = c.clon.getValue();
return c; return c;
}, },
removeNodes: func { removeNodes: func {
@ -1017,17 +1081,20 @@ var cloudScenery = {
me.cloudNode.remove(); me.cloudNode.remove();
}, },
to_buffer: func { to_buffer: func {
var lat = me.cloudNode.getNode("position/latitude-deg").getValue();
var lon = me.cloudNode.getNode("position/longitude-deg").getValue();
var alt = me.cloudNode.getNode("position/altitude-ft").getValue();
var path = me.modelNode.getNode("path").getValue(); var path = me.modelNode.getNode("path").getValue();
var orientation = me.cloudNode.getNode("orientation/true-heading-deg").getValue(); var orientation = me.cloudNode.getNode("orientation/true-heading-deg").getValue();
var b = cloudBuffer.new(lat, lon, alt, path, orientation, me.index); var b = cloudBuffer.new(me.lat, me.lon, me.alt, path, orientation, me.index, me.type);
if (getprop(lw~"config/dynamics-flag") == 1) if (local_weather.dynamics_flag == 1)
{ {
var timestamp = me.cloudNode.getNode("timestamp-sec").getValue(); b.timestamp = me.timestamp;
b.timestamp = timestamp;
if (me.type !=0) # Cumulus clouds get some extra info
{
b.flt = me.flt;
b.rel_alt = me.rel_alt;
b.evolution_timestamp = me.evolution_timestamp;
}
} }
me.removeNodes(); me.removeNodes();
@ -1036,21 +1103,106 @@ var cloudScenery = {
get_distance: func { get_distance: func {
var pos = geo.aircraft_position(); var pos = geo.aircraft_position();
var cpos = geo.Coord.new(); var cpos = geo.Coord.new();
var lat = me.cloudNode.getNode("position/latitude-deg").getValue(); var lat = me.clat.getValue();
var lon = me.cloudNode.getNode("position/longitude-deg").getValue(); var lon = me.clon.getValue();
cpos.set_latlon(lat,lon,0.0); cpos.set_latlon(lat,lon,0.0);
return pos.distance_to(cpos); return pos.distance_to(cpos);
}, },
get_course: func { get_course: func {
var pos = geo.aircraft_position(); var pos = geo.aircraft_position();
var cpos = geo.Coord.new(); var cpos = geo.Coord.new();
var lat = me.cloudNode.getNode("position/latitude-deg").getValue(); var lat = me.clat.getValue();
var lon = me.cloudNode.getNode("position/longitude-deg").getValue(); var lon = me.clon.getValue();
cpos.set_latlon(lat,lon,0.0); cpos.set_latlon(lat,lon,0.0);
return pos.course_to(cpos); return pos.course_to(cpos);
}, },
get_altitude: func { get_altitude: func {
return me.cloudNode.getNode("position/altitude-ft").getValue(); return me.calt.getValue();
},
correct_altitude: func {
var lat = me.clat.getValue();
var lon = me.clon.getValue();
var convective_alt = weather_dynamics.tile_convective_altitude[me.index-1] + local_weather.alt_20_array[me.index-1];
var elevation = compat_layer.get_elevation(lat, lon);
var alt_new = local_weather.get_convective_altitude(convective_alt, elevation, me.index);
me.target_alt = alt_new + me.rel_alt;
},
correct_altitude_and_age: func {
var lat = me.lat;
var lon = me.lon;
var convective_alt = weather_dynamics.tile_convective_altitude[me.index-1] + local_weather.alt_20_array[me.index-1];
# get terrain elevation and landcover
var elevation = -1.0; var p_cover = 0.2;# defaults if there is no info
var info = geodinfo(lat, lon);
if (info != nil)
{
elevation = info[0] * local_weather.m_to_ft;
if (info[1] != nil)
{
var landcover = info[1].names[0];
if (contains(local_weather.landcover_map,landcover)) {p_cover = local_weather.landcover_map[landcover];}
else {p_cover = 0.2;}
}
}
# correct the altitude
var alt_new = local_weather.get_convective_altitude(convective_alt, elevation, me.index);
me.target_alt = alt_new + me.rel_alt;
# correct fractional lifetime based on terrain below
var current_lifetime = math.sqrt(p_cover)/math.sqrt(0.35) * weather_dynamics.cloud_convective_lifetime_s;
var fractional_increase = (weather_dynamics.time_lw - me.evolution_timestamp)/current_lifetime;
me.flt = me.flt + fractional_increase;
me.evolution_timestamp = weather_dynamics.time_lw;
},
to_target_alt: func {
if (me.type ==0) {return;}
var alt_diff = me.target_alt - me.alt;
if (alt_diff == 0.0) {return;}
var max_vertical_movement_ft = weather_dynamics.dt_lw * weather_dynamics.cloud_max_vertical_speed_fts;
if (abs(alt_diff) < max_vertical_movement_ft)
{
me.alt = me.target_alt;
}
else if (alt_diff < 0)
{
me.alt = me.alt -max_vertical_movement_ft;
}
else
{
me.alt = me.alt + max_vertical_movement_ft;
}
setprop(lw~"clouds/tile["~me.index~"]/cloud["~me.write_index~"]/position/altitude-ft", me.alt);
},
move: func {
var windfield = weather_dynamics.windfield;
var dt = weather_dynamics.time_lw - me.timestamp;
me.lat = me.lat + windfield[1] * dt * local_weather.m_to_lat;
me.lon = me.lon + windfield[0] * dt * local_weather.m_to_lon;
setprop(lw~"clouds/tile["~me.index~"]/cloud["~me.write_index~"]/position/latitude-deg", me.lat);
setprop(lw~"clouds/tile["~me.index~"]/cloud["~me.write_index~"]/position/longitude-deg", me.lon);
me.timestamp = weather_dynamics.time_lw;
},
show: func {
var lat = me.clat.getValue();
var lon = me.clon.getValue();
var alt = me.calt.getValue();
var convective_alt = weather_dynamics.tile_convective_altitude[me.index-1] + local_weather.alt_20_array[me.index-1];
var elevation = compat_layer.get_elevation(lat, lon);
print("lat :", lat, " lon: ", lon, " alt: ", alt);
print("path: ", me.modelNode.getNode("path").getValue());
print("elevation: ", compat_layer.get_elevation(lat, lon), " cloudbase: ", convective_alt);
if (me.type !=0) {print("relative: ", me.rel_alt, "target: ", me.target_alt);}
}, },
}; };

View file

@ -1,7 +1,7 @@
######################################################## ########################################################
# routines to set up weather tiles # routines to set up weather tiles
# Thorsten Renk, July 2010 # Thorsten Renk, October 2010
######################################################## ########################################################
# function purpose # function purpose
@ -22,7 +22,7 @@
var tile_start = func { var tile_start = func {
# set thread lock # set thread lock
if (getprop(lw~"tmp/thread-flag") == 1){setprop(lw~"tmp/thread-status","computing");} if (local_weather.thread_flag == 1){setprop(lw~"tmp/thread-status","computing");}
# set the tile code # set the tile code
var current_code = getprop(lw~"tiles/code"); var current_code = getprop(lw~"tiles/code");
@ -51,9 +51,10 @@ var dir_index = getprop(lw~"tiles/tmp/dir-index");
local_weather.assemble_effect_array(); local_weather.assemble_effect_array();
print("Finished setting up tile type ",current_code, " in direction ",dir_index); if (local_weather.debug_output_flag == 1)
{print("Finished setting up tile type ",current_code, " in direction ",dir_index);}
if (getprop(lw~"tmp/thread-flag") == 1) if (local_weather.thread_flag == 1)
{setprop(lw~"tmp/thread-status","placing");} {setprop(lw~"tmp/thread-status","placing");}
else # without worker threads, tile generation is complete at this point else # without worker threads, tile generation is complete at this point
{props.globals.getNode(lw~"tiles").getChild("tile",dir_index).getNode("generated-flag").setValue(2);} {props.globals.getNode(lw~"tiles").getChild("tile",dir_index).getNode("generated-flag").setValue(2);}
@ -97,10 +98,17 @@ local_weather.set_weather_station(blat, blon, 20000.0, 14.0, 12.0, 29.78);
#create_2_8_sstratus_streak(blat, blon,5000.0,0.0); #create_2_8_sstratus_streak(blat, blon,5000.0,0.0);
create_4_8_cirrocumulus_bank(blat, blon, 6000.0, 0.0); #create_4_8_cirrocumulus_bank(blat, blon, 6000.0, 0.0);
#create_4_8_cirrocumulus_streaks(blat, blon, 6000.0, 0.0);
# create_2_8_cirrocumulus(blat, blon, 6000.0, 0.0);
#create_detailed_stratocumulus_bank(blat, blon,5000.0+alt_offset,0.0); #create_detailed_stratocumulus_bank(blat, blon,5000.0+alt_offset,0.0);
create_4_8_altocumulus_perlucidus(blat, blon, 10000.0, 0.0);
local_weather.create_effect_volume(3, blat, blon, 20000.0, 7000.0, alpha, 0.0, 80000.0, -1, -1, -1, -1, 15.0, -3,-1);
tile_finished(); tile_finished();
@ -143,12 +151,43 @@ var p = 1025.0 + rand() * 6.0; p = adjust_p(p);
# and set them at the tile center # and set them at the tile center
local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg); local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg);
# weak cumulus development
var alt = spread * 1000; var alt = spread * 1000;
var strength = rand() * 0.05; var strength = 0.0;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); var rn = rand();
if (rn > 0.5)
{
# cloud scenario 1: weak cumulus development and blue thermals
strength = rand() * 0.05;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
# generate a few blue thermals
if (local_weather.generate_thermal_lift_flag !=0)
{
local_weather.generate_thermal_lift_flag = 3;
strength = rand() * 0.4;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
local_weather.generate_thermal_lift_flag = 2;
}
}
else if (rn > 0.0)
{
# cloud scenario 2: some Cirrocumulus patches
create_2_8_cirrocumulus(blat, blon, alt + alt_offset + 5000.0, alpha);
}
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -192,36 +231,35 @@ var p = 1019.0 + rand() * 6.0; p = adjust_p(p);
# and set them at the tile center # and set them at the tile center
local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg); local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg);
# moderate cumulus development
var alt = spread * 1000; var alt = spread * 1000;
var strength = 0.0;
var rn = rand(); var rn = rand();
if (rn > 0.66) if (rn > 0.66)
{ {
# cloud scenario 1: possible Cirrus over Cumulus # cloud scenario 1: possible Cirrus over Cumulus
var strength = 0.2 + rand() * 0.4; strength = 0.2 + rand() * 0.4;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
# one or two Cirrus clouds # one or two Cirrus clouds
x = 2000.0 + rand() * 16000.0; x = 2000.0 + rand() * 16000.0;
y = 2.0 * (rand()-0.5) * 18000; y = 2.0 * (rand()-0.5) * 18000;
alt = 25000.0 + rand() * 5000.0;
var path = local_weather.select_cloud_model("Cirrus", "small"); var path = local_weather.select_cloud_model("Cirrus", "small");
compat_layer.create_cloud(path, blat + get_lat(x,y,phi), blon+get_lon(x,y,phi), alt + alt_offset,alpha); compat_layer.create_cloud(path, blat + get_lat(x,y,phi), blon+get_lon(x,y,phi), alt + alt_offset + 25000.0 + rand() * 5000.0,alpha);
if (rand() > 0.5) if (rand() > 0.5)
{ {
x = -2000.0 - rand() * 16000.0; x = -2000.0 - rand() * 16000.0;
y = 2.0 * (rand()-0.5) * 18000; y = 2.0 * (rand()-0.5) * 18000;
alt = 25000.0 + rand() * 5000.0;
var path = local_weather.select_cloud_model("Cirrus", "small"); var path = local_weather.select_cloud_model("Cirrus", "small");
compat_layer.create_cloud(path, blat + get_lat(x,y,phi), blon+get_lon(x,y,phi), alt + alt_offset,alpha); compat_layer.create_cloud(path, blat + get_lat(x,y,phi), blon+get_lon(x,y,phi), alt + alt_offset +25000.0 + rand() * 5000.0,alpha);
} }
} }
@ -229,7 +267,7 @@ else if (rn > 0.33)
{ {
# cloud scenario 2: Cirrostratus over weak Cumulus # cloud scenario 2: Cirrostratus over weak Cumulus
var strength = 0.2 + rand() * 0.2; strength = 0.2 + rand() * 0.2;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
create_2_8_cirrostratus(blat, blon, alt+alt_offset+25000.0, alpha); create_2_8_cirrostratus(blat, blon, alt+alt_offset+25000.0, alpha);
@ -239,7 +277,7 @@ else if (rn > 0.0)
{ {
# cloud scenario 3: Cirrocumulus sheet over Cumulus # cloud scenario 3: Cirrocumulus sheet over Cumulus
var strength = 0.2 + rand() * 0.2; strength = 0.2 + rand() * 0.2;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
x = 2.0 * (rand()-0.5) * 5000; x = 2.0 * (rand()-0.5) * 5000;
@ -251,6 +289,12 @@ else if (rn > 0.0)
} }
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
} }
@ -296,25 +340,26 @@ local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg);
# now a random selection of different possible cloud configuration scenarios # now a random selection of different possible cloud configuration scenarios
var alt = spread * 1000; var alt = spread * 1000;
var strength = 0.0;
var rn = rand(); var rn = rand();
if (rn > 0.833) if (rn > 0.875)
{ {
# cloud scenario 1: Altocumulus patch over weak Cumulus # cloud scenario 1: Altocumulus patch over weak Cumulus
var strength = 0.1 + rand() * 0.1; strength = 0.1 + rand() * 0.1;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
x = 2.0 * (rand()-0.5) * 5000; x = 2.0 * (rand()-0.5) * 5000;
y = 2.0 * (rand()-0.5) * 5000; y = 2.0 * (rand()-0.5) * 5000;
local_weather.create_streak("Altocumulus",blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 12000.0+alt+alt_offset,1500.0,30,1000.0,0.2,800.0,30,1000.0,0.2,800.0,alpha ,1.0); local_weather.create_streak("Altocumulus",blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 12000.0+alt+alt_offset,1500.0,30,1000.0,0.2,1200.0,30,1000.0,0.2,1200.0,alpha ,1.0);
} }
else if (rn > 0.666) else if (rn > 0.750)
{ {
# cloud scenario 2: Altocumulus streaks # cloud scenario 2: Altocumulus streaks
var strength = 0.15 + rand() * 0.2; strength = 0.15 + rand() * 0.2;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
x = 2.0 * (rand()-0.5) * 10000; x = 2.0 * (rand()-0.5) * 10000;
@ -322,14 +367,14 @@ else if (rn > 0.666)
local_weather.create_streak("Altocumulus",blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 12000.0+alt+alt_offset,1500.0,25,700.0,0.2,800.0,10,700.0,0.2,800.0,alpha ,1.4); local_weather.create_streak("Altocumulus",blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 12000.0+alt+alt_offset,1500.0,25,700.0,0.2,800.0,10,700.0,0.2,800.0,alpha ,1.4);
x = 2.0 * (rand()-0.5) * 10000; x = 2.0 * (rand()-0.5) * 10000;
y = 2.0 * (rand()-0.5) * 10000; y = 2.0 * (rand()-0.5) * 10000;
local_weather.create_streak("Altocumulus",blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 12000.0+alt+alt_offset,1500.0,22,750.0,0.2,800.0,8,750.0,0.2,800.0,alpha ,1.1); local_weather.create_streak("Altocumulus",blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 12000.0+alt+alt_offset,1500.0,22,750.0,0.2,1000.0,8,750.0,0.2,1000.0,alpha ,1.1);
} }
else if (rn > 0.5) else if (rn > 0.625)
{ {
# cloud scenario 3: Cirrus # cloud scenario 3: Cirrus
var strength = 0.1 + rand() * 0.1; strength = 0.1 + rand() * 0.1;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
x = 2.0 * (rand()-0.5) * 3000; x = 2.0 * (rand()-0.5) * 3000;
@ -337,11 +382,11 @@ else if (rn > 0.5)
local_weather.create_streak("Cirrus",blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 22000.0+alt+alt_offset,1500.0,3,9000.0,0.0, 800.0, 1,8000.0,0.0,800,0,alpha ,1.0); local_weather.create_streak("Cirrus",blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 22000.0+alt+alt_offset,1500.0,3,9000.0,0.0, 800.0, 1,8000.0,0.0,800,0,alpha ,1.0);
} }
else if (rn > 0.333) else if (rn > 0.5)
{ {
# cloud scenario 4: Cumulonimbus banks # cloud scenario 4: Cumulonimbus banks
var strength = 0.7 + rand() * 0.3; strength = 0.7 + rand() * 0.3;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
for (var i = 0; i < 3; i = i + 1) for (var i = 0; i < 3; i = i + 1)
@ -352,11 +397,11 @@ else if (rn > 0.333)
create_cloud_bank("Cumulonimbus", blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), alt+alt_offset, 1600.0, 800.0, 3000.0, 9, alpha); create_cloud_bank("Cumulonimbus", blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), alt+alt_offset, 1600.0, 800.0, 3000.0, 9, alpha);
} }
} }
else if (rn > 0.166) else if (rn > 0.375)
{ {
# cloud scenario 5: scattered Stratus # cloud scenario 5: scattered Stratus
var strength = 0.4 + rand() * 0.2; strength = 0.4 + rand() * 0.2;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
var size_offset = 0.5 * m_to_ft * local_weather.cloud_vertical_size_map["Stratus_structured"]; var size_offset = 0.5 * m_to_ft * local_weather.cloud_vertical_size_map["Stratus_structured"];
@ -364,11 +409,11 @@ else if (rn > 0.166)
local_weather.create_streak("Stratus (structured)",blat, blon, alt+6000.0+alt_offset+size_offset,1000.0,18,0.0,0.3,20000.0,18,0.0,0.3,20000.0,0.0,1.0); local_weather.create_streak("Stratus (structured)",blat, blon, alt+6000.0+alt_offset+size_offset,1000.0,18,0.0,0.3,20000.0,18,0.0,0.3,20000.0,0.0,1.0);
} }
else if (rn > 0.0) else if (rn > 0.250)
{ {
# cloud scenario 6: Cirrocumulus sheets # cloud scenario 6: Cirrocumulus sheets
var strength = 0.2 + rand() * 0.2; strength = 0.2 + rand() * 0.2;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
@ -383,10 +428,31 @@ else if (rn > 0.0)
var path = local_weather.select_cloud_model("Cirrocumulus", "large"); var path = local_weather.select_cloud_model("Cirrocumulus", "large");
compat_layer.create_cloud(path, blat + get_lat(x,y,phi), blon+get_lon(x,y,phi), alt + alt_offset +20000+ alt_variation,alpha+ beta); compat_layer.create_cloud(path, blat + get_lat(x,y,phi), blon+get_lon(x,y,phi), alt + alt_offset +20000+ alt_variation,alpha+ beta);
} }
}
else if (rn > 0.125)
{
# cloud scenario 7: Thin Cirrocumulus sheets over weak Cumulus
strength = 0.05 + rand() * 0.1;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
create_4_8_cirrocumulus_streaks(blat, blon, alt + 6000.0 + alt_offset, alpha);
}
else if (rn > 0.0)
{
# cloud scenario 8: Altocumulus perlucidus
create_4_8_altocumulus_perlucidus(blat, blon, alt + 10000.0 + alt_offset, alpha);
} }
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -435,6 +501,7 @@ local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg);
# altitude for the lowest layer # altitude for the lowest layer
var alt = spread * 1000.0; var alt = spread * 1000.0;
var strength = 0.0;
# now a random selection of different possible cloud configuration scenarios # now a random selection of different possible cloud configuration scenarios
@ -484,6 +551,11 @@ else if (rn > 0.0)
create_4_8_cirrocumulus_bank(blat, blon, alt+alt_offset + 12000.0, alpha); create_4_8_cirrocumulus_bank(blat, blon, alt+alt_offset + 12000.0, alpha);
} }
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
} }
@ -531,6 +603,7 @@ local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg);
# altitude for the lowest layer # altitude for the lowest layer
var alt = spread * 1000.0; var alt = spread * 1000.0;
var strength = 0.0;
var rn = rand(); var rn = rand();
@ -547,16 +620,16 @@ if (rn > 0.75)
var beta = rand() * 360.0; var beta = rand() * 360.0;
local_weather.create_layer("Nimbus", blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), alt+alt_offset, 500.0, 12000.0, 7000.0, beta, 1.0, 0.2, 1, 1.0); local_weather.create_layer("Nimbus", blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), alt+alt_offset, 500.0, 12000.0, 7000.0, beta, 1.0, 0.2, 1, 1.0);
local_weather.create_effect_volume(2, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 10000.0, 6000.0, beta, 0.0, alt + alt_offset, 5000.0, 0.3, -1, -1, -1,0 ); local_weather.create_effect_volume(2, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 10000.0, 6000.0, beta, 0.0, alt + alt_offset, 5000.0, 0.3, -1, -1, -1,0,-1 );
local_weather.create_effect_volume(2, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 9000.0, 5000.0, beta, 0.0, alt+alt_offset-300.0, 1500.0, 0.5, -1, -1, -1,0 ); local_weather.create_effect_volume(2, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 9000.0, 5000.0, beta, 0.0, alt+alt_offset-300.0, 1500.0, 0.5, -1, -1, -1,0,-1 );
x = 2.0 * (rand()-0.5) * 11000.0; x = 2.0 * (rand()-0.5) * 11000.0;
y = 2.0 * (rand()-0.5) * 11000.0; y = 2.0 * (rand()-0.5) * 11000.0;
var beta = rand() * 360.0; var beta = rand() * 360.0;
local_weather.create_layer("Nimbus", blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), alt+alt_offset, 500.0, 10000.0, 6000.0, beta, 1.0, 0.2, 1, 1.0); local_weather.create_layer("Nimbus", blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), alt+alt_offset, 500.0, 10000.0, 6000.0, beta, 1.0, 0.2, 1, 1.0);
local_weather.create_effect_volume(2, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 9000.0, 5000.0, beta, 0.0, alt + alt_offset, 5000.0, 0.3, -1, -1, -1,0 ); local_weather.create_effect_volume(2, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 9000.0, 5000.0, beta, 0.0, alt + alt_offset, 5000.0, 0.3, -1, -1, -1,0 ,-1);
local_weather.create_effect_volume(2, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 8000.0, 4000.0, beta, 0.0, alt+alt_offset-300.0, 1500.0, 0.5, -1, -1, -1,0 ); local_weather.create_effect_volume(2, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 8000.0, 4000.0, beta, 0.0, alt+alt_offset-300.0, 1500.0, 0.5, -1, -1, -1,0,-1 );
create_4_8_sstratus_undulatus(blat, blon, alt+alt_offset +3000.0, alpha); create_4_8_sstratus_undulatus(blat, blon, alt+alt_offset +3000.0, alpha);
create_2_8_tstratus(blat, blon, alt+alt_offset +6000.0, alpha); create_2_8_tstratus(blat, blon, alt+alt_offset +6000.0, alpha);
@ -569,8 +642,8 @@ else if (rn >0.5)
alt = alt + local_weather.cloud_vertical_size_map["Stratus"] * 0.5 * m_to_ft; alt = alt + local_weather.cloud_vertical_size_map["Stratus"] * 0.5 * m_to_ft;
create_8_8_stratus(blat, blon, alt+alt_offset,alpha); create_8_8_stratus(blat, blon, alt+alt_offset,alpha);
local_weather.create_effect_volume(3, blat, blon, 18000.0, 18000.0, 0.0, 0.0, 1800.0, 8000.0, -1, -1, -1, -1, 0); local_weather.create_effect_volume(3, blat, blon, 18000.0, 18000.0, 0.0, 0.0, 1800.0, 8000.0, -1, -1, -1, -1, 0,-1);
local_weather.create_effect_volume(3, blat, blon, 14000.0, 14000.0, 0.0, 0.0, 1500.0, 6000.0, 0.1, -1, -1, -1,0 ); local_weather.create_effect_volume(3, blat, blon, 14000.0, 14000.0, 0.0, 0.0, 1500.0, 6000.0, 0.1, -1, -1, -1,0,-1 );
create_2_8_sstratus(blat, blon, alt+alt_offset+3000,alpha); create_2_8_sstratus(blat, blon, alt+alt_offset+3000,alpha);
} }
else if (rn >0.25) else if (rn >0.25)
@ -594,6 +667,11 @@ else if (rn >0.0)
create_2_8_sstratus(blat, blon, alt+alt_offset+6000,alpha); create_2_8_sstratus(blat, blon, alt+alt_offset+6000,alpha);
} }
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
} }
@ -643,15 +721,15 @@ local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg);
# set a closed Nimbostratus layer # set a closed Nimbostratus layer
var alt = spread * 1000.0 + local_weather.cloud_vertical_size_map["Nimbus"] * 0.5 * m_to_ft; var alt = spread * 1000.0 + local_weather.cloud_vertical_size_map["Nimbus"] * 0.5 * m_to_ft;
var strength = 0.0;
#print("alt: ",spread*1000);
create_8_8_nimbus(blat, blon, alt+alt_offset, alpha); create_8_8_nimbus(blat, blon, alt+alt_offset, alpha);
# and a precipitation layer below, more rain in the center of the tile # and a precipitation layer below, more rain in the center of the tile
local_weather.create_effect_volume(3, blat, blon, 20000.0, 20000.0, alpha, 0.0, alt + alt_offset, 3000.0, 0.3, -1, -1, -1,0 ); local_weather.create_effect_volume(3, blat, blon, 20000.0, 20000.0, alpha, 0.0, alt + alt_offset, 3000.0, 0.3, -1, -1, -1,0 ,0.95);
local_weather.create_effect_volume(3, blat , blon, 16000.0, 16000.0, alpha, 0.0, alt + alt_offset - 300.0, 1500.0, 0.5, -1, -1, -1,0 ); local_weather.create_effect_volume(3, blat , blon, 16000.0, 16000.0, alpha, 0.0, alt + alt_offset - 300.0, 1500.0, 0.5, -1, -1, -1,0 ,0.8);
# and some broken Stratus cover above # and some broken Stratus cover above
@ -661,6 +739,10 @@ var rn = rand();
if (rn > 0.5){create_4_8_stratus_patches(blat, blon, alt+alt_offset+3000.0, alpha);} if (rn > 0.5){create_4_8_stratus_patches(blat, blon, alt+alt_offset+3000.0, alpha);}
else {create_4_8_stratus(blat, blon, alt+alt_offset+3000.0, alpha);} else {create_4_8_stratus(blat, blon, alt+alt_offset+3000.0, alpha);}
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -705,6 +787,7 @@ local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg);
# altitude for the lowest layer # altitude for the lowest layer
var alt = spread * 1000.0; var alt = spread * 1000.0;
var strength = 0.0;
var rn = rand(); var rn = rand();
@ -713,7 +796,7 @@ var rn = rand();
if (rn > 0.5) if (rn > 0.5)
{ {
# cloud scenario 1: strong Cumulus development # cloud scenario 1: strong Cumulus development
var strength = 0.8 + rand() * 0.2; strength = 0.8 + rand() * 0.2;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
} }
@ -721,7 +804,7 @@ else if (rn > 0.0)
{ {
# cloud scenario 2: Cirrocumulus sheets over Cumulus # cloud scenario 2: Cirrocumulus sheets over Cumulus
var strength = 0.6 + rand() * 0.2; strength = 0.6 + rand() * 0.2;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
for (var i = 0; i < 2; i = i + 1) for (var i = 0; i < 2; i = i + 1)
@ -738,6 +821,12 @@ else if (rn > 0.0)
} }
#local_weather.create_effect_volume(3, blat, blon, 20000.0, 7000.0, alpha, 0.0, 80000.0, -1, -1, -1, -1, 15.0, -3,-1);
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -782,6 +871,7 @@ local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg);
# altitude for the lowest layer # altitude for the lowest layer
var alt = spread * 1000.0; var alt = spread * 1000.0;
var strength = 0.0;
var rn = rand(); var rn = rand();
@ -789,14 +879,14 @@ var rn = rand();
if (rn > 0.8) if (rn > 0.8)
{ {
# cloud scenario 1: weak Cumulus development, some Cirrostratus # cloud scenario 1: weak Cumulus development, some Cirrostratus
var strength = 0.3 + rand() * 0.2; strength = 0.3 + rand() * 0.2;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
create_4_8_cirrostratus_patches(blat, blon, alt+alt_offset+25000.0, alpha); create_4_8_cirrostratus_patches(blat, blon, alt+alt_offset+25000.0, alpha);
} }
else if (rn > 0.6) else if (rn > 0.6)
{ {
# cloud scenario 2: weak Cumulus development under Altostratus streaks # cloud scenario 2: weak Cumulus development under Altostratus streaks
var strength = 0.1 + rand() * 0.1; strength = 0.1 + rand() * 0.1;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
var size_offset = 0.5 * m_to_ft * local_weather.cloud_vertical_size_map["Stratus_structured"]; var size_offset = 0.5 * m_to_ft * local_weather.cloud_vertical_size_map["Stratus_structured"];
@ -807,7 +897,7 @@ else if (rn > 0.6)
else if (rn > 0.4) else if (rn > 0.4)
{ {
# cloud scenario 3: Cirrocumulus bank # cloud scenario 3: Cirrocumulus bank
var strength = 0.05 + rand() * 0.05; strength = 0.05 + rand() * 0.05;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
var size_offset = 0.5 * m_to_ft * local_weather.cloud_vertical_size_map["Cirrocumulus"]; var size_offset = 0.5 * m_to_ft * local_weather.cloud_vertical_size_map["Cirrocumulus"];
@ -818,7 +908,7 @@ else if (rn > 0.4)
else if (rn > 0.2) else if (rn > 0.2)
{ {
# cloud scenario 4: Cirrocumulus undulatus # cloud scenario 4: Cirrocumulus undulatus
var strength = 0.05 + rand() * 0.05; strength = 0.05 + rand() * 0.05;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
var size_offset = 0.5 * m_to_ft * local_weather.cloud_vertical_size_map["Cirrocumulus"]; var size_offset = 0.5 * m_to_ft * local_weather.cloud_vertical_size_map["Cirrocumulus"];
@ -830,7 +920,7 @@ else if (rn > 0.0)
{ {
# cloud scenario 5: weak Cumulus development under scattered Altostratus # cloud scenario 5: weak Cumulus development under scattered Altostratus
var strength = 0.15 + rand() * 0.15; strength = 0.15 + rand() * 0.15;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
var size_offset = 0.5 * m_to_ft * local_weather.cloud_vertical_size_map["Stratus_structured"]; var size_offset = 0.5 * m_to_ft * local_weather.cloud_vertical_size_map["Stratus_structured"];
@ -839,6 +929,10 @@ else if (rn > 0.0)
} }
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -892,6 +986,7 @@ local_weather.set_weather_station(blat, blon, vis, T, D, p * hp_to_inhg);
# altitude for the lowest layer # altitude for the lowest layer
var alt = spread * 1000.0; var alt = spread * 1000.0;
var strength = 0.0;
# tropical weather has a strong daily variation, call thunderstorm only in the correct afternoon time window # tropical weather has a strong daily variation, call thunderstorm only in the correct afternoon time window
@ -901,7 +996,7 @@ var rn = rand();
if (rn > (t_factor * t_factor * t_factor * t_factor)) # call a normal convective cloud system if (rn > (t_factor * t_factor * t_factor * t_factor)) # call a normal convective cloud system
{ {
var strength = 1.0 + rand() * 0.2; strength = 1.0 + rand() * 0.2;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
} }
@ -954,10 +1049,15 @@ local_weather.cumulus_exclusion_layer(blat, blon, alt+alt_offset, n, 20000.0, 20
# some turbulence in the convection layer # some turbulence in the convection layer
local_weather.create_effect_volume(3, blat, blon, 20000.0, 20000.0, alpha, 0.0, alt+3000.0+alt_offset, -1, -1, -1, 0.4, -1,0 ); local_weather.create_effect_volume(3, blat, blon, 20000.0, 20000.0, alpha, 0.0, alt+3000.0+alt_offset, -1, -1, -1, 0.4, -1,0 ,-1);
} # end thundercloud placement } # end thundercloud placement
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
} }
@ -1019,6 +1119,7 @@ local_weather.set_weather_station(blat +get_lat(x,y,phi), blon + get_lon(x,y,phi
# altitude for the lowest layer # altitude for the lowest layer
var alt = spread * 1000.0; var alt = spread * 1000.0;
var strength = 0.0;
# thunderstorms first # thunderstorms first
@ -1072,12 +1173,17 @@ local_weather.create_streak("Stratus (thin)",blat+get_lat(x,y,phi), blon+get_lon
# some turbulence in the convection layer # some turbulence in the convection layer
x=0.0; y = 5000.0; x=0.0; y = 5000.0;
local_weather.create_effect_volume(3, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 20000.0, 11000.0, alpha, 0.0, alt+3000.0+alt_offset, -1, -1, -1, 0.4, -1,0 ); local_weather.create_effect_volume(3, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 20000.0, 11000.0, alpha, 0.0, alt+3000.0+alt_offset, -1, -1, -1, 0.4, -1,0 ,-1);
# some rain and reduced visibility in its core # some rain and reduced visibility in its core
x=0.0; y = 5000.0; x=0.0; y = 5000.0;
local_weather.create_effect_volume(3, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 20000.0, 8000.0, alpha, 0.0, alt+alt_offset, 10000.0, 0.1, -1, -1, -1,0 ); local_weather.create_effect_volume(3, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 20000.0, 8000.0, alpha, 0.0, alt+alt_offset, 10000.0, 0.1, -1, -1, -1,0,-1 );
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -1145,6 +1251,12 @@ local_weather.set_weather_station(blat +get_lat(x,y,phi), blon + get_lon(x,y,phi
# altitude for the lowest layer # altitude for the lowest layer
var alt = spread * 1000.0; var alt = spread * 1000.0;
# some weak Cumulus development
var strength = 0.1 + rand() * 0.1;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
# high Cirrus leading # high Cirrus leading
x = 2.0 * (rand()-0.5) * 1000; x = 2.0 * (rand()-0.5) * 1000;
@ -1165,6 +1277,11 @@ for (var i=0; i<6; i=i+1)
} }
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
} }
@ -1230,7 +1347,7 @@ local_weather.set_weather_station(blat +get_lat(x,y,phi), blon + get_lon(x,y,phi
# altitude for the lowest layer # altitude for the lowest layer
var alt = spread * 1000.0; var alt = spread * 1000.0;
var strength = 0.0;
# followed by random patches of Cirrostratus # followed by random patches of Cirrostratus
@ -1273,6 +1390,10 @@ var y = 8000.0;
local_weather.create_streak("Stratus",blat +get_lat(x,y,phi), blon+get_lon(x,y,phi), alt+alt_offset +5000.0,1000.0,30,0.0,0.2,20000.0,10,0.0,0.2,12000.0,alpha,1.0); local_weather.create_streak("Stratus",blat +get_lat(x,y,phi), blon+get_lon(x,y,phi), alt+alt_offset +5000.0,1000.0,30,0.0,0.2,20000.0,10,0.0,0.2,12000.0,alpha,1.0);
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -1339,7 +1460,7 @@ local_weather.set_weather_station(blat +get_lat(x,y,phi), blon + get_lon(x,y,phi
# altitude for the lowest layer # altitude for the lowest layer
var alt = spread * 1000.0 + local_weather.cloud_vertical_size_map["Nimbus"] * 0.5 * m_to_ft; var alt = spread * 1000.0 + local_weather.cloud_vertical_size_map["Nimbus"] * 0.5 * m_to_ft;
var strength = 0.0;
# closed Stratus layer # closed Stratus layer
@ -1364,12 +1485,18 @@ local_weather.create_streak("Nimbus",blat +get_lat(x,y,phi), blon+get_lon(x,y,ph
# some rain beneath the stratus # some rain beneath the stratus
x=0.0; y = -10000.0; x=0.0; y = -10000.0;
local_weather.create_effect_volume(3, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 20000.0, 10000.0, alpha, 0.0, alt+alt_offset+1000, vis * 0.7, 0.1, -1, -1, -1,0 ); local_weather.create_effect_volume(3, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 20000.0, 10000.0, alpha, 0.0, alt+alt_offset+1000, vis * 0.7, 0.1, -1, -1, -1,0 ,-1);
# heavier rain beneath the Nimbostratus # heavier rain beneath the Nimbostratus
x=0.0; y = 10000.0; x=0.0; y = 10000.0;
local_weather.create_effect_volume(3, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 20000.0, 10000.0, alpha, 0.0, alt+alt_offset, vis * 0.5, 0.3, -1, -1, -1,0 ); local_weather.create_effect_volume(3, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 20000.0, 10000.0, alpha, 0.0, alt+alt_offset, vis * 0.5, 0.3, -1, -1, -1,0,-1 );
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -1436,6 +1563,7 @@ local_weather.set_weather_station(blat +get_lat(x,y,phi), blon + get_lon(x,y,phi
# altitude for the lowest layer # altitude for the lowest layer
var alt = spread * 1000.0 + local_weather.cloud_vertical_size_map["Nimbus"] * 0.5 * m_to_ft; var alt = spread * 1000.0 + local_weather.cloud_vertical_size_map["Nimbus"] * 0.5 * m_to_ft;
var strength = 0.0;
# low Nimbostratus layer # low Nimbostratus layer
@ -1461,7 +1589,13 @@ local_weather.create_streak("Nimbus",blat +get_lat(x,y,phi), blon+get_lon(x,y,ph
# rain beneath the Nimbostratus # rain beneath the Nimbostratus
x=0.0; y = -5000.0; x=0.0; y = -5000.0;
local_weather.create_effect_volume(3, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 20000.0, 15000.0, alpha, 0.0, alt+alt_offset, vis * 0.5, 0.3, -1, -1, -1,0 ); local_weather.create_effect_volume(3, blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), 20000.0, 15000.0, alpha, 0.0, alt+alt_offset, vis * 0.5, 0.3, -1, -1, -1,0 ,-1);
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -1481,7 +1615,7 @@ tile_finished();
var set_gliders_sky_tile = func { var set_gliders_sky_tile = func {
setprop(lw~"tiles/code","glides_sky"); setprop(lw~"tiles/code","gliders_sky");
tile_start(); tile_start();
@ -1503,16 +1637,20 @@ calc_geo(blat);
# first weather info for tile center (lat, lon, visibility, temperature, dew point, pressure) # first weather info for tile center (lat, lon, visibility, temperature, dew point, pressure)
local_weather.set_weather_station(blat, blon, 35000.0, 20.0, 16.0, 1018 * hp_to_inhg); local_weather.set_weather_station(blat, blon, 35000.0, 20.0, 16.0, 1018 * hp_to_inhg);
# switch the placement of thermal effect volumes on: 1: constant lift 2: by function
setprop(lw~"tmp/generate-thermal-lift-flag",2);
var alt = 3000.0;
# add convective clouds # add convective clouds
var strength = 0.5; var strength = 0.5;
var n = int(4000 * strength); # calculate the number of placement tries from tile size 20x20km and strength var n = int(4000 * strength); # calculate the number of placement tries from tile size 20x20km and strength
local_weather.create_cumosys(blat,blon, 3000.0+alt_offset,n, 20000.0); local_weather.create_cumosys(blat,blon, alt+alt_offset,n, 20000.0);
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -1547,16 +1685,28 @@ calc_geo(blat);
# first weather info for tile center (lat, lon, visibility, temperature, dew point, pressure) # first weather info for tile center (lat, lon, visibility, temperature, dew point, pressure)
local_weather.set_weather_station(blat, blon, 45000.0, 20.0, 15.0, 1018 * hp_to_inhg); local_weather.set_weather_station(blat, blon, 45000.0, 20.0, 15.0, 1018 * hp_to_inhg);
# switch the placement of thermal effect volumes on: 1: constant lift 2: by function 3: blue local_weather.generate_thermal_lift_flag = 3;
setprop(lw~"tmp/generate-thermal-lift-flag",3);
var alt = 5000.0;
# add convective clouds # add convective clouds
# set flag to blue thermal generation
if (local_weather.generate_thermal_lift_flag !=0)
{local_weather.generate_thermal_lift_flag = 3;}
var strength = 0.9; var strength = 0.9;
var n = int(4000 * strength); # calculate the number of placement tries from tile size 20x20km and strength var n = int(4000 * strength); # calculate the number of placement tries from tile size 20x20km and strength
local_weather.create_cumosys(blat,blon, 5000.0+alt_offset,n, 20000.0); local_weather.create_cumosys(blat,blon, 5000.0+alt_offset,n, 20000.0);
# set flag back to normal thermal generation
if (local_weather.generate_thermal_lift_flag !=0)
{local_weather.generate_thermal_lift_flag = 0;}
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
@ -1723,6 +1873,10 @@ for (var i = n; i <n_layers; i=i+1)
setprop(lw~"METAR/available-flag",0); setprop(lw~"METAR/available-flag",0);
# store convective altitude and strength
append(weather_dynamics.tile_convective_altitude,alt_low);
append(weather_dynamics.tile_convective_strength,strength);
tile_finished(); tile_finished();
} }
@ -1909,6 +2063,41 @@ local_weather.create_streak("Cirrocumulus (cloudlet)",lat+get_lat(x,y,phi), lon+
} }
var create_4_8_cirrocumulus_streaks = func (lat, lon, alt, alpha) {
var phi = alpha * math.pi/180.0;
var beta = 90.0 + (rand() -0.5) * 30.0;
for (var i=0; i<2; i=i+1)
{
var x = 2.0 * (rand()-0.5) * 12000;
var y = 2.0 * (rand()-0.5) * 12000;
var tri = 1.5 + rand() * 1.5;
local_weather.create_streak("Cirrocumulus (cloudlet)",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt,300.0,10,700.0,0.1,400.0,30,700.0,0.1,400.0,alpha+beta,tri);
}
}
var create_4_8_altocumulus_perlucidus = func (lat, lon, alt, alpha) {
var phi = alpha * math.pi/180.0;
for (var i=0; i<20; i=i+1)
{
var x = 2.0 * (rand()-0.5) * 18000;
var y = 2.0 * (rand()-0.5) * 18000;
var beta = (rand() -0.5) * 180.0;
local_weather.create_streak("Altocumulus perlucidus",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt,300.0,4,1400.0,0.1,900.0,4,1400.0,0.1,900.0,alpha+beta,1.0);
}
}
var create_2_8_stratus = func (lat, lon, alt, alpha) { var create_2_8_stratus = func (lat, lon, alt, alpha) {
var phi = alpha * math.pi/180.0; var phi = alpha * math.pi/180.0;
@ -1992,12 +2181,12 @@ var create_2_8_cirrocumulus = func (lat, lon, alt, alpha) {
var phi = alpha * math.pi/180.0; var phi = alpha * math.pi/180.0;
for (var i=0; i<3; i=i+1) for (var i=0; i<25; i=i+1)
{ {
var x = 2.0 * (rand()-0.5) * 12000; var x = 2.0 * (rand()-0.5) * 18000;
var y = 2.0 * (rand()-0.5) * 12000; var y = 2.0 * (rand()-0.5) * 18000;
var beta = (rand() -0.5) * 180.0; var beta = (rand() -0.5) * 180.0;
local_weather.create_streak("Cirrocumulus (cloudlet)",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt,300.0,3,4000.0,0.2,1000.0,3,4000.0,0.2,1000.0,alpha+beta,1.0); local_weather.create_streak("Cirrocumulus (cloudlet)",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt,300.0,3,600.0,0.1,500.0,3,600.0,0.1,500.0,alpha+beta,1.0);
} }
@ -2028,14 +2217,14 @@ var beta = (rand() -0.5) * 60.0;
var alt_offset = 0.5 * local_weather.cloud_vertical_size_map["Cumulus"] * ft_to_m; var alt_offset = 0.5 * local_weather.cloud_vertical_size_map["Cumulus"] * ft_to_m;
local_weather.create_streak("Congestus",lat+get_lat(x,y+7500,phi), lon+get_lon(x,y+7500,phi), alt + alt_offset,500.0,12,1000.0,0.1,400.0,15,1000.0,0.1,400.0,alpha+90.0+beta,tri); local_weather.create_streak("Stratocumulus",lat+get_lat(x,y+7500,phi), lon+get_lon(x,y+7500,phi), alt + alt_offset,500.0,12,1000.0,0.1,400.0,15,1000.0,0.1,400.0,alpha+90.0+beta,tri);
local_weather.create_streak("Congestus",lat+get_lat(x,y-7500,phi), lon+get_lon(x,y-7500,phi), alt + alt_offset,500.0,12,1000.0,0.1,400.0,15,1000.0,0.1,400.0,alpha+270.0+beta,tri); local_weather.create_streak("Stratocumulus",lat+get_lat(x,y-7500,phi), lon+get_lon(x,y-7500,phi), alt + alt_offset,500.0,12,1000.0,0.1,400.0,15,1000.0,0.1,400.0,alpha+270.0+beta,tri);
local_weather.create_streak("Congestus bottom",lat+get_lat(x,y+5250,phi), lon+get_lon(x,y+5250,phi), alt,0.0,10,700.0,0.2,400.0,15,700.0,0.0,400.0,alpha+90.0+beta,tri); local_weather.create_streak("Stratocumulus bottom",lat+get_lat(x,y+5250,phi), lon+get_lon(x,y+5250,phi), alt,0.0,10,700.0,0.2,400.0,15,700.0,0.0,400.0,alpha+90.0+beta,tri);
local_weather.create_streak("Congestus bottom",lat+get_lat(x,y-5250,phi), lon+get_lon(x,y-5250,phi), alt,0.0,10,700.0,0.2,400.0,15,700.0,0.0,400.0,alpha+270.0+beta,tri); local_weather.create_streak("Stratocumulus bottom",lat+get_lat(x,y-5250,phi), lon+get_lon(x,y-5250,phi), alt,0.0,10,700.0,0.2,400.0,15,700.0,0.0,400.0,alpha+270.0+beta,tri);
} }
@ -2060,7 +2249,7 @@ append(elat, lat); append(elon, lon); append(erad, 4000.0 * scale * 1.2);
# set precipitation, visibility, updraft and turbulence in the cloud # set precipitation, visibility, updraft and turbulence in the cloud
local_weather.create_effect_volume(1, lat, lon, 4000.0 * 0.7 * scale, 4000.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 600.0, 0.8, -1, 0.6, 15.0,1 ); local_weather.create_effect_volume(1, lat, lon, 4000.0 * 0.7 * scale, 4000.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 600.0, 0.8, -1, 0.6, 15.0,1 ,-1);
} }
@ -2083,7 +2272,7 @@ append(elat, lat); append(elon, lon); append(erad, 6000.0 * scale * 1.2);
# set precipitation, visibility, updraft and turbulence in the cloud # set precipitation, visibility, updraft and turbulence in the cloud
local_weather.create_effect_volume(1, lat, lon, 6000.0 * 0.7 * scale, 6000.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 500.0, 1.0, -1, 0.8, 20.0,1 ); local_weather.create_effect_volume(1, lat, lon, 6000.0 * 0.7 * scale, 6000.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 500.0, 1.0, -1, 0.8, 20.0,1,-1 );
} }
@ -2114,7 +2303,7 @@ local_weather.create_layer("Stratus (thin)", lat+get_lat(0,-4000,phi), lon+get_l
# set the exclusion region for the Cumulus layer # set the exclusion region for the Cumulus layer
append(elat, lat); append(elon, lon); append(erad, 7500.0 * scale * 1.2); append(elat, lat); append(elon, lon); append(erad, 7500.0 * scale * 1.2);
local_weather.create_effect_volume(1, lat, lon, 7500.0 * 0.7 * scale, 7500.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 500.0, 1.0, -1, 1.0, 25.0,1 ); local_weather.create_effect_volume(1, lat, lon, 7500.0 * 0.7 * scale, 7500.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 500.0, 1.0, -1, 1.0, 25.0,1,-1 );
} }

View file

@ -16,7 +16,7 @@ varying float fogFactor;
void main(void) void main(void)
{ {
float shade = 0.9; float shade = 0.8;
float cloud_height = 1000.0; float cloud_height = 1000.0;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
@ -35,8 +35,8 @@ void main(void)
// scaling in the homogeneous component of pos. // scaling in the homogeneous component of pos.
gl_Position = vec4(0.0, 0.0, 0.0, 1.0); gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
gl_Position.xyz = gl_Vertex.x * u; gl_Position.xyz = gl_Vertex.x * u;
gl_Position.xyz += gl_Vertex.y * r * 0.25; gl_Position.xyz += gl_Vertex.y * r * 0.35;
gl_Position.xyz += gl_Vertex.z * w * 0.25; gl_Position.xyz += gl_Vertex.z * w * 0.35;
//gl_Position.xyz += gl_Vertex.y * r * wScale; //gl_Position.xyz += gl_Vertex.y * r * wScale;
//gl_Position.xyz += gl_Vertex.z * w * hScale; //gl_Position.xyz += gl_Vertex.z * w * hScale;
gl_Position.xyz += gl_Color.xyz; gl_Position.xyz += gl_Color.xyz;

View file

@ -5,6 +5,11 @@
#version 120 #version 120
#define TEXTURE_MIP_LEVELS 10
#define TEXTURE_PIX_COUNT 1024 //pow(2,TEXTURE_MIP_LEVELS)
#define BINARY_SEARCH_COUNT 10
#define BILINEAR_SMOOTH_FACTOR 2.0
varying vec4 rawpos; varying vec4 rawpos;
varying vec4 ecPosition; varying vec4 ecPosition;
varying vec3 VNormal; varying vec3 VNormal;
@ -16,6 +21,7 @@ varying vec4 constantColor;
uniform sampler3D NoiseTex; uniform sampler3D NoiseTex;
uniform sampler2D BaseTex; uniform sampler2D BaseTex;
uniform sampler2D NormalTex; uniform sampler2D NormalTex;
uniform sampler2D QDMTex;
uniform float depth_factor; uniform float depth_factor;
uniform float tile_size; uniform float tile_size;
uniform float quality_level; // From /sim/rendering/quality-level uniform float quality_level; // From /sim/rendering/quality-level
@ -24,8 +30,96 @@ uniform vec3 night_color;
const float scale = 1.0; const float scale = 1.0;
int linear_search_steps = 10; int linear_search_steps = 10;
int GlobalIterationCount = 0;
int gIterationCap = 64;
float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds) void QDM(inout vec3 p, inout vec3 v)
{
const int MAX_LEVEL = TEXTURE_MIP_LEVELS;
const float NODE_COUNT = TEXTURE_PIX_COUNT;
const float TEXEL_SPAN_HALF = 1.0 / NODE_COUNT / 2.0;
float fDeltaNC = TEXEL_SPAN_HALF * depth_factor;
vec3 p2 = p;
float level = MAX_LEVEL;
vec2 dirSign = (sign(v.xy) + 1.0) * 0.5;
GlobalIterationCount = 0;
float d = 0.0;
while (level >= 0.0 && GlobalIterationCount < gIterationCap)
{
vec4 uv = vec4(p2.xyz, level);
d = texture2DLod(QDMTex, uv.xy, uv.w).w;
if (d > p2.z)
{
//predictive point of ray traversal
vec3 tmpP2 = p + v * d;
//current node count
float nodeCount = pow(2.0, (MAX_LEVEL - level));
//current and predictive node ID
vec4 nodeID = floor(vec4(p2.xy, tmpP2.xy)*nodeCount);
//check if we are crossing the current cell
if (nodeID.x != nodeID.z || nodeID.y != nodeID.w)
{
//calculate distance to nearest bound
vec2 a = p2.xy - p.xy;
vec2 p3 = (nodeID.xy + dirSign) / nodeCount;
vec2 b = p3.xy - p.xy;
vec2 dNC = (b.xy * p2.z) / a.xy;
//take the nearest cell
d = min(d,min(dNC.x, dNC.y))+fDeltaNC;
level++;
//use additional convergence speed-up
#ifdef USE_QDM_ASCEND_INTERVAL
if(frac(level*0.5) > EPSILON)
level++;
#elseif USE_QDM_ASCEND_CONST
level++;
#endif
}
p2 = p + v * d;
}
level--;
GlobalIterationCount++;
}
//
// Manual Bilinear filtering
//
float rayLength = length(p2.xy - p.xy) + fDeltaNC;
float dA = p2.z * (rayLength - BILINEAR_SMOOTH_FACTOR * TEXEL_SPAN_HALF) / rayLength;
float dB = p2.z * (rayLength + BILINEAR_SMOOTH_FACTOR * TEXEL_SPAN_HALF) / rayLength;
vec4 p2a = vec4(p + v * dA, 0.0);
vec4 p2b = vec4(p + v * dB, 0.0);
dA = texture2DLod(NormalTex, p2a.xy, p2a.w).w;
dB = texture2DLod(NormalTex, p2b.xy, p2b.w).w;
dA = abs(p2a.z - dA);
dB = abs(p2b.z - dB);
p2 = mix(p2a.xyz, p2b.xyz, dA / (dA + dB));
p = p2;
}
float ray_intersect_QDM(vec2 dp, vec2 ds)
{
vec3 p = vec3( dp, 0.0 );
vec3 v = vec3( ds, 1.0 );
QDM( p, v );
return p.z;
}
float ray_intersect_relief(vec2 dp, vec2 ds)
{ {
float size = 1.0 / float(linear_search_steps); float size = 1.0 / float(linear_search_steps);
float depth = 0.0; float depth = 0.0;
@ -34,7 +128,7 @@ float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds)
for(int i = 0; i < linear_search_steps - 1; ++i) for(int i = 0; i < linear_search_steps - 1; ++i)
{ {
depth += size; depth += size;
float t = step(0.95, texture2D(reliefMap, dp + ds * depth).a); float t = step(0.95, texture2D(NormalTex, dp + ds * depth).a);
if(best_depth > 0.996) if(best_depth > 0.996)
if(depth >= t) if(depth >= t)
best_depth = depth; best_depth = depth;
@ -46,7 +140,7 @@ float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds)
for(int i = 0; i < binary_search_steps; ++i) for(int i = 0; i < binary_search_steps; ++i)
{ {
size *= 0.5; size *= 0.5;
float t = step(0.95, texture2D(reliefMap, dp + ds * depth).a); float t = step(0.95, texture2D(NormalTex, dp + ds * depth).a);
if(depth >= t) if(depth >= t)
{ {
best_depth = depth; best_depth = depth;
@ -58,6 +152,14 @@ float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds)
return(best_depth); return(best_depth);
} }
float ray_intersect(vec2 dp, vec2 ds)
{
if ( quality_level >= 4.0 )
return ray_intersect_QDM( dp, ds );
else
return ray_intersect_relief( dp, ds );
}
void main (void) void main (void)
{ {
if ( quality_level >= 3.5 ) { if ( quality_level >= 3.5 ) {
@ -68,7 +170,7 @@ void main (void)
vec3 s = vec3(dot(V, VTangent), dot(V, VBinormal), dot(VNormal, -V)); vec3 s = vec3(dot(V, VTangent), dot(V, VBinormal), dot(VNormal, -V));
vec2 ds = s.xy * depth_factor / s.z; vec2 ds = s.xy * depth_factor / s.z;
vec2 dp = gl_TexCoord[0].st - ds; vec2 dp = gl_TexCoord[0].st - ds;
float d = ray_intersect(NormalTex, dp, ds); float d = ray_intersect(dp, ds);
vec2 uv = dp + ds * d; vec2 uv = dp + ds * d;
vec3 N = texture2D(NormalTex, uv).xyz * 2.0 - 1.0; vec3 N = texture2D(NormalTex, uv).xyz * 2.0 - 1.0;
@ -89,7 +191,7 @@ void main (void)
vec3 sl = normalize( vec3( dot( l, VTangent ), dot( l, VBinormal ), dot( -l, VNormal ) ) ); vec3 sl = normalize( vec3( dot( l, VTangent ), dot( l, VBinormal ), dot( -l, VNormal ) ) );
ds = sl.xy * depth_factor / sl.z; ds = sl.xy * depth_factor / sl.z;
dp -= ds * d; dp -= ds * d;
float dl = ray_intersect(NormalTex, dp, ds); float dl = ray_intersect(dp, ds);
if ( dl < d - 0.05 ) if ( dl < d - 0.05 )
shadow_factor = dot( constantColor.xyz, vec3( 1.0, 1.0, 1.0 ) ) * 0.25; shadow_factor = dot( constantColor.xyz, vec3( 1.0, 1.0, 1.0 ) ) * 0.25;
} }

View file

@ -71,4 +71,54 @@
<stretch>true</stretch> <stretch>true</stretch>
</empty> </empty>
</group> </group>
</PropertyList>
<group>
<layout>hbox</layout>
<default-padding>6</default-padding>
<empty>
<stretch>true</stretch>
</empty>
<button>
<legend>OK</legend>
<default>true</default>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<button>
<legend>Apply</legend>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
</button>
<button>
<legend>Reset</legend>
<equal>true</equal>
<binding>
<command>dialog-update</command>
</binding>
</button>
<button>
<legend>Cancel</legend>
<equal>true</equal>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
<empty>
<stretch>true</stretch>
</empty>
</group>
</PropertyList>

View file

@ -119,32 +119,32 @@
<halign>left</halign> <halign>left</halign>
<label>-180</label> <label>-180</label>
</text> </text>
<slider> <slider>
<width>75</width> <width>75</width>
<height>25</height> <height>25</height>
<min>-180</min> <min>-180</min>
<max>180</max> <max>180</max>
<property>/ai/models/wingman/controls/break-deg-rel</property> <property>/ai/models/wingman/controls/break-deg-rel</property>
<binding> <binding>
<command>dialog-apply</command> <command>dialog-apply</command>
</binding> </binding>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script> <script>
var v = getprop("/ai/models/wingman/controls/break-deg-rel"); var v = getprop("/ai/models/wingman/controls/break-deg-rel");
foreach (var c; props.globals.getNode("/ai/models").getChildren("wingman")){ foreach (var c; props.globals.getNode("/ai/models").getChildren("wingman")){
print("FFF ", v, " ", c.getNode("name").getValue()); print("FFF ", v, " ", c.getNode("name").getValue());
c.getNode("controls/break-deg-rel",1).setDoubleValue(v); c.getNode("controls/break-deg-rel",1).setDoubleValue(v);
} }
</script> </script>
</binding> </binding>
</slider> </slider>
<text> <text>
<halign>left</halign> <halign>left</halign>
<label>180</label> <label>180</label>
</text> </text>
</group> </group>
<text> <text>
@ -156,15 +156,8 @@
</group> </group>
</group> </group>
<group> <group>
<layout>hbox</layout> <layout>hbox</layout>
@ -182,6 +175,26 @@
</text> </text>
</group> </group>
<group>
<layout>hbox</layout>
<text>
<halign>left</halign>
<label>Set Formation</label>
</text>
<button>
<x>40</x>
<y>10</y>
<legend>Open/Close</legend>
<binding>
<command>nasal</command>
<script>formation.formation_dialog.toggle()</script>
</binding>
</button>
</group>
<empty> <empty>
<stretch>true</stretch> <stretch>true</stretch>
</empty> </empty>

View file

@ -33,7 +33,7 @@
<y>320</y> <y>320</y>
<width>100</width> <width>100</width>
<height>20</height> <height>20</height>
<min>25000.0</min> <min>29000.0</min>
<max>55000.0</max> <max>55000.0</max>
<property>/local-weather/config/distance-to-load-tile-m</property> <property>/local-weather/config/distance-to-load-tile-m</property>
<binding> <binding>

View file

@ -35,9 +35,6 @@
<value>Coldfront</value> <value>Coldfront</value>
<value>Warmfront</value> <value>Warmfront</value>
<value>Tropical</value> <value>Tropical</value>
<value>---</value>
<value>Glider's sky</value>
<value>Blue thermals</value>
<!--<value>Test tile</value>--> <!--<value>Test tile</value>-->
<binding> <binding>
<command>dialog-apply</command> <command>dialog-apply</command>
@ -104,7 +101,7 @@
<value>constant in tile</value> <value>constant in tile</value>
<value>aloft interpolated</value> <value>aloft interpolated</value>
<value>aloft waypoints</value> <value>aloft waypoints</value>
<!--<value>airmass interpolated</value>--> <!-- <value>airmass interpolated</value> -->
<binding> <binding>
<command>dialog-apply</command> <command>dialog-apply</command>
</binding> </binding>
@ -150,8 +147,8 @@
<y>150</y> <y>150</y>
<width>15</width> <width>15</width>
<height>15</height> <height>15</height>
<label>worker threads</label> <label>generate thermals</label>
<property>/local-weather/tmp/thread-flag</property> <property>/local-weather/config/generate-thermal-lift-flag</property>
<binding> <binding>
<command>dialog-apply</command> <command>dialog-apply</command>
</binding> </binding>
@ -162,8 +159,8 @@
<y>125</y> <y>125</y>
<width>15</width> <width>15</width>
<height>15</height> <height>15</height>
<label>asymmetric range</label> <label>debug output</label>
<property>/local-weather/tmp/asymmetric-tile-loading-flag</property> <property>/local-weather/config/debug-output-flag</property>
<binding> <binding>
<command>dialog-apply</command> <command>dialog-apply</command>
</binding> </binding>
@ -193,6 +190,18 @@
</binding> </binding>
</checkbox> </checkbox>
<checkbox>
<x>150</x>
<y>100</y>
<width>15</width>
<height>15</height>
<label>dynamical convection</label>
<property>/local-weather/config/dynamical-convection-flag</property>
<binding>
<command>dialog-apply</command>
</binding>
</checkbox>
<text> <text>
<x>10</x> <x>10</x>
<y>75</y> <y>75</y>
@ -250,7 +259,7 @@
<button> <button>
<x>45</x> <x>45</x>
<y>0</y> <y>0</y>
<legend>Clear clouds</legend> <legend>Clear / End</legend>
<!--<default>true</default>--> <!--<default>true</default>-->
<equal>true</equal> <equal>true</equal>
<binding> <binding>
@ -262,7 +271,7 @@
<button> <button>
<x>135</x> <x>135</x>
<y>0</y> <y>0</y>
<legend>Cancel</legend> <legend>Close</legend>
<equal>true</equal> <equal>true</equal>
<key>Esc</key> <key>Esc</key>
<binding> <binding>

View file

@ -260,6 +260,8 @@
<binding> <binding>
<command>nasal</command> <command>nasal</command>
<script> <script>
setprop("/sim/presets/parkpos", "");
if (!mode.airport.getBoolValue()) { if (!mode.airport.getBoolValue()) {
setprop("/sim/presets/airport-id", ""); setprop("/sim/presets/airport-id", "");
setprop("/sim/presets/runway", ""); setprop("/sim/presets/runway", "");

View file

@ -0,0 +1,90 @@
<?xml version="1.0"?>
<PropertyList>
<name>model-cockpit-view</name>
<x>5</x>
<y>3</y>
<layout>hbox</layout>
<default-padding>0</default-padding>
<color>
<enabled>false</enabled>
<red>0</red>
<green>0</green>
<blue>0</blue>
<alpha>0</alpha>
</color>
<button>
<legend>&lt;</legend>
<pref-width>20</pref-width>
<pref-height>20</pref-height>
<color>
<red>0.5</red>
<green>0.5</green>
<blue>0.5</blue>
<alpha>0.3</alpha>
</color>
<binding>
<command>nasal</command>
<script>model_cockpit_view.model_cockpit_view_handler.next(-1)</script>
</binding>
</button>
<button>
<legend>&gt;</legend>
<pref-width>20</pref-width>
<pref-height>20</pref-height>
<color>
<red>0.5</red>
<green>0.5</green>
<blue>0.5</blue>
<alpha>0.3</alpha>
</color>
<binding>
<command>nasal</command>
<script>model_cockpit_view.model_cockpit_view_handler.next(1)</script>
</binding>
</button>
<whatever>
<pref-width>6</pref-width>
</whatever>
<text>
<pref-width>0</pref-width>
<live>1</live>
<property>/sim/current-view/model-cockpit-view</property>
<color>
<red>1</red>
<green>1</green>
<blue>1</blue>
<alpha>1</alpha>
</color>
<font>
<name>HELVETICA_14</name>
</font>
</text>
<button>
<legend/>
<pref-width>200</pref-width>
<border>0</border>
<color>
<red>1</red>
<green>1</green>
<blue>1</blue>
<alpha>0</alpha>
</color>
<binding>
<command>nasal</command>
<script>
if (size(lsoview.model_cockpit_view_handler.list) &lt;= 1)
return;
var isopen = !!getprop("sim/gui/dialogs/model-cockpit-view/open");
var toggle = isopen ? "dialog-close" : "dialog-show";
fgcommand(toggle, props.Node.new({ "dialog-name": "model-cockpit-view" }));
</script>
</binding>
</button>
</PropertyList>

View file

@ -30,6 +30,8 @@ command interface /autopilot/route-manager/input:
var list = cmdarg().getNode("list"); var list = cmdarg().getNode("list");
var cmd = routem.getNode("input", 1); var cmd = routem.getNode("input", 1);
var route = routem.getNode("route", 1); var route = routem.getNode("route", 1);
var dep = routem.getNode("departure", 1);
var dest = routem.getNode("destination", 1);
var sel_index = func { var sel_index = func {
return int(selection.getValue()); return int(selection.getValue());
@ -59,8 +61,8 @@ command interface /autopilot/route-manager/input:
cmd.setValue("@delete" ~ sel_index()); cmd.setValue("@delete" ~ sel_index());
} }
var auto_route = func { var route = func {
cmd.setValue(); cmd.setValue("@route" ~ sel_index());
} }
var jump_to = func { var jump_to = func {
@ -88,10 +90,15 @@ command interface /autopilot/route-manager/input:
var departureRunways = dlg.getNode("departure-runways", 1); var departureRunways = dlg.getNode("departure-runways", 1);
var destRunways = dlg.getNode("destination-runways", 1); var destRunways = dlg.getNode("destination-runways", 1);
var sids = dlg.getNode("sids", 1);
var stars = dlg.getNode("stars", 1);
var updateRunways = func { var updateRunways = func {
var depIcao = routem.getNode("departure").getNode("airport").getValue(); var depIcao = dep.getNode("airport").getValue();
departureRunways.removeChildren("value"); departureRunways.removeChildren("value");
var currentRunway = dep.getNode("runway").getValue();
var foundCurrent = 0;
var apt = airportinfo(depIcao); var apt = airportinfo(depIcao);
if (apt != nil) { if (apt != nil) {
@ -99,11 +106,20 @@ command interface /autopilot/route-manager/input:
foreach (var rwy; keys(apt.runways)) { foreach (var rwy; keys(apt.runways)) {
departureRunways.getNode("value[" ~ i ~ "]", 1).setValue(rwy); departureRunways.getNode("value[" ~ i ~ "]", 1).setValue(rwy);
i += 1; i += 1;
if (rwy == currentRunway) {
foundCurrent = 1;
}
} }
} }
var destIcao = routem.getNode("destination").getNode("airport").getValue(); if (!foundCurrent) {
dep.getNode("runway").clearValue();
}
var destIcao = dest.getNode("airport").getValue();
destRunways.removeChildren("value"); destRunways.removeChildren("value");
currentRunway = dest.getNode("runway").getValue();
foundCurrent = 0;
var apt = airportinfo(destIcao); var apt = airportinfo(destIcao);
if (apt != nil) { if (apt != nil) {
@ -111,11 +127,68 @@ command interface /autopilot/route-manager/input:
foreach (var rwy; keys(apt.runways)) { foreach (var rwy; keys(apt.runways)) {
destRunways.getNode("value[" ~ i ~ "]", 1).setValue(rwy); destRunways.getNode("value[" ~ i ~ "]", 1).setValue(rwy);
i += 1; i += 1;
if (rwy == currentRunway) {
foundCurrent = 1;
}
} }
} }
if (!foundCurrent) {
dest.getNode("runway").clearValue();
}
print("updated runways");
gui.dialog_update("route-manager"); gui.dialog_update("route-manager");
} }
var updateSIDs = func {
sids.removeChildren("value");
var depIcao = dep.getNode("airport").getValue();
var rwy = dep.getNode("runway").getValue();
var apt = airportinfo(depIcao);
if (apt == nil or apt.runways[rwy] == nil) {
dep.getNode("sid").clearValue();
gui.dialog_update("route-manager", "sid");
return;
}
sids.getNode("value[0]", 1).setValue("(none)");
var i=1;
foreach (var s; apt.runways[rwy].sids) {
sids.getNode("value[" ~ i ~ "]", 1).setValue(s);
i += 1;
}
gui.dialog_update("route-manager", "sid");
}
var updateSTARs = func {
stars.removeChildren("value");
var icao = dest.getNode("airport").getValue();
var rwy = dest.getNode("runway").getValue();
var apt = airportinfo(icao);
if (apt == nil or apt.runways[rwy] == nil) {
dest.getNode("star").clearValue();
gui.dialog_update("route-manager", "star");
return;
}
var i=1;
stars.getNode("value[0]", 1).setValue("(none)");
foreach (var s; apt.runways[rwy].stars) {
stars.getNode("value[" ~ i ~ "]", 1).setValue(s);
i += 1;
}
gui.dialog_update("route-manager", "star");
}
# initialise departure values based on current position
cmd.setValue("@posinit");
updateRunways();
updateSIDs();
updateSTARs();
</open> </open>
<close> <close>
@ -189,6 +262,31 @@ command interface /autopilot/route-manager/input:
<property>/autopilot/route-manager/departure/runway</property> <property>/autopilot/route-manager/departure/runway</property>
<editable>false</editable> <editable>false</editable>
<properties>/sim/gui/dialogs/route-manager/departure-runways</properties> <properties>/sim/gui/dialogs/route-manager/departure-runways</properties>
<binding>
<command>dialog-apply</command>
<object-name>departure-runway</object-name>
</binding>
<binding>
<command>nasal</command>
<script>updateSIDs();</script>
</binding>
</combo>
<text>
<label>SID:</label>
</text>
<combo>
<name>sid</name>
<pref-width>100</pref-width>
<property>/autopilot/route-manager/departure/sid</property>
<editable>false</editable>
<properties>/sim/gui/dialogs/route-manager/sids</properties>
<binding>
<command>dialog-apply</command>
<object-name>sid</object-name>
</binding>
</combo> </combo>
</group> </group>
@ -229,6 +327,32 @@ command interface /autopilot/route-manager/input:
<property>/autopilot/route-manager/destination/runway</property> <property>/autopilot/route-manager/destination/runway</property>
<editable>false</editable> <editable>false</editable>
<properties>/sim/gui/dialogs/route-manager/destination-runways</properties> <properties>/sim/gui/dialogs/route-manager/destination-runways</properties>
<binding>
<command>dialog-apply</command>
<object-name>destination-runway</object-name>
</binding>
<binding>
<command>nasal</command>
<script>updateSTARs();</script>
</binding>
</combo>
<text>
<label>STAR:</label>
</text>
<combo>
<name>star</name>
<pref-width>100</pref-width>
<property>/autopilot/route-manager/destination/star</property>
<editable>false</editable>
<properties>/sim/gui/dialogs/route-manager/stars</properties>
<binding>
<command>dialog-apply</command>
<object-name>star</object-name>
</binding>
</combo> </combo>
</group> </group>
<!-- <!--
@ -341,6 +465,7 @@ command interface /autopilot/route-manager/input:
<pref-width>70</pref-width> <pref-width>70</pref-width>
<binding> <binding>
<command>dialog-apply</command> <command>dialog-apply</command>
<object-name>input</object-name>
</binding> </binding>
<binding> <binding>
<command>nasal</command> <command>nasal</command>
@ -389,6 +514,14 @@ command interface /autopilot/route-manager/input:
<script>remove()</script> <script>remove()</script>
</binding> </binding>
</button> </button>
<button>
<legend>Route</legend>
<binding>
<command>nasal</command>
<script>route()</script>
</binding>
</button>
<!-- <!--
<button> <button>
<legend>Auto-route</legend> <legend>Auto-route</legend>

View file

@ -457,9 +457,9 @@
</menu> </menu>
<menu> <menu>
<label>ATC/AI</label> <label>AI</label>
<item> <item>
<label>ATC Options</label> <label>AI Options</label>
<binding> <binding>
<command>dialog-show</command> <command>dialog-show</command>
<dialog-name>ai</dialog-name> <dialog-name>ai</dialog-name>
@ -576,6 +576,15 @@
</binding> </binding>
</item> </item>
<item>
<label>Reload HUD</label>
<binding>
<command>reinit</command>
<subsystem>hud</subsystem>
</binding>
</item>
<item> <item>
<label>Reload Panel</label> <label>Reload Panel</label>
<binding> <binding>

View file

@ -1313,13 +1313,16 @@ Shared parameters for various materials.
<path>Models/Buildings/red-barn.ac</path> <path>Models/Buildings/red-barn.ac</path>
<path>Models/Buildings/horse-stable.ac</path> <path>Models/Buildings/horse-stable.ac</path>
<path>Models/Buildings/cow-stable.ac</path> <path>Models/Buildings/cow-stable.ac</path>
<path>Models/Buildings/farmhouse1.ac</path> <path>Models/Agriculture/farmhouse1.ac</path>
<path>Models/Buildings/farmhouse2.ac</path> <path>Models/Agriculture/farmhouse2.ac</path>
<path>Models/Buildings/farmhouse3.ac</path> <path>Models/Agriculture/farmhouse3.ac</path>
<coverage-m2>750000</coverage-m2> <coverage-m2>750000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group>
<!-- Disabled to avoid a tremendous osg performance penalty when
deleting scenery tiles, caused by tens of thousands of shared
horse/cow objects. Need a better implementation!
<object-group> <object-group>
<range-m>1000</range-m> <range-m>1000</range-m>
<object> <object>
@ -1332,7 +1335,7 @@ Shared parameters for various materials.
<coverage-m2>300000</coverage-m2> <coverage-m2>300000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group> -->
<wood-coverage>1000000.0</wood-coverage> <wood-coverage>1000000.0</wood-coverage>
<wood-size>20000.0</wood-size> <wood-size>20000.0</wood-size>
<tree-density>4000.0</tree-density> <tree-density>4000.0</tree-density>
@ -1376,13 +1379,16 @@ Shared parameters for various materials.
<path>Models/Buildings/red-barn.ac</path> <path>Models/Buildings/red-barn.ac</path>
<path>Models/Buildings/horse-stable.ac</path> <path>Models/Buildings/horse-stable.ac</path>
<path>Models/Buildings/cow-stable.ac</path> <path>Models/Buildings/cow-stable.ac</path>
<path>Models/Buildings/farmhouse1.ac</path> <path>Models/Agriculture/farmhouse1.ac</path>
<path>Models/Buildings/farmhouse2.ac</path> <path>Models/Agriculture/farmhouse2.ac</path>
<path>Models/Buildings/farmhouse3.ac</path> <path>Models/Agriculture/farmhouse3.ac</path>
<coverage-m2>750000</coverage-m2> <coverage-m2>750000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group>
<!-- Disabled to avoid a tremendous osg performance penalty when
deleting scenery tiles, caused by tens of thousands of shared
horse/cow objects. Need a better implementation!
<object-group> <object-group>
<range-m>1000</range-m> <range-m>1000</range-m>
<object> <object>
@ -1395,7 +1401,7 @@ Shared parameters for various materials.
<coverage-m2>300000</coverage-m2> <coverage-m2>300000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group> -->
<wood-coverage>500000.0</wood-coverage> <wood-coverage>500000.0</wood-coverage>
<tree-texture>Textures/Trees/mixed-summer.png</tree-texture> <tree-texture>Textures/Trees/mixed-summer.png</tree-texture>
<tree-varieties>8</tree-varieties> <tree-varieties>8</tree-varieties>
@ -1437,13 +1443,16 @@ Shared parameters for various materials.
<path>Models/Buildings/red-barn.ac</path> <path>Models/Buildings/red-barn.ac</path>
<path>Models/Buildings/horse-stable.ac</path> <path>Models/Buildings/horse-stable.ac</path>
<path>Models/Buildings/cow-stable.ac</path> <path>Models/Buildings/cow-stable.ac</path>
<path>Models/Buildings/farmhouse1.ac</path> <path>Models/Agriculture/farmhouse1.ac</path>
<path>Models/Buildings/farmhouse2.ac</path> <path>Models/Agriculture/farmhouse2.ac</path>
<path>Models/Buildings/farmhouse3.ac</path> <path>Models/Agriculture/farmhouse3.ac</path>
<coverage-m2>750000</coverage-m2> <coverage-m2>750000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group>
<!-- Disabled to avoid a tremendous osg performance penalty when
deleting scenery tiles, caused by tens of thousands of shared
horse/cow objects. Need a better implementation!
<object-group> <object-group>
<range-m>1000</range-m> <range-m>1000</range-m>
<object> <object>
@ -1456,7 +1465,7 @@ Shared parameters for various materials.
<coverage-m2>300000</coverage-m2> <coverage-m2>300000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group> -->
<wood-coverage>500000.0</wood-coverage> <wood-coverage>500000.0</wood-coverage>
<wood-size>20000.0</wood-size> <wood-size>20000.0</wood-size>
<tree-density>5000.0</tree-density> <tree-density>5000.0</tree-density>
@ -2133,13 +2142,16 @@ Shared parameters for various materials.
<path>Models/Buildings/red-barn.ac</path> <path>Models/Buildings/red-barn.ac</path>
<path>Models/Buildings/horse-stable.ac</path> <path>Models/Buildings/horse-stable.ac</path>
<path>Models/Buildings/cow-stable.ac</path> <path>Models/Buildings/cow-stable.ac</path>
<path>Models/Buildings/farmhouse1.ac</path> <path>Models/Agriculture/farmhouse1.ac</path>
<path>Models/Buildings/farmhouse2.ac</path> <path>Models/Agriculture/farmhouse2.ac</path>
<path>Models/Buildings/farmhouse3.ac</path> <path>Models/Agriculture/farmhouse3.ac</path>
<coverage-m2>750000</coverage-m2> <coverage-m2>750000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group>
<!-- Disabled to avoid a tremendous osg performance penalty when
deleting scenery tiles, caused by tens of thousands of shared
horse/cow objects. Need a better implementation!
<object-group> <object-group>
<range-m>1000</range-m> <range-m>1000</range-m>
<object> <object>
@ -2152,7 +2164,7 @@ Shared parameters for various materials.
<coverage-m2>300000</coverage-m2> <coverage-m2>300000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group> -->
<wood-coverage>1000000.0</wood-coverage> <wood-coverage>1000000.0</wood-coverage>
<wood-size>20000.0</wood-size> <wood-size>20000.0</wood-size>
<tree-density>4000.0</tree-density> <tree-density>4000.0</tree-density>
@ -2195,13 +2207,16 @@ Shared parameters for various materials.
<path>Models/Buildings/red-barn.ac</path> <path>Models/Buildings/red-barn.ac</path>
<path>Models/Buildings/horse-stable.ac</path> <path>Models/Buildings/horse-stable.ac</path>
<path>Models/Buildings/cow-stable.ac</path> <path>Models/Buildings/cow-stable.ac</path>
<path>Models/Buildings/farmhouse1.ac</path> <path>Models/Agriculture/farmhouse1.ac</path>
<path>Models/Buildings/farmhouse2.ac</path> <path>Models/Agriculture/farmhouse2.ac</path>
<path>Models/Buildings/farmhouse3.ac</path> <path>Models/Agriculture/farmhouse3.ac</path>
<coverage-m2>750000</coverage-m2> <coverage-m2>750000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group>
<!-- Disabled to avoid a tremendous osg performance penalty when
deleting scenery tiles, caused by tens of thousands of shared
horse/cow objects. Need a better implementation!
<object-group> <object-group>
<range-m>1000</range-m> <range-m>1000</range-m>
<object> <object>
@ -2214,7 +2229,7 @@ Shared parameters for various materials.
<coverage-m2>300000</coverage-m2> <coverage-m2>300000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group> -->
<wood-coverage>150000.0</wood-coverage> <wood-coverage>150000.0</wood-coverage>
<wood-size>10000.0</wood-size> <wood-size>10000.0</wood-size>
<tree-density>5000.0</tree-density> <tree-density>5000.0</tree-density>
@ -2257,13 +2272,16 @@ Shared parameters for various materials.
<path>Models/Buildings/red-barn.ac</path> <path>Models/Buildings/red-barn.ac</path>
<path>Models/Buildings/horse-stable.ac</path> <path>Models/Buildings/horse-stable.ac</path>
<path>Models/Buildings/cow-stable.ac</path> <path>Models/Buildings/cow-stable.ac</path>
<path>Models/Buildings/farmhouse1.ac</path> <path>Models/Agriculture/farmhouse1.ac</path>
<path>Models/Buildings/farmhouse2.ac</path> <path>Models/Agriculture/farmhouse2.ac</path>
<path>Models/Buildings/farmhouse3.ac</path> <path>Models/Agriculture/farmhouse3.ac</path>
<coverage-m2>750000</coverage-m2> <coverage-m2>750000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group>
<!-- Disabled to avoid a tremendous osg performance penalty when
deleting scenery tiles, caused by tens of thousands of shared
horse/cow objects. Need a better implementation!
<object-group> <object-group>
<range-m>1000</range-m> <range-m>1000</range-m>
<object> <object>
@ -2276,7 +2294,7 @@ Shared parameters for various materials.
<coverage-m2>300000</coverage-m2> <coverage-m2>300000</coverage-m2>
<heading-type>random</heading-type> <heading-type>random</heading-type>
</object> </object>
</object-group> </object-group> -->
<wood-coverage>150000.0</wood-coverage> <wood-coverage>150000.0</wood-coverage>
<wood-size>10000.0</wood-size> <wood-size>10000.0</wood-size>
<tree-density>5000.0</tree-density> <tree-density>5000.0</tree-density>

View file

@ -249,10 +249,8 @@ Started September 2000 by David Megginson, david@megginson.com
<path>Aircraft/Generic/Panels/generic-trans-mini-panel.xml</path> <path>Aircraft/Generic/Panels/generic-trans-mini-panel.xml</path>
</panel_2> </panel_2>
<hud> <hud>
<path>Huds/Default/default.xml</path> <path n="1">Huds/default.xml</path> <!-- new HUD -->
<path>Huds/NTPS.xml</path> <!-- new HUD --> <visibility n="1" type="bool">false</visibility> <!-- new HUD -->
<visibility type="bool">false</visibility>
<visibility type="bool">false</visibility> <!-- new HUD -->
<font> <font>
<name type="string">Helvetica.txf</name> <name type="string">Helvetica.txf</name>
<size type="float">8</size> <size type="float">8</size>
@ -598,7 +596,7 @@ Started September 2000 by David Megginson, david@megginson.com
</atc> </atc>
<ai-traffic> <ai-traffic>
<enabled type="bool" userarchive="y">true</enabled> <enabled type="bool" userarchive="y">false</enabled>
<level type="int" userarchive="y">1</level> <level type="int" userarchive="y">1</level>
</ai-traffic> </ai-traffic>
@ -618,6 +616,7 @@ Started September 2000 by David Megginson, david@megginson.com
<!-- <scenario>aircraft_demo</scenario> --> <!-- <scenario>aircraft_demo</scenario> -->
<!-- <scenario>refueling_demo</scenario> --> <!-- <scenario>refueling_demo</scenario> -->
<!-- <scenario>lead_aircraft</scenario> --> <!-- <scenario>lead_aircraft</scenario> -->
<!-- <scenario>vinson_demo</scenario> -->
</ai> </ai>
<multiplay> <multiplay>