1
0
Fork 0

Merge branch 'master' into work

This commit is contained in:
Alexis 2012-08-26 18:51:37 +02:00
commit 8b46328515
75 changed files with 52000 additions and 3981 deletions

View file

@ -51,7 +51,7 @@
</marker-beacon>
<heading-indicator>
<name>heading-indicator</name>
<name>heading-indicator-dg</name>
<number>0</number>
<suction>/systems/vacuum/suction-inhg</suction>
</heading-indicator>

View file

@ -335,9 +335,6 @@ electrical_bus_2 = func() {
var bus_volts = vbus_volts;
var load = 0.0;
# Turn Coordinator Power
setprop("/systems/electrical/outputs/turn-coordinator", bus_volts);
# Map Lights Power
if ( getprop("/controls/switches/nav-lights" ) ) {
setprop("/systems/electrical/outputs/map-lights", bus_volts);
@ -404,6 +401,12 @@ avionics_bus_1 = func() {
bus_volts = ebus1_volts;
}
# Turn Coordinator Power
setprop("/systems/electrical/outputs/turn-coordinator", bus_volts);
# Directional Gyro Power
setprop("/systems/electrical/outputs/DG", bus_volts);
# Avionics Fan Power
setprop("/systems/electrical/outputs/avionics-fan", bus_volts);

View file

@ -0,0 +1,125 @@
<?xml version="1.0"?>
<!--
**********************************************************************
instrumentation.xml
c172p instrumentation configuration. This file selects the
instrumentation modules that should be available.
You can have several instances of the same instrument type.
The value inside the name tag becomes the node in the property tree.
If two instruments have the same name you must use the number tag
to separate them. They become name[number] in the property tree.
Some instruments have additional configuration tags like static-port
and pitot-port. The static- and pitot-ports (and any other system that
an instrument depend on) have to be configured in the systems
configuration file: generic-systems.xml
The values in this file are the default values. If any configuration
tags are omitted in an aircraft specific version of this configuration
file, these values will be used (they are hardcoded).
**********************************************************************
-->
<PropertyList>
<adf>
<name>adf</name>
<number>0</number>
</adf>
<airspeed-indicator>
<name>airspeed-indicator</name>
<number>0</number>
<total-pressure>/systems/pitot/total-pressure-inhg</total-pressure>
<static-pressure>/systems/static/pressure-inhg</static-pressure>
</airspeed-indicator>
<altimeter>
<name>altimeter</name>
<number>0</number>
<static-pressure>/systems/static/pressure-inhg</static-pressure>
<quantum>0</quantum>
<tau>0</tau>
</altimeter>
<attitude-indicator>
<name>attitude-indicator</name>
<number>0</number>
<suction>/systems/vacuum/suction-inhg</suction>
</attitude-indicator>
<clock>
<name>clock</name>
<number>0</number>
</clock>
<dme>
<name>dme</name>
<number>0</number>
</dme>
<altimeter>
<name>encoder</name>
<number>0</number>
<static-pressure>/systems/static/pressure-inhg</static-pressure>
<quantum>10</quantum>
<tau>0.1</tau>
</altimeter>
<marker-beacon>
<name>marker-beacon</name>
<number>0</number>
</marker-beacon>
<heading-indicator-dg>
<name>heading-indicator</name>
<number>0</number>
<suction>/systems/vacuum/suction-inhg</suction>
</heading-indicator-dg>
<KT-70>
<name>kt-70</name>
<number>0</number>
</KT-70>
<magnetic-compass>
<name>magnetic-compass</name>
<number>0</number>
</magnetic-compass>
<nav-radio>
<name>nav</name>
<number>0</number>
</nav-radio>
<nav-radio>
<name>nav</name>
<number>1</number>
</nav-radio>
<slip-skid-ball>
<name>slip-skid-ball</name>
<number>0</number>
</slip-skid-ball>
<transponder>
<name>transponder</name>
<number>0</number>
<mode-c-altitude>/instrumentation/encoder/mode-c-alt-ft</mode-c-altitude>
</transponder>
<turn-indicator>
<name>turn-indicator</name>
<number>0</number>
</turn-indicator>
<vertical-speed-indicator>
<name>vertical-speed-indicator</name>
<number>0</number>
<static-pressure>/systems/static/pressure-inhg</static-pressure>
</vertical-speed-indicator>
</PropertyList>

View file

@ -104,6 +104,11 @@
<!-- Electrical Bus 2 Outputs -->
<output>
<name>Directional Gyro</name>
<prop>/systems/electrical/outputs/DG</prop>
</output>
<output>
<name>Turn Coordinator Power</name>
<prop>/systems/electrical/outputs/turn-coordinator</prop>
@ -341,6 +346,14 @@
<!-- connect bus 2 outputs -->
<connector>
<input>Electrical Bus 2</input>
<output>Directional Gyro</output>
<switch>
<prop>/controls/circuit-breakers/directional-gyro</prop>
</switch>
</connector>
<connector>
<input>Electrical Bus 2</input>
<output>Turn Coordinator Power</output>

View file

@ -128,7 +128,9 @@ Started October 23 2001 by John Check, fgpanels@rockfish.net
</flight-recorder>
<menubar include="Dialogs/c172p-menu.xml"/>
<instrumentation n="0">
<path>Aircraft/c172p/Systems/instrumentation.xml</path>
</instrumentation>
</sim>
<!-- trim for level cruise -->
@ -284,6 +286,14 @@ Started October 23 2001 by John Check, fgpanels@rockfish.net
</weight>
</payload>
<limits>
<mass-and-balance>
<maximum-ramp-mass-lbs>2407</maximum-ramp-mass-lbs>
<maximum-takeoff-mass-lbs>2400</maximum-takeoff-mass-lbs>
<maximum-landing-mass-lbs>2400</maximum-landing-mass-lbs>
</mass-and-balance>
</limits>
<input>
<keyboard>
<key n="76">

View file

@ -46,6 +46,8 @@ effect : The effect to be used for this material. (default:
ambient, diffuse, specular, emissive, and shininess are copied into the
parameter section of the effect created for this material.
parameters : Additional parameters to be used in the effect. See README.effects for format information.
wrapu : True if the texture should repeat horizontally over a surface, false if
it should not repeat (default: true).

42222
Docs/getstart-fr.pdf Normal file

File diff suppressed because it is too large Load diff

View file

@ -91,7 +91,7 @@
<terrain_alt><use>/environment/mean-terrain-elevation-m</use></terrain_alt>
<overcast><use>/rendering/scene/overcast</use></overcast>
<eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt>
<mysnow_level><use>/environment/mysnow-level-m</use></mysnow_level>
<snow_level><use>/environment/snow-level-m</use></snow_level>
<dust_cover_factor><use>/environment/surface/dust-cover-factor</use></dust_cover_factor>
<fogtype><use>/sim/rendering/shaders/skydome</use></fogtype>
<fogstructure><use>/environment/fog-structure</use></fogstructure>

View file

@ -2,11 +2,39 @@
<PropertyList>
<name>Effects/display</name>
<parameters>
<exposure type="float"><use>/sim/rendering/rembrandt/exposure</use></exposure>
<show-buffers type="bool"><use>/sim/rendering/rembrandt/show-buffers</use></show-buffers>
<bloom type="bool"><use>/sim/rendering/rembrandt/bloom</use></bloom>
<bloom-strength type="float"><use>/sim/rendering/rembrandt/bloom-strength</use></bloom-strength>
<bloom-buffers type="bool"><use>/sim/rendering/rembrandt/bloom-buffers</use></bloom-buffers>
<texture n="0">
<image>Textures\noise_tex.jpg</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<texture n="1">
<image>Textures\film-dirt.png</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<cinema>
<vignette><use>/sim/rendering/rembrandt/cinema/vignette</use></vignette>
<inner-circle><use>/sim/rendering/rembrandt/cinema/inner-circle</use></inner-circle>
<outer-circle><use>/sim/rendering/rembrandt/cinema/outer-circle</use></outer-circle>
<color-shift><use>/sim/rendering/rembrandt/cinema/color-shift</use></color-shift>
<red-shift><use>/sim/rendering/rembrandt/cinema/red-shift</use></red-shift>
<green-shift><use>/sim/rendering/rembrandt/cinema/green-shift</use></green-shift>
<blue-shift><use>/sim/rendering/rembrandt/cinema/blue-shift</use></blue-shift>
<distortion><use>/sim/rendering/rembrandt/cinema/distortion</use></distortion>
<distortion-factor><use>/sim/rendering/rembrandt/cinema/distortion-factor</use></distortion-factor>
<color-fringe><use>/sim/rendering/rembrandt/cinema/color-fringe</use></color-fringe>
<color-fringe-factor><use>/sim/rendering/rembrandt/cinema/color-fringe-factor</use></color-fringe-factor>
<film-wear><use>/sim/rendering/rembrandt/cinema/film-wear</use></film-wear>
</cinema>
<buffer-nw-enabled><use>/sim/rendering/rembrandt/debug-buffer[0]/enabled</use></buffer-nw-enabled>
<buffer-nw-name><use>/sim/rendering/rembrandt/debug-buffer[0]/name</use></buffer-nw-name>
@ -17,6 +45,236 @@
<buffer-se-enabled><use>/sim/rendering/rembrandt/debug-buffer[3]/enabled</use></buffer-se-enabled>
<buffer-se-name><use>/sim/rendering/rembrandt/debug-buffer[3]/name</use></buffer-se-name>
</parameters>
<technique n="9">
<predicate>
<and>
<property>/sim/rendering/rembrandt/night-vision</property>
<equal>
<value type="float">0.0</value>
<float-property>/sim/rendering/rembrandt/show-buffers</float-property>
</equal>
</and>
</predicate>
<pass>
<render-bin>
<bin-number>99999</bin-number>
<bin-name>RenderBin</bin-name>
</render-bin>
<texture-unit>
<unit>0</unit>
<type>buffer</type>
<name>lighting</name>
</texture-unit>
<texture-unit>
<unit>1</unit>
<type>buffer</type>
<name>bloom-3</name>
</texture-unit>
<texture-unit>
<unit>2</unit>
<type>buffer</type>
<name>spec-emis</name>
</texture-unit>
<texture-unit>
<unit>3</unit>
<type>buffer</type>
<name>diffuse</name>
</texture-unit>
<texture-unit>
<unit>4</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>
<program>
<vertex-shader>Shaders/fullscreen.vert</vertex-shader>
<fragment-shader>Shaders/night-vision.frag</fragment-shader>
</program>
<uniform>
<name>lighting_tex</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>bloom_tex</name>
<type>sampler-2d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>spec_emis_tex</name>
<type>sampler-2d</type>
<value type="int">2</value>
</uniform>
<uniform>
<name>color_tex</name>
<type>sampler-2d</type>
<value type="int">3</value>
</uniform>
<uniform>
<name>noise_tex</name>
<type>sampler-2d</type>
<value type="int">4</value>
</uniform>
<uniform>
<name>bloomEnabled</name>
<type>bool</type>
<value type="bool"><use>bloom</use></value>
</uniform>
<uniform>
<name>bloomStrength</name>
<type>float</type>
<value><use>bloom-strength</use></value>
</uniform>
<uniform>
<name>bloomBuffers</name>
<type>bool</type>
<value><use>bloom-buffers</use></value>
</uniform>
</pass>
</technique>
<technique n="10">
<predicate>
<and>
<or>
<property>/sim/rendering/rembrandt/cinema/vignette</property>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
</or>
<equal>
<value type="float">0.0</value>
<float-property>/sim/rendering/rembrandt/show-buffers</float-property>
</equal>
</and>
</predicate>
<pass>
<render-bin>
<bin-number>99999</bin-number>
<bin-name>RenderBin</bin-name>
</render-bin>
<texture-unit>
<unit>0</unit>
<type>buffer</type>
<name>lighting</name>
</texture-unit>
<texture-unit>
<unit>1</unit>
<type>buffer</type>
<name>bloom-3</name>
</texture-unit>
<texture-unit>
<unit>2</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>
<program>
<vertex-shader>Shaders/fullscreen.vert</vertex-shader>
<fragment-shader>Shaders/cinema.frag</fragment-shader>
</program>
<uniform>
<name>lighting_tex</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>bloom_tex</name>
<type>sampler-2d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>film_tex</name>
<type>sampler-2d</type>
<value type="int">2</value>
</uniform>
<uniform>
<name>bloomEnabled</name>
<type>bool</type>
<value type="bool"><use>bloom</use></value>
</uniform>
<uniform>
<name>bloomStrength</name>
<type>float</type>
<value><use>bloom-strength</use></value>
</uniform>
<uniform>
<name>bloomBuffers</name>
<type>bool</type>
<value><use>bloom-buffers</use></value>
</uniform>
<uniform>
<name>vignette</name>
<type>bool</type>
<value><use>cinema/vignette</use></value>
</uniform>
<uniform>
<name>innerCircle</name>
<type>float</type>
<value><use>cinema/inner-circle</use></value>
</uniform>
<uniform>
<name>outerCircle</name>
<type>float</type>
<value><use>cinema/outer-circle</use></value>
</uniform>
<uniform>
<name>colorShift</name>
<type>bool</type>
<value><use>cinema/color-shift</use></value>
</uniform>
<uniform>
<name>redShift</name>
<type>float-vec3</type>
<value><use>cinema/red-shift</use></value>
</uniform>
<uniform>
<name>greenShift</name>
<type>float-vec3</type>
<value><use>cinema/green-shift</use></value>
</uniform>
<uniform>
<name>blueShift</name>
<type>float-vec3</type>
<value><use>cinema/blue-shift</use></value>
</uniform>
<uniform>
<name>distortion</name>
<type>bool</type>
<value><use>cinema/distortion</use></value>
</uniform>
<uniform>
<name>distortionFactor</name>
<type>float-vec3</type>
<value><use>cinema/distortion-factor</use></value>
</uniform>
<uniform>
<name>colorFringe</name>
<type>bool</type>
<value><use>cinema/color-fringe</use></value>
</uniform>
<uniform>
<name>colorFringeFactor</name>
<type>float</type>
<value><use>cinema/color-fringe-factor</use></value>
</uniform>
<uniform>
<name>filmWear</name>
<type>bool</type>
<value><use>cinema/film-wear</use></value>
</uniform>
</pass>
</technique>
<technique n="11">
<pass>
<render-bin>
@ -89,11 +347,6 @@
<type>sampler-2d</type>
<value type="int">5</value>
</uniform>
<uniform>
<name>exposure</name>
<type>float</type>
<value type="float"><use>exposure</use></value>
</uniform>
<uniform>
<name>showBuffers</name>
<type>bool</type>

View file

@ -8,24 +8,7 @@
<g_sample_rad type="float">0.03</g_sample_rad>
<random_size type="float">800.0</random_size>
</parameters>
<technique n="10">
<predicate>
<and>
<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>
<extension-supported>GL_EXT_gpu_shader4</extension-supported>
</and>
</predicate>
<technique n="11">
<pass>
<texture-unit>
<unit>0</unit>
@ -98,77 +81,4 @@
</uniform>
</pass>
</technique>
<technique n="11">
<pass>
<texture-unit>
<unit>0</unit>
<type>buffer</type>
<name>depth</name>
</texture-unit>
<texture-unit>
<unit>1</unit>
<type>buffer</type>
<name>normal</name>
</texture-unit>
<texture-unit>
<unit>2</unit>
<type>buffer</type>
<name>spec-emis</name>
</texture-unit>
<texture-unit>
<unit>3</unit>
<type>noise</type>
</texture-unit>
<program>
<vertex-shader>Shaders/ssao.vert</vertex-shader>
<fragment-shader>Shaders/ssao-ati.frag</fragment-shader>
<fragment-shader>Shaders/gbuffer-functions.frag</fragment-shader>
</program>
<uniform>
<name>depth_tex</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>normal_tex</name>
<type>sampler-2d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>spec_emis_tex</name>
<type>sampler-2d</type>
<value type="int">2</value>
</uniform>
<uniform>
<name>noise_tex</name>
<type>sampler-2d</type>
<value type="int">3</value>
</uniform>
<uniform>
<name>g_scale</name>
<type>float</type>
<value><use>g_scale</use></value>
</uniform>
<uniform>
<name>g_bias</name>
<type>float</type>
<value><use>g_bias</use></value>
</uniform>
<uniform>
<name>g_intensity</name>
<type>float</type>
<value><use>g_intensity</use></value>
</uniform>
<uniform>
<name>g_sample_rad</name>
<type>float</type>
<value><use>g_sample_rad</use></value>
</uniform>
<uniform>
<name>random_size</name>
<type>float</type>
<value><use>random_size</use></value>
</uniform>
</pass>
</technique>
</PropertyList>

View file

@ -37,6 +37,20 @@
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<texture n="11">
<image>Textures/Terrain/void.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="12">
<image>Textures/Terrain/void.png</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<transparent>false</transparent>
<render-bin>
<bin-number>0</bin-number>
@ -52,22 +66,30 @@
<terrain_alt><use>/environment/mean-terrain-elevation-m</use></terrain_alt>
<overcast><use>/rendering/scene/overcast</use></overcast>
<eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt>
<mysnow_level><use>/environment/mysnow-level-m</use></mysnow_level>
<snow_level><use>/environment/snow-level-m</use></snow_level>
<dust_cover_factor><use>/environment/surface/dust-cover-factor</use></dust_cover_factor>
<wetness><use>/environment/surface/wetness</use></wetness>
<fogtype><use>/sim/rendering/shaders/skydome</use></fogtype>
<fogstructure><use>/environment/fog-structure</use></fogstructure>
<quality_level><use>/sim/rendering/shaders/landmass</use></quality_level>
<tquality_level><use>/sim/rendering/shaders/transition</use></tquality_level>
</parameters>
<!-- put techniques at a "high" index to allow derived effects to
insert their own techniques first. -->
<technique n="4">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<or>
<less-equal>
<value type="float">4.0</value>
<float-property>/sim/rendering/shaders/landmass</float-property>
</less-equal>
<less-equal>
<value type="float">3.0</value>
<float-property>/sim/rendering/shaders/transition</float-property>
</less-equal>
</or>
<or>
<less-equal>
<value type="float">2.0</value>
@ -99,31 +121,27 @@
<bin-number>-1</bin-number>
<bin-name>RenderBin</bin-name>
</render-bin>
<texture-unit>
<!--<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>
<type>noise</type>
<internal-format><use>texture[0]/internal-format</use></internal-format>
</texture-unit>-->
<program>
<vertex-shader n="0">Shaders/include_fog.vert</vertex-shader>
<!--<vertex-shader n="0">Shaders/include_fog.vert</vertex-shader>
<vertex-shader n="1">Shaders/default.vert</vertex-shader>
<fragment-shader n="0">Shaders/include_fog.frag</fragment-shader>
<fragment-shader n="1">Shaders/terrain-nocolor.frag</fragment-shader>
<fragment-shader n="1">Shaders/terrain-nocolor.frag</fragment-shader>-->
<vertex-shader>Shaders/trivial.vert</vertex-shader>
<fragment-shader>Shaders/trivial.frag</fragment-shader>
</program>
<uniform>
<!--<uniform>
<name>texture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
</uniform>-->
<color-mask type="vec4d">0 0 0 0</color-mask>
</pass>
<pass>
@ -144,29 +162,45 @@
<bin-number><use>render-bin/bin-number</use></bin-number>
<bin-name><use>render-bin/bin-name</use></bin-name>
</render-bin>
<!--<render-bin>
<bin-number>1</bin-number>
<bin-name>RenderBin</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>
<internal-format><use>texture[0]/internal-format</use></internal-format>
</texture-unit>
<texture-unit>
<unit>1</unit>
<type>noise</type>
</texture-unit>
<texture-unit>
<unit>5</unit>
<image><use>texture[12]/image</use></image>
<filter><use>texture[12]/filter</use></filter>
<wrap-s><use>texture[12]/wrap-s</use></wrap-s>
<wrap-t><use>texture[12]/wrap-t</use></wrap-t>
<internal-format><use>texture[12]/internal-format</use></internal-format>
</texture-unit>
<texture-unit>
<unit>6</unit>
<image><use>texture[10]/image</use></image>
<filter><use>texture[10]/filter</use></filter>
<wrap-s><use>texture[10]/wrap-s</use></wrap-s>
<wrap-t><use>texture[10]/wrap-t</use></wrap-t>
<internal-format>
<use>texture[10]/internal-format</use>
</internal-format>
<internal-format><use>texture[10]/internal-format</use></internal-format>
</texture-unit>
<texture-unit>
<unit>7</unit>
<image><use>texture[11]/image</use></image>
<filter><use>texture[11]/filter</use></filter>
<wrap-s><use>texture[11]/wrap-s</use></wrap-s>
<wrap-t><use>texture[11]/wrap-t</use></wrap-t>
<internal-format><use>texture[11]/internal-format</use></internal-format>
</texture-unit>
<program>
<vertex-shader>Shaders/terrain-haze-detailed.vert</vertex-shader>
@ -218,20 +252,35 @@
<value><use>eye_alt</use></value>
</uniform>
<uniform>
<name>mysnowlevel</name>
<name>snowlevel</name>
<type>float</type>
<value> <use>mysnow_level</use></value>
<value><use>snow_level</use></value>
</uniform>
<uniform>
<name>dust_cover_factor</name>
<type>float</type>
<value><use>dust_cover_factor</use></value>
</uniform>
<uniform>
<name>wetness</name>
<type>float</type>
<value><use>wetness</use></value>
</uniform>
<uniform>
<name>fogstructure</name>
<type>float</type>
<value><use>fogstructure</use></value>
</uniform>
<uniform>
<name>quality_level</name>
<type>int</type>
<value><use>quality_level</use></value>
</uniform>
<uniform>
<name>tquality_level</name>
<type>int</type>
<value><use>tquality_level</use></value>
</uniform>
<uniform>
<name>texture</name>
<type>sampler-2d</type>
@ -242,15 +291,26 @@
<type>sampler-3d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>mix_texture</name>
<type>sampler-2d</type>
<value type="int">5</value>
</uniform>
<uniform>
<name>snow_texture</name>
<type>sampler-2d</type>
<value type="int">6</value>
</uniform>
<uniform>
<name>detail_texture</name>
<type>sampler-2d</type>
<value type="int">7</value>
</uniform>
<uniform>
<name>colorMode</name>
<type>int</type>
<value>2</value> <!-- AMBIENT_AND_DIFFUSE -->
<value>2</value>
<!-- AMBIENT_AND_DIFFUSE -->
</uniform>
<depth>
<function>lequal</function>
@ -258,8 +318,6 @@
</depth>
</pass>
</technique>
<technique n="5">
<predicate>
<and>
@ -301,9 +359,7 @@
<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>
<internal-format><use>texture[0]/internal-format</use></internal-format>
</texture-unit>
<program>
<vertex-shader n="0">Shaders/include_fog.vert</vertex-shader>
@ -342,9 +398,7 @@
<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>
<internal-format><use>texture[0]/internal-format</use></internal-format>
</texture-unit>
<program>
<vertex-shader>Shaders/terrain-haze.vert</vertex-shader>
@ -403,7 +457,8 @@
<uniform>
<name>colorMode</name>
<type>int</type>
<value>2</value> <!-- AMBIENT_AND_DIFFUSE -->
<value>2</value>
<!-- AMBIENT_AND_DIFFUSE -->
</uniform>
<depth>
<function>lequal</function>
@ -411,7 +466,6 @@
</depth>
</pass>
</technique>
<technique n="10">
<predicate>
<and>
@ -454,9 +508,7 @@
<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>
<internal-format><use>texture[0]/internal-format</use></internal-format>
<environment>
<mode>modulate</mode>
</environment>
@ -479,12 +531,10 @@
</uniform -->
</pass>
</technique>
<technique n="11">
<predicate>
<and>
<property>/sim/rendering/shaders/generic</property>
<or>
<less-equal>
<value type="float">2.0</value>
@ -502,26 +552,14 @@
<pass>
<lighting>true</lighting>
<material>
<ambient>
<use>material/ambient</use>
</ambient>
<diffuse>
<use>material/diffuse</use>
</diffuse>
<specular>
<use>material/specular</use>
</specular>
<emissive>
<use>material/emissive</use>
</emissive>
<shininess>
<use>material/shininess</use>
</shininess>
<ambient><use>material/ambient</use></ambient>
<diffuse><use>material/diffuse</use></diffuse>
<specular><use>material/specular</use></specular>
<emissive><use>material/emissive</use></emissive>
<shininess><use>material/shininess</use></shininess>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<alpha-test>
<use>transparent</use>
</alpha-test>
<alpha-test><use>transparent</use></alpha-test>
<shade-model>smooth</shade-model>
<cull-face>back</cull-face>
<render-bin>
@ -530,21 +568,11 @@
</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>
<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>
<program>
<vertex-shader n="0">Shaders/include_fog.vert</vertex-shader>
@ -562,56 +590,28 @@
<pass>
<lighting>true</lighting>
<material>
<ambient>
<use>material/ambient</use>
</ambient>
<diffuse>
<use>material/diffuse</use>
</diffuse>
<specular>
<use>material/specular</use>
</specular>
<emissive>
<use>material/emissive</use>
</emissive>
<shininess>
<use>material/shininess</use>
</shininess>
<ambient><use>material/ambient</use></ambient>
<diffuse><use>material/diffuse</use></diffuse>
<specular><use>material/specular</use></specular>
<emissive><use>material/emissive</use></emissive>
<shininess><use>material/shininess</use></shininess>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<blend>
<use>transparent</use>
</blend>
<alpha-test>
<use>transparent</use>
</alpha-test>
<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>
<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>
<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>
<program>
<vertex-shader>Shaders/include_fog.vert</vertex-shader>
@ -622,44 +622,32 @@
<uniform>
<name>visibility</name>
<type>float</type>
<value>
<use>visibility</use>
</value>
<value><use>visibility</use></value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value>
<use>avisibility</use>
</value>
<value><use>avisibility</use></value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value>
<use>lthickness</use>
</value>
<value><use>lthickness</use></value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value>
<use>scattering</use>
</value>
<value><use>scattering</use></value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value>
<use>terminator</use>
</value>
<value><use>terminator</use></value>
</uniform>
<uniform>
<name>fogType</name>
<type>int</type>
<value>
<use>fogtype</use>
</value>
<value><use>fogtype</use></value>
</uniform>
<uniform>
<name>texture</name>
@ -678,62 +666,32 @@
</depth>
</pass>
</technique>
<technique n="12">
<pass>
<lighting>true</lighting>
<material>
<ambient>
<use>material/ambient</use>
</ambient>
<diffuse>
<use>material/diffuse</use>
</diffuse>
<specular>
<use>material/specular</use>
</specular>
<emissive>
<use>material/emissive</use>
</emissive>
<shininess>
<use>material/shininess</use>
</shininess>
<ambient><use>material/ambient</use></ambient>
<diffuse><use>material/diffuse</use></diffuse>
<specular><use>material/specular</use></specular>
<emissive><use>material/emissive</use></emissive>
<shininess><use>material/shininess</use></shininess>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<blend>
<use>transparent</use>
</blend>
<alpha-test>
<use>transparent</use>
</alpha-test>
<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>
<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>
<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>
<environment>
<mode>modulate</mode>
</environment>

View file

@ -27,7 +27,7 @@
<terrain_alt><use>/environment/mean-terrain-elevation-m</use></terrain_alt>
<overcast><use>/rendering/scene/overcast</use></overcast>
<eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt>
<mysnow_level><use>/environment/mysnow-level-m</use></mysnow_level>
<snow_level><use>/environment/snow-level-m</use></snow_level>
<dust_cover_factor><use>/environment/surface/dust-cover-factor</use></dust_cover_factor>
<fogtype><use>/sim/rendering/shaders/skydome</use></fogtype>
<fogstructure><use>/environment/fog-structure</use></fogstructure>
@ -53,48 +53,7 @@
</or>
</and>
</predicate>
<pass>
<lighting>true</lighting>
<material>
<ambient type="vec4d">1.0 1.0 1.0 1.0</ambient>
<diffuse type="vec4d">1.0 1.0 1.0 1.0</diffuse>
<color-mode>off</color-mode>
</material>
<render-bin>
<bin-number>-1</bin-number>
<bin-name>RenderBin</bin-name>
</render-bin>
<blend>
<source>src-alpha</source>
<destination>one-minus-src-alpha</destination>
</blend>
<alpha-test>
<comparison>gequal</comparison>
<reference type="float">0.1</reference>
</alpha-test>
<texture-unit>
<unit>0</unit>
<type>2d</type>
<image>
<use>texture[0]/image</use>
</image>
<wrap-s>clamp</wrap-s>
<wrap-t>clamp</wrap-t>
</texture-unit>
<program>
<!-- <vertex-shader n="0">Shaders/include_fog.vert</vertex-shader> -->
<vertex-shader n="1">Shaders/tree.vert</vertex-shader>
<fragment-shader n="0">Shaders/include_fog.frag</fragment-shader>
<fragment-shader n="1">Shaders/tree.frag</fragment-shader>
</program>
<uniform>
<name>texture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<color-mask type="vec4d">0 0 0 0</color-mask>
</pass>
<pass>
<lighting>true</lighting>
<material>
@ -174,11 +133,13 @@
<type>int</type>
<value>2</value> <!-- AMBIENT_AND_DIFFUSE -->
</uniform>
<depth>
<!--<depth>
<function>lequal</function>
<write-mask type="bool">false</write-mask>
</depth>
</depth>-->
</pass>
</technique>
<technique n="9">

View file

@ -37,8 +37,548 @@
<generate>
<normal type="int">15</normal>
<tangent type="int">6</tangent>
<binormal type="int">7</binormal>
<!--<binormal type="int">7</binormal>-->
</generate>
<technique n="2">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<property>/sim/rendering/shaders/urban</property>
<less-equal>
<value type="float">4.0</value>
<float-property>/sim/rendering/shaders/urban</float-property>
</less-equal>
<equal>
<property>/sim/rendering/random-buildings</property>
<value type="bool">false</value>
</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>
<or>
<extension-supported>GL_ATI_shader_texture_lod</extension-supported> <!-- not available in NVidia driver -->
<extension-supported>GL_ARB_shader_texture_lod</extension-supported> <!-- not available in NVidia driver -->
<extension-supported>GL_EXT_gpu_shader4</extension-supported>
</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-lightfield.vert</vertex-shader>
<fragment-shader>Shaders/urban-lightfield.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>
<!-- BEGIN fog include -->
<uniform>
<name>visibility</name>
<type>float</type>
<value>
<use>visibility</use>
</value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value>
<use>avisibility</use>
</value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value>
<use>lthickness</use>
</value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value>
<use>scattering</use>
</value>
</uniform>
<uniform>
<name>ground_scattering</name>
<type>float</type>
<value><use>ground_scattering</use></value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value>
<use>terminator</use>
</value>
</uniform>
<uniform>
<name>terrain_alt</name>
<type>float</type>
<value><use>terrain_alt</use></value>
</uniform>
<uniform>
<name>overcast</name>
<type>float</type>
<value><use>overcast</use></value>
</uniform>
<uniform>
<name>eye_alt</name>
<type>float</type>
<value><use>eye_alt</use></value>
</uniform>
<uniform>
<name>snowlevel</name>
<type>float</type>
<value><use>snow_level</use></value>
</uniform>
<uniform>
<name>dust_cover_factor</name>
<type>float</type>
<value> <use>dust_cover_factor</use></value>
</uniform>
<uniform>
<name>wetness</name>
<type>float</type>
<value><use>wetness</use></value>
</uniform>
<uniform>
<name>fogstructure</name>
<type>float</type>
<value><use>fogstructure</use></value>
</uniform>
<!-- END fog include -->
</pass>
</technique>
<technique n="3">
<predicate>
<and>
<property>/sim/rendering/shaders/urban</property>
<less-equal>
<value type="float">1.0</value>
<float-property>/sim/rendering/shaders/urban</float-property>
</less-equal>
<equal>
<property>/sim/rendering/random-buildings</property>
<value type="bool">false</value>
</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>
<!-- quality level below 4.0 doesn't require GL_ATI_shader_texture_lod or GL_ARB_shader_texture_lod -->
</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>
<type>noise</type>
</texture-unit>
<program>
<vertex-shader>Shaders/urban-lightfield.vert</vertex-shader>
<fragment-shader>Shaders/urban-lightfield.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>
<!-- BEGIN fog include -->
<uniform>
<name>visibility</name>
<type>float</type>
<value>
<use>visibility</use>
</value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value>
<use>avisibility</use>
</value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value>
<use>lthickness</use>
</value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value>
<use>scattering</use>
</value>
</uniform>
<uniform>
<name>ground_scattering</name>
<type>float</type>
<value><use>ground_scattering</use></value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value>
<use>terminator</use>
</value>
</uniform>
<uniform>
<name>terrain_alt</name>
<type>float</type>
<value><use>terrain_alt</use></value>
</uniform>
<uniform>
<name>overcast</name>
<type>float</type>
<value><use>overcast</use></value>
</uniform>
<uniform>
<name>eye_alt</name>
<type>float</type>
<value><use>eye_alt</use></value>
</uniform>
<uniform>
<name>snowlevel</name>
<type>float</type>
<value><use>snow_level</use></value>
</uniform>
<uniform>
<name>dust_cover_factor</name>
<type>float</type>
<value> <use>dust_cover_factor</use></value>
</uniform>
<uniform>
<name>wetness</name>
<type>float</type>
<value><use>wetness</use></value>
</uniform>
<uniform>
<name>fogstructure</name>
<type>float</type>
<value><use>fogstructure</use></value>
</uniform>
<!-- END fog include -->
<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>NoiseTex</name>
<type>sampler-3d</type>
<value type="int">2</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>
</pass>
</technique>
<technique n="6">
<predicate>
<and>

View file

@ -17,25 +17,33 @@
-->
<PropertyList>
<weather-scenarios>
<scenario>
<name type="string">Disabled</name>
<description type="string">METAR weather generation is disabled. Use the above controls to setup your weather.</description>
</scenario>
<scenario>
<name type="string">Live data</name>
<description type="string">
Fetch live weather data for your nearest airport from noaa.gov. You need a working internet connection.
All the controls in this dialog are computed automatically, once a valid METAR is received.
</description>
<local-weather>
<tile-type>live</tile-type>
<tile-management>METAR</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">Manual input</name>
<description type="string">Enter your favorite METAR weather in the textbox below. A valid METAR syntax is required.</description>
<description type="string">Enter your favorite METAR weather in the textbox above. A valid METAR syntax is required.</description>
<local-weather>
<tile-type>manual</tile-type>
<tile-management>METAR</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">Fair weather</name>
<metar type="string">XXXX 012345Z 15003KT 12SM SCT041 FEW200 20/08 Q1015 NOSIG</metar>
<description type="string">A lovely day for trip to your favorite 100$ hamburger airfield</description>
<local-weather>
<tile-type>High-pressure-core</tile-type>
<tile-management>realistic-weather</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">Thunderstorm</name>
@ -45,6 +53,10 @@
Be prepared for reduction of visibility in showers and strong gusts
near thunderstorms
</description>
<local-weather>
<tile-type>Thunderstorms</tile-type>
<tile-management>realistic-weather</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">Stormy Monday</name>
@ -285,6 +297,7 @@
<metar-max-age-min type="long">240</metar-max-age-min>
<metar-updates-environment type="bool">true</metar-updates-environment>
<metar-updates-winds-aloft type="bool">true</metar-updates-winds-aloft>
<metar-updates-snow-level type="bool" userarchive="y">true</metar-updates-snow-level>
<control-fdm-atmosphere type="bool">true</control-fdm-atmosphere>
<contrail-altitude type="double">30000</contrail-altitude>
<!-- definitions for the metar generated fog/mist/haze layer -->
@ -340,15 +353,15 @@
<!-- definitions for the scattering skydome shader -->
<ground-visibility-m type="double" userarchive="n">16000.0</ground-visibility-m>
<air-pollution-norm type="double" userarchive="n">0.0</air-pollution-norm>
<air-pollution-norm type="double" userarchive="y">0.0</air-pollution-norm>
<ground-haze-thickness-m type="double" userarchive="n">2000.0</ground-haze-thickness-m>
<terminator-relative-position-m type="double" userarchive="n">1000000.0</terminator-relative-position-m>
<mean-terrain-elevation-m type="double" userarchive="n">0.0</mean-terrain-elevation-m>
<mysnow-level-m type="double" userarchive="n">3200.0</mysnow-level-m>
<fog-structure type="double" userarchive="n">0.0</fog-structure>
<fog-structure type="double" userarchive="y">0.0</fog-structure>
<!-- definitions for the environment at surface interface -->
<surface>
<scattering type="double" userarchive="n">0.7</scattering>
<dust-cover-factor type="double" userarchive="n">0.0</dust-cover-factor>
<dust-cover-factor type="double" userarchive="y">0.0</dust-cover-factor>
<wetness type="double" userarchive="y">0.0</wetness>
</surface>
</PropertyList>

View file

@ -415,11 +415,27 @@
<name>MetarController:snow-level</name>
<type>gain</type>
<gain>1.0</gain>
<input>
<enable>
<condition>
<property>/environment/metar/valid</property>
<property>/environment/params/metar-updates-snow-level</property>
<property>/environment/params/metar-updates-environment</property>
<property>/environment/metar/snow-cover</property>
<property>/environment/metar/valid</property>
<less-than>
<expression>
<difference>
<product>
<property>/environment/metar/station-elevation-ft</property>
<value>0.3048</value>
</product>
<property>/environment/snow-level-m</property>
</difference>
</expression>
<value>0</value>
</less-than>
</condition>
</enable>
<input>
<expression>
<sum>
<product>
@ -432,6 +448,7 @@
</input>
<input>3200</input>
<output>/environment/snow-level-m</output>
<max>3200</max>
<min>-425</min>
<max>7500</max>
</filter>
</PropertyList>

View file

@ -442,7 +442,7 @@ Shared parameters for various materials.
<material n="2010">
<name>Railroad</name>
<!--<name>Transport</name>-->
<name>Transport</name>
<texture>Terrain/gravel.png</texture>
<xsize>400</xsize>
<ysize>400</ysize>

View file

@ -1435,9 +1435,21 @@
</equals>
</condition>
<name>Sand</name>
<texture-set>
<texture>Terrain/sand4.png</texture>
<texture n="11">Terrain/sand_hires.png</texture>
</texture-set>
<texture-set>
<texture>Terrain/sand5.png</texture>
<texture n="11">Terrain/sand_hires.png</texture>
</texture-set>
<texture-set>
<texture>Terrain/sand6.png</texture>
<texture n="11">Terrain/sand_hires.png</texture>
</texture-set>
<!--<texture>Terrain/sand4.png</texture>
<texture>Terrain/sand5.png</texture>
<texture>Terrain/sand6.png</texture>-->
<xsize>2000</xsize>
<ysize>2000</ysize>
<light-coverage>10000000.0</light-coverage>
@ -1463,8 +1475,12 @@
<name>ScrubCover</name>
<name>Scrub</name>
<name>Sclerophyllous</name>
<texture-set>
<texture>Terrain/shrub1.png</texture>
<!--
<texture n="11">Terrain/grass_hires.png</texture>
<texture n="12">Terrain/dirtrock.png</texture>
</texture-set>
<!-- <texture>Terrain/shrub1.png</texture>
<texture>Terrain/shrub.png</texture>
<texture>Terrain/shrub2.png</texture>
<texture>Terrain/shrub3.png</texture>
@ -1664,9 +1680,21 @@
<name>DryLake</name>
<name>IntermittentReservoir</name>
<name>IntermittentLake</name>
<texture-set>
<texture>Terrain/sand1.png</texture>
<texture n="11">Terrain/sand3.png</texture>
</texture-set>
<texture-set>
<texture>Terrain/sand2.png</texture>
<texture n="11">Terrain/sand1.png</texture>
</texture-set>
<texture-set>
<texture>Terrain/sand3.png</texture>
<texture n="11">Terrain/sand2.png</texture>
</texture-set>
<!--<texture>Terrain/sand1.png</texture>
<texture>Terrain/sand2.png</texture>
<texture>Terrain/sand3.png</texture>-->
<xsize>2000</xsize>
<ysize>2000</ysize>
<solid>1</solid>
@ -1766,9 +1794,24 @@
<name>HerbTundraCover</name>
<name>HerbTundra</name>
<effect>Effects/herbtundra</effect>
<texture-set>
<texture>Terrain/herbtundra.png</texture>
<texture n="11">Terrain/grass_hires.png</texture>
<texture n="12">Terrain/rock.png</texture>
</texture-set>
<texture-set>
<texture>Terrain/herbtundra2.png</texture>
<texture n="11">Terrain/grass_hires.png</texture>
<texture n="12">Terrain/rock.png</texture>
</texture-set>
<texture-set>
<texture>Terrain/herbtundra3.png</texture>
<texture n="11">Terrain/grass_hires.png</texture>
<texture n="12">Terrain/rock.png</texture>
</texture-set>
<!--<texture>Terrain/herbtundra.png</texture>
<texture>Terrain/herbtundra2.png</texture>
<texture>Terrain/herbtundra3.png</texture>-->
<xsize>2000</xsize>
<ysize>2000</ysize>
<light-coverage>4000000.0</light-coverage>

View file

@ -38,3 +38,5 @@ WRITE ALLOW $FG_HOME/state/*.xml
WRITE ALLOW $FG_HOME/aircraft-data/*.xml
WRITE ALLOW $FG_HOME/Wildfire/*.xml
WRITE ALLOW $FG_HOME/runtime-jetways/*.xml
WRITE ALLOW $FG_HOME/Input/Joysticks/*.xml

View file

@ -0,0 +1,64 @@
# PropertyElement
# ==============================================================================
# Baseclass for all property controlled elements/objects
#
var PropertyElement = {
# Constructor
#
# @param node Node to be used for element or vector [parent, type] for
# creation of a new node with name type and given parent
# @param id ID/Name (Should be unique)
new: func(node, id)
{
if( typeof(node) == 'vector' )
var node = _createNodeWithIndex(node[0], node[1]);
else
var node = aircraft.makeNode(node);
if( !isa(node, props.Node) )
return debug.warn("Not a props.Node!");
var m = {
parents: [PropertyElement],
_node: node
};
if( id != nil )
m.set("id", id);
return m;
},
# Destructor (has to be called manually!)
del: func()
{
me._node.remove();
},
set: func(key, value)
{
me._node.getNode(key, 1).setValue(value);
return me;
},
setBool: func(key, value)
{
me._node.getNode(key, 1).setBoolValue(value);
return me;
},
setDouble: func(key, value)
{
me._node.getNode(key, 1).setDoubleValue(value);
return me;
},
setInt: func(key, value)
{
me._node.getNode(key, 1).setIntValue(value);
return me;
},
get: func(key, default = nil)
{
var node = me._node.getNode(key);
if( node != nil )
return node.getValue();
else
return default;
}
};

840
Nasal/canvas/api.nas Normal file
View file

@ -0,0 +1,840 @@
# Helper function to create a node with the first available index for the given
# path relative to the given node
#
var _createNodeWithIndex = func(node, path, min_index = 0)
{
var node = aircraft.makeNode(node);
# TODO do we need an upper limit? (50000 seems already seems unreachable)
for(var i = min_index; i < 50000; i += 1)
{
var p = path ~ "[" ~ i ~ "]";
if( node.getNode(p) == nil )
return node.getNode(p, 1);
}
debug.warn("Unable to get child (already 50000 exist)");
return nil;
};
# Internal helper
var _createColorNodes = func(parent, name)
{
var node = parent.getNode(name, 1);
return [ node.getNode("red", 1),
node.getNode("green", 1),
node.getNode("blue", 1),
node.getNode("alpha", 1) ];
};
var _setColorNodes = func(nodes, color)
{
if( typeof(nodes) != "vector" )
{
debug.warn("This element doesn't support setting color");
return;
}
if( size(color) == 1 )
color = color[0];
if( typeof(color) != "vector" )
return debug.warn("Wrong type for color");
if( size(color) < 3 or size(color) > 4 )
return debug.warn("Color needs 3 or 4 values (RGB or RGBA)");
for(var i = 0; i < size(color); i += 1)
nodes[i].setDoubleValue( color[i] );
if( size(color) == 3 )
# default alpha is 1
nodes[3].setDoubleValue(1);
};
var _getColor = func(color)
{
if( size(color) == 1 )
var color = color[0];
if( typeof(color) == 'scalar' )
return color;
if( typeof(color) != "vector" )
return debug.warn("Wrong type for color");
if( size(color) < 3 or size(color) > 4 )
return debug.warn("Color needs 3 or 4 values (RGB or RGBA)");
var str = 'rgb';
if( size(color) == 4 )
str ~= 'a';
str ~= '(';
# rgb = [0,255], a = [0,1]
for(var i = 0; i < size(color); i += 1)
str ~= (i > 0 ? ',' : '') ~ (i < 3 ? int(color[i] * 255) : color[i]);
return str ~ ')';
};
var _arg2valarray = func
{
var ret = arg;
while ( typeof(ret) == "vector"
and size(ret) == 1 and typeof(ret[0]) == "vector" )
ret = ret[0];
return ret;
}
# Transform
# ==============================================================================
# A transformation matrix which is used to transform an #Element on the canvas.
# The dimensions of the matrix are 3x3 where the last row is always 0 0 1:
#
# a c e
# b d f
# 0 0 1
#
# See http://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined for details.
#
var Transform = {
new: func(node, vals = nil)
{
var m = {
parents: [Transform],
_node: node,
a: node.getNode("m[0]", 1),
b: node.getNode("m[1]", 1),
c: node.getNode("m[2]", 1),
d: node.getNode("m[3]", 1),
e: node.getNode("m[4]", 1),
f: node.getNode("m[5]", 1)
};
var use_vals = typeof(vals) == 'vector' and size(vals) == 6;
# initialize to identity matrix
m.a.setDoubleValue(use_vals ? vals[0] : 1);
m.b.setDoubleValue(use_vals ? vals[1] : 0);
m.c.setDoubleValue(use_vals ? vals[2] : 0);
m.d.setDoubleValue(use_vals ? vals[3] : 1);
m.e.setDoubleValue(use_vals ? vals[4] : 0);
m.f.setDoubleValue(use_vals ? vals[5] : 0);
return m;
},
setTranslation: func
{
var trans = _arg2valarray(arg);
me.e.setDoubleValue(trans[0]);
me.f.setDoubleValue(trans[1]);
return me;
},
# Set rotation (Optionally around a specified point instead of (0,0))
#
# setRotation(rot)
# setRotation(rot, cx, cy)
#
# @note If using with rotation center different to (0,0) don't use
# #setTranslation as it would interfere with the rotation.
setRotation: func(angle)
{
var center = _arg2valarray(arg);
var s = math.sin(angle);
var c = math.cos(angle);
me.a.setDoubleValue(c);
me.b.setDoubleValue(s);
me.c.setDoubleValue(-s);
me.d.setDoubleValue(c);
if( size(center) == 2 )
{
me.e.setDoubleValue( (-center[0] * c) + (center[1] * s) + center[0] );
me.f.setDoubleValue( (-center[0] * s) - (center[1] * c) + center[1] );
}
return me;
},
# Set scale (either as parameters or array)
#
# If only one parameter is given its value is used for both x and y
# setScale(x, y)
# setScale([x, y])
setScale: func
{
var scale = _arg2valarray(arg);
me.a.setDoubleValue(scale[0]);
me.d.setDoubleValue(size(scale) >= 2 ? scale[1] : scale[0]);
return me;
},
getScale: func()
{
# TODO handle rotation
return [me.a.getValue(), me.d.getValue()];
}
};
# Element
# ==============================================================================
# Baseclass for all elements on a canvas
#
var Element = {
# Constructor
#
# @param node Node to be used for element or vector [parent, type] for
# creation of a new node with name type and given parent
# @param id ID/Name (Should be unique)
new: func(node, id)
{
var m = { parents: [PropertyElement.new(node, id), Element] };
m._center = [
m._node.getNode("center[0]"),
m._node.getNode("center[1]")
];
return m;
},
# Trigger an update of the element
#
# Elements are automatically updated once a frame, with a delay of one frame.
# If you wan't to get an element updated in the current frame you have to use
# this method.
update: func()
{
me.setInt("update", 1);
},
# Hide/Show element
#
# @param visible Whether the element should be visible
setVisible: func(visible = 1)
{
me.setBool("visible", visible);
},
# Hide element (Shortcut for setVisible(0))
hide: func me.setVisible(0),
# Show element (Shortcut for setVisible(1))
show: func me.setVisible(1),
#
setGeoPosition: func(lat, lon)
{
me._getTf()._node.getNode("m-geo[4]", 1).setValue("N" ~ lat);
me._getTf()._node.getNode("m-geo[5]", 1).setValue("E" ~ lon);
return me;
},
# Create a new transformation matrix
#
# @param vals Default values (Vector of 6 elements)
createTransform: func(vals = nil)
{
var node = _createNodeWithIndex(me._node, "tf", 1); # tf[0] is reserved for
# setRotation
return Transform.new(node, vals);
},
# Shortcut for setting translation
setTranslation: func { me._getTf().setTranslation(arg); return me; },
# Set rotation around transformation center (see #setCenter).
#
# @note This replaces the the existing transformation. For additional scale or
# translation use additional transforms (see #createTransform).
setRotation: func(rot)
{
if( me['_tf_rot'] == nil )
# always use the first matrix slot to ensure correct rotation
# around transformation center.
me['_tf_rot'] = Transform.new(me._node.getNode("tf[0]", 1));
me._tf_rot.setRotation(rot, me.getCenter());
return me;
},
# Shortcut for setting scale
setScale: func { me._getTf().setScale(arg); return me; },
# Shortcut for getting scale
getScale: func me._getTf().getScale(),
# Set the fill/background/boundingbox color
#
# @param color Vector of 3 or 4 values in [0, 1]
setColorFill: func me.set('fill', _getColor(arg)),
#
getBoundingBox: func()
{
var bb = me._node.getNode("bounding-box");
var min_x = bb.getNode("min-x").getValue();
if( min_x != nil )
return [ min_x,
bb.getNode("min-y").getValue(),
bb.getNode("max-x").getValue(),
bb.getNode("max-y").getValue() ];
else
return [0, 0, 0, 0];
},
# Set transformation center (currently only used for rotation)
setCenter: func()
{
var center = _arg2valarray(arg);
if( size(center) != 2 )
return debug.warn("invalid arg");
if( me._center[0] == nil )
me._center[0] = me._node.getNode("center[0]", 1);
if( me._center[1] == nil )
me._center[1] = me._node.getNode("center[1]", 1);
me._center[0].setDoubleValue(center[0] or 0);
me._center[1].setDoubleValue(center[1] or 0);
return me;
},
# Get transformation center
getCenter: func()
{
var bb = me.getBoundingBox();
var center = [0, 0];
if( me._center[0] != nil )
center[0] = me._center[0].getValue() or 0;
if( me._center[1] != nil )
center[1] = me._center[1].getValue() or 0;
if( bb[0] >= bb[2] or bb[1] >= bb[3] )
return center;
return [ 0.5 * (bb[0] + bb[2]) + center[0],
0.5 * (bb[1] + bb[3]) + center[1] ];
},
# Internal Transform for convenience transform functions
_getTf: func
{
if( me['_tf'] == nil )
me['_tf'] = me.createTransform();
return me._tf;
}
};
# Group
# ==============================================================================
# Class for a group element on a canvas
#
var Group = {
new: func(node, id)
{
return { parents: [Group, Element.new(node, id)] };
},
# Create a child of given type with specified id.
# type can be group, text
createChild: func(type, id = nil)
{
var factory = me._element_factories[type];
if( factory == nil )
{
debug.dump("canvas.Group.createChild(): unknown type (" ~ type ~ ")");
return nil;
}
return factory([me._node, type], id);
},
# Get first child with given id (breadth-first search)
#
# @note Use with care as it can take several miliseconds (for me eg. ~2ms).
getElementById: func(id)
{
# TODO can we improve the queue or better port this to C++ or use some kind
# of lookup hash? Searching is really slow now...
var stack = [me._node];
var index = 0;
while( index < size(stack) )
{
var node = stack[index];
index += 1;
if( node != me._node )
{
var node_id = node.getNode("id");
if( node_id != nil and node_id.getValue() == id )
# Create element from existing node
return me._element_factories[ node.getName() ](node, nil);
}
foreach(var c; node.getChildren())
# element nodes have type NONE and valid element names (those in the the
# factor list)
if( c.getType() == "NONE"
and me._element_factories[ c.getName() ] != nil )
append(stack, c);
}
},
# Remove all children
removeAllChildren: func()
{
foreach(var type; keys(me._element_factories))
me._node.removeChildren(type, 0);
return me;
}
};
# Map
# ==============================================================================
# Class for a group element on a canvas with possibly geopgraphic positions
# which automatically get projected according to the specified projection.
#
var Map = {
new: func(node, id)
{
return { parents: [Map, Group.new(node, id)] };
}
# TODO
};
# Text
# ==============================================================================
# Class for a text element on a canvas
#
var Text = {
new: func(node, id)
{
return { parents: [Text, Element.new(node, id)] };
},
# Set the text
setText: func(text)
{
# add space because osg seems to remove last character if its a space
me.set("text", typeof(text) == 'scalar' ? text ~ ' ' : "");
},
# Set alignment
#
# @param algin String, one of:
# left-top
# left-center
# left-bottom
# center-top
# center-center
# center-bottom
# right-top
# right-center
# right-bottom
# left-baseline
# center-baseline
# right-baseline
# left-bottom-baseline
# center-bottom-baseline
# right-bottom-baseline
#
setAlignment: func(align)
{
me.set("alignment", align);
},
# Set the font size
setFontSize: func(size, aspect = 1)
{
me.setDouble("character-size", size);
me.setDouble("character-aspect-ratio", aspect);
},
# Set font (by name of font file)
setFont: func(name)
{
me.set("font", name);
},
# Enumeration of values for drawing mode:
TEXT: 1, # The text itself
BOUNDINGBOX: 2, # A bounding box (only lines)
FILLEDBOUNDINGBOX: 4, # A filled bounding box
ALIGNMENT: 8, # Draw a marker (cross) at the position of the text
# Set draw mode. Binary combination of the values above. Since I haven't found
# a bitwise or we have to use a + instead.
#
# eg. my_text.setDrawMode(Text.TEXT + Text.BOUNDINGBOX);
setDrawMode: func(mode)
{
me.setInt("draw-mode", mode);
},
# Set bounding box padding
setPadding: func(pad)
{
me.setDouble("padding", pad);
},
setMaxWidth: func(w)
{
me.setDouble("max-width", w);
},
setColor: func me.set('fill', _getColor(arg)),
setColorFill: func me.set('background', _getColor(arg))
};
# Path
# ==============================================================================
# Class for an (OpenVG) path element on a canvas
#
var Path = {
# Path segment commands (VGPathCommand)
VG_CLOSE_PATH: 0,
VG_MOVE_TO: 2,
VG_MOVE_TO_ABS: 2,
VG_MOVE_TO_REL: 3,
VG_LINE_TO: 4,
VG_LINE_TO_ABS: 4,
VG_LINE_TO_REL: 5,
VG_HLINE_TO: 6,
VG_HLINE_TO_ABS: 6,
VG_HLINE_TO_REL: 7,
VG_VLINE_TO: 8,
VG_VLINE_TO_ABS: 8,
VG_VLINE_TO_REL: 9,
VG_QUAD_TO: 10,
VG_QUAD_TO_ABS: 10,
VG_QUAD_TO_REL: 11,
VG_CUBIC_TO: 12,
VG_CUBIC_TO_ABS: 12,
VG_CUBIC_TO_REL: 13,
VG_SQUAD_TO: 14,
VG_SQUAD_TO_ABS: 14,
VG_SQUAD_TO_REL: 15,
VG_SCUBIC_TO: 16,
VG_SCUBIC_TO_ABS: 16,
VG_SCUBIC_TO_REL: 17,
VG_SCCWARC_TO: 20, # Note that CC and CCW commands are swapped. This is
VG_SCCWARC_TO_ABS:20, # needed due to the different coordinate systems used.
VG_SCCWARC_TO_REL:21, # In OpenVG values along the y-axis increase from bottom
VG_SCWARC_TO: 18, # to top, whereas in the Canvas system it is flipped.
VG_SCWARC_TO_ABS: 18,
VG_SCWARC_TO_REL: 19,
VG_LCCWARC_TO: 24,
VG_LCCWARC_TO_ABS:24,
VG_LCCWARC_TO_REL:25,
VG_LCWARC_TO: 22,
VG_LCWARC_TO_ABS: 22,
VG_LCWARC_TO_REL: 23,
# Number of coordinates per command
num_coords: [
0, 0, # VG_CLOSE_PATH
2, 2, # VG_MOVE_TO
2, 2, # VG_LINE_TO
1, 1, # VG_HLINE_TO
1, 1, # VG_VLINE_TO
4, 4, # VG_QUAD_TO
6, 6, # VG_CUBIC_TO
2, 2, # VG_SQUAD_TO
4, 4, # VG_SCUBIC_TO
5, 5, # VG_SCCWARC_TO
5, 5, # VG_SCWARC_TO
5, 5, # VG_LCCWARC_TO
5, 5 # VG_LCWARC_TO
],
#
new: func(node, id)
{
return {
parents: [Path, Element.new(node, id)],
_num_cmds: 0,
_num_coords: 0
};
},
# Remove all existing path data
reset: func
{
me._node.removeChildren('cmd', 0);
me._node.removeChildren('coord', 0);
me._node.removeChildren('coord-geo', 0);
me._num_cmds = 0;
me._num_coords = 0;
return me;
},
# Set the path data (commands and coordinates)
setData: func(cmds, coords)
{
me.reset();
me._node.setValues({cmd: cmds, coord: coords});
me._num_cmds = size(cmds);
me._num_coords = size(coords);
return me;
},
setDataGeo: func(cmds, coords)
{
me.reset();
me._node.setValues({cmd: cmds, 'coord-geo': coords});
me._num_cmds = size(cmds);
me._num_coords = size(coords);
return me;
},
# Add a path segment
addSegment: func(cmd, coords...)
{
var coords = _arg2valarray(coords);
var num_coords = me.num_coords[cmd];
if( size(coords) != num_coords )
debug.warn
(
"Invalid number of arguments (expected " ~ (num_coords + 1) ~ ")"
);
else
{
me.setInt("cmd[" ~ (me._num_cmds += 1) ~ "]", cmd);
for(var i = 0; i < num_coords; i += 1)
me.setDouble("coord[" ~ (me._num_coords += 1) ~ "]", coords[i]);
}
return me;
},
# Move path cursor
moveTo: func me.addSegment(me.VG_MOVE_TO_ABS, arg),
move: func me.addSegment(me.VG_MOVE_TO_REL, arg),
# Add a line
lineTo: func me.addSegment(me.VG_LINE_TO_ABS, arg),
line: func me.addSegment(me.VG_LINE_TO_REL, arg),
# Add a horizontal line
horizTo: func me.addSegment(me.VG_HLINE_TO_ABS, arg),
horiz: func me.addSegment(me.VG_HLINE_TO_REL, arg),
# Add a vertical line
vertTo: func me.addSegment(me.VG_VLINE_TO_ABS, arg),
vert: func me.addSegment(me.VG_VLINE_TO_REL, arg),
# Add a quadratic Bézier curve
quadTo: func me.addSegment(me.VG_QUAD_TO_ABS, arg),
quad: func me.addSegment(me.VG_QUAD_TO_REL, arg),
# Add a cubic Bézier curve
cubicTo: func me.addSegment(me.VG_CUBIC_TO_ABS, arg),
cubic: func me.addSegment(me.VG_CUBIC_TO_REL, arg),
# Add a smooth quadratic Bézier curve
quadTo: func me.addSegment(me.VG_SQUAD_TO_ABS, arg),
quad: func me.addSegment(me.VG_SQUAD_TO_REL, arg),
# Add a smooth cubic Bézier curve
cubicTo: func me.addSegment(me.VG_SCUBIC_TO_ABS, arg),
cubic: func me.addSegment(me.VG_SCUBIC_TO_REL, arg),
# Draw an elliptical arc (shorter counter-clockwise arc)
arcSmallCCWTo: func me.addSegment(me.VG_SCCWARC_TO_ABS, arg),
arcSmallCCW: func me.addSegment(me.VG_SCCWARC_TO_REL, arg),
# Draw an elliptical arc (shorter clockwise arc)
arcSmallCWTo: func me.addSegment(me.VG_SCWARC_TO_ABS, arg),
arcSmallCW: func me.addSegment(me.VG_SCWARC_TO_REL, arg),
# Draw an elliptical arc (longer counter-clockwise arc)
arcLargeCCWTo: func me.addSegment(me.VG_LCCWARC_TO_ABS, arg),
arcLargeCCW: func me.addSegment(me.VG_LCCWARC_TO_REL, arg),
# Draw an elliptical arc (shorter clockwise arc)
arcLargeCWTo: func me.addSegment(me.VG_LCWARC_TO_ABS, arg),
arcLargeCW: func me.addSegment(me.VG_LCWARC_TO_REL, arg),
# Close the path (implicit lineTo to first point of path)
close: func me.addSegment(me.VG_CLOSE_PATH),
setColor: func me.setStroke(_getColor(arg)),
setColorFill: func me.setFill(_getColor(arg)),
setFill: func(fill)
{
me.set('fill', fill);
},
setStroke: func(stroke)
{
me.set('stroke', stroke);
},
setStrokeLineWidth: func(width)
{
me.setDouble('stroke-width', width);
},
# Set stroke linecap
#
# @param linecap String, "butt", "round" or "square"
#
# See http://www.w3.org/TR/SVG/painting.html#StrokeLinecapProperty for details
setStrokeLineCap: func(linecap)
{
me.set('stroke-linecap', linecap);
},
# Set stroke dasharray
#
# @param pattern Vector, Vector of alternating dash and gap lengths
# [on1, off1, on2, ...]
setStrokeDashArray: func(pattern)
{
if( typeof(pattern) == 'vector' )
me.set('stroke-dasharray', string.join(',', pattern));
else
debug.warn("setStrokeDashArray: vector expected!");
return me;
}
};
# Image
# ==============================================================================
# Class for an image element on a canvas
#
var Image = {
new: func(node, id)
{
var m = {
parents: [Image, Element.new(node, id)]
};
m.color_fill = _createColorNodes(m._node, "color-fill");
return m;
},
# Set image file to be used
#
# @param file Path to file or canvas (Use canvas://... for canvas, eg.
# canvas://by-index/texture[0])
setFile: func(file)
{
me.set("file", file);
},
# Set rectangular region of source image to be used
#
# @param left Rectangle minimum x coordinate
# @param top Rectangle minimum y coordinate
# @param right Rectangle maximum x coordinate
# @param bottom Rectangle maximum y coordinate
# @param normalized Whether to use normalized ([0,1]) or image
# ([0, image_width]/[0, image_height]) coordinates
setSourceRect: func(left, top, right, bottom, normalized = 1)
{
me._node.getNode("source", 1).setValues({
left: left,
top: top,
right: right,
bottom: bottom,
normalized: normalized
});
return me;
},
# Set size of image element
setSize: func(width, height)
{
me._node.setValues({size: [width, height]});
return me;
}
};
# Element factories used by #Group elements to create children
Group._element_factories = {
"group": Group.new,
"map": Map.new,
"text": Text.new,
"path": Path.new,
"image": Image.new
};
# Canvas
# ==============================================================================
# Class for a canvas
#
var Canvas = {
# Place this canvas somewhere onto the object. Pass criterions for placement
# as a hash, eg:
#
# my_canvas.addPlacement({
# "texture": "EICAS.png",
# "node": "PFD-Screen",
# "parent": "Some parent name"
# });
#
# Note that we can choose whichever of the three filter criterions we use for
# matching the target object for our placement. If none of the three fields is
# given every texture of the model will be replaced.
addPlacement: func(vals)
{
var placement = _createNodeWithIndex(me.texture, "placement");
placement.setValues(vals);
return placement;
},
# Create a new group with the given name
#
# @param id Optional id/name for the group
createGroup: func(id = nil)
{
return Group.new([me.texture, "group"], id);
},
# Set the background color
#
# @param color Vector of 3 or 4 values in [0, 1]
setColorBackground: func { _setColorNodes(me.color, arg); return me; },
# Get path of canvas to be used eg. in Image::setFile
getPath: func()
{
return "canvas://by-index/texture[" ~ me._node.getIndex() ~ "]";
}
};
# Create a new canvas. Pass parameters as hash, eg:
#
# var my_canvas = canvas.new({
# "name": "PFD-Test",
# "size": [512, 512],
# "view": [768, 1024],
# "mipmapping": 1
# });
var new = func(vals)
{
var m = { parents: [Canvas] };
m.texture = _createNodeWithIndex(Canvas.property_root, "texture");
m.color = _createColorNodes(m.texture, "color-background");
m.texture.setValues(vals);
return m;
};
# Get the first existing canvas with the given name
#
# @param name Name of the canvas
# @return #Canvas, if canvas with #name exists
# nil, otherwise
var get = func(name)
{
var node_canvas = nil;
if( isa(name, props.Node) )
node_canvas = name;
else if( typeof(name) == 'scalar' )
{
foreach(var c; Canvas.property_root.getChildren("texture"))
{
if( c.getValue("name") == name )
node_canvas = c;
}
}
if( node_canvas == nil )
{
debug.warn("Canvas not found: " ~ name);
return nil;
}
return {
parents: [Canvas],
texture: node_canvas,
color: _createColorNodes(node_canvas, "color-background")
};
};
# ------------------------------------------------------------------------------
# Show warnings if API used with too old version of FlightGear without Canvas
# support (Wrapped in anonymous function do not polute the canvas namespace)
(func {
var version_str = getprop("/sim/version/flightgear");
if( string.scanf(version_str, "%u.%u.%u", var fg_version = []) < 1 )
debug.warn("Canvas: Error parsing flightgear version (" ~ version_str ~ ")");
else
{
if( fg_version[0] < 2
or (fg_version[0] == 2 and fg_version[1] < 8) )
{
debug.warn("Canvas: FlightGear version too old (" ~ version_str ~ ")");
gui.popupTip
(
"FlightGear v2.8.0 or newer needed for Canvas support!",
600,
{button: {legend: "Ok", binding: {command: "dialog-close"}}}
);
}
}
Canvas.property_root = props.globals.getNode("canvas/by-index", 1);
})();

75
Nasal/canvas/gui.nas Normal file
View file

@ -0,0 +1,75 @@
var Dialog = {
# Constructor
#
# @param size_dlg Dialog size ([width, height])
new: func(size_dlg, id = nil)
{
var m = {
parents: [Dialog, PropertyElement.new(["/sim/gui/canvas", "window"], id)]
};
m.setInt("size[0]", size_dlg[0]);
m.setInt("size[1]", size_dlg[1]);
return m;
},
# Create the canvas to be used for this dialog
#
# @return The new canvas
createCanvas: func()
{
var size_dlg = [
me.get("size[0]"),
me.get("size[1]")
];
me._canvas = new({
size: [2 * size_dlg[0], 2 * size_dlg[1]],
view: size_dlg,
placement: {
type: "window",
index: me._node.getIndex()
}
});
},
# Set an existing canvas to be used for this dialog
setCanvas: func(canvas_)
{
if( !isa(canvas_, canvas.Canvas) )
return debug.warn("Not a canvas.Canvas");
canvas_.addPlacement({type: "window", index: me._node.getIndex()});
me['_canvas'] = canvas_;
},
# Get the displayed canvas
getCanvas: func()
{
return me['_canvas'];
},
setPosition: func(x, y)
{
me.setInt("x", x);
me.setInt("y", y);
},
move: func(x, y)
{
me.setInt("x", me.get("x", 0) + x);
me.setInt("y", me.get("y", 0) + y);
},
# Raise to top of window stack
raise: func()
{
me.setBool("raise-top", 1);
}
};
var Event = {
PUSH: 1,
RELEASE: 2,
DRAG: 8,
MOVE: 16,
SCROLL: 512,
LEFT_MOUSE_BUTTON: 1,
MIDDLE_MOUSE_BUTTON: 2,
RIGHT_MOUSE_BUTTON: 4
};

437
Nasal/canvas/svg.nas Normal file
View file

@ -0,0 +1,437 @@
# Parse an xml file into a canvas group element
#
# @param group The canvas.Group instance to append the parsed elements to
# @param path The path of the svg file (absolute or relative to FG_ROOT)
# @param options Optional hash of options
var parsesvg = func(group, path, options = nil)
{
if( !isa(group, Group) )
die("Invalid argument group (type != Group)");
if( options == nil )
options = {};
if( typeof(options) != "hash" )
die("Options need to be of type hash!");
var custom_font_mapper = options['font-mapper'];
var font_mapper = func(family, weight)
{
if( typeof(custom_font_mapper) == 'func' )
{
var font = custom_font_mapper(family, weight);
if( font != nil )
return font;
}
return "LiberationFonts/LiberationMono-Bold.ttf";
};
var level = 0;
var skip = 0;
var stack = [group];
var close_stack = []; # helper for check tag closing
# lookup table for element ids (for <use> element)
var id_dict = {};
# ----------------------------------------------------------------------------
# Create a new child an push it onto the stack
var pushElement = func(type, id = nil)
{
append(stack, stack[-1].createChild(type, id));
append(close_stack, level);
if( typeof(id) == 'scalar' and size(id) )
id_dict[ id ] = stack[-1];
};
# ----------------------------------------------------------------------------
# Parse a transformation (matrix)
# http://www.w3.org/TR/SVG/coords.html#TransformAttribute
var parseTransform = func(tf)
{
if( tf == nil )
return;
tf = std.string.new(tf);
var end = 0;
while(1)
{
var start_type = tf.find_first_not_of("\t\n ", end);
if( start_type < 0 )
break;
var end_type = tf.find_first_of("(\t\n ", start_type + 1);
if( end_type < 0 )
break;
var start_args = tf.find('(', end_type);
if( start_args < 0 )
break;
var values = [];
end = start_args;
while(1)
{
var start_num = tf.find_first_not_of(",\t\n ", end + 1);
if( start_num < 0 )
break;
if( tf[start_num] == ')' )
break;
end = tf.find_first_of("),\t\n ", start_num + 1);
if( end < 0 )
break;
append(values, tf.substr(start_num, end - start_num));
}
var type = tf.substr(start_type, end_type - start_type);
if( type == "translate" )
# translate(<tx> [<ty>]), which specifies a translation by tx and ty. If
# <ty> is not provided, it is assumed to be zero.
stack[-1].createTransform().setTranslation
(
values[0],
size(values) > 1 ? values[1] : 0,
);
else if( type == "matrix" )
{
if( size(values) == 6 )
stack[-1].createTransform(values);
else
debug.dump('invalid transform', type, values);
}
else
debug.dump(['unknown transform', type, values]);
}
};
# ----------------------------------------------------------------------------
# Parse a path
# http://www.w3.org/TR/SVG/paths.html#PathData
# map svg commands OpenVG commands
var cmd_map = {
z: Path.VG_CLOSE_PATH,
m: Path.VG_MOVE_TO,
l: Path.VG_LINE_TO,
h: Path.VG_HLINE_TO,
v: Path.VG_VLINE_TO,
q: Path.VG_QUAD_TO,
c: Path.VG_CUBIC_TO,
t: Path.VG_SQUAD_TO,
s: Path.VG_SCUBIC_TO
};
var parsePath = func(d)
{
if( d == nil )
return;
var path_data = std.string.new(d);
var pos = 0;
var cmds = [];
var coords = [];
while(1)
{
# skip trailing spaces
pos = path_data.find_first_not_of("\t\n ", pos);
if( pos < 0 )
break;
# get command
var cmd = path_data.substr(pos, 1);
pos += 1;
# and get all following arguments
var args = [];
while(1)
{
pos = path_data.find_first_not_of(",\t\n ", pos);
if( pos < 0 )
break;
var start_num = pos;
pos = path_data.find_first_not_of("e-.0123456789", start_num);
if( start_num == pos )
break;
append(args, path_data.substr(start_num, pos > 0 ? pos - start_num : nil));
}
# now execute the command
var rel = string.islower(cmd[0]);
var cmd = string.lc(cmd);
if( cmd == 'a' )
{
for(var i = 0; i + 7 <= size(args); i += 7)
{
# SVG: (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+
# OpenVG: rh,rv,rot,x0,y0
if( args[i + 3] )
var cmd_vg = args[i + 4] ? Path.VG_LCCWARC_TO : Path.VG_LCWARC_TO;
else
var cmd_vg = args[i + 4] ? Path.VG_SCCWARC_TO : Path.VG_SCWARC_TO;
append(cmds, rel ? cmd_vg + 1: cmd_vg);
append(coords, args[i],
args[i + 1],
args[i + 2],
args[i + 5],
args[i + 6] );
}
if( math.mod(size(args), 7) > 0 )
debug.dump('too much coords for cmd', cmd, args);
}
else
{
var cmd_vg = cmd_map[cmd];
if( cmd_vg == nil )
{
debug.dump('command not found', cmd, args);
continue;
}
var num_coords = Path.num_coords[int(cmd_vg)];
if( num_coords == 0 )
append(cmds, cmd_vg);
else
{
for(var i = 0; i + num_coords <= size(args); i += num_coords)
{
append(cmds, rel ? cmd_vg + 1: cmd_vg);
for(var j = i; j < i + num_coords; j += 1)
append(coords, args[j]);
# If a moveto is followed by multiple pairs of coordinates, the
# subsequent pairs are treated as implicit lineto commands.
if( cmd == 'm' )
cmd_vg = cmd_map['l'];
}
if( math.mod(size(args), num_coords) > 0 )
debug.warn('too much coords for cmd: ' ~ cmd);
}
}
}
stack[-1].setData(cmds, coords);
};
# ----------------------------------------------------------------------------
# Parse a css style attribute
var parseStyle = func(style)
{
if( style == nil )
return {};
var styles = {};
foreach(var part; split(';', style))
{
if( !size(part = string.trim(part)) )
continue;
if( size(part = split(':',part)) != 2 )
continue;
var key = string.trim(part[0]);
if( !size(key) )
continue;
var value = string.trim(part[1]);
if( !size(value) )
continue;
styles[key] = value;
}
return styles;
}
# ----------------------------------------------------------------------------
# Parse a css color
var parseColor = func(s)
{
var color = [0, 0, 0];
if( s == nil )
return color;
if( size(s) == 7 and substr(s, 0, 1) == '#' )
{
return [ std.stoul(substr(s, 1, 2), 16) / 255,
std.stoul(substr(s, 3, 2), 16) / 255,
std.stoul(substr(s, 5, 2), 16) / 255 ];
}
return color;
};
# ----------------------------------------------------------------------------
# XML parsers element open callback
var start = func(name, attr)
{
level += 1;
if( skip )
return;
if( level == 1 )
{
if( name != 'svg' )
die("Not an svg file (root=" ~ name ~ ")");
else
return;
}
var style = parseStyle(attr['style']);
if( style['display'] == 'none' )
{
skip = level - 1;
return;
}
else if( name == "g" )
{
pushElement('group', attr['id']);
}
else if( name == "text" )
{
pushElement('text', attr['id']);
stack[-1].setTranslation(attr['x'], attr['y']);
# http://www.w3.org/TR/SVG/text.html#TextAnchorProperty
var h_align = style["text-anchor"];
if( h_align == "end" )
h_align = "right";
else if( h_align == "middle" )
h_align = "center";
else # "start"
h_align = "left";
stack[-1].setAlignment(h_align ~ "-baseline");
# TODO vertical align
stack[-1].setColor(parseColor(style['fill']));
stack[-1].setFont
(
font_mapper(style["font-family"], style["font-weight"])
);
var font_size = style["font-size"];
if( font_size != nil )
# eg. font-size: 123px
stack[-1].setFontSize(substr(font_size, 0, size(font_size) - 2));
}
else if( name == "path" or name == "rect" )
{
pushElement('path', attr['id']);
var d = attr['d'];
if( name == "rect" )
{
var width = attr['width'];
var height = attr['height'];
var x = attr['x'];
var y = attr['y'];
d = sprintf("M%f,%f v%f h%f v%fz", x, y, height, width, -height);
}
parsePath(d);
stack[-1].set('fill', style['fill']);
var w = style['stroke-width'];
stack[-1].setStrokeLineWidth( w != nil ? w : 1 );
stack[-1].set('stroke', style['stroke'] or "none");
var linecap = style['stroke-linecap'];
if( linecap != nil )
stack[-1].setStrokeLineCap(style['stroke-linecap']);
# http://www.w3.org/TR/SVG/painting.html#StrokeDasharrayProperty
var dash = style['stroke-dasharray'];
if( dash and size(dash) > 3 )
# at least 2 comma separated values...
stack[-1].setStrokeDashArray(split(',', dash));
var cx = attr['inkscape:transform-center-x'];
var cy = attr['inkscape:transform-center-y'];
if( cx != nil or cy != nil )
stack[-1].setCenter(cx or 0, -(cy or 0));
}
else if( name == "tspan" )
{
return;
}
else if( name == "use" )
{
var ref = attr["xlink:href"];
if( ref == nil or size(ref) < 2 or ref[0] != `#` )
return debug.dump("Invalid or missing href", ref);
var el_src = id_dict[ substr(ref, 1) ];
if( el_src == nil )
return print("parsesvg: Reference to unknown element (" ~ ref ~ ")");
# Create new element and copy sub branch from source node
pushElement(el_src._node.getName(), attr['id']);
props.copy(el_src._node, stack[-1]._node);
# copying also overrides the id so we need to set it again
stack[-1]._node.getNode("id").setValue(attr['id']);
}
else
{
print("parsesvg: skipping unknown element '" ~ name ~ "'");
skip = level;
return;
}
parseTransform(attr['transform']);
};
# XML parsers element close callback
var end = func(name)
{
level -= 1;
if( skip )
{
if( level <= skip )
skip = 0;
return;
}
if( size(close_stack) and (level + 1) == close_stack[-1] )
{
pop(stack);
pop(close_stack);
}
};
# XML parsers element data callback
var data = func(data)
{
if( skip )
return;
if( size(data) and isa(stack[-1], Text) )
stack[-1].setText(data);
};
if( path[0] != '/' )
path = getprop("/sim/fg-root") ~ "/" ~ path;
call(func parsexml(path, start, end, data), nil, var err = []);
if( size(err) )
{
debug.dump(err);
return 0;
}
return 1;
}

View file

@ -856,47 +856,55 @@ var showWeightDialog = func {
var contentArea = dialog[name].addChild("group");
contentArea.set("layout", "hbox");
contentArea.set("default-padding", 10);
dialog[name].addChild("empty");
var limits = dialog[name].addChild("group");
limits.set("layout", "table");
limits.set("halign", "center");
var row = 0;
var massLimits = props.globals.getNode("/limits/mass-and-balance");
var tablerow = func(name, node, format ) {
var n = isa( node, props.Node ) ? node : massLimits.getNode( node );
if( n == nil ) return;
var label = limits.addChild("text");
label.set("row", row);
label.set("col", 0);
label.set("halign", "right");
label.set("label", name ~ ":");
var val = limits.addChild("text");
val.set("row", row);
val.set("col", 1);
val.set("halign", "left");
val.set("label", "0123457890123456789");
val.set("format", format);
val.set("property", n.getPath());
val.set("live", 1);
row += 1;
}
var grossWgt = props.globals.getNode(fdmdata.grosswgt);
if(grossWgt != nil) {
var gwg = dialog[name].addChild("group");
gwg.set("layout", "hbox");
gwg.addChild("empty").set("stretch", 1);
gwg.addChild("text").set("label", "Gross Weight:");
var txt = gwg.addChild("text");
txt.set("label", "0123456789");
txt.set("format", "%.0f lb");
txt.set("property", fdmdata.grosswgt);
txt.set("live", 1);
gwg.addChild("empty").set("stretch", 1);
tablerow("Gross Weight", grossWgt, "%.0f lb");
}
var massLimits = props.globals.getNode("/limits/mass-and-balance");
if(massLimits != nil ) {
var weightitem = func( group, name, node, format ) {
group.set("layout", "hbox");
var n = isa( node, props.Node ) ? node : massLimits.getNode( node );
if( n == nil ) return;
group.addChild("empty").set("stretch", 1);
group.addChild("text").set("label", name ~ ":" );
var txt = group.addChild("text");
txt.set("label", "");
txt.set("format", format );
txt.set("property", n.getPath() );
txt.set("live", 1);
group.addChild("empty").set("stretch", 1);
tablerow("Max. Ramp Weight", "maximum-ramp-mass-lbs", "%.0f lb" );
tablerow("Max. Takeoff Weight", "maximum-takeoff-mass-lbs", "%.0f lb" );
tablerow("Max. Landing Weight", "maximum-landing-mass-lbs", "%.0f lb" );
tablerow("Max. Zero Fuel Weight", "maximum-zero-fuel-mass-lbs", "%.0f lb" );
}
weightitem( dialog[name].addChild("group"), "Max. Ramp Weight", "maximum-ramp-mass-lbs", "%.0f lb" );
weightitem( dialog[name].addChild("group"), "Max. Takeoff Weight", "maximum-takeoff-mass-lbs", "%.0f lb" );
weightitem( dialog[name].addChild("group"), "Max. Landing Weight", "maximum-landing-mass-lbs", "%.0f lb" );
weightitem( dialog[name].addChild("group"), "Max. Zero Fuel Weight", "maximum-zero-fuel-mass-lbs", "%.0f lb" );
if( fdmdata.cg != nil ) {
var n = massLimits.getNode("cg/dimension");
weightitem( dialog[name].addChild("group"), "CG", fdmdata.cg, "%.1f " ~ (n == nil ? "in" : n.getValue()));
}
weightitem = nil;
var n = props.globals.getNode("/limits/mass-and-balance/cg/dimension");
tablerow("Center of Gravity", props.globals.getNode(fdmdata.cg), "%.1f " ~ (n == nil ? "in" : n.getValue()));
}
dialog[name].addChild("hrule");
@ -934,6 +942,7 @@ var showWeightDialog = func {
tcell(fuelTable, "text", 0, 0).set("label", "Tank");
tcell(fuelTable, "text", 0, 3).set("label", "Pounds");
tcell(fuelTable, "text", 0, 4).set("label", "Gallons");
tcell(fuelTable, "text", 0, 5).set("label", "Fraction");
var tanks = props.globals.getNode("/consumables/fuel").getChildren("tank");
for(var i=0; i<size(tanks); i+=1) {
@ -951,6 +960,9 @@ var showWeightDialog = func {
if(cap == nil ) { continue; }
cap = cap.getValue();
# Ignore tanks of capacity 0
if (cap == 0) { continue; }
var title = tcell(fuelTable, "text", i+1, 0);
title.set("label", tname);
title.set("halign", "right");
@ -974,15 +986,52 @@ var showWeightDialog = func {
lbs.set("property", tankprop ~ "/level-lbs");
lbs.set("label", "0123456");
lbs.set("format", cap < 1 ? "%.3f" : cap < 10 ? "%.2f" : "%.1f" );
lbs.set("halign", "right");
lbs.set("live", 1);
var gals = tcell(fuelTable, "text", i+1, 4);
gals.set("property", tankprop ~ "/level-gal_us");
gals.set("label", "0123456");
gals.set("format", cap < 1 ? "%.3f" : cap < 10 ? "%.2f" : "%.1f" );
gals.set("halign", "right");
gals.set("live", 1);
var per = tcell(fuelTable, "text", i+1, 5);
per.set("property", tankprop ~ "/level-norm");
per.set("label", "0123456");
per.set("format", "%.2f");
per.set("halign", "right");
per.set("live", 1);
}
varbar = tcell(fuelTable, "hrule", size(tanks)+1, 0);
varbar.set("colspan", 6);
var total_label = tcell(fuelTable, "text", size(tanks)+2, 2);
total_label.set("label", "Total:");
total_label.set("halign", "right");
var lbs = tcell(fuelTable, "text", size(tanks)+2, 3);
lbs.set("property", "/consumables/fuel/total-fuel-lbs");
lbs.set("label", "0123456");
lbs.set("format", "%.1f" );
lbs.set("halign", "right");
lbs.set("live", 1);
var gals = tcell(fuelTable, "text",size(tanks) +2, 4);
gals.set("property", "/consumables/fuel/total-fuel-gal_us");
gals.set("label", "0123456");
gals.set("format", "%.1f" );
gals.set("halign", "right");
gals.set("live", 1);
var per = tcell(fuelTable, "text", size(tanks)+2, 5);
per.set("property", "/consumables/fuel/total-fuel-norm");
per.set("label", "0123456");
per.set("format", "%.2f");
per.set("halign", "right");
per.set("live", 1);
var weightArea = contentArea.addChild("group");
weightArea.set("layout", "vbox");
weightArea.addChild("text").set("label", "Payload");

686
Nasal/joystick.nas Normal file
View file

@ -0,0 +1,686 @@
# Joystick configuration library.
var DIALOGROOT = "/sim/gui/dialogs/joystick-config";
var MAX_AXES = 8;
var MAX_BUTTONS = 24;
# Hash of the custom axis/buttons
var custom_bindings = {};
# Class for an individual joystick axis binding
var Axis = {
new: func(name, prop, invertable) {
var m = { parents: [Axis] };
m.name = name;
m.prop = prop;
m.invertable = invertable;
m.inverted = 0;
return m;
},
clone: func() {
var m = { parents: [Axis] };
m.name = me.name;
m.prop = me.prop;
m.invertable = me.invertable;
m.inverted = me.inverted;
return m;
},
match: func(prop) {
return 0;
},
parse: func(prop) { },
readProps: func(props) {},
getName: func() { return me.name; },
getBinding: func(axis) { return props.Node.new(); },
isInvertable: func() { return me.invertable; },
isInverted: func() { return me.inverted; },
setInverted: func(b) {
if (me.invertable) me.inverted = b;
},
};
var CustomAxis = {
new: func() {
var m = { parents: [CustomAxis, Axis.new("Custom", "", 0) ] };
me.custom_binding = nil;
return m;
},
clone: func() {
var m = { parents: [CustomAxis, Axis.new("Custom", "", 0) ] };
m.custom_binding = me.custom_binding;
return m;
},
match: func(prop) {
var p = props.Node.new();
if (prop.getNode("binding") != nil) {
props.copy(prop.getNode("binding"), p);
me.custom_binding = p;
return 1;
} else {
return 0;
}
},
getBinding: func(axis) {
var p = props.Node.new().getNode("axis[" ~ axis ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
props.copy(me.custom_binding, p.getNode("binding", 1));
return p;
},
};
var UnboundAxis = {
new: func() {
var m = { parents: [UnboundAxis, Axis.new("None", "", 0) ] };
return m;
},
clone: func() {
var m = { parents: [UnboundAxis, Axis.new("None", "", 0) ] };
return m;
},
match: func(prop) {
return 1;
},
getBinding: func(axis) {
return nil;
},
};
var PropertyScaleAxis = {
new: func(name, prop, deadband=0, factor=1, offset=0) {
var m = { parents: [PropertyScaleAxis, Axis.new(name, prop, 1) ] };
m.prop=prop;
m.deadband = deadband;
m.factor = factor;
m.offset = offset;
return m;
},
clone: func() {
var m = { parents: [PropertyScaleAxis, Axis.new(me.name, me.prop, 1) ] };
m.inverted = me.inverted;
m.prop= me.prop;
m.deadband = me.deadband;
m.factor = me.factor;
m.offset = me.offset;
return m;
},
match: func(prop) {
var cmd = prop.getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("binding", 1).getNode("property", 1).getValue();
return ((cmd == "property-scale") and (p == me.prop));
},
parse: func(p) {
me.deadband = p.getNode("binding", 1).getNode("dead-band", 1).getValue();
if (p.getNode("binding", 1).getNode("factor", 1).getValue() != nil) {
me.inverted = (p.getNode("binding", 1).getNode("factor", 1).getValue() < 0);
}
me.offset = p.getNode("binding", 1).getNode("offset", 1).getValue();
},
getBinding: func(axis) {
var p = props.Node.new();
p = p.getNode("axis[" ~ axis ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("binding", 1).getNode("command", 1).setValue("property-scale");
p.getNode("binding", 1).getNode("property", 1).setValue(me.prop);
p.getNode("binding", 1).getNode("dead-band", 1).setValue(me.deadband);
if (me.inverted) {
p.getNode("binding", 1).getNode("factor", 1).setValue(0 - me.factor);
} else {
p.getNode("binding", 1).getNode("factor", 1).setValue(me.factor);
}
p.getNode("binding", 1).getNode("offset", 1).setValue(me.offset);
return p;
},
};
var NasalScaleAxis = {
new: func(name, script, prop) {
var m = { parents: [NasalScaleAxis, Axis.new(name, prop, 0) ] };
m.script = script;
m.prop = prop;
return m;
},
clone: func() {
var m = { parents: [NasalScaleAxis, Axis.new(me.name, me.prop, 0) ] };
m.script = me.script;
m.prop = me.prop;
return m;
},
match: func(prop) {
var cmd = prop.getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("binding", 1).getNode("script", 1).getValue();
if ((p != nil) and (cmd == "nasal")) {
p = string.trim(p);
p = string.replace(p, ";", "");
p = p ~ ";";
return (p == me.script);
} else {
return 0;
}
},
getBinding: func(axis) {
var p = props.Node.new().getNode("axis[" ~ axis ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("binding", 1).getNode("command", 1).setValue("nasal");
p.getNode("binding", 1).getNode("script", 1).setValue(me.script);
return p;
},
};
var NasalLowHighAxis = {
new: func(name, lowscript, highscript, prop) {
var m = { parents: [NasalLowHighAxis, Axis.new(name, prop, 1) ] };
m.lowscript = lowscript;
m.highscript = highscript;
return m;
},
clone: func() {
var m = { parents: [NasalLowHighAxis, Axis.new(me.name, me.prop, 1) ] };
m.inverted = me.inverted;
m.lowscript = me.lowscript;
m.highscript = me.highscript;
return m;
},
match: func(prop) {
var cmd = prop.getNode("low", 1).getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("low", 1).getNode("binding", 1).getNode("script", 1).getValue();
if ((p == nil) or (cmd != "nasal")) return 0;
p = string.trim(p);
p = string.replace(p, ";", "");
p = p ~ ";";
if (p == me.lowscript) {
return 1;
}
if (p == me.highscript) {
me.inverted = 1;
return 1;
}
return 0;
},
getBinding: func(axis) {
var p = props.Node.new().getNode("axis[" ~ axis ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("low", 1).getNode("binding", 1).getNode("command", 1).setValue("nasal");
p.getNode("high", 1).getNode("binding", 1).getNode("command", 1).setValue("nasal");
if (me.inverted) {
p.getNode("low", 1).getNode("binding", 1).getNode("script", 1).setValue(me.highscript);
p.getNode("high", 1).getNode("binding", 1).getNode("script", 1).setValue(me.lowscript);
} else {
p.getNode("low", 1).getNode("binding", 1).getNode("script", 1).setValue(me.lowscript);
p.getNode("high", 1).getNode("binding", 1).getNode("script", 1).setValue(me.highscript);
}
return p;
},
};
var axisBindings = [
PropertyScaleAxis.new("Aileron", "/controls/flight/aileron"),
PropertyScaleAxis.new("Elevator", "/controls/flight/elevator"),
PropertyScaleAxis.new("Rudder", "/controls/flight/rudder"),
NasalScaleAxis.new("Throttle", "controls.throttleAxis();", "/controls/engines/engine[0]/throttle") ,
NasalScaleAxis.new("Mixture", "controls.mixtureAxis();", "/controls/engines/engine[0]/mixture") ,
NasalScaleAxis.new("Propeller", "controls.propellerAxis();", "/controls/engines/engine[0]/propeller-pitch") ,
NasalLowHighAxis.new("View (horizontal)",
"setprop(\"/sim/current-view/goal-heading-offset-deg\", getprop(\"/sim/current-view/goal-heading-offset-deg\") + 30);",
"setprop(\"/sim/current-view/goal-heading-offset-deg\", getprop(\"/sim/current-view/goal-heading-offset-deg\") - 30);",
"/sim/current-view/goal-heading-offset-deg"),
NasalLowHighAxis.new("View (vertical)",
"setprop(\"/sim/current-view/goal-pitch-offset-deg\", getprop(\"/sim/current-view/goal-pitch-offset-deg\") - 20);",
"setprop(\"/sim/current-view/goal-pitch-offset-deg\", getprop(\"/sim/current-view/goal-pitch-offset-deg\") + 20);",
"/sim/current-view/goal-heading-offset-deg"),
# PropertyScaleAxis.new("Aileron Trim", "/controls/flight/aileron-trim"),
# PropertyScaleAxis.new("Elevator Trim", "/controls/flight/elevator-trim"),
# PropertyScaleAxis.new("Rudder Trim", "/controls/flight/rudder-trim"),
PropertyScaleAxis.new("Brake Left", "/controls/gear/brake-left", 0, 0.5, 1.0),
PropertyScaleAxis.new("Brake Right", "/controls/gear/brake-right", 0, 0.5, 1.0),
NasalLowHighAxis.new("Aileron Trim", "controls.aileronTrim(-1);", "controls.aileronTrim(1);", "/controls/flight/aileron-trim"),
NasalLowHighAxis.new("Elevator Trim", "controls.elevatorTrim(-1);", "controls.elevatorTrim(1);", "/controls/flight/elevator-trim"),
NasalLowHighAxis.new("Rudder Trim", "controls.rudderTrim(-1);", "controls.rudderTrim(1);", "/controls/flight/rudder-trim"),
CustomAxis.new(),
UnboundAxis.new(),
];
# Button bindings
var ButtonBinding = {
new: func(name, binding, repeatable) {
var m = { parents: [ButtonBinding] };
m.name = name;
m.binding = binding;
m.repeatable = repeatable;
return m;
},
clone: func() {
var m = { parents: [ButtonBinding] };
m.name = me.name;
m.binding= me.binding;
m.repeatable = me.repeatable;
return m;
},
match: func(prop) {
return 0;
},
getName: func() { return me.name; },
getBinding: func(button) { return nil; },
isRepeatable: func() { return me.repeatable; }
};
var CustomButton = {
new: func() {
var m = { parents: [CustomButton, ButtonBinding.new("Custom", "", 0) ] };
m.custom_binding = nil;
return m;
},
clone: func() {
var m = { parents: [CustomButton, ButtonBinding.new("Custom", "", 0) ] };
m.custom_binding = me.custom_binding;
return m;
},
match: func(prop) {
if (prop.getNode("binding") != nil) {
var p = props.Node.new();
props.copy(prop.getNode("binding"), p);
me.custom_binding = p;
return 1;
} else {
return 0;
}
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
props.copy(me.custom_binding, p.getNode("binding", 1));
return p;
},
};
var UnboundButton = {
new: func() {
var m = { parents: [UnboundButton, ButtonBinding.new("None", "", 0) ] };
return m;
},
clone: func() {
var m = { parents: [UnboundButton, ButtonBinding.new("None", "", 0) ] };
return m;
},
match: func(prop) {
return (prop.getNode("binding") != nil);
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
return p;
},
};
var PropertyToggleButton = {
new: func(name, prop) {
var m = { parents: [PropertyToggleButton, ButtonBinding.new(name, prop, 0) ] };
return m;
},
clone: func() {
var m = { parents: [PropertyToggleButton, ButtonBinding.new(me.name, me.binding, 0) ] };
return m;
},
match: func(prop) {
var c = prop.getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("binding", 1).getNode("property", 1).getValue();
return ((c == "property-toggle") and (p == me.prop));
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("binding", 1).getNode("command", 1).setValue("property-toggle");
p.getNode("binding", 1).getNode("property", 1).setValue(me.binding);
return p;
},
};
var PropertyAdjustButton = {
new: func(name, prop, step) {
var m = { parents: [PropertyAdjustButton, ButtonBinding.new(name, prop, 0) ] };
m.step = step;
return m;
},
clone: func() {
var m = { parents: [PropertyAdjustButton, ButtonBinding.new(me.name, me.binding, 0) ] };
m.step = me.step;
return m;
},
match: func(prop) {
var c = prop.getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("binding", 1).getNode("property", 1).getValue();
var s = prop.getNode("binding", 1).getNode("step", 1).getValue();
return ((c == "property-adjust") and (p == me.binding) and (s == me.step));
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("binding", 1).getNode("command", 1).setValue("property-adjust");
p.getNode("binding", 1).getNode("property", 1).setValue(me.binding);
p.getNode("binding", 1).getNode("step", 1).setValue(me.step);
return p;
},
};
var NasalButton = {
new: func(name, script, repeatable) {
var m = { parents: [NasalButton, ButtonBinding.new(name, script, repeatable) ] };
return m;
},
clone: func() {
var m = { parents: [NasalButton, ButtonBinding.new(me.name, me.binding, me.repeatable) ] };
return m;
},
match: func(prop) {
var c = prop.getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("binding", 1).getNode("script", 1).getValue();
if (p == nil) { return 0; }
p = string.trim(p);
p = string.replace(p, ";", "");
p = p ~ ";";
return ((c == "nasal") and (p == me.binding));
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("binding", 1).getNode("command", 1).setValue("nasal");
p.getNode("binding", 1).getNode("script", 1).setValue(me.binding);
p.getNode("repeatable", 1).setValue(me.repeatable);
return p;
},
};
var NasalHoldButton = {
new: func(name, script, scriptUp) {
var m = { parents: [NasalHoldButton, ButtonBinding.new(name, script, 0) ] };
m.scriptUp = scriptUp;
return m;
},
clone: func() {
var m = { parents: [NasalHoldButton, ButtonBinding.new(me.name, me.binding, 0) ] };
m.scriptUp = me.scriptUp;
return m;
},
match: func(prop) {
var c = prop.getNode("mod-up", 1).getNode("binding", 1).getNode("command", 1).getValue();
var p1 = prop.getNode("binding", 1).getNode("script", 1).getValue();
var p2 = prop.getNode("mod-up", 1).getNode("binding", 1).getNode("script", 1).getValue();
if (p2 == nil) { return 0; }
p1 = string.trim(p1);
p1 = string.replace(p1, ";", "");
p1 = p1 ~ ";";
return ((c == "nasal") and (p1 == me.binding));
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("repeatable", 1).setValue("false");
p.getNode("binding", 1).getNode("command", 1).setValue("nasal");
p.getNode("binding", 1).getNode("script", 1).setValue(me.binding);
p.getNode("mod-up", 1).getNode("binding", 1).getNode("command", 1).setValue("nasal");
p.getNode("mod-up", 1).getNode("binding", 1).getNode("script", 1).setValue(me.scriptUp);
return p;
},
};
var buttonBindings = [
NasalButton.new("Elevator Trim Up", "controls.elevatorTrim(-1);", 1),
NasalButton.new("Elevator Trim Down", "controls.elevatorTrim(1);", 1),
NasalButton.new("Rudder Trim Left", "controls.rudderTrim(-1);", 1),
NasalButton.new("Rudder Trim Right", "controls.rudderTrim(1);", 1),
NasalButton.new("Aileron Trim Left", "controls.aileronTrim(-1);", 1),
NasalButton.new("Aileron Trim Right", "controls.aileronTrim(1);", 1),
NasalHoldButton.new("FGCom PTT", "controls.ptt(1);", "controls.ptt(-1);"),
NasalHoldButton.new("Trigger", "controls.trigger(1);", "controls.trigger(0);"),
NasalHoldButton.new("Flaps Up", "controls.flapsDown(-1);", "controls.flapsDown(0);"),
NasalHoldButton.new("Flaps Down", "controls.flapsDown(1);", "controls.flapsDown(0);"),
NasalHoldButton.new("Gear Up", "controls.gearDown(-1);", "controls.gearDown(0);"),
NasalHoldButton.new("Gear Down", "controls.gearDown(1);", "controls.gearDown(0);"),
NasalHoldButton.new("Spoilers Retract", "controls.stepSpoilers(-1);", "controls.stepSpoilers(0);"),
NasalHoldButton.new("Spoilers Deploy", "controls.stepSpoilers(1);", "controls.stepSpoilers(0);"),
NasalHoldButton.new("Brakes", "controls.applyBrakes(1);", "controls.applyBrakes(0);"),
NasalButton.new("View Decrease", "view.decrease(0.75);", 1),
NasalButton.new("View Increase", "view.increase(0.75);", 1),
NasalButton.new("View Cycle Forwards", "view.stepView(1);", 0),
NasalButton.new("View Cycle Backwards", "view.stepView(-1);", 0),
PropertyAdjustButton.new("View Left", "/sim/current-view/goal-heading-offset-deg", "30.0"),
PropertyAdjustButton.new("View Right", "/sim/current-view/goal-heading-offset-deg", "-30.0"),
PropertyAdjustButton.new("View Up", "/sim/current-view/goal-pitch-offset-deg", "20.0"),
PropertyAdjustButton.new("View Down", "/sim/current-view/goal-pitch-offset-deg", "-20.0"),
CustomButton.new(),
];
# Parse config from the /input tree and write it to the
# dialog_root.
var readConfig = func(dialog_root="/sim/gui/dialogs/joystick-config") {
var js_name = getprop(dialog_root ~ "/selected-joystick");
var joysticks = props.globals.getNode("/input/joysticks").getChildren("js");
if (size(joystick) == 0) { return 0; }
if (js_name == nil) {
js_name = joysticks[0].getNode("id").getValue();
}
var js = nil;
forindex (var i; joysticks) {
if ((joysticks[i].getNode("id") != nil) and
(joysticks[i].getNode("id").getValue() == js_name))
{
js = joysticks[i];
setprop(dialog_root ~ "/selected-joystick", js_name);
setprop(dialog_root ~ "/selected-joystick-index", i);
setprop(dialog_root ~ "/selected-joystick-config", joysticks[i].getNode("source").getValue());
}
}
# Set up the axes assignments
var axes = js.getChildren("axis");
for (var axis = 0; axis < MAX_AXES; axis = axis +1) {
var p = props.globals.getNode(dialog_root ~ "/axis[" ~ axis ~ "]", 1);
p.remove();
p = props.globals.getNode(dialog_root ~ "/axis[" ~ axis ~ "]", 1);
# Note that we can't simply use an index into the axes array
# as that doesn't work for a sparsley populated set of axes.
# E.g. one with n="3"
var a = js.getNode("axis[" ~ axis ~ "]");
if (a != nil) {
# Read properties from bindings
props.copy(a, p.getNode("original_binding", 1));
var binding = nil;
foreach (var b; joystick.axisBindings) {
if ((binding == nil) and (a != nil) and b.match(a)) {
binding = b.clone();
binding.parse(a);
p.getNode("binding", 1).setValue(binding.getName());
p.getNode("invertable", 1).setValue(binding.isInvertable());
p.getNode("inverted", 1).setValue(binding.isInverted());
}
}
if (binding == nil) {
# No binding for this axis
p.getNode("binding", 1).setValue("None");
p.getNode("invertable", 1).setValue(0);
p.getNode("inverted", 1).setValue(0);
p.removeChild("original_binding");
}
} else {
p.getNode("binding", 1).setValue("None");
p.getNode("invertable", 1).setValue(0);
p.getNode("inverted", 1).setValue(0);
p.removeChild("original_binding");
}
}
# Set up button assignment.
var buttons = js.getChildren("button");
for (var button = 0; button < MAX_BUTTONS; button = button + 1) {
var btn = props.globals.getNode(dialog_root ~ "/button[" ~ button ~ "]", 1);
btn.remove();
btn = props.globals.getNode(dialog_root ~ "/button[" ~ button ~ "]", 1);
# Note that we can't simply use an index into the buttons array
# as that doesn't work for a sparsley populated set of buttons.
# E.g. one with n="3"
var a = js.getNode("button[" ~ button ~ "]");
if (a != nil) {
# Read properties from bindings
props.copy(a, p.getNode("original_binding", 1));
var binding = nil;
foreach (var b; joystick.buttonBindings) {
if ((binding == nil) and (a != nil) and b.match(a)) {
binding = b.clone();
btn.getNode("binding", 1).setValue(binding.getName());
props.copy(b.getBinding(button), btn.getNode("original_binding", 1));
}
}
if (b == nil) {
btn.getNode("binding", 1).setValue("None");
btn.removeChild("original_binding");
}
} else {
btn.getNode("binding", 1).setValue("None");
btn.removeChild("original_binding");
}
}
}
var writeConfig = func(dialog_root="/sim/gui/dialogs/joystick-config") {
# Write out the joystick file.
var config = props.Node.new();
var id = getprop(dialog_root ~ "/selected-joystick");
config.getNode("name", 1).setValue(id);
var axes = props.globals.getNode(dialog_root).getChildren("axis");
forindex (var axis; axes) {
var name = getprop(dialog_root ~ "/axis[" ~ axis ~ "]/binding");
if (name != "None") {
foreach (var binding; axisBindings) {
if (binding.getName() == name) {
var b = binding.clone();
b.setInverted(getprop(dialog_root ~ "/axis[" ~ axis ~ "]/inverted"));
# Generate the axis and binding
var axisnode = config.getNode("axis[" ~ axis ~ "]", 1);
if (name == "Custom") {
props.copy(props.globals.getNode(dialog_root ~ "/axis[" ~ axis ~ "]/original_binding", 1), axisnode);
} else {
props.copy(b.getBinding(axis), axisnode);
}
}
}
}
}
var buttons = props.globals.getNode(dialog_root).getChildren("button");
forindex (var btn; buttons) {
var name = getprop(dialog_root ~ "/button[" ~ btn ~ "]/binding");
if (name != "None") {
foreach (var binding; buttonBindings) {
if (binding.getName() == name) {
var b = binding.clone();
# Generate the axis and binding
var buttonprop = config.getNode("button[" ~ btn ~ "]", 1);
if (name == "Custom") {
props.copy(props.globals.getNode(dialog_root ~ "/button[" ~ btn ~ "]/original_binding", 1), buttonprop);
} else {
props.copy(b.getBinding(btn), buttonprop);
}
}
}
}
}
var filename = id;
filename = string.replace(filename, " ", "");
filename = string.replace(filename, ".", "");
filename = string.replace(filename, "/", "");
# Write out the file
io.write_properties(getprop("/sim/fg-home") ~ "/Input/Joysticks/" ~ filename ~ ".xml", config);
}

74
Nasal/std/string.nas Normal file
View file

@ -0,0 +1,74 @@
# ------------------------------------------------------------------------------
# A C++ like string class (http://en.cppreference.com/w/cpp/string/basic_string)
# ------------------------------------------------------------------------------
# capture global string
var _string = string;
var string = {
# public:
new: func(str)
{
return { parents: [string], _str: str };
},
find_first_of: func(s, pos = 0)
{
return me._find(pos, size(me._str), s, 1);
},
find: func(s, pos = 0)
{
return me.find_first_of(s, pos);
},
find_first_not_of: func(s, pos = 0)
{
return me._find(pos, size(me._str), s, 0);
},
substr: func(pos, len = nil)
{
return substr(me._str, pos, len);
},
size: func()
{
return size(me._str);
},
# private:
_eq: func(pos, s)
{
for(var i = 0; i < size(s); i += 1)
if( me._str[pos] == s[i] )
return 1;
return 0;
},
_find: func(first, last, s, eq)
{
var sign = first <= last ? 1 : -1;
for(var i = first; sign * i < last; i += sign)
if( me._eq(i, s) == eq )
return i;
return -1;
}
};
# converts a string to an unsigned integer
var stoul = func(str, base = 10)
{
var val = 0;
for(var pos = 0; pos < size(str); pos += 1)
{
var c = str[pos];
if( _string.isdigit(c) )
var digval = c - `0`;
else if( _string.isalpha(c) )
var digval = _string.toupper(c) - `A` + 10;
else
break;
if( digval >= base )
break;
val = val * base + digval;
}
return val;
};

View file

@ -3,7 +3,7 @@
## A cellular automaton forest fire model with the ability to
## spread over the multiplayer network.
##
## Copyright (C) 2007 - 2011 Anders Gidenstam (anders(at)gidenstam.org)
## Copyright (C) 2007 - 2012 Anders Gidenstam (anders(at)gidenstam.org)
## This file is licensed under the GPL license version 2 or later.
##
###############################################################################
@ -95,7 +95,7 @@ var resolve_foam_drop = func (pos, radius, volume, source=1) {
# x < last event - fast forward all the way to current time (use 0).
# NOTE: Can be VERY time consuming.
# -1 - skip to current time.
var load_event_log = func (filename, skip_ahead_until=-1) {
var load_event_log = func (filename, skip_ahead_until) {
CAFire.load_event_log(filename, skip_ahead_until);
}
@ -129,6 +129,9 @@ var restore_on_startup_pp = "environment/wildfire/restore-on-startup";
var crash_fire_pp = "environment/wildfire/fire-on-crash";
var impact_fire_pp = "environment/wildfire/fire-on-impact";
var report_score_pp = "environment/wildfire/report-score";
var event_file_pp = "environment/wildfire/events-file";
var time_hack_pp = "environment/wildfire/time-hack-gmt";
# Format: "yyyy:mm:dd:hh:mm:ss"
# Internal properties to control the models
var models_enabled_pp = "environment/wildfire/models/enabled";
var fire_LOD_pp = "environment/wildfire/models/fire-lod";
@ -428,6 +431,7 @@ CAFireModels.MODEL = { # Model paths
"soot" : "Models/Effects/Wildfire/soot.xml",
"foam" : "Models/Effects/Wildfire/foam.xml",
"water" : "",
"retardant" : "Models/Effects/Wildfire/retardant.xml",
"protected" : "",
"none" : "",
};
@ -673,11 +677,40 @@ CAFire.resolve_water_drop = func (lat, lon, radius, volume=0) {
}
############################################################
# Resolve a fire retardant drop.
# For now: Assume that water makes the affected cell nonflammable forever
# and extinguishes it if burning.
# For now: Assume that the retardant makes the affected cell nonflammable
# forever and extinguishes it if burning.
# Note: volume is unused ATM.
CAFire.resolve_retardant_drop = func (lat, lon, radius, volume=0) {
return me.resolve_water_drop(lat, lon, radius, volume);
trace("CAFire.resolve_retardant_drop: Dumping retardant at " ~
lat ~", " ~ lon ~ " radius " ~ radius ~".");
var x = int(lon*60/me.CELL_SIZE);
var y = int(lat*60/me.CELL_SIZE);
var r = int(2*radius/(me.CELL_SIZE*1852.0));
var result = { extinguished : 0, protected : 0, waste : 0 };
for (var dx = -r; dx <= r; dx += 1) {
for (var dy = -r; dy <= r; dy += 1) {
var cell = me.get_cell(x + dx, y + dy);
if (cell == nil) {
cell = FireCell.new(x + dx, y + dy);
me.set_cell(x + dx, y + dy,
cell);
}
if (cell != nil) {
var res = cell.extinguish("retardant");
if (res > 0) {
result.extinguished += 1;
} else {
if (res == 0) result.protected += 1;
else result.waste += 1;
}
} else {
result.waste += 1;
}
}
}
append(me.event_log,
[SimTime.current_time(), "retardant_drop", lat, lon, radius]);
return result;
}
############################################################
# Resolve a foam drop.
@ -738,6 +771,8 @@ CAFire.save_event_log = func (filename) {
event.getNode("radius", 1).setDoubleValue(e[4]);
if (e[1] == "foam_drop")
event.getNode("radius", 1).setDoubleValue(e[4]);
if (e[1] == "retardant_drop")
event.getNode("radius", 1).setDoubleValue(e[4]);
# debug.dump(e);
i += 1;
@ -756,7 +791,7 @@ CAFire.save_event_log = func (filename) {
# to current time.
# x < last event - fast forward all the way to current time (use 0).
# -1 - skip to current time.
CAFire.load_event_log = func (filename, skip_ahead_until=-1) {
CAFire.load_event_log = func (filename, skip_ahead_until) {
me.load_count += 1;
var logbase = "/tmp/wildfire-load-log[" ~ me.load_count ~ "]";
if (!fgcommand("loadxml",
@ -782,7 +817,7 @@ CAFire.load_event_log = func (filename, skip_ahead_until=-1) {
event.getNode("type").getValue()];
# Fast forward state.
while (me.generation * me.GENERATION_DURATION <= e[0]) {
while (me.generation * me.GENERATION_DURATION < e[0]) {
# print("between event ff " ~ me.generation);
me.update();
}
@ -804,6 +839,12 @@ CAFire.load_event_log = func (filename, skip_ahead_until=-1) {
event.getNode("radius").getValue());
me.event_log[size(me.event_log) - 1][0] = e[0];
}
if (event.getNode("type").getValue() == "retardant_drop") {
me.resolve_retardant_drop(event.getNode("latitude").getValue(),
event.getNode("longitude").getValue(),
event.getNode("radius").getValue());
me.event_log[size(me.event_log) - 1][0] = e[0];
}
}
if (first) {
me.reset(1, SimTime.current_time());
@ -920,6 +961,8 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
props.globals.initNode(restore_on_startup_pp, 0, "BOOL");
props.globals.initNode(models_enabled_pp, 1, "BOOL");
props.globals.initNode(report_score_pp, 1, "BOOL");
props.globals.initNode(event_file_pp, "", "STRING");
props.globals.initNode(time_hack_pp, "", "STRING");
props.globals.initNode(fire_LOD_pp, 10, "INT");
props.globals.initNode(smoke_LOD_pp, 10, "INT");
@ -939,10 +982,35 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
CAFire.save_event_log(SAVEDIR ~ "fire_log.xml");
});
if (getprop(restore_on_startup_pp)) {
# Determine the skip-ahead-to time, if any.
var time_hack = time_string_to_epoch(getprop(time_hack_pp));
if (time_hack > SimTime.current_time()) {
printlog("alert",
"wildfire.nas: Ignored time hack " ~
(SimTime.current_time() - time_hack) ~
" seconds into the future.");
# Skip ahead to current time instead.
time_hack = -1;
} elsif (time_hack > 0) {
printlog("alert",
"wildfire.nas: Time hack " ~
(SimTime.current_time() - time_hack) ~
" seconds ago.");
} else {
# Skip ahead to current time instead.
time_hack = -1;
}
if (getprop(event_file_pp) != "") {
settimer(func {
# Delay loading the log until the terrain is there. Note: hack.
CAFire.load_event_log(SAVEDIR ~ "fire_log.xml", 1);
CAFire.load_event_log(getprop(event_file_pp), time_hack);
}, 3);
} elsif (getprop(restore_on_startup_pp)) {
settimer(func {
# Delay loading the log until the terrain is there. Note: hack.
# Restore skips ahead to current time.
CAFire.load_event_log(SAVEDIR ~ "fire_log.xml", -1);
}, 3);
}
@ -952,17 +1020,16 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
wildfire.ignite(geo.aircraft_position());
});
# Detect impact
# Detect impact.
var impact_node = props.globals.getNode("sim/ai/aircraft/impact/bomb", 1);
setlistener("sim/ai/aircraft/impact/bomb", func(n) {
if (getprop(impact_fire_pp) and n.getBoolValue()){
var node = props.globals.getNode(n.getValue(), 1);
var impactpos = geo.Coord.new();
impactpos.set_latlon(
node.getNode("impact/latitude-deg").getValue(),
node.getNode("impact/longitude-deg").getValue()
);
impactpos.set_latlon
(node.getNode("impact/latitude-deg").getValue(),
node.getNode("impact/longitude-deg").getValue());
wildfire.ignite(impactpos);
}
@ -972,6 +1039,40 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
});
###############################################################################
###############################################################################
# Utility functions
# Convert a time string in the format yyyy[:mm[:dd[:hh[:mm[:ss]]]]]
# to seconds since 1970:01:01:00:00:00.
#
# Note: This is an over simplified approximation.
var time_string_to_epoch = func (time) {
var res = [];
if (string.scanf(time, "%d:%d:%d:%d:%d:%d", var res1 = []) != 0) {
res = res1;
} elsif (string.scanf(time, "%d:%d:%d:%d:%d", var res2 = []) != 0) {
res = res2 ~ [0];
} elsif (string.scanf(time, "%d:%d:%d:%d", var res3 = []) != 0) {
res = res3 ~ [0, 0];
} elsif (string.scanf(time, "%d:%d:%d", var res4 = []) != 0) {
res = res4 ~ [0, 0, 0];
} elsif (string.scanf(time, "%d:%d", var res5 = []) != 0) {
res = res5 ~ [0, 0, 0, 0];
} elsif (string.scanf(time, "%d", var res6 = []) != 0) {
res = res6 ~ [0, 0, 0, 0, 0];
} else {
return -1;
}
return
(res[0] - 1970) * 3.15569e7 +
(res[1] - 1) * 2.63e+6 +
(res[2] - 1) * 86400 +
res[3] * 3600 +
res[4] * 60 +
res[5];
}
###############################################################################
## WildFire configuration dialog.
## Partly based on Till Bush's multiplayer dialog
@ -1088,7 +1189,7 @@ var dialog = {
#################################################################
select_and_load : func {
var selector = gui.FileSelector.new
(func (n) { CAFire.load_event_log(n.getValue()); },
(func (n) { load_event_log(n.getValue(), -1); },
"Load Wildfire log", # dialog title
"Load", # button text
["*.xml"], # pattern for files

94
Shaders/cinema.frag Normal file
View file

@ -0,0 +1,94 @@
uniform sampler2D lighting_tex;
uniform sampler2D bloom_tex;
uniform sampler2D film_tex;
uniform bool colorShift;
uniform vec3 redShift;
uniform vec3 greenShift;
uniform vec3 blueShift;
uniform bool vignette;
uniform float innerCircle;
uniform float outerCircle;
uniform bool distortion;
uniform vec3 distortionFactor;
uniform bool colorFringe;
uniform float colorFringeFactor;
uniform bool filmWear;
uniform vec2 fg_BufferSize;
uniform float osg_SimulationTime;
// uniform float shutterFreq;
// uniform float shutterDuration;
uniform bool bloomEnabled;
uniform float bloomStrength;
uniform bool bloomBuffers;
void main() {
vec2 c1 = gl_TexCoord[0].xy;
vec2 initialCoords = c1;
vec2 c2;
if (distortion) {
c1 = 2.0 * initialCoords - vec2(1.,1.);
c1 *= vec2( 1.0, fg_BufferSize.y / fg_BufferSize.x );
float r = length(c1);
c1 += c1 * dot(distortionFactor.xy, vec2(r*r, r*r*r*r));
c1 /= distortionFactor.z;
c1 *= vec2( 1.0, fg_BufferSize.x / fg_BufferSize.y );
c1 = c1 * .5 + .5;
if (colorFringe) {
c2 = 2.0 * initialCoords - vec2(1.,1.);
c2 *= vec2( 1.0, fg_BufferSize.y / fg_BufferSize.x );
r = length(c2);
c2 += c2 * dot(distortionFactor.xy*colorFringeFactor, vec2(r*r, r*r*r*r));
c2 /= distortionFactor.z;
c2 *= vec2( 1.0, fg_BufferSize.x / fg_BufferSize.y );
c2 = c2 * .5 + .5;
}
}
vec3 dirt = vec3(1.0);
if (filmWear) {
dirt = texture2D(film_tex, initialCoords*vec2( 1.0, fg_BufferSize.y / fg_BufferSize.x ) + vec2(0.0, osg_SimulationTime * 7.7)).rgb;
}
vec4 color = texture2D( lighting_tex, c1 );
if (bloomEnabled && bloomBuffers)
color += bloomStrength * texture2D( bloom_tex, c1 );
if (distortion && colorFringe) {
color.g = texture2D( lighting_tex, c2 ).g;
if (bloomEnabled && bloomBuffers)
color.g += bloomStrength * texture2D( bloom_tex, c2 ).g;
}
if (colorShift) {
vec3 col2;
col2.r = dot(color.rgb, redShift);
col2.g = dot(color.rgb, greenShift);
col2.b = dot(color.rgb, blueShift);
color.rgb = col2;
}
if (vignette) {
vec2 c = 2.0 * initialCoords - vec2(1.,1.);
c = c * vec2( 1.0, fg_BufferSize.y / fg_BufferSize.x );
float l = length(c);
float f = smoothstep( innerCircle, innerCircle * outerCircle, l );
color.rgb = (1.0 - f) * color.rgb;
}
// if ((osg_FrameNumber % 6) == 0)
// f = 1.0;
gl_FragColor = color * vec4(dirt, 1.0);
}

View file

@ -15,11 +15,13 @@ void main() {
// Position and scaling
vec3 position = gl_Vertex.xyz * gl_Normal.xxy;
float sr = sin(gl_FogCoord);
float cr = cos(gl_FogCoord);
float sr = sin(gl_FogCoord + gl_Color.x);
float cr = cos(gl_FogCoord + gl_Color.x);
// Rotation of the generic quad to specific one for the tree.
position.xy = vec2(dot(position.xy, vec2(cr, sr)), dot(position.xy, vec2(-sr, cr)));
// Move to correct location (stored in gl_Color)
position = position + gl_Color.xyz;
gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);

View file

@ -6,7 +6,6 @@ uniform sampler2D bufferNE_tex;
uniform sampler2D bufferSW_tex;
uniform sampler2D bufferSE_tex;
uniform float exposure;
uniform bool showBuffers;
uniform bool bloomEnabled;
@ -18,14 +17,6 @@ uniform bool bufferNE_enabled;
uniform bool bufferSW_enabled;
uniform bool bufferSE_enabled;
vec3 HDR(vec3 L) {
L = L * exposure;
L.r = L.r < 1.413 ? pow(L.r * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.r);
L.g = L.g < 1.413 ? pow(L.g * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.g);
L.b = L.b < 1.413 ? pow(L.b * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.b);
return L;
}
void main() {
vec2 coords = gl_TexCoord[0].xy;
vec4 color;
@ -42,13 +33,11 @@ void main() {
color = texture2D( lighting_tex, coords );
if (bloomEnabled && bloomBuffers)
color = color + bloomStrength * texture2D( bloom_tex, coords );
//color = vec4( HDR( color.rgb ), 1.0 );
}
} else {
color = texture2D( lighting_tex, coords );
if (bloomEnabled && bloomBuffers)
color = color + bloomStrength * texture2D( bloom_tex, coords );
//color = vec4( HDR( color.rgb ), 1.0 );
}
gl_FragColor = color;
}

View file

@ -56,8 +56,8 @@ void relWind(out float rel_wind_speed_kts, out float rel_wind_from_rad)
float rel_wind_speed_from_north_kts = WindN*fps2kts + speed_north_kts;
//combine relative speeds north and east to get relative windspeed in kts
rel_wind_speed_kts = sqrt(pow(abs(rel_wind_speed_from_east_kts), 2)
+ pow(abs(rel_wind_speed_from_north_kts), 2));
rel_wind_speed_kts = sqrt(pow(abs(rel_wind_speed_from_east_kts), 2.0)
+ pow(abs(rel_wind_speed_from_north_kts), 2.0));
//calculate the relative wind direction
float rel_wind_from_deg = degrees(atan(rel_wind_speed_from_east_kts, rel_wind_speed_from_north_kts));
@ -79,8 +79,8 @@ void main()
{
mat4 RotationMatrix;
float relWindspd=0;
float relWinddir=0;
float relWindspd=0.0;
float relWinddir=0.0;
// compute relative wind speed and direction
relWind (relWindspd, relWinddir);
@ -93,9 +93,9 @@ void main()
vec4 pos = gl_Vertex;
vec4 oldpos = gl_Vertex;
float freq = (10 * relWindspd) + 10;
float freq = (10.0 * relWindspd) + 10.0;
pos.y = sin((pos.x * 5.0 + tsec * freq )/5.0) * 0.5 ;
pos.y += sin((pos.z * 5.0 + tsec * freq/2)/5.0) * 0.125 ;
pos.y += sin((pos.z * 5.0 + tsec * freq/2.0)/5.0) * 0.125 ;
pos.y *= pow(pos.x - Offset, 2.0) * AmpFactor;

42
Shaders/night-vision.frag Normal file
View file

@ -0,0 +1,42 @@
// Night vision effect inspired by http://www.geeks3d.com/20091009/shader-library-night-vision-post-processing-filter-glsl/
uniform sampler2D color_tex;
uniform sampler2D lighting_tex;
uniform sampler2D bloom_tex;
uniform sampler2D spec_emis_tex;
uniform sampler2D noise_tex;
uniform bool bloomEnabled;
uniform float bloomStrength;
uniform bool bloomBuffers;
uniform vec2 fg_BufferSize;
uniform float osg_SimulationTime;
void main() {
vec2 coords = gl_TexCoord[0].xy;
vec4 color;
vec2 uv;
uv.x = 0.4*sin(osg_SimulationTime*50.0);
uv.y = 0.4*cos(osg_SimulationTime*50.0);
vec3 n = texture2D(noise_tex, (coords*3.5) + uv).rgb;
vec2 c1 = coords + (n.xy*0.005);
color = texture2D( lighting_tex, c1 );
if (bloomEnabled && bloomBuffers)
color = color + bloomStrength * texture2D( bloom_tex, c1 );
float lum = dot(color.rgb, vec3(.3, .59, .11));
color.rgb *= (4.0 - 3.0*smoothstep(0.2, 0.3, lum));
// color.rgb += texture2D( spec_emis_tex, c1 ).b;
// color.rgb += texture2D( bloom_tex, c1 ).rgb;
color.rgb = (color.rgb + (n*0.2)) * vec3(0.1, 0.95, 0.2);
vec2 c = 2.0 * coords - vec2(1.,1.);
c = c * vec2( 1.0, fg_BufferSize.y / fg_BufferSize.x );
float l = length(c);
float f = smoothstep( 0.7, 1.1, l );
color.rgb = (1 - f) * color.rgb;
gl_FragColor = color;
}

View file

@ -1,63 +0,0 @@
#version 120
uniform sampler2D normal_tex;
uniform sampler2D depth_tex;
uniform sampler2D spec_emis_tex;
uniform sampler3D noise_tex;
uniform vec2 fg_BufferSize;
uniform vec3 fg_Planes;
uniform vec4 fg_du;
uniform vec4 fg_dv;
uniform float g_scale;
uniform float g_bias;
uniform float g_intensity;
uniform float g_sample_rad;
uniform float random_size;
uniform int osg_FrameNumber;
varying vec4 ray;
const vec2 v[4] = vec2[](vec2(1.0,0.0),vec2(-1.0,0.0),vec2(0.0,1.0),vec2(0.0,-1.0));
vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex );
vec3 normal_decode(vec2 enc);
vec2 getRandom( in vec2 uv ) {
int level = osg_FrameNumber - ((osg_FrameNumber / 64) * 64);
return normalize( texture3D( noise_tex, vec3(uv*50.0, float(level) / 64.0) ).xy * 0.14 - 0.07 );
}
vec3 getPosition(in vec2 uv, in vec2 uv0, in vec4 ray0) {
vec2 duv = uv - uv0;
vec4 ray = ray0 + fg_du * duv.x + fg_dv * duv.y;
vec3 viewDir = normalize( ray.xyz );
return position(viewDir, uv, depth_tex);
}
float doAmbientOcclusion(in vec2 tcoord, in vec2 uv, in vec3 p, in vec3 cnorm, in vec4 ray) {
vec3 diff = getPosition(tcoord+uv,tcoord,ray)-p;
float d = length(diff);
vec3 v = diff / d;
d *= g_scale;
return max(0.0, dot( cnorm,v ) - g_bias) * (1.0/(1.0+d)) * g_intensity;
}
void main() {
vec2 coords = gl_TexCoord[0].xy;
float initialized = texture2D( spec_emis_tex, coords ).a;
if ( initialized < 0.1 )
discard;
vec3 normal = normal_decode(texture2D( normal_tex, coords ).rg);
vec3 viewDir = normalize(ray.xyz);
vec3 pos = position(viewDir, coords, depth_tex);
vec2 rand = getRandom(coords);
float ao = 0.0;
float rad = g_sample_rad;
int iterations = 4;
for (int j = 0; j < 1; ++j ) {
vec2 coord1 = reflect( v[j], rand ) * rad;
vec2 coord2 = vec2( coord1.x*0.707 - coord1.y*0.707, coord1.x*0.707 + coord1.y*0.707 );
ao += doAmbientOcclusion(coords,coord1*0.25,pos,normal,ray);
ao += doAmbientOcclusion(coords,coord2*0.5,pos,normal,ray);
ao += doAmbientOcclusion(coords,coord1*0.75,pos,normal,ray);
ao += doAmbientOcclusion(coords,coord2,pos,normal,ray);
}
ao /= 16.0;
gl_FragColor = vec4( vec3(1.0 - ao), 1.0 );
}

View file

@ -13,7 +13,7 @@ uniform float g_bias;
uniform float g_intensity;
uniform float g_sample_rad;
uniform float random_size;
uniform unsigned int osg_FrameNumber;
uniform float osg_SimulationTime;
varying vec4 ray;
@ -23,8 +23,8 @@ vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex );
vec3 normal_decode(vec2 enc);
vec2 getRandom( in vec2 uv ) {
unsigned int level = osg_FrameNumber - ((osg_FrameNumber / 64U) * 64U);
return normalize( texture3D( noise_tex, vec3(uv*50.0, float(level) / 64.0) ).xy * 0.14 - 0.07 );
float level = osg_SimulationTime - float(int(osg_SimulationTime));
return normalize( texture3D( noise_tex, vec3(uv*50.0, level) ).xy * 0.14 - 0.07 );
}
vec3 getPosition(in vec2 uv, in vec2 uv0, in vec4 ray0) {
vec2 duv = uv - uv0;

View file

@ -5,23 +5,16 @@
varying vec4 diffuse_term;
varying vec3 normal;
varying vec3 relPos;
varying vec4 rawPos;
varying vec3 rawPos;
//varying vec3 ecViewdir;
//varying vec3 hazeColor;
//varying float fogCoord;
uniform sampler2D texture;
uniform sampler3D NoiseTex;
uniform sampler2D snow_texture;
uniform sampler2D detail_texture;
uniform sampler2D mix_texture;
//varying float ct;
//varying float delta_z;
//varying float alt;
varying float earthShade;
//varying float yprime;
//varying float vertex_alt;
varying float yprime_alt;
varying float mie_angle;
varying float steepness;
@ -30,27 +23,71 @@ varying float steepness;
uniform float visibility;
uniform float avisibility;
uniform float scattering;
//uniform float ground_scattering;
uniform float terminator;
uniform float terrain_alt;
uniform float hazeLayerAltitude;
uniform float overcast;
//uniform float altitude;
uniform float eye_alt;
uniform float mysnowlevel;
uniform float snowlevel;
uniform float dust_cover_factor;
uniform float wetness;
uniform float fogstructure;
uniform int quality_level;
uniform int tquality_level;
const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
float alt;
float eShade;
float luminance(vec3 color)
{
return dot(vec3(0.212671, 0.715160, 0.072169), color);
float rand2D(in vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
float cosine_interpolate(in float a, in float b, in float x)
{
float ft = x * 3.1415927;
float f = (1.0 - cos(ft)) * .5;
return a*(1.0-f) + b*f;
}
float simple_interpolate(in float a, in float b, in float x)
{
return a + smoothstep(0.0,1.0,x) * (b-a);
//return mix(a,b,x);
}
float interpolatedNoise2D(in float x, in float y)
{
float integer_x = x - fract(x);
float fractional_x = x - integer_x;
float integer_y = y - fract(y);
float fractional_y = y - integer_y;
float v1 = rand2D(vec2(integer_x, integer_y));
float v2 = rand2D(vec2(integer_x+1.0, integer_y));
float v3 = rand2D(vec2(integer_x, integer_y+1.0));
float v4 = rand2D(vec2(integer_x+1.0, integer_y +1.0));
float i1 = simple_interpolate(v1 , v2 , fractional_x);
float i2 = simple_interpolate(v3 , v4 , fractional_x);
return simple_interpolate(i1 , i2 , fractional_y);
}
float Noise2D(in vec2 coord, in float wavelength)
{
return interpolatedNoise2D(coord.x/wavelength, coord.y/wavelength);
}
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{
@ -69,25 +106,22 @@ return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
float fog_func (in float targ)
{
float fade_mix;
// for large altitude > 30 km, we switch to some component of quadratic distance fading to
// create the illusion of improved visibility range
targ = 1.25 * targ; // need to sync with the distance to which terrain is drawn
targ = 1.25 * targ * smoothstep(0.04,0.06,targ); // need to sync with the distance to which terrain is drawn
if (alt < 30000.0)
{return exp(-targ - targ * targ * targ * targ);}
else if (alt < 50000.0)
{
if (alt < 30000.0) {
return exp(-targ - targ * targ * targ * targ);
}
else if (alt < 50000.0) {
fade_mix = (alt - 30000.0)/20000.0;
return fade_mix * exp(-targ*targ - pow(targ,4.0)) + (1.0 - fade_mix) * exp(-targ - pow(targ,4.0));
}
else
{
else {
return exp(- targ * targ - pow(targ,4.0));
}
@ -95,6 +129,7 @@ else
void main()
{
float dist = length(relPos);
// this is taken from default.frag
vec3 n;
@ -102,13 +137,157 @@ void main()
vec4 color = gl_Color;
vec3 lightDir = gl_LightSource[0].position.xyz;
vec3 halfVector = gl_LightSource[0].halfVector.xyz;
//vec3 halfVector = normalize(normalize(lightDir) + normalize(ecViewdir));
vec4 texel;
vec4 snow_texel;
vec4 detail_texel;
vec4 mix_texel;
vec4 fragColor;
vec4 specular = vec4(0.0);
float intensity;
// get noise at different wavelengths
// used: 5m, 5m gradient, 10m, 10m gradient: heightmap of the closeup terrain, 10m also snow
// 50m: detail texel
// 250m: detail texel
// 500m: distortion and overlay
// 1500m: overlay, detail, dust, fog
// 2000m: overlay, detail, snow, fog
float noise_10m;
float noise_5m;
noise_10m = Noise2D(rawPos.xy, 10.0);
noise_5m = Noise2D(rawPos.xy ,5.0);
float noisegrad_10m;
float noisegrad_5m;
float noise_50m;
float noise_250m;
float noise_500m = Noise2D(rawPos.xy, 500.0);
float noise_1500m = Noise2D(rawPos.xy, 1500.0);
float noise_2000m = Noise2D(rawPos.xy, 2000.0);
//
// get the texels
texel = texture2D(texture, gl_TexCoord[0].st);
float distortion_factor = 1.0;
vec2 stprime;
int flag = 1;
int mix_flag = 1;
if (quality_level > 3)
{
snow_texel = texture2D(snow_texture, gl_TexCoord[0].st);
}
if (tquality_level > 2)
{
mix_texel = texture2D(mix_texture, gl_TexCoord[0].st * 1.3);
if (mix_texel.a <0.1) {mix_flag = 0;}
}
if (tquality_level > 3)
{
stprime = vec2 (0.86*gl_TexCoord[0].s + 0.5*gl_TexCoord[0].t, 0.5*gl_TexCoord[0].s - 0.86*gl_TexCoord[0].t);
//distortion_factor = 0.9375 + (1.0 * nvL[2]);
distortion_factor = 0.97 + 0.06 * noise_500m;
stprime = stprime * distortion_factor * 15.0;
if (quality_level > 4)
{
stprime = stprime + normalize(relPos).xy * 0.02 * (noise_10m + 0.5 * noise_5m - 0.75);
}
detail_texel = texture2D(detail_texture, stprime);
if (detail_texel.a <0.1) {flag = 0;}
}
// texture preparation according to detail level
// mix in hires texture patches
float dist_fact;
float nSum;
float mix_factor;
if (tquality_level > 2)
{
// first the second texture overlay
if (mix_flag == 1)
{
nSum = nSum + 0.2 * (2.0 * noise_2000m + 2.0 * noise_1500m + noise_500m);
nSum = nSum + 0.2 * (1.0 -smoothstep(0.9,0.95, abs(steepness)));
mix_factor = smoothstep(0.5, 0.54, nSum);
texel = mix(texel, mix_texel, mix_factor);
}
// then the detail texture overlay
}
if (tquality_level > 3)
{
if (dist < 40000.0)
{
if (flag == 1)
{
noise_50m = Noise2D(rawPos.xy, 50.0);
noise_250m = Noise2D(rawPos.xy, 250.0);
dist_fact = 0.1 * smoothstep(15000.0,40000.0, dist) - 0.03 * (1.0 - smoothstep(500.0,5000.0, dist));
nSum = ((1.0 -noise_2000m) + noise_1500m + 2.0 * noise_250m +noise_50m)/5.0;
nSum = nSum - 0.03 * (1.0 -smoothstep(0.9,0.95, abs(steepness)));
mix_factor = smoothstep(0.47, 0.54, nSum - dist_fact);
if (mix_factor > 0.8) {mix_factor = 0.8;}
texel = mix(texel, detail_texel,mix_factor);
}
}
}
vec4 dust_color;
float snow_alpha;
if (quality_level > 3)
{
// mix dust
dust_color = vec4 (0.76, 0.71, 0.56, 1.0);
texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor + 3.0 * dust_cover_factor * (((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) );
// mix snow
snow_alpha = smoothstep(0.75, 0.85, abs(steepness));
texel = mix(texel, snow_texel, smoothstep(snowlevel, snowlevel+200.0, snow_alpha * (relPos.z + eye_alt)+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0));
}
// get distribution of water when terrain is wet
float water_threshold1;
float water_threshold2;
float water_factor =0.0;
if ((dist < 5000.0)&& (quality_level > 3) && (wetness>0.0))
{
water_threshold1 = 1.0-0.5* wetness;
water_threshold2 = 1.0 - 0.3 * wetness;
water_factor = smoothstep(water_threshold1, water_threshold2 , (0.3 * (2.0 * (1.0-noise_10m) + (1.0 -noise_5m)) * (1.0 - smoothstep(2000.0, 5000.0, dist))) - 5.0 * (1.0 -steepness));
}
// darken wet terrain
texel.rgb = texel.rgb * (1.0 - 0.6 * wetness);
// light computations
vec4 light_specular = gl_LightSource[0].specular;
@ -118,62 +297,29 @@ void main()
n = normalize(n);
NdotL = dot(n, lightDir);
if ((tquality_level > 3) && (mix_flag ==1)&& (dist < 2000.0) && (quality_level > 4))
{
noisegrad_10m = (noise_10m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),10.0))/0.05;
noisegrad_5m = (noise_5m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),5.0))/0.05;
NdotL = NdotL + 1.0 * (noisegrad_10m + 0.5* noisegrad_5m) * mix_factor/0.8 * (1.0 - smoothstep(1000.0, 2000.0, dist));
}
if (NdotL > 0.0) {
color += diffuse_term * NdotL;
NdotHV = max(dot(n, halfVector), 0.0);
if (gl_FrontMaterial.shininess > 0.0)
specular.rgb = (gl_FrontMaterial.specular.rgb
if (gl_FrontMaterial.shininess > 0.0) {
specular.rgb = ((gl_FrontMaterial.specular.rgb + (water_factor * vec3 (1.0, 1.0, 1.0)))
* light_specular.rgb
* pow(NdotHV, gl_FrontMaterial.shininess));
* pow(NdotHV, gl_FrontMaterial.shininess + (20.0 * water_factor)));
}
}
color.a = diffuse_term.a;
// This shouldn't be necessary, but our lighting becomes very
// saturated. Clamping the color before modulating by the texture
// is closer to what the OpenGL fixed function pipeline does.
color = clamp(color, 0.0, 1.0);
texel = texture2D(texture, gl_TexCoord[0].st);
snow_texel = texture2D(snow_texture, gl_TexCoord[0].st);
// this is the snow and dust generating part, ger some noise vectors
vec4 noisevec = texture3D(NoiseTex, (rawPos.xyz)*0.003); // small scale noise
//vec4 nvL = texture3D(NoiseTex, (rawPos.xyz)*0.00066);
vec4 nvL = texture3D(NoiseTex, (rawPos.xyz)*0.0001); // large scale noise
vec4 nvR = texture3D(NoiseTex, (rawPos.xyz)*0.00003); // really large scale noise
//float ns=0.06;
// ns += nvL[0]*0.4;
//ns += nvL[1]*0.6;
//ns += nvL[2]*2.0;
//ns += nvL[3]*4.0;
//ns += noisevec[0]*0.1;
//ns += noisevec[1]*0.4;
//ns += noisevec[2]*0.8;
//ns += noisevec[3]*2.1;
// gradient effect for snow
// mix dust
vec4 dust_color = vec4 (0.76, 0.71, 0.56, 1.0);
//dust_color.rgb = dust_color.rgb * nvL[1];
texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor + 3.0 * dust_cover_factor * nvL[1],0.0, 1.0) );
float snow_alpha = smoothstep(0.7, 0.8, abs(steepness));
//vec4 snow_texel = clamp(ns+nvL[2]*4.1+vec4(0.1, 0.1, nvL[2]*2.2, 1.0), 0.7, 1.0);
//snow_texel.a = snow_alpha * snow_texel.a;
// mix snow
texel = mix(texel, snow_texel, smoothstep(mysnowlevel, mysnowlevel+200.0, snow_alpha * (relPos.z + eye_alt)+ (noisevec[1] * abs(noisevec[1])+ nvL[1])*1500.0));
// gradient
//fragColor = mix(vec4(ns-0.30, ns-0.29, ns-0.37, 1.0), fragColor, smoothstep(0.0, 0.40, steepness));// +nvL[2]*1.3));
fragColor = color * texel + specular;
@ -181,10 +327,10 @@ vec4 nvR = texture3D(NoiseTex, (rawPos.xyz)*0.00003); // really large scale no
float delta_z = hazeLayerAltitude - eye_alt;
float dist = length(relPos);
if (dist > 40.0)
if (dist > max(40.0, 0.04 * min(visibility,avisibility)))
//if ((gl_FragCoord.y > ylimit) || (gl_FragCoord.x < zlimit1) || (gl_FragCoord.x > zlimit2))
//if (dist > 40.0)
{
alt = eye_alt;
@ -214,8 +360,12 @@ if (delta_z > 0.0) // we're inside the layer
else // we may look through upper layer edge
{
H = dist * ct;
if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
else {distance_in_layer = dist;}
if (H > delta_z) {
distance_in_layer = dist/H * delta_z;
}
else {
distance_in_layer = dist;
}
vAltitude = min(distance_in_layer,visibility) * ct;
delta_zv = delta_z - vAltitude;
}
@ -247,21 +397,32 @@ transmission_arg = (dist-distance_in_layer)/avisibility;
float eqColorFactor;
//float scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, relPos.z + eye_alt);
if (visibility < avisibility)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 0.8 * visibility * fogstructure * (( 0.4 * nvL[1] + 0.6 * nvR[1]) -0.1) ));
//transmission_arg = transmission_arg + (distance_in_layer/visibility);
if (quality_level > 3)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/visibility);
}
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -scattering);
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 0.8 * avisibility * fogstructure * (( 0.4 * nvL[1] + 0.6 * nvR[1]) -0.1) ));
//transmission_arg = transmission_arg + (distance_in_layer/avisibility);
if (quality_level > 3)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) ));
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
}
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -scattering);
}
@ -284,12 +445,13 @@ hazeColor.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
// now dim the light for haze
earthShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
eShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
// Mie-like factor
if (lightArg < 5.0)
{intensity = length(hazeColor);
{
intensity = length(hazeColor);
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
}
@ -308,10 +470,9 @@ hazeColor.y = hazeColor.y * 0.9;
// additional blue in indirect light
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
intensity = length(hazeColor);
hazeColor = intensity * normalize(mix(hazeColor, 1.5* vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.25, fade_out,earthShade) ));
hazeColor = intensity * normalize(mix(hazeColor, 1.5* vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.25, fade_out,eShade) ));
// change haze color to blue hue for strong fogging
//intensity = length(hazeColor);
hazeColor = intensity * normalize(mix(hazeColor, 2.0 * vec3 (0.55, 0.6, 0.8), (1.0-smoothstep(0.3,0.8,eqColorFactor))));
@ -320,32 +481,12 @@ hazeColor = intensity * normalize(mix(hazeColor, 2.0 * vec3 (0.55, 0.6, 0.8), (
float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
// randomness
//hazeColor.rgb = hazeColor.rgb + 0.2 * hazeColor.rgb * nvL[1];
// determine the right mix of transmission and haze
//fragColor.xyz = transmission * fragColor.xyz + (1.0-transmission) * eqColorFactor * hazeColor * earthShade;
//fragColor.rgb = mix(fragColor.rgb, vec3 (1.0, 1.0, 1.0), overcast );
fragColor.xyz = mix(eqColorFactor * hazeColor * earthShade, fragColor.xyz,transmission);
fragColor.xyz = mix(eqColorFactor * hazeColor * eShade, fragColor.xyz,transmission);
gl_FragColor = fragColor;
}
else // if dist < 40.0 no fogging at all
else // if dist < threshold no fogging at all
{
gl_FragColor = fragColor;
}
//gl_FragColor.rgb = 5.0 * nvL[1] * vec3 (1.0, 1.0, 1.0);
}

View file

@ -21,18 +21,15 @@
varying vec4 diffuse_term;
varying vec3 normal;
varying vec3 relPos;
varying vec4 rawPos;
varying vec3 rawPos;
//varying vec3 ecViewdir;
varying float earthShade;
//varying float yprime;
//varying float vertex_alt;
//varying float earthShade;
varying float yprime_alt;
varying float mie_angle;
varying float steepness;
uniform int colorMode;
uniform float hazeLayerAltitude;
uniform float terminator;
@ -40,8 +37,10 @@ uniform float terrain_alt;
uniform float avisibility;
uniform float visibility;
uniform float overcast;
//uniform float scattering;
uniform float ground_scattering;
uniform float eye_alt;
float earthShade;
// This is the value used in the skydome scattering shader - use the same here for consistency?
@ -72,9 +71,10 @@ void main()
float vertex_alt;
float scattering;
rawPos = gl_Vertex;
rawPos = gl_Vertex.xyz;
steepness = dot(normalize(gl_Normal), vec3 (0.0, 0.0, 1.0));
// this code is copied from default.vert
//vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
@ -98,20 +98,41 @@ void main()
// here start computations for the haze layer
// we need several geometrical quantities
// first current altitude of eye position in model space
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
// and relative position to vector
relPos = gl_Vertex.xyz - ep.xyz;
//ecViewdir = (gl_ModelViewMatrix * (ep - gl_Vertex)).xyz;
// unfortunately, we need the distance in the vertex shader, although the more accurate version
// is later computed in the fragment shader again
float dist = length(relPos);
// altitude of the vertex in question, somehow zero leads to artefacts, so ensure it is at least 100m
vertex_alt = max(gl_Vertex.z,100.0);
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
// early culling of vertices which can't be seen due to ground haze despite being in aloft visibility range
float delta_z = hazeLayerAltitude - eye_alt;
//if (((dist * (relPos.z - delta_z)/relPos.z > visibility ) && (relPos.z < 0.0) && (delta_z < 0.0) && (dist > 30000.0)))
if (0==1)
{
gl_Position = vec4(0.0, 0.0, -1000.0, 1.0); // move outside of view frustrum, gets culled before reaching fragment shader
earthShade = 1.0;
mie_angle = 1.0;
yprime_alt = 0.0;
}
else
{
// branch dependent on daytime
if (terminator < 1000000.0) // the full, sunrise and sunset computation
@ -164,13 +185,13 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
// correct ambient light intensity and hue before sunrise
if (earthShade < 0.5)
{
light_ambient = light_ambient * (0.4 + 0.6 * smoothstep(0.2, 0.5, earthShade));
light_ambient = light_ambient * (0.7 + 0.3 * smoothstep(0.2, 0.5, earthShade));
intensity = length(light_ambient.xyz);
light_ambient.xyz = intensity * normalize(mix(light_ambient.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.5,earthShade) ));
light_ambient.xyz = intensity * normalize(mix(light_ambient.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.8,earthShade) ));
intensity = length(light_diffuse.xyz);
light_diffuse.xyz = intensity * normalize(mix(light_diffuse.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.5,earthShade) ));
light_diffuse.xyz = intensity * normalize(mix(light_diffuse.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.7,earthShade) ));
}
@ -224,6 +245,12 @@ else // the faster, full-day version without lightfields
}
// a sky/earth irradiation map model - the sky creates much more diffuse radiation than the ground, so
// steep faces end up shaded more
light_ambient = light_ambient * ((1.0+steepness)/2.0 * 1.2 + (1.0-steepness)/2.0 * 0.2);
// default lighting based on texture and material using the light we have just computed
diffuse_term = diffuse_color* light_diffuse;
@ -239,5 +266,8 @@ else // the faster, full-day version without lightfields
// gl_FrontFacing in the fragment shader.
gl_FrontColor.rgb = constant_term.rgb; gl_FrontColor.a = 1.0;
gl_BackColor.rgb = constant_term.rgb; gl_BackColor.a = 0.0;
}
}

View file

@ -6,18 +6,10 @@ varying vec4 diffuse_term;
varying vec3 normal;
varying vec3 relPos;
//varying vec3 hazeColor;
//varying float fogCoord;
uniform sampler2D texture;
//varying float ct;
//varying float delta_z;
//varying float alt;
varying float earthShade;
//varying float yprime;
//varying float vertex_alt;
varying float yprime_alt;
varying float mie_angle;
@ -37,6 +29,7 @@ const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
float alt;
float eShade;
float luminance(vec3 color)
{
@ -133,8 +126,8 @@ void main()
float delta_z = hazeLayerAltitude - eye_alt;
float dist = length(relPos);
if (dist > 40.0)
if (dist > max(40.0, 0.04 * min(visibility,avisibility)))
//if (dist > 40.0)
{
alt = eye_alt;
@ -231,7 +224,7 @@ hazeColor.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
// now dim the light for haze
float eShade = earthShade;
eShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
// Mie-like factor
@ -271,7 +264,6 @@ hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 4
// determine the right mix of transmission and haze
//fragColor.xyz = transmission * fragColor.xyz + (1.0-transmission) * eqColorFactor * hazeColor * earthShade;
fragColor.xyz = mix(eqColorFactor * hazeColor * eShade, fragColor.xyz,transmission);

View file

@ -22,7 +22,7 @@ varying vec4 diffuse_term;
varying vec3 normal;
varying vec3 relPos;
varying float earthShade;
//varying float earthShade;
//varying float yprime;
//varying float vertex_alt;
varying float yprime_alt;
@ -46,6 +46,9 @@ uniform float ground_scattering;
const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
float earthShade;
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{
//x = x - 0.5;
@ -159,13 +162,13 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
// correct ambient light intensity and hue before sunrise
if (earthShade < 0.5)
{
light_ambient = light_ambient * (0.4 + 0.6 * smoothstep(0.2, 0.5, earthShade));
light_ambient = light_ambient * (0.7 + 0.3 * smoothstep(0.2, 0.5, earthShade));
intensity = length(light_ambient.xyz);
light_ambient.xyz = intensity * normalize(mix(light_ambient.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.5,earthShade) ));
light_ambient.xyz = intensity * normalize(mix(light_ambient.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.8,earthShade) ));
intensity = length(light_diffuse.xyz);
light_diffuse.xyz = intensity * normalize(mix(light_diffuse.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.5,earthShade) ));
light_diffuse.xyz = intensity * normalize(mix(light_diffuse.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.7,earthShade) ));
}

View file

@ -3,8 +3,6 @@
// based on earlier work by Frederic Bouvier, Tim Moore, and Yves Sablonier.
// © Emilian Huminiuc 2011
// Ambient term comes in gl_Color.rgb.
#version 120
varying vec4 RawPos;
@ -69,10 +67,12 @@ void main()
if (gl_FrontMaterial.shininess > 0.0)
specular = gl_FrontMaterial.specular * gl_LightSource[0].specular * pf;
vec4 diffuseColor = gl_FrontMaterial.emission +
vec4(1.0) * (gl_LightModel.ambient + gl_LightSource[0].ambient) +
Diffuse * gl_FrontMaterial.diffuse;
// vec4 diffuseColor = gl_FrontMaterial.emission +
// vec4(1.0) * (gl_LightModel.ambient + gl_LightSource[0].ambient) +
// Diffuse * gl_FrontMaterial.diffuse;
vec4 ambientColor = gl_LightModel.ambient + gl_LightSource[0].ambient;
//vec4 diffuseColor = gl_Color + Diffuse * gl_FrontMaterial.diffuse + ambientColor;
vec4 diffuseColor = vec4(Diffuse) + ambientColor; //ATI workaround
diffuseColor += specular * gl_FrontMaterial.specular;
// This shouldn't be necessary, but our lighting becomes very

View file

@ -1,23 +1,15 @@
// -*-C++-*-
// written by Thorsten Renk, Oct 2011, based on default.frag
// Ambient term comes in gl_Color.rgb.
varying vec4 diffuse_term;
varying vec3 normal;
varying vec3 relPos;
//varying vec3 hazeColor;
//varying float fogCoord;
uniform sampler2D texture;
//varying float ct;
//varying float delta_z;
//varying float alt;
varying float earthShade;
//varying float yprime;
//varying float vertex_alt;
varying float yprime_alt;
varying float mie_angle;
@ -25,14 +17,13 @@ varying float mie_angle;
uniform float visibility;
uniform float avisibility;
uniform float scattering;
//uniform float ground_scattering;
uniform float terminator;
uniform float terrain_alt;
uniform float hazeLayerAltitude;
uniform float overcast;
//uniform float altitude;
uniform float eye_alt;
const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
@ -68,7 +59,7 @@ float fade_mix;
// for large altitude > 30 km, we switch to some component of quadratic distance fading to
// create the illusion of improved visibility range
targ = 1.25 * targ; // need to sync with the distance to which terrain is drawn
targ = 1.25 * targ * smoothstep(0.07,0.1,targ); // need to sync with the distance to which terrain is drawn
if (alt < 30000.0)
@ -88,43 +79,13 @@ else
void main()
{
// this is taken from default.frag
vec3 n;
float NdotL, NdotHV, fogFactor;
vec4 color = gl_Color;
vec3 lightDir = gl_LightSource[0].position.xyz;
vec3 halfVector = gl_LightSource[0].halfVector.xyz;
vec4 texel;
vec4 fragColor;
vec4 specular = vec4(0.0);
float intensity;
vec4 light_specular = gl_LightSource[0].specular;
// If gl_Color.a == 0, this is a back-facing polygon and the
// normal should be reversed.
n = (2.0 * gl_Color.a - 1.0) * normal;
n = normalize(n);
NdotL = dot(n, lightDir);
if (NdotL > 0.0) {
color += diffuse_term * NdotL;
NdotHV = max(dot(n, halfVector), 0.0);
if (gl_FrontMaterial.shininess > 0.0)
specular.rgb = (gl_FrontMaterial.specular.rgb
* light_specular.rgb
* pow(NdotHV, gl_FrontMaterial.shininess));
}
color.a = diffuse_term.a;
// This shouldn't be necessary, but our lighting becomes very
// saturated. Clamping the color before modulating by the texture
// is closer to what the OpenGL fixed function pipeline does.
color = clamp(color, 0.0, 1.0);
texel = texture2D(texture, gl_TexCoord[0].st);
fragColor = color * texel + specular;
vec4 fragColor = gl_Color * texture2D(texture, gl_TexCoord[0].st);
@ -134,8 +95,9 @@ void main()
float delta_z = hazeLayerAltitude - eye_alt;
float dist = length(relPos);
if (dist > 40.0)
if (dist > max(40.0, 0.07 * min(visibility,avisibility)))
//if (dist > 40.0)
//if (0==1)
{
alt = eye_alt;
@ -232,8 +194,8 @@ hazeColor.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
// now dim the light for haze
float eShade = earthShade;
eShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
//float eShade = earthShade;
float eShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
// Mie-like factor
@ -266,8 +228,8 @@ hazeColor = intensity * normalize(mix(hazeColor, 2.0 * vec3 (0.55, 0.6, 0.8), (
// reduce haze intensity when looking at shaded surfaces, only in terminator region
float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
//float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
//hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
// determine the right mix of transmission and haze

View file

@ -18,19 +18,16 @@
// the surface normal is passed in gl_{Front,Back}Color. The alpha
// component is set to 1 for front, 0 for back in order to work around
// bugs with gl_FrontFacing in the fragment shader.
varying vec4 diffuse_term;
varying vec3 normal;
//varying vec4 diffuse_term;
//varying vec3 normal;
varying vec3 relPos;
varying float earthShade;
//varying float earthShade;
//varying float yprime;
//varying float vertex_alt;
varying float yprime_alt;
varying float mie_angle;
uniform int colorMode;
uniform float hazeLayerAltitude;
uniform float terminator;
@ -41,6 +38,7 @@ uniform float overcast;
//uniform float scattering;
uniform float ground_scattering;
float earthShade;
// This is the value used in the skydome scattering shader - use the same here for consistency?
const float EarthRadius = 5800000.0;
@ -75,8 +73,12 @@ void main()
float numVarieties = gl_Normal.z;
float texFract = floor(fract(gl_MultiTexCoord0.x) * numVarieties) / numVarieties;
texFract += floor(gl_MultiTexCoord0.x) / numVarieties;
float sr = sin(gl_FogCoord);
float cr = cos(gl_FogCoord);
// Determine the rotation for the tree. The Fog Coordinate provides rotation information
// to rotate one of the quands by 90 degrees. We then apply an additional position seed
// so that trees aren't all oriented N/S
float sr = sin(gl_FogCoord + gl_Color.x);
float cr = cos(gl_FogCoord + gl_Color.x);
gl_TexCoord[0] = vec4(texFract, gl_MultiTexCoord0.y, 0.0, 0.0);
// scaling
@ -84,11 +86,13 @@ void main()
// Rotation of the generic quad to specific one for the tree.
position.xy = vec2(dot(position.xy, vec2(cr, sr)), dot(position.xy, vec2(-sr, cr)));
// Move to correct location (stored in gl_Color)
position = position + gl_Color.xyz;
gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);
vec3 ecPosition = vec3(gl_ModelViewMatrix * vec4(position, 1.0));
normal = normalize(-ecPosition);
//normal = normalize(-ecPosition);
float n = dot(normalize(gl_LightSource[0].position.xyz), normalize(-ecPosition));
@ -226,20 +230,13 @@ else // the faster, full-day version without lightfields
}
// default lighting based on texture and material using the light we have just computed
// tree shader lighting
vec3 diffuse = gl_FrontMaterial.diffuse.rgb * max(0.1, n);
vec4 ambientColor = gl_FrontLightModelProduct.sceneColor + light_ambient * gl_FrontMaterial.ambient;
gl_FrontColor = ambientColor + light_diffuse * vec4(diffuse, 1.0);
diffuse_term = diffuse_color* light_diffuse;
vec4 constant_term = gl_FrontMaterial.emission + ambient_color *
(gl_LightModel.ambient + light_ambient);
// Super hack: if diffuse material alpha is less than 1, assume a
// transparency animation is at work
if (gl_FrontMaterial.diffuse.a < 1.0)
diffuse_term.a = gl_FrontMaterial.diffuse.a;
else
diffuse_term.a = gl_Color.a;
// Another hack for supporting two-sided lighting without using
// gl_FrontFacing in the fragment shader.
gl_FrontColor.rgb = constant_term.rgb; gl_FrontColor.a = 1.0;
gl_BackColor.rgb = constant_term.rgb; gl_BackColor.a = 0.0;
}

View file

@ -18,8 +18,12 @@ void main(void)
float numVarieties = gl_Normal.z;
float texFract = floor(fract(gl_MultiTexCoord0.x) * numVarieties) / numVarieties;
texFract += floor(gl_MultiTexCoord0.x) / numVarieties;
float sr = sin(gl_FogCoord);
float cr = cos(gl_FogCoord);
// Determine the rotation for the tree. The Fog Coordinate provides rotation information
// to rotate one of the quands by 90 degrees. We then apply an additional position seed
// so that trees aren't all oriented N/S
float sr = sin(gl_FogCoord + gl_Color.x);
float cr = cos(gl_FogCoord + gl_Color.x);
gl_TexCoord[0] = vec4(texFract, gl_MultiTexCoord0.y, 0.0, 0.0);
// scaling

12
Shaders/trivial.frag Normal file
View file

@ -0,0 +1,12 @@
// -*-C++-*-
void main()
{
gl_FragColor = vec4 (1.0, 1.0, 1.0, 1.0);
}

18
Shaders/trivial.vert Normal file
View file

@ -0,0 +1,18 @@
// -*-C++-*-
// Shader that uses OpenGL state values to do per-pixel lighting
//
// The only light used is gl_LightSource[0], which is assumed to be
// directional.
//
// Diffuse colors come from the gl_Color, ambient from the material. This is
// equivalent to osg::Material::DIFFUSE.
#version 120
#define MODE_OFF 0
#define MODE_DIFFUSE 1
#define MODE_AMBIENT_AND_DIFFUSE 2
void main()
{
gl_Position = ftransform();
}

View file

@ -76,7 +76,7 @@ void main (void)
//vec3 ambient = fg_SunAmbientColor.rgb;
vec3 N;
vec3 dotN;
float emission = dot( gl_FrontLightModelProduct.sceneColor.rgb + gl_FrontMaterial.emission,
float emission = dot( gl_FrontLightModelProduct.sceneColor.rgb + gl_FrontMaterial.emission.rgb,
vec3( 0.3, 0.59, 0.11 ) );
float pf;
@ -154,8 +154,8 @@ void main (void)
ambient_Correction = clamp(ambient_Correction, -1.0, 1.0);
color.a = texel.a * alpha;
//vec4 fragColor = vec4(color.rgb * mixedcolor.rgb + ambient_Correction.rgb, color.a);
vec4 fragColor = vec4(color.rgb * mixedcolor, color.a);
vec4 fragColor = vec4(color.rgb * mixedcolor.rgb + ambient_Correction.rgb, color.a);
//vec4 fragColor = vec4(color.rgb * mixedcolor, color.a);
//////////////////////////////////////////////////////////////////////
// BEGIN lightmap

View file

@ -0,0 +1,537 @@
// -*- mode: C; -*-
// Licence: GPL v2
// Author: Frederic Bouvier.
// Adapted from the paper by F. Policarpo et al. : Real-time Relief Mapping on Arbitrary Polygonal Surfaces
// Adapted from the paper and sources by M. Drobot in GPU Pro : Quadtree Displacement Mapping with Height Blending
#version 120
#extension GL_ATI_shader_texture_lod : enable
#extension GL_ARB_shader_texture_lod : enable
#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 vec3 rawpos;
varying vec4 ecPosition;
varying vec3 VNormal;
varying vec3 VTangent;
//varying vec3 VBinormal;
//varying vec3 Normal;
varying vec4 constantColor;
varying vec3 light_diffuse;
varying vec3 relPos;
varying float yprime_alt;
varying float mie_angle;
//varying float steepness;
uniform sampler3D NoiseTex;
uniform sampler2D BaseTex;
uniform sampler2D NormalTex;
uniform sampler2D QDMTex;
uniform float depth_factor;
uniform float tile_size;
uniform float quality_level;
uniform float visibility;
uniform float avisibility;
uniform float scattering;
uniform float terminator;
uniform float terrain_alt;
uniform float hazeLayerAltitude;
uniform float overcast;
uniform float eye_alt;
uniform float snowlevel;
uniform float dust_cover_factor;
uniform float wetness;
uniform float fogstructure;
uniform vec3 night_color;
const float scale = 1.0;
int linear_search_steps = 10;
int GlobalIterationCount = 0;
int gIterationCap = 64;
const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
float alt;
float eShade;
float rand2D(in vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
float simple_interpolate(in float a, in float b, in float x)
{
return a + smoothstep(0.0,1.0,x) * (b-a);
}
float interpolatedNoise2D(in float x, in float y)
{
float integer_x = x - fract(x);
float fractional_x = x - integer_x;
float integer_y = y - fract(y);
float fractional_y = y - integer_y;
float v1 = rand2D(vec2(integer_x, integer_y));
float v2 = rand2D(vec2(integer_x+1.0, integer_y));
float v3 = rand2D(vec2(integer_x, integer_y+1.0));
float v4 = rand2D(vec2(integer_x+1.0, integer_y +1.0));
float i1 = simple_interpolate(v1 , v2 , fractional_x);
float i2 = simple_interpolate(v3 , v4 , fractional_x);
return simple_interpolate(i1 , i2 , fractional_y);
}
float Noise2D(in vec2 coord, in float wavelength)
{
return interpolatedNoise2D(coord.x/wavelength, coord.y/wavelength);
}
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{
x = x - 0.5;
// use the asymptotics to shorten computations
if (x > 30.0) {return e;}
if (x < -15.0) {return 0.0;}
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
}
// this determines how light is attenuated in the distance
// physically this should be exp(-arg) but for technical reasons we use a sharper cutoff
// for distance > visibility
float fog_func (in float targ)
{
float fade_mix;
// for large altitude > 30 km, we switch to some component of quadratic distance fading to
// create the illusion of improved visibility range
targ = 1.25 * targ * smoothstep(0.04,0.06,targ); // need to sync with the distance to which terrain is drawn
if (alt < 30000.0)
{return exp(-targ - targ * targ * targ * targ);}
else if (alt < 50000.0)
{
fade_mix = (alt - 30000.0)/20000.0;
return fade_mix * exp(-targ*targ - pow(targ,4.0)) + (1.0 - fade_mix) * exp(-targ - pow(targ,4.0));
}
else
{
return exp(- targ * targ - pow(targ,4.0));
}
}
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 depth = 0.0;
float best_depth = 1.0;
for(int i = 0; i < linear_search_steps - 1; ++i)
{
depth += size;
float t = step(0.95, texture2D(NormalTex, dp + ds * depth).a);
if(best_depth > 0.996)
if(depth >= t)
best_depth = depth;
}
depth = best_depth;
const int binary_search_steps = 5;
for(int i = 0; i < binary_search_steps; ++i)
{
size *= 0.5;
float t = step(0.95, texture2D(NormalTex, dp + ds * depth).a);
if(depth >= t)
{
best_depth = depth;
depth -= 2.0 * size;
}
depth += size;
}
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)
{
if ( quality_level >= 3.0 ) {
linear_search_steps = 20;
}
vec3 normal = normalize(VNormal);
vec3 tangent = normalize(VTangent);
//vec3 binormal = normalize(VBinormal);
vec3 binormal = normalize(cross(normal, tangent));
vec3 ecPos3 = ecPosition.xyz / ecPosition.w;
vec3 V = normalize(ecPos3);
vec3 s = vec3(dot(V, tangent), dot(V, binormal), dot(normal, -V));
vec2 ds = s.xy * depth_factor / s.z;
vec2 dp = gl_TexCoord[0].st - ds;
float d = ray_intersect(dp, ds);
vec2 uv = dp + ds * d;
vec3 N = texture2D(NormalTex, uv).xyz * 2.0 - 1.0;
float emis = N.z;
N.z = sqrt(1.0 - min(1.0,dot(N.xy, N.xy)));
float Nz = N.z;
N = normalize(N.x * tangent + N.y * binormal + N.z * normal);
vec3 l = gl_LightSource[0].position.xyz;
vec3 diffuse = gl_Color.rgb * max(0.0, dot(N, l));
float shadow_factor = 1.0;
// Shadow
if ( quality_level >= 2.0 ) {
dp += ds * d;
vec3 sl = normalize( vec3( dot( l, tangent ), dot( l, binormal ), dot( -l, normal ) ) );
ds = sl.xy * depth_factor / sl.z;
dp -= ds * d;
float dl = ray_intersect(dp, ds);
if ( dl < d - 0.05 )
shadow_factor = dot( constantColor.xyz, vec3( 1.0, 1.0, 1.0 ) ) * 0.25;
}
// end shadow
vec4 ambient_light = constantColor + vec4 (light_diffuse,1.0) * vec4(diffuse, 1.0);
float reflectance = ambient_light.r * 0.3 + ambient_light.g * 0.59 + ambient_light.b * 0.11;
if ( shadow_factor < 1.0 )
ambient_light = constantColor + vec4(light_diffuse,1.0) * shadow_factor * vec4(diffuse, 1.0);
float emission_factor = (1.0 - smoothstep(0.15, 0.25, reflectance)) * emis;
vec4 tc = texture2D(BaseTex, uv);
emission_factor *= 0.5*pow(tc.r+0.8*tc.g+0.2*tc.b, 2.0) -0.2;
ambient_light += (emission_factor * vec4(night_color, 0.0));
vec4 finalColor = texture2D(BaseTex, uv);
// texel postprocessing by shader effects
// dust effect
vec4 dust_color;
float noise_1500m = Noise2D(rawpos.xy, 1500.0);
float noise_2000m = Noise2D(rawpos.xy, 2000.0);
if (quality_level > 2)
{
// mix dust
dust_color = vec4 (0.76, 0.71, 0.56, 1.0);
finalColor = mix(finalColor, dust_color, clamp(0.5 * dust_cover_factor + 3.0 * dust_cover_factor * (((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) );
}
// darken wet terrain
finalColor.rgb = finalColor.rgb * (1.0 - 0.6 * wetness);
finalColor *= ambient_light;
vec4 p = vec4( ecPos3 + tile_size * V * (d-1.0) * depth_factor / s.z, 1.0 );
//finalColor.rgb = fog_Func(finalColor.rgb, fogType);
// here comes the terrain haze model
float dist = length(relPos);
float delta_z = hazeLayerAltitude - eye_alt;
if (dist > max(40.0, 0.04 * min(visibility,avisibility)))
{
alt = eye_alt;
float transmission;
float vAltitude;
float delta_zv;
float H;
float distance_in_layer;
float transmission_arg;
float intensity;
vec3 lightDir = gl_LightSource[0].position.xyz;
// angle with horizon
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
if (delta_z > 0.0) // we're inside the layer
{
if (ct < 0.0) // we look down
{
distance_in_layer = dist;
vAltitude = min(distance_in_layer,min(visibility, avisibility)) * ct;
delta_zv = delta_z - vAltitude;
}
else // we may look through upper layer edge
{
H = dist * ct;
if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
else {distance_in_layer = dist;}
vAltitude = min(distance_in_layer,visibility) * ct;
delta_zv = delta_z - vAltitude;
}
}
else // we see the layer from above, delta_z < 0.0
{
H = dist * -ct;
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
{
distance_in_layer = 0.0;
delta_zv = 0.0;
}
else
{
vAltitude = H + delta_z;
distance_in_layer = vAltitude/H * dist;
vAltitude = min(distance_in_layer,visibility) * (-ct);
delta_zv = vAltitude;
}
}
// ground haze cannot be thinner than aloft visibility in the model,
// so we need to use aloft visibility otherwise
transmission_arg = (dist-distance_in_layer)/avisibility;
float eqColorFactor;
if (visibility < avisibility)
{
if (quality_level > 3)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/visibility);
}
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -scattering);
}
else
{
if (quality_level > 3)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) ));
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
}
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -scattering);
}
transmission = fog_func(transmission_arg);
// there's always residual intensity, we should never be driven to zero
if (eqColorFactor < 0.2) eqColorFactor = 0.2;
float lightArg = (terminator-yprime_alt)/100000.0;
vec3 hazeColor;
hazeColor.b = light_func(lightArg, 1.330e-05, 0.264, 2.527, 1.08e-05, 1.0);
hazeColor.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
hazeColor.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
// now dim the light for haze
eShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
// Mie-like factor
if (lightArg < 5.0)
{intensity = length(hazeColor);
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
}
// high altitude desaturation of the haze color
intensity = length(hazeColor);
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
// blue hue of haze
hazeColor.x = hazeColor.x * 0.83;
hazeColor.y = hazeColor.y * 0.9;
// additional blue in indirect light
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
intensity = length(hazeColor);
hazeColor = intensity * normalize(mix(hazeColor, 1.5* vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.25, fade_out,eShade) ));
// change haze color to blue hue for strong fogging
hazeColor = intensity * normalize(mix(hazeColor, 2.0 * vec3 (0.55, 0.6, 0.8), (1.0-smoothstep(0.3,0.8,eqColorFactor))));
// reduce haze intensity when looking at shaded surfaces, only in terminator region
float shadow = mix( min(1.0 + dot(VNormal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
finalColor.xyz = mix(eqColorFactor * hazeColor * eShade, finalColor.xyz,transmission);
gl_FragColor = finalColor;
}
else // if dist < threshold no fogging at all
{
gl_FragColor = finalColor;
}
// gl_FragColor = finalColor;
if (dot(normal,-V) > 0.1) {
vec4 iproj = gl_ProjectionMatrix * p;
iproj /= iproj.w;
gl_FragDepth = (iproj.z+1.0)/2.0;
} else {
gl_FragDepth = gl_FragCoord.z;
}
}

View file

@ -0,0 +1,279 @@
// -*-C++-*-
// Shader that uses OpenGL state values to do per-pixel lighting
//
// The only light used is gl_LightSource[0], which is assumed to be
// directional.
//
// Diffuse colors come from the gl_Color, ambient from the material. This is
// equivalent to osg::Material::DIFFUSE.
// Haze part added by Thorsten Renk, Oct. 2011
#define MODE_OFF 0
#define MODE_DIFFUSE 1
#define MODE_AMBIENT_AND_DIFFUSE 2
// The constant term of the lighting equation that doesn't depend on
// the surface normal is passed in gl_{Front,Back}Color. The alpha
// component is set to 1 for front, 0 for back in order to work around
// bugs with gl_FrontFacing in the fragment shader.
varying vec3 relPos;
varying vec3 rawPos;
varying vec3 VNormal;
//varying vec3 Normal;
varying vec3 VTangent;
//varying vec3 VBinormal;
varying vec4 ecPosition;
varying vec4 constantColor;
varying vec3 light_diffuse;
varying float yprime_alt;
varying float mie_angle;
//varying float steepness;
uniform int colorMode;
uniform float hazeLayerAltitude;
uniform float terminator;
uniform float terrain_alt;
uniform float avisibility;
uniform float visibility;
uniform float overcast;
uniform float ground_scattering;
uniform float eye_alt;
attribute vec3 tangent;//, binormal;
float earthShade;
float steepness;
// This is the value used in the skydome scattering shader - use the same here for consistency?
const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{
//x = x - 0.5;
// use the asymptotics to shorten computations
if (x < -15.0) {return 0.0;}
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
}
void main()
{
vec4 light_ambient;
//float yprime_alt;
float yprime;
float lightArg;
float intensity;
float vertex_alt;
float scattering;
rawPos = gl_Vertex.xyz;
steepness = dot(normalize(gl_Normal), vec3 (0.0, 0.0, 1.0));
VNormal = normalize(gl_NormalMatrix * gl_Normal);
ecPosition = gl_ModelViewMatrix * gl_Vertex;
// Normal = normalize(gl_Normal);
VTangent = gl_NormalMatrix * tangent;
// VBinormal = gl_NormalMatrix * binormal;
// this code is copied from default.vert
//vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
//normal = gl_NormalMatrix * gl_Normal;
vec4 ambient_color, diffuse_color;
if (colorMode == MODE_DIFFUSE) {
diffuse_color = gl_Color;
ambient_color = gl_FrontMaterial.ambient;
} else if (colorMode == MODE_AMBIENT_AND_DIFFUSE) {
diffuse_color = gl_Color;
ambient_color = gl_Color;
} else {
diffuse_color = gl_FrontMaterial.diffuse;
ambient_color = gl_FrontMaterial.ambient;
}
// here start computations for the haze layer
// we need several geometrical quantities
// first current altitude of eye position in model space
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
// and relative position to vector
relPos = gl_Vertex.xyz - ep.xyz;
// unfortunately, we need the distance in the vertex shader, although the more accurate version
// is later computed in the fragment shader again
float dist = length(relPos);
// altitude of the vertex in question, somehow zero leads to artefacts, so ensure it is at least 100m
vertex_alt = max(gl_Vertex.z,100.0);
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
// early culling of vertices which can't be seen due to ground haze despite being in aloft visibility range
float delta_z = hazeLayerAltitude - eye_alt;
//if (((dist * (relPos.z - delta_z)/relPos.z > visibility ) && (relPos.z < 0.0) && (delta_z < 0.0) && (dist > 30000.0)))
if (0==1)
{
gl_Position = vec4(0.0, 0.0, -1000.0, 1.0); // move outside of view frustrum, gets culled before reaching fragment shader
earthShade = 1.0;
mie_angle = 1.0;
yprime_alt = 0.0;
}
else
{
// branch dependent on daytime
if (terminator < 1000000.0) // the full, sunrise and sunset computation
{
// establish coordinates relative to sun position
vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0));
// yprime is the distance of the vertex into sun direction
yprime = -dot(relPos, lightHorizon);
// this gets an altitude correction, higher terrain gets to see the sun earlier
yprime_alt = yprime - sqrt(2.0 * EarthRadius * vertex_alt);
// two times terminator width governs how quickly light fades into shadow
// now the light-dimming factor
earthShade = 0.6 * (1.0 - smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt)) + 0.4;
// parametrized version of the Flightgear ground lighting function
lightArg = (terminator-yprime_alt)/100000.0;
// directional scattering for low sun
if (lightArg < 5.0)
{mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
else
{mie_angle = 1.0;}
light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
light_diffuse = light_diffuse * scattering;
light_ambient.b = light_func(lightArg, 0.000506, 0.131, -3.315, 0.000457, 0.5);
light_ambient.g = light_func(lightArg, 2.264e-05, 0.134, 0.967, 3.66e-05, 0.4);
light_ambient.r = light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.33);
light_ambient.a = 0.0;
// correct ambient light intensity and hue before sunrise
if (earthShade < 0.5)
{
light_ambient = light_ambient * (0.7 + 0.3 * smoothstep(0.2, 0.5, earthShade));
intensity = length(light_ambient.xyz);
light_ambient.xyz = intensity * normalize(mix(light_ambient.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.8,earthShade) ));
intensity = length(light_diffuse.xyz);
light_diffuse.xyz = intensity * normalize(mix(light_diffuse.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.7,earthShade) ));
}
// the haze gets the light at the altitude of the haze top if the vertex in view is below
// but the light at the vertex if the vertex is above
vertex_alt = max(vertex_alt,hazeLayerAltitude);
if (vertex_alt > hazeLayerAltitude)
{
if (dist > 0.8 * avisibility)
{
vertex_alt = mix(vertex_alt, hazeLayerAltitude, smoothstep(0.8*avisibility, avisibility, dist));
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
else
{
vertex_alt = hazeLayerAltitude;
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
else // the faster, full-day version without lightfields
{
//vertex_alt = max(gl_Vertex.z,100.0);
earthShade = 1.0;
mie_angle = 1.0;
if (terminator > 3000000.0)
{light_diffuse = vec3 (1.0, 1.0, 1.0);
light_ambient = vec4 (0.33, 0.4, 0.5, 0.0); }
else
{
lightArg = (terminator/100000.0 - 10.0)/20.0;
light_diffuse.b = 0.78 + lightArg * 0.21;
light_diffuse.g = 0.907 + lightArg * 0.091;
light_diffuse.r = 0.904 + lightArg * 0.092;
light_ambient.b = 0.41 + lightArg * 0.08;
light_ambient.g = 0.333 + lightArg * 0.06;
light_ambient.r = 0.316 + lightArg * 0.016;
}
light_diffuse = light_diffuse * scattering;
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
}
// a sky/earth irradiation map model - the sky creates much more diffuse radiation than the ground, so
// steep faces end up shaded more
light_ambient = light_ambient * ((1.0+steepness)/2.0 * 1.2 + (1.0-steepness)/2.0 * 0.2);
// default lighting based on texture and material using the light we have just computed
gl_FrontColor = gl_Color;
constantColor = gl_FrontMaterial.emission
+ gl_Color * (gl_LightModel.ambient + light_ambient);
}
}

View file

@ -18,7 +18,7 @@ varying vec4 rawpos;
varying vec4 ecPosition;
varying vec3 VNormal;
varying vec3 VTangent;
varying vec3 VBinormal;
//varying vec3 VBinormal;
varying vec3 Normal;
varying vec4 constantColor;
@ -177,7 +177,8 @@ void main (void)
}
vec3 normal = normalize(VNormal);
vec3 tangent = normalize(VTangent);
vec3 binormal = normalize(VBinormal);
//vec3 binormal = normalize(VBinormal);
vec3 binormal = normalize(cross(normal, tangent));
vec3 ecPos3 = ecPosition.xyz / ecPosition.w;
vec3 V = normalize(ecPos3);
vec3 s = vec3(dot(V, tangent), dot(V, binormal), dot(normal, -V));

View file

@ -7,10 +7,10 @@ varying vec4 ecPosition;
varying vec3 VNormal;
varying vec3 Normal;
varying vec3 VTangent;
varying vec3 VBinormal;
//varying vec3 VBinormal;
varying vec4 constantColor;
attribute vec3 tangent, binormal;
attribute vec3 tangent;//, binormal;
////fog "include"////////
// uniform int fogType;

View file

@ -86,10 +86,10 @@ void main(void)
cover = min(min(min(min(CloudCover0, CloudCover1),CloudCover2),CloudCover3),CloudCover4);
} else {
// hack to allow for Overcast not to be set by Local Weather
if (Overcast == 0){
cover = 5;
if (Overcast == 0.0){
cover = 5.0;
} else {
cover = Overcast * 5;
cover = Overcast * 5.0;
}
}
@ -207,5 +207,5 @@ void main(void)
vec3( 0.3, 0.59, 0.11 )
);
float specular = smoothstep(0.0, 3.5, cover);
encode_gbuffer(Normal, finalColor.rgb, 254, specular, 128, emission, gl_FragCoord.z);
encode_gbuffer(Normal, finalColor.rgb, 254, specular, 128.0, emission, gl_FragCoord.z);
}

View file

@ -48,7 +48,7 @@ void main(void)
float Angle;
float windFactor = sqrt(pow(abs(WindE),2)+pow(abs(WindN),2)) * 0.05;
float windFactor = sqrt(WindE * WindE + WindN * WindN) * 0.05;
if (WindN == 0.0 && WindE == 0.0) {
Angle = 0.0;

View file

@ -94,10 +94,10 @@ void main(void)
cover = min(min(min(min(CloudCover0, CloudCover1),CloudCover2),CloudCover3),CloudCover4);
} else {
// hack to allow for Overcast not to be set by Local Weather
if (Overcast == 0){
cover = 5;
if (Overcast == 0.0){
cover = 5.0;
} else {
cover = Overcast * 5;
cover = Overcast * 5.0;
}
}

View file

@ -1,9 +1,9 @@
// This shader is mostly an adaptation of the shader found at
// http://www.bonzaisoftware.com/water_tut.html and its glsl conversion
// available at http://forum.bonzaisoftware.com/viewthread.php?tid=10
// © Michael Horsch - 2005
// Michael Horsch - 2005
// Major update and revisions - 2011-10-07
// © Emilian Huminiuc and Vivian Meazza
// Emilian Huminiuc and Vivian Meazza
#version 120
@ -39,7 +39,7 @@ void main(void)
float Angle;
float windFactor = sqrt(pow(abs(WindE),2)+pow(abs(WindN),2)) * 0.05;
float windFactor = sqrt(WindE * WindE + WindN * WindN) * 0.05;
if (WindN == 0.0 && WindE == 0.0) {
Angle = 0.0;

View file

@ -115,7 +115,7 @@ void sumWaves(float angle, float dangle, float windScale, float factor, out floa
{
mat4 RotationMatrix;
float deriv;
vec4 P = waterTex1 * 1024;
vec4 P = waterTex1 * 1024.0;
rotationmatrix(radians(angle + dangle * windScale + 0.6 * sin(P.x * factor)), RotationMatrix);
P *= RotationMatrix;
@ -239,17 +239,17 @@ void main(void)
wave0.amp = WaveAmp;
wave0.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 45;
angle -= 45.0;
wave1.freq = WaveFreq * 2.0 ;
wave1.amp = WaveAmp * 1.25;
wave1.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle += 30;
angle += 30.0;
wave2.freq = WaveFreq * 3.5;
wave2.amp = WaveAmp * 0.75;
wave2.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 50;
angle -= 50.0;
wave3.freq = WaveFreq * 3.0 ;
wave3.amp = WaveAmp * 0.75;
wave3.dir = vec2(cos(radians(angle)), sin(radians(angle)));
@ -270,17 +270,17 @@ void main(void)
wave0.amp = waveamp;
wave0.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 20;
angle -= 20.0;
wave1.freq = WaveFreq * 2.0 ;
wave1.amp = waveamp * 1.25;
wave1.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle += 35;
angle += 35.0;
wave2.freq = WaveFreq * 3.5;
wave2.amp = waveamp * 0.75;
wave2.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 45;
angle -= 45.0;
wave3.freq = WaveFreq * 3.0 ;
wave3.amp = waveamp * 0.75;
wave3.dir = vec2(cos(radians(angle)), sin(radians(angle)));

View file

@ -83,7 +83,7 @@ void main(void)
float Angle;
float windFactor = sqrt(pow(abs(WindE),2)+pow(abs(WindN),2)) * 0.05;
float windFactor = sqrt(WindE * WindE + WindN * WindN) * 0.05;
if (WindN == 0.0 && WindE == 0.0) {
Angle = 0.0;
}else{

View file

@ -97,7 +97,7 @@ float evaluateWaveSharp(Wave w, vec2 pos, float t, float k)
float evaluateWaveDerivSharp(Wave w, vec2 pos, float t, float k)
{
return k*w.freq*w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k - 1) * cos( dot(w.dir, pos)*w.freq + t*w.phase) ;
return k*w.freq*w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k - 1.0) * cos( dot(w.dir, pos)*w.freq + t*w.phase) ;
}
void sumWaves(float angle, float dangle, float windScale, float factor, out float ddx, float ddy)
@ -192,17 +192,17 @@ void main(void)
wave0.amp = WaveAmp ;
wave0.dir = vec2(cos(radians(angle)), sin(radians(angle))) ;
angle -= 45 ;
angle -= 45.0 ;
wave1.freq = WaveFreq * 2.0 ;
wave1.amp = WaveAmp * 1.25 ;
wave1.dir = vec2(cos(radians(angle)), sin(radians(angle))) ;
angle += 30;
angle += 30.0;
wave2.freq = WaveFreq * 3.5 ;
wave2.amp = WaveAmp * 0.75 ;
wave2.dir = vec2(cos(radians(angle)), sin(radians(angle))) ;
angle -= 50 ;
angle -= 50.0 ;
wave3.freq = WaveFreq * 3.0 ;
wave3.amp = WaveAmp * 0.75 ;
wave3.dir = vec2(cos(radians(angle)), sin(radians(angle))) ;
@ -223,17 +223,17 @@ void main(void)
wave0.amp = waveamp ;
wave0.dir = vec2(cos(radians(angle)), sin(radians(angle))) ;
angle -= 20 ;
angle -= 20.0 ;
wave1.freq = WaveFreq * 2.0 ;
wave1.amp = waveamp * 1.25 ;
wave1.dir = vec2(cos(radians(angle)), sin(radians(angle))) ;
angle += 35 ;
angle += 35.0 ;
wave2.freq = WaveFreq * 3.5 ;
wave2.amp = waveamp * 0.75 ;
wave2.dir = vec2(cos(radians(angle)), sin(radians(angle))) ;
angle -= 45 ;
angle -= 45.0 ;
wave3.freq = WaveFreq * 3.0 ;
wave3.amp = waveamp * 0.75 ;
wave3.dir = vec2(cos(radians(angle)), sin(radians(angle))) ;
@ -259,10 +259,10 @@ void main(void)
cover = min(min(min(min(CloudCover0, CloudCover1),CloudCover2),CloudCover3),CloudCover4) ;
} else {
// hack to allow for Overcast not to be set by Local Weather
if (Overcast == 0){
cover = 5;
if (Overcast == 0.0){
cover = 5.0;
} else {
cover = Overcast * 5;
cover = Overcast * 5.0;
}
}

View file

@ -90,7 +90,7 @@ float evaluateWaveSharp(Wave w, vec2 pos, float t, float k)
float evaluateWaveDerivSharp(Wave w, vec2 pos, float t, float k)
{
return k*w.freq*w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k - 1) * cos( dot(w.dir, pos)*w.freq + t*w.phase);
return k*w.freq*w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k - 1.0) * cos( dot(w.dir, pos)*w.freq + t*w.phase);
}
void sumWaves(float angle, float dangle, float windScale, float factor, out float ddx, float ddy)
@ -173,7 +173,7 @@ void main(void)
//uncomment to test
//range = -20000;
if (range > -15000 || dot(Normal,H) > 0.95 ) {
if (range > -15000.0 || dot(Normal,H) > 0.95 ) {
float ddx = 0.0, ddy = 0.0;
float ddx1 = 0.0, ddy1 = 0.0;
@ -187,17 +187,17 @@ void main(void)
wave0.amp = WaveAmp;
wave0.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 45;
angle -= 45.0;
wave1.freq = WaveFreq * 2.0 ;
wave1.amp = WaveAmp * 1.25;
wave1.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle += 30;
angle += 30.0;
wave2.freq = WaveFreq * 3.5;
wave2.amp = WaveAmp * 0.75;
wave2.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 50;
angle -= 50.0;
wave3.freq = WaveFreq * 3.0 ;
wave3.amp = WaveAmp * 0.75;
wave3.dir = vec2(cos(radians(angle)), sin(radians(angle)));
@ -218,17 +218,17 @@ void main(void)
wave0.amp = waveamp;
wave0.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 20;
angle -= 20.0;
wave1.freq = WaveFreq * 2.0 ;
wave1.amp = waveamp * 1.25;
wave1.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle += 35;
angle += 35.0;
wave2.freq = WaveFreq * 3.5;
wave2.amp = waveamp * 0.75;
wave2.dir = vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 45;
angle -= 45.0;
wave3.freq = WaveFreq * 3.0 ;
wave3.amp = waveamp * 0.75;
wave3.dir = vec2(cos(radians(angle)), sin(radians(angle)));

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
Textures/Terrain/void.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

BIN
Textures/film-dirt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
Textures/noise_tex.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View file

@ -43,6 +43,7 @@
<!-- Environment menu -->
<environment>Environment</environment>
<global-weather>Weather</global-weather>
<environment-settings>Environment Settings</environment-settings>
<time-settings>Time Settings</time-settings>
<wildfire-settings>Wildfire Settings</wildfire-settings>
<terrasync>Scenery Download</terrasync>
@ -111,6 +112,7 @@
<aircraft-keys>Aircraft Help</aircraft-keys>
<common-keys>Common Aircraft Keys</common-keys>
<basic-keys>Basic Simulator Keys</basic-keys>
<joystick-config>Joystick Configuration</joystick-config>
<joystick-info>Joystick Information</joystick-info>
<tutorial-start>Tutorials</tutorial-start>
<menu-about>About</menu-about>

View file

@ -167,7 +167,7 @@
<enable-skyblend-desc>Enable sky blending</enable-skyblend-desc>
<disable-textures-desc>Disable textures</disable-textures-desc>
<enable-textures-desc>Enable textures</enable-textures-desc>
<materials-file-desc>Specify the materials file used to render the scenery (default: materials.xml)</materials-file-desc>
<materials-file-desc>Specify the materials file used to render the scenery (default: Materials/regions/materials.xml)</materials-file-desc>
<texture-filtering-desc>Anisotropic Texture Filtering: values should be 1 (default),2,4,8 or 16</texture-filtering-desc>
<disable-wireframe-desc>Disable wireframe drawing mode</disable-wireframe-desc>
<enable-wireframe-desc>Enable wireframe drawing mode</enable-wireframe-desc>

View file

@ -0,0 +1,437 @@
<?xml version="1.0"?>
<PropertyList>
<nasal>
<open><![CDATA[
var assignButton = func(cmd) {
var i = getprop("/sim/gui/dialogs/joystick-config/current-button");
setprop("/sim/gui/dialogs/joystick-config/button[" ~ i ~ "]/binding", cmd);
joystick.writeConfig();
fgcommand("reinit", props.Node.new({"subsystem": "input"}));
fgcommand("dialog-close", props.Node.new({"dialog-name": "button-config"}));
fgcommand("dialog-close", props.Node.new({"dialog-name": "joystick-config"}));
fgcommand("dialog-show", props.Node.new({"dialog-name": "joystick-config"}));
}
]]></open>
<close><![CDATA[
]]></close>
</nasal>
<name>button-config</name>
<layout>vbox</layout>
<resizable>true</resizable>
<modal>true</modal>
<default-padding>3</default-padding>
<group>
<layout>hbox</layout>
<default-padding>1</default-padding>
<empty><stretch>true</stretch></empty>
<text>
<label>Button Configuration</label>
</text>
<empty><stretch>true</stretch></empty>
<button>
<legend></legend>
<key>Esc</key>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<border>2</border>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<text>
<halign>left</halign>
<label>Select the command you wish to assign to this button</label>
</text>
<hrule/>
<group>
<layout>table</layout>
<text>
<row>0</row>
<col>0</col>
<label>Flight surface trim</label>
</text>
<button>
<row>1</row>
<col>0</col>
<halign>fill</halign>
<legend>Elevator Trim Up</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Elevator Trim Up");
</script>
</binding>
</button>
<button>
<row>2</row>
<col>0</col>
<halign>fill</halign>
<legend>Elevator Trim Down</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Elevator Trim Down");
</script>
</binding>
</button>
<button>
<row>3</row>
<col>0</col>
<halign>fill</halign>
<legend>Rudder Trim Left</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Rudder Trim Left");
</script>
</binding>
</button>
<button>
<row>4</row>
<col>0</col>
<halign>fill</halign>
<legend>Rudder Trim Right</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Rudder Trim Right");
</script>
</binding>
</button>
<button>
<row>5</row>
<col>0</col>
<halign>fill</halign>
<legend>Aileron Trim Left</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Aileron Trim Left");
</script>
</binding>
</button>
<button>
<row>6</row>
<col>0</col>
<halign>fill</halign>
<legend>Aileron Trim Right</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Aileron Trim Right");
</script>
</binding>
</button>
<text>
<row>0</row>
<col>1</col>
<label>Control Surfaces</label>
</text>
<button>
<row>1</row>
<col>1</col>
<halign>fill</halign>
<legend>Flaps Up</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Flaps Up");
</script>
</binding>
</button>
<button>
<row>2</row>
<col>1</col>
<halign>fill</halign>
<legend>Flaps Down</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Flaps Down");
</script>
</binding>
</button>
<button>
<row>3</row>
<col>1</col>
<halign>fill</halign>
<legend>Gear Up</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Gear Up");
</script>
</binding>
</button>
<button>
<row>4</row>
<col>1</col>
<halign>fill</halign>
<legend>Gear Down</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Gear Down");
</script>
</binding>
</button>
<button>
<row>5</row>
<col>1</col>
<halign>fill</halign>
<legend>Spoilers Retract</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Spoilers Retract");
</script>
</binding>
</button>
<button>
<row>6</row>
<col>1</col>
<halign>fill</halign>
<legend>Spoilers Deploy</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Spoilers Deploy");
</script>
</binding>
</button>
<text>
<row>0</row>
<col>2</col>
<label>Other Aircraft Controls</label>
</text>
<button>
<row>1</row>
<col>2</col>
<halign>fill</halign>
<legend>Brakes</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Brakes");
</script>
</binding>
</button>
<button>
<row>2</row>
<col>2</col>
<halign>fill</halign>
<legend>FGCom PTT</legend>
<binding>
<command>nasal</command>
<script>
assignButton("FGCom PTT");
</script>
</binding>
</button>
<button>
<row>3</row>
<col>2</col>
<halign>fill</halign>
<legend>Trigger</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Trigger");
</script>
</binding>
</button>
<button>
<row>4</row>
<col>2</col>
<halign>fill</halign>
<legend>Custom</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Custom");
</script>
</binding>
</button>
<button>
<row>5</row>
<col>2</col>
<halign>fill</halign>
<legend>None</legend>
<binding>
<command>nasal</command>
<script>
assignButton("None");
</script>
</binding>
</button>
<text>
<row>0</row>
<col>3</col>
<label>View</label>
</text>
<button>
<row>1</row>
<col>3</col>
<halign>fill</halign>
<legend>View Decrease</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Decrease");
</script>
</binding>
</button>
<button>
<row>2</row>
<col>3</col>
<halign>fill</halign>
<legend>View Increase</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Increase");
</script>
</binding>
</button>
<button>
<row>3</row>
<col>3</col>
<halign>fill</halign>
<legend>View Cycle Forwards</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Cycle Forwards");
</script>
</binding>
</button>
<button>
<row>4</row>
<col>3</col>
<halign>fill</halign>
<legend>View Cycle Backwards</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Cycle Backwards");
</script>
</binding>
</button>
<button>
<row>5</row>
<col>3</col>
<halign>fill</halign>
<legend>View Left</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Left");
</script>
</binding>
</button>
<button>
<row>6</row>
<col>3</col>
<halign>fill</halign>
<legend>View Right</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Right");
</script>
</binding>
</button>
<button>
<row>7</row>
<col>3</col>
<halign>fill</halign>
<legend>View Up</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Up");
</script>
</binding>
</button>
<button>
<row>8</row>
<col>3</col>
<halign>fill</halign>
<legend>View Down</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Down");
</script>
</binding>
</button>
</group>
<group>
<empty>
<stretch>true</stretch>
</empty>
<layout>hbox</layout>
<button>
<legend>Close</legend>
<default>true</default>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
<empty>
<stretch>true</stretch>
</empty>
</group>
</PropertyList>

View file

@ -0,0 +1,259 @@
<?xml version="1.0"?>
<PropertyList>
<name>environment-settings</name>
<modal>false</modal>
<resizable>false</resizable>
<layout>vbox</layout>
<default-padding>3</default-padding>
<!-- Title bar with close button -->
<group>
<layout>hbox</layout>
<default-padding>1</default-padding>
<empty>
<stretch>true</stretch>
</empty>
<text>
<label>Environmental Settings</label>
</text>
<empty>
<stretch>true</stretch>
</empty>
<button>
<legend/>
<key>Esc</key>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<border>2</border>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<group>
<layout>table</layout>
<text>
<row>0</row>
<col>0</col>
<label>Ground textures:</label>
<halign>right</halign>
</text>
<combo>
<row>0</row>
<col>1</col>
<name>season</name>
<halign>left</halign>
<live>true</live>
<property>/sim/startup/season</property>
<value>summer</value>
<value>winter</value>
<binding>
<command>dialog-apply</command>
<object-name>season</object-name>
</binding>
</combo>
<button>
<row>0</row>
<col>2</col>
<legend>Reload Scenery</legend>
<binding>
<command>reinit</command>
<subsystem>tile-manager</subsystem>
</binding>
</button>
</group>
<hrule/>
<group>
<layout>table</layout>
<text>
<row>0</row>
<col>0</col>
<colspan>4</colspan>
<halign>left</halign>
<label>Ground conditions (requires shaders effects)</label>
</text>
<checkbox>
<row>1</row>
<col>0</col>
<colspan>4</colspan>
<halign>left</halign>
<label>Set maximum snow level from METAR</label>
<name>metar-snow</name>
<property>/environment/params/metar-updates-snow-level</property>
<binding>
<command>dialog-apply</command>
<object-name>metar-snow</object-name>
</binding>
</checkbox>
<text>
<label>Snow line</label>
<halign>left</halign>
<row>2</row>
<col>0</col>
</text>
<text>
<label>-425m</label>
<halign>right</halign>
<row>2</row>
<col>1</col>
</text>
<slider>
<name>snow-level</name>
<row>2</row>
<col>2</col>
<min>-425.0</min>
<max>7500.0</max>
<live>true</live>
<property>/environment/snow-level-m</property>
<binding>
<command>dialog-apply</command>
<object-name>snow-level</object-name>
</binding>
</slider>
<text>
<label>7500m</label>
<halign>left</halign>
<row>2</row>
<col>3</col>
</text>
<text>
<row>2</row>
<col>4</col>
<label>12345678</label>
<format>%.fm</format>
<live>true</live>
<property>/environment/snow-level-m</property>
</text>
<text>
<label>Dust cover</label>
<halign>left</halign>
<row>3</row>
<col>0</col>
</text>
<text>
<label>none</label>
<halign>right</halign>
<row>3</row>
<col>1</col>
</text>
<slider>
<name>dust-level</name>
<row>3</row>
<col>2</col>
<min>0.0</min>
<max>0.7</max>
<live>true</live>
<property>/environment/surface/dust-cover-factor</property>
<binding>
<command>dialog-apply</command>
<object-name>dust-level</object-name>
</binding>
</slider>
<text>
<label>dusty</label>
<halign>left</halign>
<row>3</row>
<col>3</col>
</text>
<text>
<label>Wetness</label>
<halign>left</halign>
<row>4</row>
<col>0</col>
</text>
<text>
<label>dry</label>
<halign>right</halign>
<row>4</row>
<col>1</col>
</text>
<slider>
<name>wetness</name>
<row>4</row>
<col>2</col>
<min>0.0</min>
<max>0.7</max>
<live>true</live>
<property>/environment/surface/wetness</property>
<binding>
<command>dialog-apply</command>
<object-name>wetness</object-name>
</binding>
</slider>
<text>
<label>wet</label>
<halign>left</halign>
<row>4</row>
<col>3</col>
</text>
</group>
<hrule/>
<group>
<empty>
<stretch>true</stretch>
</empty>
<layout>hbox</layout>
<button>
<legend>OK</legend>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<button>
<legend>Apply</legend>
<binding>
<command>dialog-apply</command>
</binding>
</button>
<button>
<legend>Close</legend>
<default>true</default>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
<empty>
<stretch>true</stretch>
</empty>
</group>
</PropertyList>

View file

@ -0,0 +1,463 @@
<?xml version="1.0"?>
<PropertyList>
<nasal>
<open><![CDATA[
var dlgRoot = cmdarg();
# Debug only
io.load_nasal("/home/stuart/FlightGear/data/Nasal/joystick.nas");
var DIALOG_ROOT = "/sim/gui/dialogs/joystick-config";
# Read the current bindings
joystick.readConfig();
# Fill in the joystick names combo box.
var joysticks = props.globals.getNode("/input/joysticks").getChildren("js");
var jsselect = gui.findElementByName(dlgRoot, "jsselect" );
forindex (var joystick_index; joysticks) {
var js = joysticks[joystick_index];
var js_id = "unknown";
if ((js.getNode("id") != nil) and (js.getNode("id").getValue() != nil))
{
js_id = js.getNode("id").getValue();
}
jsselect.getNode("value[" ~ joystick_index ~ "]", 1).setValue(js_id);
}
var table = gui.findElementByName(dlgRoot, "axistable");
table.removeChildren("checkbox");
table.removeChildren("combo");
# Fill in the valid axis bindings
for (var i = 0; i < joystick.MAX_AXES; i = i + 1) {
# Label
var t = table.getChild("text", 2*i + 4, 1);
t.getNode("row", 1).setValue(i + 1);
t.getNode("col", 1).setValue(0);
t.getNode("label", 1).setValue("Axis " ~ i);
# Raw data
t = table.getChild("text", 2*i + 5, 1);
t.getNode("property", 1).setValue("/devices/status/joysticks/joystick[" ~ joystick_index ~ "]/axis[" ~ i ~ "]");
t.getNode("row", 1).setValue(i +1 );
t.getNode("col", 1).setValue(1);
t.getNode("label", 1).setValue("01234");
t.getNode("format", 1).setValue("%2.2f");
t.getNode("halign", 1).setValue("right");
t.getNode("live", 1).setValue(1);
# Binding
t = table.getChild("combo", i, 1);
t.getNode("name", 1).setValue("axis" ~ i ~ "binding");
t.getNode("row", 1).setValue(i + 1);
t.getNode("col", 1).setValue("2");
t.getNode("halign", 1).setValue("fill");
t.getNode("pref-width", 1).setValue("150");
t.getNode("live", 1).setValue(1);
t.getNode("property", 1).setValue(DIALOG_ROOT ~ "/axis[" ~ i ~ "]/binding");
forindex (var idx; joystick.axisBindings) {
t.getChild("value", idx, 1).setValue(joystick.axisBindings[idx].getName());
}
var b = t.getChild("binding", 0, 1);
b.getNode("command", 1).setValue("dialog-apply");
b.getNode("object-name", 1).setValue("axis" ~ i ~ "binding");
b = t.getChild("binding", 1, 1);
b.getNode("command", 1).setValue("nasal");
b.getNode("script", 1).setValue("updateConfig();");
# Inverted
t = table.getChild("checkbox", i, 1);
t.getNode("name", 1).setValue("axis" ~ i ~ "inverted");
t.getNode("property", 1).setValue(DIALOG_ROOT ~ "/axis[" ~ i ~ "]/inverted");
t.getNode("row", 1).setValue(i +1 );
t.getNode("col", 1).setValue(3);
t.getNode("visible", 1).getNode("property", 1).setValue(DIALOG_ROOT ~ "/axis[" ~ i ~ "]/invertable");
t.getNode("live", 1).setValue(1);
var b = t.getChild("binding", 0, 1);
b.getNode("command", 1).setValue("dialog-apply");
b.getNode("object-name", 1).setValue("axis" ~ i ~ "inverted");
b = t.getChild("binding", 1, 1);
b.getNode("command", 1).setValue("nasal");
b.getNode("script", 1).setValue("updateConfig();");
}
# Set up the buttons.
table = gui.findElementByName(dlgRoot, "buttontable");
table.removeChildren("checkbox");
table.removeChildren("button");
var row = 1;
var col = 0;
for (var button = 0; button < joystick.MAX_BUTTONS; button = button + 1) {
t = table.getChild("checkbox", button, 1);
t.getNode("property", 1).setValue("/devices/status/joysticks/joystick[" ~ joystick_index ~ "]/button[" ~ button ~ "]");
t.getNode("row", 1).setValue(row );
t.getNode("col", 1).setValue(col);
t.getNode("live", 1).setValue(1);
t = table.getChild("button", button, 1);
t.getNode("name", 1).setValue("button" ~ button);
t.getNode("pref-width", 1).setValue(130);
t.getNode("halign", 1).setValue("fill");
t.getNode("live", 1).setValue("fill");
t.getNode("row", 1).setValue(row );
t.getNode("col", 1).setValue(col +1);
t.getNode("legend", 1).setValue(getprop(DIALOG_ROOT ~ "/button[" ~ button ~ "]/binding"));
var b = t.getChild("binding", 0, 1);
b.getNode("command", 1).setValue("property-assign");
b.getNode("property", 1).setValue("/sim/gui/dialogs/joystick-config/current-button");
b.getNode("value", 1).setValue(button);
b = t.getChild("binding", 1, 1);
b.getNode("command", 1).setValue("dialog-show");
b.getNode("dialog-name", 1).setValue("button-config");
col = col + 2;
if (col > 5) {
row = row +1;
col = 0;
}
}
var updateConfig = func() {
joystick.writeConfig();
fgcommand("reinit", props.Node.new({"subsystem": "input"}));
fgcommand("dialog-close", props.Node.new({"dialog-name": "joystick-config"}));
fgcommand("dialog-show", props.Node.new({"dialog-name": "joystick-config"}));
}
]]></open>
<close><![CDATA[
]]></close>
</nasal>
<name>joystick-config</name>
<layout>vbox</layout>
<resizable>true</resizable>
<default-padding>3</default-padding>
<group>
<layout>hbox</layout>
<default-padding>1</default-padding>
<empty><stretch>true</stretch></empty>
<text>
<label>Joystick Configuration</label>
</text>
<empty><stretch>true</stretch></empty>
<button>
<legend></legend>
<key>Esc</key>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<border>2</border>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<group>
<layout>table</layout>
<default-padding>2</default-padding>
<empty>
<width>150</width>
<col>0</col>
<row>0</row>
</empty>
<text>
<label>Aileron: </label>
<halign>right</halign>
<col>1</col>
<row>0</row>
</text>
<text>
<label>-0.00000</label>
<halign>left</halign>
<format>%.5f</format>
<property>/controls/flight/aileron</property>
<live>1</live>
<col>2</col>
<row>0</row>
</text>
<text>
<label>Elevator: </label>
<halign>right</halign>
<col>1</col>
<row>1</row>
</text>
<text>
<label>-0.00000</label>
<halign>left</halign>
<format>%.5f</format>
<property>/controls/flight/elevator</property>
<live>1</live>
<col>2</col>
<row>1</row>
</text>
<text>
<label>Rudder: </label>
<halign>right</halign>
<col>3</col>
<row>0</row>
</text>
<text>
<label>-0.00000</label>
<halign>left</halign>
<format>%.5f</format>
<property>/controls/flight/rudder</property>
<live>1</live>
<col>4</col>
<row>0</row>
</text>
<text>
<label>Throttle: </label>
<halign>right</halign>
<col>3</col>
<row>1</row>
</text>
<text>
<label>-0.00000</label>
<halign>left</halign>
<format>%.5f</format>
<property>/controls/engines/engine/throttle</property>
<live>1</live>
<col>4</col>
<row>1</row>
</text>
<empty>
<width>150</width>
<col>5</col>
<row>0</row>
</empty>
</group>
<!-- Joystick selector -->
<group>
<layout>table</layout>
<halign>left</halign>
<text>
<row>0</row>
<col>0</col>
<halign>right</halign>
<label>Joystick</label>
</text>
<combo>
<name>jsselect</name>
<row>0</row>
<col>1</col>
<halign>left</halign>
<property>/sim/gui/dialogs/joystick-config/selected-joystick</property>
<pref-width>350</pref-width>
<binding>
<command>dialog-apply</command>
<object-name>jsselect</object-name>
</binding>
<binding>
<command>nasal</command>
<script>
fgcommand("dialog-close", props.Node.new({"dialog-name": "joystick-config"}));
fgcommand("dialog-show", props.Node.new({"dialog-name": "joystick-config"}));
</script>
</binding>
</combo>
<text>
<row>1</row>
<col>0</col>
<halign>right</halign>
<label>Configuration File</label>
</text>
<text>
<row>1</row>
<col>1</col>
<halign>left</halign>
<label>Joystick Confgig</label>
<property>/sim/gui/dialogs/joystick-config/selected-joystick-config</property>
</text>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<valign>top</valign>
<halign>fill</halign>
<!-- Axis list -->
<group>
<layout>table</layout>
<valign>top</valign>
<name>axistable</name>
<!-- Header Row -->
<text>
<row>0</row>
<col>0</col>
<label>Axis</label>
</text>
<text>
<row>0</row>
<col>1</col>
<label>Input</label>
</text>
<text>
<row>0</row>
<col>2</col>
<label>Control</label>
</text>
<text>
<row>0</row>
<col>3</col>
<label>Inverted?</label>
</text>
<!-- Axes get added here based on above template -->
</group>
<vrule/>
<!-- Buttons -->
<group>
<layout>table</layout>
<valign>top</valign>
<name>buttontable</name>
<!-- Header row-->
<text>
<row>0</row><col>0</col>
<label>Input</label>
</text>
<text>
<row>0</row><col>1</col>
<label>Control</label>
</text>
<text>
<row>0</row><col>2</col>
<label>Input</label>
</text>
<text>
<row>0</row><col>3</col>
<label>Control</label>
</text>
<text>
<row>0</row><col>4</col>
<label>Input</label>
</text>
<text>
<row>0</row><col>5</col>
<label>Control</label>
</text>
<buttontemplate>
<name>buttontemplate</name>
<checkbox>
<row>1</row><col>0</col>
<halign>right</halign>
<live>1</live>
<readonly>1</readonly>
<property>/devices/status/joysticks/joystick[0]/button[0]</property>
</checkbox>
<text>
<row>1</row><col>1</col>
<property>/sim/gui/dialogs/joystick-config/button[0]</property>
<label>01234567890</label>
<halign>left</halign>
<live>true</live>
</text>
<button>
<row>1</row><col>2</col>
<legend>...</legend>
<binding>
<command>property-assign</command>
<property>/sim/gui/dialogs/joystick-config/current-button</property>
<value>0</value>
</binding>
<binding>
<command>dialog-show</command>
<dialog-name>button-config</dialog-name>
</binding>
</button>
</buttontemplate>
<!-- Buttons get added here based on above template -->
</group>
</group>
<hrule/>
<!-- Button bar -->
<group>
<layout>hbox</layout>
<empty>
<stretch>true</stretch>
</empty>
<button>
<legend>Close</legend>
<binding>
<command>dialog-close</command>
</binding>
</button>
<empty>
<stretch>true</stretch>
</empty>
</group>
</PropertyList>

View file

@ -1,157 +0,0 @@
<?xml version="1.0"?>
<PropertyList>
<name>local_weather_environment</name>
<width>400</width>
<height>210</height>
<modal>false</modal>
<text>
<x>5</x>
<y>180</y>
<label>Environment parameters (only used by detailed shaders)</label>
</text>
<text>
<x>5</x>
<y>150</y>
<label>Snow line:</label>
</text>
<text>
<x>120</x>
<y>150</y>
<label>0 m </label>
</text>
<slider>
<x>190</x>
<y>150</y>
<width>90</width>
<height>20</height>
<min>0.0</min>
<max>7500.0</max>
<property>/environment/mysnow-level-m</property>
<binding>
<command>dialog-apply</command>
</binding>
</slider>
<text>
<x>290</x>
<y>150</y>
<label>7500 m</label>
</text>
<text>
<x>340</x>
<y>150</y>
<label>12345678</label>
<format>%.fm</format>
<live>true</live>
<property>/environment/mysnow-level-m</property>
</text>
<text>
<x>5</x>
<y>120</y>
<label>Terrain dust cover:</label>
</text>
<text>
<x>120</x>
<y>120</y>
<label>none </label>
</text>
<slider>
<x>190</x>
<y>120</y>
<width>90</width>
<height>20</height>
<min>0.0</min>
<max>0.7</max>
<property>/environment/surface/dust-cover-factor</property>
<binding>
<command>dialog-apply</command>
</binding>
</slider>
<text>
<x>290</x>
<y>120</y>
<label>dusty</label>
</text>
<text>
<x>5</x>
<y>90</y>
<label>Fog properties:</label>
</text>
<text>
<x>120</x>
<y>90</y>
<label>smooth </label>
</text>
<slider>
<x>190</x>
<y>90</y>
<width>90</width>
<height>20</height>
<min>0.0</min>
<max>12.0</max>
<property>/environment/fog-structure</property>
<binding>
<command>dialog-apply</command>
</binding>
</slider>
<text>
<x>290</x>
<y>90</y>
<label>structured</label>
</text>
<group>
<x>10</x>
<y>10</y>
<button>
<x>0</x>
<y>0</y>
<legend>OK</legend>
<!--<default>true</default>-->
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<button>
<x>265</x>
<y>0</y>
<legend>Cancel</legend>
<equal>true</equal>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
</PropertyList>

File diff suppressed because it is too large Load diff

View file

@ -86,7 +86,7 @@
i = 0;
foreach (var park; a.parking()) {
parking.getNode("value[" ~ i ~ "]", 1).setValue(park);
parking.getNode("value[" ~ i ~ "]", 1).setValue(park.name);
i += 1;
}

View file

@ -52,7 +52,7 @@
</enable>
</checkbox>
<empty>
<pref-width>66</pref-width>
<pref-width>63</pref-width>
</empty>
<text>
<label>Strength</label>
@ -111,7 +111,7 @@
</enable>
</checkbox>
<empty>
<pref-width>-4</pref-width>
<pref-width>-7</pref-width>
</empty>
<text>
<label>Strength</label>
@ -170,7 +170,7 @@
</binding>
</checkbox>
<empty>
<pref-width>45</pref-width>
<pref-width>42</pref-width>
</empty>
<text>
<label>Map size</label>
@ -231,7 +231,7 @@
<property>/sim/rendering/shadows/filtering</property>
</text>
<empty>
<pref-width>67</pref-width>
<pref-width>222</pref-width>
</empty>
</group>
@ -289,7 +289,7 @@
<property>/sim/rendering/shadows/num-cascades</property>
</text>
<empty>
<pref-width>67</pref-width>
<pref-width>222</pref-width>
</empty>
</group>
@ -297,10 +297,6 @@
<layout>hbox</layout>
<halign>right</halign>
<empty>
<pref-width>130</pref-width>
</empty>
<text>
<label>Cascades</label>
<enable>
@ -373,6 +369,667 @@
<object-name>shadow-cascade-4</object-name>
</binding>
</input>
<empty>
<pref-width>147</pref-width>
</empty>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<halign>left</halign>
<checkbox>
<halign>left</halign>
<label>Night vision</label>
<name>night-vision</name>
<property>/sim/rendering/rembrandt/night-vision</property>
<binding>
<command>dialog-apply</command>
<object-name>night-vision</object-name>
</binding>
</checkbox>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<halign>left</halign>
<checkbox>
<halign>left</halign>
<label>Vignette</label>
<name>vignette</name>
<property>/sim/rendering/rembrandt/cinema/vignette</property>
<binding>
<command>dialog-apply</command>
<object-name>vignette</object-name>
</binding>
<enable>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
</enable>
</checkbox>
<empty>
<pref-width>34</pref-width>
</empty>
<text>
<label>Inner circle</label>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/vignette</property>
</and>
</enable>
</text>
<slider>
<name>inner-circle</name>
<min>0.0</min>
<max>1.5</max>
<step>0.01</step>
<property>/sim/rendering/rembrandt/cinema/inner-circle</property>
<binding>
<command>dialog-apply</command>
<object-name>inner-circle</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/vignette</property>
</and>
</enable>
</slider>
<text>
<label>12345678</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/inner-circle</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/vignette</property>
</and>
</enable>
</text>
</group>
<group>
<layout>hbox</layout>
<halign>right</halign>
<text>
<label>Outer circle</label>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/vignette</property>
</and>
</enable>
</text>
<slider>
<name>outer-circle</name>
<min>1.0</min>
<max>2.0</max>
<step>0.01</step>
<property>/sim/rendering/rembrandt/cinema/outer-circle</property>
<binding>
<command>dialog-apply</command>
<object-name>outer-circle</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/vignette</property>
</and>
</enable>
</slider>
<text>
<label>12345678</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/outer-circle</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/vignette</property>
</and>
</enable>
</text>
<empty>
<pref-width>222</pref-width>
</empty>
</group>
<group>
<layout>hbox</layout>
<halign>left</halign>
<checkbox>
<halign>left</halign>
<label>Color shift</label>
<name>color-shift</name>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
<binding>
<command>dialog-apply</command>
<object-name>color-shift</object-name>
</binding>
<enable>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
</enable>
</checkbox>
<empty>
<pref-width>37</pref-width>
</empty>
<text>
<label>Red shift</label>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
<slider>
<name>red-shift-r</name>
<min>0.0</min>
<max>1.0</max>
<step>0.004</step>
<property>/sim/rendering/rembrandt/cinema/red-shift/x</property>
<binding>
<command>dialog-apply</command>
<object-name>red-shift-r</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/red-shift/x</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
<slider>
<name>red-shift-g</name>
<min>0.0</min>
<max>1.0</max>
<step>0.004</step>
<property>/sim/rendering/rembrandt/cinema/red-shift/y</property>
<binding>
<command>dialog-apply</command>
<object-name>red-shift-g</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/red-shift/y</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
<slider>
<name>red-shift-b</name>
<min>0.0</min>
<max>1.0</max>
<step>0.004</step>
<property>/sim/rendering/rembrandt/cinema/red-shift/z</property>
<binding>
<command>dialog-apply</command>
<object-name>red-shift-b</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/red-shift/z</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
</group>
<group>
<layout>hbox</layout>
<halign>right</halign>
<text>
<label>Green shift</label>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
<slider>
<name>green-shift-r</name>
<min>0.0</min>
<max>1.0</max>
<step>0.004</step>
<property>/sim/rendering/rembrandt/cinema/green-shift/x</property>
<binding>
<command>dialog-apply</command>
<object-name>green-shift-r</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/green-shift/x</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
<slider>
<name>green-shift-g</name>
<min>0.0</min>
<max>1.0</max>
<step>0.004</step>
<property>/sim/rendering/rembrandt/cinema/green-shift/y</property>
<binding>
<command>dialog-apply</command>
<object-name>green-shift-g</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/green-shift/y</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
<slider>
<name>green-shift-b</name>
<min>0.0</min>
<max>1.0</max>
<step>0.004</step>
<property>/sim/rendering/rembrandt/cinema/green-shift/z</property>
<binding>
<command>dialog-apply</command>
<object-name>green-shift-b</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/green-shift/z</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
</group>
<group>
<layout>hbox</layout>
<halign>right</halign>
<text>
<label>Blue shift</label>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
<slider>
<name>blue-shift-r</name>
<min>0.0</min>
<max>1.0</max>
<step>0.004</step>
<property>/sim/rendering/rembrandt/cinema/blue-shift/x</property>
<binding>
<command>dialog-apply</command>
<object-name>blue-shift-r</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/blue-shift/x</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
<slider>
<name>blue-shift-g</name>
<min>0.0</min>
<max>1.0</max>
<step>0.004</step>
<property>/sim/rendering/rembrandt/cinema/blue-shift/y</property>
<binding>
<command>dialog-apply</command>
<object-name>blue-shift-g</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/blue-shift/y</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
<slider>
<name>blue-shift-b</name>
<min>0.0</min>
<max>1.0</max>
<step>0.004</step>
<property>/sim/rendering/rembrandt/cinema/blue-shift/z</property>
<binding>
<command>dialog-apply</command>
<object-name>blue-shift-b</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/blue-shift/z</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</and>
</enable>
</text>
</group>
<group>
<layout>hbox</layout>
<halign>left</halign>
<checkbox>
<halign>left</halign>
<label>Distortion</label>
<name>distortion</name>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
<binding>
<command>dialog-apply</command>
<object-name>distortion</object-name>
</binding>
<enable>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
</enable>
</checkbox>
<empty>
<pref-width>48</pref-width>
</empty>
<text>
<label>Factors</label>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
</and>
</enable>
</text>
<slider>
<name>distortion-factor-x</name>
<min>-0.5</min>
<max>0.5</max>
<step>0.01</step>
<property>/sim/rendering/rembrandt/cinema/distortion-factor/x</property>
<binding>
<command>dialog-apply</command>
<object-name>distortion-factor-x</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/distortion-factor/x</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
</and>
</enable>
</text>
<slider>
<name>distortion-factor-y</name>
<min>-0.5</min>
<max>0.5</max>
<step>0.01</step>
<property>/sim/rendering/rembrandt/cinema/distortion-factor/y</property>
<binding>
<command>dialog-apply</command>
<object-name>distortion-factor-y</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/distortion-factor/y</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
</and>
</enable>
</text>
<slider>
<name>distortion-factor-z</name>
<min>0.5</min>
<max>1.5</max>
<step>0.001</step>
<property>/sim/rendering/rembrandt/cinema/distortion-factor/z</property>
<binding>
<command>dialog-apply</command>
<object-name>distortion-factor-z</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
</and>
</enable>
</slider>
<text>
<label>1234</label>
<format>%.2f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/distortion-factor/z</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
</and>
</enable>
</text>
</group>
<group>
<layout>hbox</layout>
<halign>left</halign>
<checkbox>
<halign>left</halign>
<label>Color fringe</label>
<name>color-fringe</name>
<property>/sim/rendering/rembrandt/cinema/color-fringe</property>
<binding>
<command>dialog-apply</command>
<object-name>color-fringe</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
</and>
</enable>
</checkbox>
<empty>
<pref-width>42</pref-width>
</empty>
<text>
<label>Factor</label>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
<property>/sim/rendering/rembrandt/cinema/color-fringe</property>
</and>
</enable>
</text>
<slider>
<name>color-fringe-factor</name>
<min>0.96</min>
<max>1.04</max>
<step>0.001</step>
<property>/sim/rendering/rembrandt/cinema/color-fringe-factor</property>
<binding>
<command>dialog-apply</command>
<object-name>color-fringe-factor</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
<property>/sim/rendering/rembrandt/cinema/color-fringe</property>
</and>
</enable>
</slider>
<text>
<label>12345678</label>
<format>%.3f</format>
<live>true</live>
<property>/sim/rendering/rembrandt/cinema/color-fringe-factor</property>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<property>/sim/rendering/rembrandt/cinema/distortion</property>
<property>/sim/rendering/rembrandt/cinema/color-fringe</property>
</and>
</enable>
</text>
</group>
<group>
<layout>hbox</layout>
<halign>left</halign>
<checkbox>
<halign>left</halign>
<label>Film wear</label>
<name>film-wear</name>
<property>/sim/rendering/rembrandt/cinema/film-wear</property>
<binding>
<command>dialog-apply</command>
<object-name>film-wear</object-name>
</binding>
<enable>
<and>
<not><property>/sim/rendering/rembrandt/night-vision</property></not>
<or>
<property>/sim/rendering/rembrandt/cinema/vignette</property>
<property>/sim/rendering/rembrandt/cinema/color-shift</property>
</or>
</and>
</enable>
</checkbox>
</group>
<hrule/>

View file

@ -207,31 +207,8 @@
<group>
<layout>table</layout>
<text>
<row>0</row>
<col>0</col>
<colspan>2</colspan>
<label>Season (ground textures): </label>
<halign>right</halign>
</text>
<combo>
<row>0</row>
<col>2</col>
<colspan>2</colspan>
<name>season</name>
<halign>left</halign>
<live>true</live>
<property>/sim/startup/season</property>
<value>summer</value>
<value>winter</value>
<binding>
<command>dialog-apply</command>
<object-name>season</object-name>
</binding>
</combo>
<checkbox>
<row>1</row>
<row>0</row>
<col>0</col>
<halign>left</halign>
<label>Animated jetways</label>
@ -244,7 +221,7 @@
</checkbox>
<checkbox>
<row>2</row>
<row>1</row>
<col>0</col>
<halign>left</halign>
<label>Random buildings</label>
@ -256,8 +233,20 @@
</binding>
</checkbox>
<text>
<row>1</row>
<col>1</col>
<colspan>3</colspan>
<color>
<red>1.0</red>
<green>0.6</green>
<blue>0.6</blue>
</color>
<label>Warning: Requires lots of memory</label>
</text>
<checkbox>
<row>3</row>
<row>2</row>
<col>0</col>
<halign>left</halign>
<label>Random objects</label>
@ -270,7 +259,7 @@
</checkbox>
<checkbox>
<row>4</row>
<row>3</row>
<col>0</col>
<halign>left</halign>
<label>Random vegetation</label>
@ -282,7 +271,7 @@
</binding>
</checkbox>
<text>
<row>4</row>
<row>3</row>
<col>1</col>
<label>density</label>
<enable>
@ -290,7 +279,7 @@
</enable>
</text>
<slider>
<row>4</row>
<row>3</row>
<col>2</col>
<name>vegetation-density</name>
<min>0</min>
@ -303,7 +292,7 @@
</binding>
</slider>
<text>
<row>4</row>
<row>3</row>
<col>3</col>
<label>12345678</label>
<format>%.1f</format>

View file

@ -71,6 +71,60 @@
</empty>
</group>
<group>
<layout>hbox</layout>
<halign>right</halign>
<text>
<halign>left</halign>
<label>Transition</label>
</text>
<slider>
<name>transition</name>
<min>0.0</min>
<max>5.0</max>
<step>1.0</step>
<fraction>0.17</fraction>
<live>true</live>
<property>/sim/rendering/shaders/transition</property>
<binding>
<command>dialog-apply</command>
<object-name>transition</object-name>
</binding>
</slider>
<empty>
<pref-width>55</pref-width>
</empty>
</group>
<group>
<layout>hbox</layout>
<halign>right</halign>
<text>
<halign>left</halign>
<label>Urban</label>
</text>
<slider>
<name>urban</name>
<min>0.0</min>
<max>5.0</max>
<step>1.0</step>
<fraction>0.17</fraction>
<live>true</live>
<property>/sim/rendering/shaders/urban</property>
<binding>
<command>dialog-apply</command>
<object-name>urban</object-name>
</binding>
</slider>
<empty>
<pref-width>55</pref-width>
</empty>
</group>
<group>
<layout>hbox</layout>
<halign>right</halign>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -276,18 +276,16 @@
<item>
<name>global-weather</name>
<binding>
<condition>
<not><property>/nasal/local_weather/enabled</property></not>
</condition>
<command>dialog-show</command>
<dialog-name>weather</dialog-name>
</binding>
</item>
<item>
<name>environment-settings</name>
<binding>
<condition>
<property>/nasal/local_weather/enabled</property>
</condition>
<command>dialog-show</command>
<dialog-name>local_weather_tiles</dialog-name>
<dialog-name>environment-settings</dialog-name>
</binding>
</item>

View file

@ -55,7 +55,6 @@ Started September 2000 by David Megginson, david@megginson.com
<units>feet</units>
<save-on-exit type="bool" userarchive="y">true</save-on-exit>
<restore-defaults type="bool">false</restore-defaults>
<browser-app write="n">firefox -new-tab "%u"</browser-app>
<!-- help viewer; only used under Unix -->
<terminal-ansi-colors type="bool">true</terminal-ansi-colors>
<season type="string" preserve="y">summer</season>
@ -72,6 +71,37 @@ Started September 2000 by David Megginson, david@megginson.com
<bloom type="bool" userarchive="y">true</bloom>
<bloom-strength type="float" userarchive="y">1.0</bloom-strength>
<bloom-buffers type="bool">true</bloom-buffers>
<night-vision type="bool">false</night-vision>
<cinema>
<vignette type="bool">false</vignette>
<inner-circle type="float" userarchive="y">0.8</inner-circle>
<outer-circle type="float" userarchive="y">1.3</outer-circle>
<color-shift type="bool">false</color-shift>
<red-shift>
<x type="float" userarchive="y">.393</x>
<y type="float" userarchive="y">.769</y>
<z type="float" userarchive="y">.189</z>
</red-shift>
<green-shift>
<x type="float" userarchive="y">.349</x>
<y type="float" userarchive="y">.686</y>
<z type="float" userarchive="y">.168</z>
</green-shift>
<blue-shift>
<x type="float" userarchive="y">.272</x>
<y type="float" userarchive="y">.534</y>
<z type="float" userarchive="y">.131</z>
</blue-shift>
<distortion type="bool">false</distortion>
<distortion-factor>
<x type="float" userarchive="y">0.0</x>
<y type="float" userarchive="y">0.0</y>
<z type="float" userarchive="y">1.0</z>
</distortion-factor>
<color-fringe type="bool">false</color-fringe>
<color-fringe-factor type="float" userarchive="y">1.0</color-fringe-factor>
<film-wear type="bool">false</film-wear>
</cinema>
<exposure type="float" userarchive="y">1.0</exposure>
<use-color-for-depth type="bool">false</use-color-for-depth>
<no-16bit-buffer type="bool">true</no-16bit-buffer>