Board index FlightGear Development Aircraft

F-16 upgraded to 'production' status

Questions and discussion about creating aircraft. Flight dynamics, 3d models, cockpits, systems, animation, textures.

Re: F-16 upgraded to 'production' status

Postby Thorsten » Sun Oct 27, 2019 12:13 pm

Sample code for the Maverick (including the corrected light behavior)

Code: Select all
<?xml version="1.0"?>

<PropertyList>

   <path>AGM-65.ac</path>

  <animation>
    <type>select</type>
      <object-name>AGM-65Body</object-name>
      <object-name>AGM-65Glass</object-name>
      <object-name>AGM-65Wings</object-name>
      <object-name>AGM-65Back</object-name>
      <object-name>CamFrame</object-name>
      <object-name>CamSphere</object-name>
      <object-name>Lens</object-name>
      <object-name>AGM-65Back</object-name>
      <object-name>AGM-65Mounts</object-name>
    <condition>
      <property>payload/armament/agm-65/flags/msl-id-200</property>
    </condition>
  </animation>

  <effect> 
    <inherits-from>Aircraft/f16/Models/Effects/glass/glassIR</inherits-from> 
    <object-name>AGM-65Glass</object-name>
  </effect>

  <effect>
      <inherits-from>Aircraft/f16/Models/Effects/fuselage/model-combined-fuselage</inherits-from>
      <parameters>
          <metallic type="float">0.80</metallic>
          <ambient-factor type="float">0.0</ambient-factor>
          <rain-enabled type="int">0</rain-enabled>
          <ambient-correction type="float">0.00</ambient-correction>
          <reflection-enabled type="int">0</reflection-enabled>
      </parameters>
      <object-name>AGM-65Body</object-name>
      <object-name>AGM-65Wings</object-name>
      <object-name>AGM-65Back</object-name>
      <object-name>CamFrame</object-name>
      <object-name>CamSphere</object-name>
      <object-name>Lens</object-name>
  </effect>

    <particlesystem>
       <name>smoke</name>
       <texture>../smoke.png</texture>

       <emissive type="bool">false</emissive>
       <lighting type="bool">false</lighting>

       <condition>
             <property>payload/armament/agm-65/flags/smoke-id-200</property>
       </condition>

       <attach>world</attach>

       <placer>
         <type>point</type>
       </placer>

       <offsets>
          <x-m>1.90437</x-m>
          <y-m>0</y-m>
          <z-m>0</z-m>
       </offsets>

       <shooter>
         <theta-min-deg>-1.5</theta-min-deg>
         <theta-max-deg>1.5</theta-max-deg>
         <phi-min-deg>-1.5</phi-min-deg>
         <phi-max-deg>1.5</phi-max-deg>
         <speed-mps>
           <value>0</value>
           <spread>0</spread>
         </speed-mps>
         <rotation-speed>
           <x-min-deg-sec>0</x-min-deg-sec>
           <y-min-deg-sec>0</y-min-deg-sec>
           <z-min-deg-sec>0</z-min-deg-sec>
           <x-max-deg-sec>0</x-max-deg-sec>
           <y-max-deg-sec>0</y-max-deg-sec>
           <z-max-deg-sec>0</z-max-deg-sec>
         </rotation-speed>
       </shooter>

       <counter>
         <particles-per-sec>
           <value>50</value>
           <spread>0</spread>
         </particles-per-sec>
       </counter>
         
       <align>billboard</align>

       <particle>
         <start>
           <color>
         <red><expression><product><value>0.8</value><property>rendering/scene/diffuse/red</property></product></expression></red>
         <green><expression><product><value>0.8</value><property>rendering/scene/diffuse/red</property></product></expression></green>
         <blue><expression><product><value>0.8</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
             <alpha><value> 0.5 </value></alpha>
           </color>
           <size>
             <value>1.0</value>
           </size>
         </start>

         <end>
           <color>
         <red><expression><product><value>0.8</value><property>rendering/scene/diffuse/red</property></product></expression></red>
         <green><expression><product><value>0.8</value><property>rendering/scene/diffuse/red</property></product></expression></green>
         <blue><expression><product><value>0.8</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
             <alpha><value> 0.1 </value></alpha>
           </color>
           <size>
             <value>6</value>
           </size>
         </end>

         <life-sec>
           <value>30</value>
         </life-sec>
           
         <mass-kg>  0.5 </mass-kg>
         <radius-m> 0.5 </radius-m>
       </particle>

       <program>
         <fluid>               air  </fluid>
         <gravity type="bool"> true </gravity>
         <wind typ="bool">     true </wind>
       </program>

     </particlesystem>

    <particlesystem>
         <name>explosion-inner</name>
         <texture>../smoke.png</texture>

         <emissive type="bool">true</emissive>
         <lighting type="bool">false</lighting>

         <condition>
             <property>payload/armament/agm-65/flags/explode-id-200</property>
         </condition>

         <attach>world</attach>

         <placer>
           <type>point</type>
         </placer>

         <shooter>
           <theta-min-deg>35</theta-min-deg>
           <theta-max-deg>65</theta-max-deg>
           <phi-min-deg>-180</phi-min-deg>
           <phi-max-deg>180</phi-max-deg>
           <speed-mps>
             <value>170</value>
             <spread>40</spread>
           </speed-mps>
           <rotation-speed>
             <x-min-deg-sec>0</x-min-deg-sec>
             <y-min-deg-sec>0</y-min-deg-sec>
             <z-min-deg-sec>0</z-min-deg-sec>
             <x-max-deg-sec>0</x-max-deg-sec>
             <y-max-deg-sec>0</y-max-deg-sec>
             <z-max-deg-sec>0</z-max-deg-sec>
           </rotation-speed>
         </shooter>

         <counter>
           <particles-per-sec>
             <value>20</value>
             <spread>10</spread>
           </particles-per-sec>
         </counter>
           
         <align>billboard</align>

         <particle>
           <start>
             <color>
               <red><value>   1.0 </value></red>
               <green><value> 1.0 </value></green>
               <blue><value>  0.4 </value></blue>
               <alpha><value> 1 </value></alpha>
             </color>
             <size>
               <value>5</value>
             </size>
           </start>

           <end>
             <color>
               <red><value>   1.0 </value></red>
               <green><value> 0.5 </value></green>
               <blue><value>  0.2 </value></blue>
               <alpha><value> 0.7 </value></alpha>
             </color>
             <size>
               <value>8</value>
             </size>
           </end>

           <life-sec>
             <value>0.4</value>
           </life-sec>
             
           <mass-kg>  5 </mass-kg>
           <radius-m> 0.5 </radius-m>
         </particle>

         <program>
           <fluid>               air  </fluid>
           <gravity type="bool"> true </gravity>
           <wind typ="bool">     true </wind>
         </program>

       </particlesystem>

    <particlesystem>
         <name>explosion-outer</name>
         <texture>../smoke.png</texture>

         <emissive type="bool">true</emissive>
         <lighting type="bool">false</lighting>

         <condition>
             <property>payload/armament/agm-65/flags/explode-id-200</property>
         </condition>

         <attach>world</attach>

         <placer>
           <type>point</type>
         </placer>

         <shooter>
           <theta-min-deg>-180</theta-min-deg>
           <theta-max-deg>180</theta-max-deg>
           <phi-min-deg>-180</phi-min-deg>
           <phi-max-deg>180</phi-max-deg>
           <speed-mps>
             <value>400</value>
             <spread>80</spread>
           </speed-mps>
           <rotation-speed>
             <x-min-deg-sec>0</x-min-deg-sec>
             <y-min-deg-sec>0</y-min-deg-sec>
             <z-min-deg-sec>0</z-min-deg-sec>
             <x-max-deg-sec>0</x-max-deg-sec>
             <y-max-deg-sec>0</y-max-deg-sec>
             <z-max-deg-sec>0</z-max-deg-sec>
           </rotation-speed>
         </shooter>

         <counter>
           <particles-per-sec>
             <value>50</value>
             <spread>10</spread>
           </particles-per-sec>
         </counter>
           
         <align>billboard</align>

         <particle>
           <start>
             <color>
               <red><value>   1.0 </value></red>
               <green><value> 1.0 </value></green>
               <blue><value>  0.4 </value></blue>
               <alpha><value> 1 </value></alpha>
             </color>
             <size>
               <value>5</value>
             </size>
           </start>

           <end>
             <color>
               <red><value>   1.0 </value></red>
               <green><value> 0.5 </value></green>
               <blue><value>  0.2 </value></blue>
               <alpha><value> 0.7 </value></alpha>
             </color>
             <size>
               <value>14</value>
             </size>
           </end>

           <life-sec>
             <value>1.0</value>
           </life-sec>
             
           <mass-kg>  5 </mass-kg>
           <radius-m> 0.5 </radius-m>
         </particle>

         <program>
           <fluid>               air  </fluid>
           <gravity type="bool"> true </gravity>
           <wind typ="bool">     true </wind>
         </program>

       </particlesystem>

      <particlesystem>
         <name>explosion-smoke-inner</name>
         <texture>../smoke.png</texture>

         <emissive type="bool">false</emissive>
         <lighting type="bool">false</lighting>

         <condition>
          <and>
             <property>payload/armament/agm-65/flags/explode-id-200</property>
          <not>
             <property>payload/armament/agm-65/flags/explode-water-id-200</property>
           </not>
          </and>
         </condition>

         <attach>world</attach>

         <placer>
           <type>point</type>
         </placer>

         <shooter>
           <theta-min-deg>30</theta-min-deg>
           <theta-max-deg>40</theta-max-deg>
           <phi-min-deg>-180</phi-min-deg>
           <phi-max-deg>180</phi-max-deg>
           <speed-mps>
             <value>300</value>
             <spread>100</spread>
           </speed-mps>
           <rotation-speed>
             <x-min-deg-sec>0</x-min-deg-sec>
             <y-min-deg-sec>0</y-min-deg-sec>
             <z-min-deg-sec>0</z-min-deg-sec>
             <x-max-deg-sec>0</x-max-deg-sec>
             <y-max-deg-sec>0</y-max-deg-sec>
             <z-max-deg-sec>30</z-max-deg-sec>
           </rotation-speed>
         </shooter>

         <counter>
           <particles-per-sec>
             <value>200</value>
             <spread>5</spread>
           </particles-per-sec>
         </counter>
           
         <align>billboard</align>

         <particle>
           <start>
             <color>
            <red><expression><product><value>0.3</value><property>rendering/scene/diffuse/red</property></product></expression></red>
            <green><expression><product><value>0.3</value><property>rendering/scene/diffuse/red</property></product></expression></green>
            <blue><expression><product><value>0.25</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
               <alpha><value> 1.0 </value></alpha>
             </color>
             <size>
               <value>3</value>
             </size>
           </start>

           <end>
             <color>
            <red><expression><product><value>0.4</value><property>rendering/scene/diffuse/red</property></product></expression></red>
            <green><expression><product><value>0.4</value><property>rendering/scene/diffuse/red</property></product></expression></green>
            <blue><expression><product><value>0.4</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
               <alpha><value> 1.0 </value></alpha>
               <alpha><value> 0.1 </value></alpha>
             </color>
             <size>
               <value>5</value>
             </size>
           </end>

           <life-sec>
             <value>18</value>
           </life-sec>
             
           <mass-kg>  6.0 </mass-kg>
           <radius-m> 0.5 </radius-m>
         </particle>

         <program>
           <fluid>               air  </fluid>
           <gravity type="bool"> true </gravity>
           <wind typ="bool">     true </wind>
         </program>

       </particlesystem>



      <particlesystem>
         <name>explosion-smoke-outer</name>
         <texture>../smoke.png</texture>

         <emissive type="bool">false</emissive>
         <lighting type="bool">false</lighting>

         <condition>
         <and>
             <property>payload/armament/agm-65/flags/explode-smoke-id-200</property>
          <not>
             <property>payload/armament/agm-65/flags/explode-water-id-200</property>
           </not>
          </and>
         </condition>

         <attach>world</attach>

         <placer>
           <type>point</type>
         </placer>

         <shooter>
           <theta-min-deg>0</theta-min-deg>
           <theta-max-deg>50</theta-max-deg>
           <phi-min-deg>-180</phi-min-deg>
           <phi-max-deg>180</phi-max-deg>
           <speed-mps>
             <value>150</value>
             <spread>120</spread>
           </speed-mps>
           <rotation-speed>
             <x-min-deg-sec>0</x-min-deg-sec>
             <y-min-deg-sec>0</y-min-deg-sec>
             <z-min-deg-sec>0</z-min-deg-sec>
             <x-max-deg-sec>0</x-max-deg-sec>
             <y-max-deg-sec>0</y-max-deg-sec>
             <z-max-deg-sec>0</z-max-deg-sec>
           </rotation-speed>
         </shooter>

         <counter>
           <particles-per-sec>
             <value>8</value>
             <spread>5</spread>
           </particles-per-sec>
         </counter>
           
         <align>billboard</align>

         <particle>
           <start>
             <color>
         <red><expression><product><value>0.3</value><property>rendering/scene/diffuse/red</property></product></expression></red>
         <green><expression><product><value>0.3</value><property>rendering/scene/diffuse/red</property></product></expression></green>
         <blue><expression><product><value>0.25</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
               <alpha><value> 1.0 </value></alpha>
             </color>
             <size>
               <value>12</value>
             </size>
           </start>

           <end>
             <color>
         <red><expression><product><value>0.4</value><property>rendering/scene/diffuse/red</property></product></expression></red>
         <green><expression><product><value>0.4</value><property>rendering/scene/diffuse/red</property></product></expression></green>
         <blue><expression><product><value>0.4</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
               <alpha><value> 0.5 </value></alpha>
             </color>
             <size>
               <value>24</value>
             </size>
           </end>

           <life-sec>
             <value>28</value>
           </life-sec>
             
           <mass-kg>  5.0 </mass-kg>
           <radius-m> 0.5 </radius-m>
         </particle>

         <program>
           <fluid>               air  </fluid>
           <gravity type="bool"> true </gravity>
           <wind typ="bool">     true </wind>
         </program>

       </particlesystem>


      <particlesystem>
         <name>explosion-debris</name>
         <texture>../lava.png</texture>

         <emissive type="bool">false</emissive>
         <lighting type="bool">false</lighting>

         <condition>
          <and>
             <property>payload/armament/agm-65/flags/explode-id-200</property>
          <not>
             <property>payload/armament/agm-65/flags/explode-water-id-200</property>
           </not>
          </and>
         </condition>

         <attach>world</attach>

         <placer>
           <type>point</type>
         </placer>

         <shooter>
           <theta-min-deg>35</theta-min-deg>
           <theta-max-deg>55</theta-max-deg>
           <phi-min-deg>-180</phi-min-deg>
           <phi-max-deg>180</phi-max-deg>
           <speed-mps>
             <value>300</value>
             <spread>200</spread>
           </speed-mps>
           <rotation-speed>
             <x-min-deg-sec>0</x-min-deg-sec>
             <y-min-deg-sec>0</y-min-deg-sec>
             <z-min-deg-sec>100</z-min-deg-sec>
             <x-max-deg-sec>0</x-max-deg-sec>
             <y-max-deg-sec>0</y-max-deg-sec>
             <z-max-deg-sec>300</z-max-deg-sec>
           </rotation-speed>
         </shooter>

         <counter>
           <particles-per-sec>
             <value>200</value>
             <spread>5</spread>
           </particles-per-sec>
         </counter>
           
         <align>billboard</align>

         <particle>
           <start>
             <color>
         <red><expression><product><value>0.2</value><property>rendering/scene/diffuse/red</property></product></expression></red>
         <green><expression><product><value>0.2</value><property>rendering/scene/diffuse/red</property></product></expression></green>
         <blue><expression><product><value>0.2</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
               <alpha><value> 1.0 </value></alpha>
             </color>
             <size>
               <value>0.5</value>
             </size>
           </start>

           <end>
             <color>
         <red><expression><product><value>0.2</value><property>rendering/scene/diffuse/red</property></product></expression></red>
         <green><expression><product><value>0.2</value><property>rendering/scene/diffuse/red</property></product></expression></green>
         <blue><expression><product><value>0.2</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
               <alpha><value> 0.1 </value></alpha>
             </color>
             <size>
               <value>0.5</value>
             </size>
           </end>

           <life-sec>
             <value>10</value>
           </life-sec>
             
           <mass-kg>  14.0 </mass-kg>
           <radius-m> 0.5 </radius-m>
         </particle>

         <program>
           <fluid>               air  </fluid>
           <gravity type="bool"> true </gravity>
           <wind typ="bool">     true </wind>
         </program>

       </particlesystem>


      <particlesystem>
         <name>explosion-water-inner</name>
         <texture>../smoke.png</texture>

         <emissive type="bool">false</emissive>
         <lighting type="bool">false</lighting>

         <condition>
          <and>
             <property>payload/armament/agm-65/flags/explode-id-200</property>
             <property>payload/armament/agm-65/flags/explode-water-id-200</property>
          </and>
         </condition>

         <attach>world</attach>

         <placer>
           <type>point</type>
         </placer>

         <shooter>
           <theta-min-deg>0</theta-min-deg>
           <theta-max-deg>5</theta-max-deg>
           <phi-min-deg>-180</phi-min-deg>
           <phi-max-deg>180</phi-max-deg>
           <speed-mps>
             <value>350</value>
             <spread>350</spread>
           </speed-mps>
           <rotation-speed>
             <x-min-deg-sec>0</x-min-deg-sec>
             <y-min-deg-sec>0</y-min-deg-sec>
             <z-min-deg-sec>-30</z-min-deg-sec>
             <x-max-deg-sec>0</x-max-deg-sec>
             <y-max-deg-sec>0</y-max-deg-sec>
             <z-max-deg-sec>30</z-max-deg-sec>
           </rotation-speed>
         </shooter>

         <counter>
           <particles-per-sec>
             <value>500</value>
             <spread>5</spread>
           </particles-per-sec>
         </counter>
           
         <align>billboard</align>

         <particle>
           <start>
             <color>
         <red><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></red>
         <green><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></green>
         <blue><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
               <alpha><value> 0.5 </value></alpha>
             </color>
             <size>
               <value>4.0</value>
             </size>
           </start>

           <end>
             <color>
         <red><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></red>
         <green><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></green>
         <blue><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
               <alpha><value> 0.2 </value></alpha>
             </color>
             <size>
               <value>2.0</value>
             </size>
           </end>

           <life-sec>
             <value>20</value>
           </life-sec>
             
           <mass-kg>  15.0 </mass-kg>
           <radius-m> 0.5 </radius-m>
         </particle>

         <program>
           <fluid>               air  </fluid>
           <gravity type="bool"> true </gravity>
           <wind typ="bool">     true </wind>
         </program>

       </particlesystem>


      <particlesystem>
         <name>explosion-water-outer</name>
         <texture>../smoke.png</texture>

         <emissive type="bool">false</emissive>
         <lighting type="bool">false</lighting>

         <condition>
          <and>
             <property>payload/armament/agm-65/flags/explode-smoke-id-200</property>
             <property>payload/armament/agm-65/flags/explode-water-id-200</property>
          </and>
         </condition>

         <attach>world</attach>

         <placer>
           <type>point</type>
         </placer>

         <shooter>
           <theta-min-deg>0</theta-min-deg>
           <theta-max-deg>70</theta-max-deg>
           <phi-min-deg>-180</phi-min-deg>
           <phi-max-deg>180</phi-max-deg>
           <speed-mps>
             <value>80</value>
             <spread>60</spread>
           </speed-mps>
           <rotation-speed>
             <x-min-deg-sec>0</x-min-deg-sec>
             <y-min-deg-sec>0</y-min-deg-sec>
             <z-min-deg-sec>-50</z-min-deg-sec>
             <x-max-deg-sec>0</x-max-deg-sec>
             <y-max-deg-sec>0</y-max-deg-sec>
             <z-max-deg-sec>50</z-max-deg-sec>
           </rotation-speed>
         </shooter>

         <counter>
           <particles-per-sec>
             <value>60</value>
             <spread>5</spread>
           </particles-per-sec>
         </counter>
           
         <align>billboard</align>

         <particle>
           <start>
             <color>
         <red><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></red>
         <green><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></green>
         <blue><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
               <alpha><value> 0.5 </value></alpha>
             </color>
             <size>
               <value>10.0</value>
             </size>
           </start>

           <end>
             <color>
         <red><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></red>
         <green><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></green>
         <blue><expression><product><value>1.0</value><property>rendering/scene/diffuse/red</property></product></expression></blue>
               <alpha><value> 0.2 </value></alpha>
             </color>
             <size>
               <value>14.0</value>
             </size>
           </end>

           <life-sec>
             <value>18</value>
           </life-sec>
             
           <mass-kg>  8.0 </mass-kg>
           <radius-m> 0.5 </radius-m>
         </particle>

         <program>
           <fluid>               air  </fluid>
           <gravity type="bool"> true </gravity>
           <wind typ="bool">     true </wind>
         </program>

       </particlesystem>

   <animation>
        <type>rotate</type>
        <object-name>explosion-smoke-inner</object-name>
      <object-name>explosion-smoke-outer</object-name>
      <offset-deg>0</offset-deg>
        <factor>1</factor>
        <property>payload/armament/agm-65/flags/explode-angle</property>      
        <center>
         <x-m>0</x-m>
          <y-m>0</y-m>
          <z-m>0</z-m>
        </center>
        <axis>
          <x>1</x>
          <y>0</y>
          <z>0</z>
        </axis>
    </animation>      


   <animation>
        <object-name>AGM-65Body</object-name>
      <object-name>AGM-65Glass</object-name>
      <object-name>AGM-65Wings</object-name>
      <object-name>AGM-65Back</object-name>
      <object-name>CamFrame</object-name>
      <object-name>CamSphere</object-name>
      <object-name>Lens</object-name>
      <object-name>AGM-65Back</object-name>
      <object-name>AGM-65Mounts</object-name>
        <enable-hot type="bool">false</enable-hot>
    </animation>
   
</PropertyList>


That should now cover explosions for warheads ranging from ~100 to ~1000 lbs - since I'm kind of hoping you're not planning to equip the plane with the B-43, that should cover pretty much all other weapons - except the cluster bomb, for which I'd like to look at the current implementation first.

I have some more changes in the animation script in the pipeline - we can do a flash illumination of the clouds for instance and a bit more sophisticated terrain interaction - maybe start a wildfire if a forest is hit in dry weather...
Thorsten
 
Posts: 11642
Joined: Mon Nov 02, 2009 8:33 am

Re: F-16 upgraded to 'production' status

Postby Necolatis » Sun Oct 27, 2019 12:23 pm

Cool.

Nice.

Wildfire? Problem with that is they continue to burn on some landclasses they get gigantic big and FPS drops to a crawl, since I found out I have been avoiding it.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2108
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: F-16 upgraded to 'production' status

Postby J Maverick 16 » Sun Oct 27, 2019 12:34 pm

Thorsten wrote in Sun Oct 27, 2019 12:13 pm:That should now cover explosions for warheads ranging from ~100 to ~1000 lbs

That's awesome, again, thanks for what you've done.

Thorsten wrote in Sun Oct 27, 2019 12:13 pm:since I'm kind of hoping you're not planning to equip the plane with the B-43, that should cover pretty much all other weapons

Well the B61-7 and -12 are available on the F-16 but just as dead weight dummy loads without required code, explosions, etc. to make them work at all. This was made to avoid any kind of trouble with the community or whoever is against nukes which we fairly respect and are not against. The only reason they are there is that like other payloads, they are available in the RL F-16.


Thorsten wrote in Sun Oct 27, 2019 12:13 pm:except the cluster bomb, for which I'd like to look at the current implementation first.

This is a point of discussion we've been talking a lot about how it could be done efficiently and without affecting frame rate performance etc. An enlightenment from you would be really appreciated. :)
Regards, Mav
Breakin' the sound barrier every day!

Scenery designer, basic livery maker, aircraft developer (KC-137R, F-16, A330, C-32J, MH-60)
Flying with Thrustmaster FCS Flight Pack + MFD Cougar
Find me also on Instagram & Twitter @j_maverick16 and YouTube
User avatar
J Maverick 16
 
Posts: 885
Joined: Sat Feb 01, 2014 6:26 pm
Location: Northern Italy
Callsign: J-Mav16, REBEL84
Version: 2020.1.1
OS: macOS 10.12.6

Re: F-16 upgraded to 'production' status

Postby Thorsten » Sun Oct 27, 2019 3:11 pm

Wildfire? Problem with that is they continue to burn on some landclasses they get gigantic big and FPS drops to a crawl, since I found out I have been avoiding it.


Never tested it, perhaps I should... Anyway - I would suggest to implement such effects (also buildings on fire and craters) on an opt-in basis.

This is a point of discussion we've been talking a lot about how it could be done efficiently and without affecting frame rate performance etc. An enlightenment from you would be really appreciated.


I would first have tried sector emitter as well - is that problematic? Usually the framerate drops when particles take a lot of the screen and are many - for a cluster bomb which you'd usually see exploding from up in the air, the second is true but the first is not.

(The Shuttle entry plasma trail uses two emitters which produce 10.000 particles per second each - this doesn't seem to add up to a big problem as such...)

If there's too many particles, I'd try combining several fireball pictures on one particle and rotate the whole thing fast - the net effect will be the impression of a turbulent highly volatile flame-front.

If nothing else helps, there could be a shader-based solution as well, supposedly shader based particles are really efficient.

How large is the area be hit by the cluster ammunition supposed to be? As far as I remember, the weapon can be set to a certain dispersion...
Thorsten
 
Posts: 11642
Joined: Mon Nov 02, 2009 8:33 am

Re: F-16 upgraded to 'production' status

Postby Necolatis » Mon Oct 28, 2019 8:18 pm

The explode effect is probably decent.

We have been talking about the dispersement of the bomblets though.

Submodels would probably be too many to fire at once, and insane to make 250 submodels.
Particle effect with billboards would probably not look good either.

CBU-87 actually has been modelled with 250 seperate bomblets inside. And the missile-code gives a property called deploy which goes from 0 to 1 in specified time after an initial fall time, which could be used for animating it. (does use time though, not altitude)
Making 250 translate animations of those would be kind of insane though.

Anyway, not sure there is any solution to it in FG. If I had been asked before the 250 submodels had been modeled, I would have said don't do it, we cant animate them.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2108
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: F-16 upgraded to 'production' status

Postby Thorsten » Tue Oct 29, 2019 6:25 am

Submodels would probably be too many to fire at once, and insane to make 250 submodels.


I'm guessing you wouldn't need that many - just visually 'many'. In actual reality some 30-40 might already look plenty - your eyes would assume that you can't simpl track all of them.

Given that we can simulate ~450 different switches and gauges in a cockpit which each having its own translation /rotation animation, I'd say it's not a hopeless number. It may turn out the submodel code itself is so inefficient that there's no chance, but just the rendering part seems doable.
Thorsten
 
Posts: 11642
Joined: Mon Nov 02, 2009 8:33 am

Re: F-16 upgraded to 'production' status

Postby Necolatis » Wed Oct 30, 2019 12:44 am

Good point, thanks.

The FGAddon F-16 has been updated.
- Ripple settings in MFD WPN page
- PAIR or SGL setting in WPN page
- When radar has nothing selected, TGP will now look at next steerpoint
- Livery updates and additions
- Sound updates from GEED.
- LAU-68 rocket pods
- Many other additions, changes and bugfixes.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2108
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: F-16 upgraded to 'production' status

Postby Thorsten » Wed Oct 30, 2019 12:12 pm

Quick feedback to the TGP lock to waypoint:

I've tried to target KXTA airport buildings with the Maverick. On first run I've been using the airport designation as waypoint - that turned out to be too far off the buildings. The problem is that after locking and firing, the view jumps back to 'amidst the runways far far away' so that it took me too long to lock the next target - so I got two missiles off.

On the second run, the route manager decided to play tricks on me and jumped away from the waypoint to the next one some 20 miles out.

For the third run, I programmed a lat/lon combination in the middle of the buildings, and that turned out to be reasonable - I managed to get all six missiles targeted and off before coming 3 miles to the field, so I didn't have to overfly it. I scored only two good hits though...

The trouble is related to the above - sometimes I lock, but see it ain't perfect - so I have to unlock - but the moment I do, the view jumps back to the waypoint. Similarly, sometimes I would like to zoom in - but the moment I do, the view is back at the waypoint. Which costs time.

So the ideal workflow for a camera-targeted attack would be

* have basically three modes - 1) 'free', i.e. do not try to point the TGP at all 2) 'to target', i.e. when released, always point to radar target or waypoint and 3) 'compensate motion', i.e. when unlocking keep the spot where it was locked to allow for corrections [1]

* do not command the view to jump back to a default when changing zoom level

With such changes, I believe it would be entirely doable to get six missiles targeted and fired during a single approach without any need to get even close to the target site - which is what they're for after all...

I have yet to test the pairwise drop /ripple settings.

[1] Since I believe tanks or other vehicles are usually moving in columns as well, the mode would be useful as we can expect to find the subsequent target 'right next' to the previous one - rather than at a pre-progammed default location
Thorsten
 
Posts: 11642
Joined: Mon Nov 02, 2009 8:33 am

Re: F-16 upgraded to 'production' status

Postby J Maverick 16 » Wed Oct 30, 2019 12:21 pm

Thorsten wrote in Wed Oct 30, 2019 12:12 pm:3) 'compensate motion', i.e. when unlocking keep the spot where it was locked to allow for corrections

I absolutely agree with this one, would definitely simplify life a lot when requiring multiple passes on a single spot or requiring a lock adjustments of a previous targeting.
Regards, Mav
Breakin' the sound barrier every day!

Scenery designer, basic livery maker, aircraft developer (KC-137R, F-16, A330, C-32J, MH-60)
Flying with Thrustmaster FCS Flight Pack + MFD Cougar
Find me also on Instagram & Twitter @j_maverick16 and YouTube
User avatar
J Maverick 16
 
Posts: 885
Joined: Sat Feb 01, 2014 6:26 pm
Location: Northern Italy
Callsign: J-Mav16, REBEL84
Version: 2020.1.1
OS: macOS 10.12.6

Re: F-16 upgraded to 'production' status

Postby Necolatis » Wed Oct 30, 2019 2:46 pm

Fixed on github. Will port to FGAddon when it has been throughout tested.

Thorsten wrote in Wed Oct 30, 2019 12:12 pm:* do not command the view to jump back to a default when changing zoom level


Changing zoom level or NARO/WIDE do not move the TGP view. If that happens to you some weird bug is going on.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2108
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: F-16 upgraded to 'production' status

Postby Necolatis » Wed Oct 30, 2019 3:28 pm

If you want to test the TGP changes here is the tgp.nas file:

Code: Select all
# Copyright (C) 2016  onox
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Lines below FLIRCameraUpdater has been modified/added by Nikolai V. Chr.
#
# Position of the FLIR camera ([z (back), x (right), y (up)])
var coords_cam = [
    getprop("/sim/view[105]/config/z-offset-m"),
    getprop("/sim/view[105]/config/x-offset-m"),
    getprop("/sim/view[105]/config/y-offset-m")
];
io.include("Aircraft/Generic/updateloop.nas");
#io.load_nasal(getprop("/sim/fg-root") ~ "/Aircraft/c172p/Nasal/generic/math_ext.nas","math_ext");
var FLIRCameraUpdater = {

    new: func {
        var m = {
            parents: [FLIRCameraUpdater, Updatable]
        };
        m.loop = UpdateLoop.new(components: [m], update_period: 0.0);

        # Create a function to update the position of the FLIR camera
        m.update_cam = me._get_flir_auto_updater(180.0);

        # Create a function to update the position using an input device
        m.manual_update_cam = me._get_flir_updater(180.0, m.update_cam);

        m.click_coord_cam = nil;

        m.listeners = std.Vector.new();

        m.offsetP = 0;
        m.offsetH = 0;

        return m;
    },

    enable: func {
        #me.loop.reset();
        me.loop.enable();
    },

    disable: func {
        #me.remove_listeners();
        me.loop.disable();
    },

    enable_or_disable: func (enable) {
        if (enable) {
            me.enable();
        }
        else {
            me.disable();
        }
    },

    remove_listeners: func {
        foreach (var listener; me.listeners.vector) {
            removelistener(listener);
        }
        me.listeners.clear();
    },

    reset: func {
        #print("reset called?!?!");
        return;
        me.remove_listeners();
        me.listeners.append(setlistener("/sim/signals/click", func {
            var lat = getprop("/sim/input/click/latitude-deg");
            var lon = getprop("/sim/input/click/longitude-deg");
            var elev = getprop("/sim/input/click/elevation-m");

            var click_position = geo.Coord.new().set_latlon(lat, lon, elev);

            var origin_position = geo.aircraft_position();
            var distance_m = origin_position.direct_distance_to(click_position);

            if (getprop("/aircraft/flir/locks/auto-track")) {
                me.click_coord_cam = click_position;
                setprop("/aircraft/flir/target/auto-track", 1);
                logger.screen.white(sprintf("New tracking position at %d meter distance", distance_m));
            }
            else {
                setprop("/aircraft/flir/target/auto-track", 0);
                me.click_coord_cam = nil;
                logger.screen.red("Press F6 to enable automatic tracking by FLIR camera");
            }
        }));

        me.listeners.append(setlistener("/aircraft/flir/locks/auto-track", func (n) {
            setprop("/aircraft/flir/target/auto-track", 0);
            me.click_coord_cam = nil;
            if (n.getBoolValue()) {
                logger.screen.green("Automatic tracking by FLIR camera enabled. Click on the terrain to start tracking.");
            }
            else {
                logger.screen.red("Automatic tracking by FLIR camera disabled");
            }
        }));
    },

    update: func (dt) {
        var roll_deg  = getprop("/orientation/roll-deg");
        var pitch_deg = getprop("/orientation/pitch-deg");
        var heading   = getprop("/orientation/heading-deg");

        var computer = me._get_flir_computer(roll_deg, pitch_deg, heading);

        if (getprop("/aircraft/flir/target/auto-track") and me.click_coord_cam != nil) {
            var (yaw, pitch, distance) = computer(coords_cam, me.click_coord_cam);
            if (lock_tgp) {
                me.update_cam(roll_deg, pitch_deg, yaw, pitch);
            } else {
                me.update_cam(roll_deg, pitch_deg, yaw+me.offsetH, pitch+me.offsetP);
            }
        }
#        else {
#            me.manual_update_cam(roll_deg, pitch_deg);
#        }
    },

    aim: func () {
        var roll_deg  = getprop("/orientation/roll-deg");
        var pitch_deg = getprop("/orientation/pitch-deg");
        var heading   = getprop("/orientation/heading-deg");

        var computer = me._get_flir_computer(roll_deg, pitch_deg, heading);

        if (getprop("sim/current-view/view-number") ==12 and me.click_coord_cam != nil) {
            var (yaw, pitch, distance) = computer(coords_cam, me.click_coord_cam);
            me.update_cam(roll_deg, pitch_deg, yaw, pitch);
        }
    },

    ######################################################################
    # Gyro stabilization                                                 #
    ######################################################################

    _get_flir_updater: func (offset, updater) {
        return func (roll_deg, pitch_deg) {
            var yaw   = getprop("/aircraft/flir/input/yaw-deg") + (180.0 - offset);
            var pitch = getprop("/aircraft/flir/input/pitch-deg");

            updater(roll_deg, pitch_deg, yaw, pitch);
        };
    },

    ######################################################################
    # Automatic tracking computation                                     #
    ######################################################################

    _get_flir_auto_updater: func (offset) {
        return func (roll_deg, pitch_deg, yaw, pitch) {
            (yaw, pitch) = math_ext.get_yaw_pitch_body(roll_deg, pitch_deg, yaw, pitch, offset);

            setprop("/aircraft/flir/target/yaw-deg", yaw);
            setprop("/aircraft/flir/target/pitch-deg", pitch);
            if (getprop("sim/current-view/view-number") ==12) {
                setprop("/sim/current-view/goal-heading-offset-deg", -yaw);
                setprop("/sim/current-view/goal-pitch-offset-deg", pitch);
            }
            setprop("sim/view[105]/heading-offset-deg", yaw);
            setprop("sim/view[105]/pitch-offset-deg", pitch);
        };
    },

    _get_flir_computer: func (roll_deg, pitch_deg, heading) {
        return func (coords, target) {
            var (position_2d, position) = math_ext.get_point(coords[0], coords[1], coords[2], roll_deg, pitch_deg, heading);
            return math_ext.get_yaw_pitch_distance_inert(position_2d, position, target, heading);
        }
    }

};

math_ext.get_yaw_pitch_distance_inert = func (position_2d, position, target_position, heading, f=nil) {
    # Does the same as Onox's version, except takes curvature of Earth into account.
    var heading_deg = positioned.courseAndDistance(position_2d, target_position)[0] - heading;
    var pitch_deg   = vector.Math.getPitch(position, target_position);
    var distance_m  = position.direct_distance_to(target_position);
    return [heading_deg, pitch_deg, distance_m];
}

var flir_updater = FLIRCameraUpdater.new();

setlistener("/sim/signals/fdm-initialized", func {
    setlistener("/aircraft/flir/target/view-enabled", func (node) {
        flir_updater.enable_or_disable(node.getBoolValue());
    }, 1, 0);
});

setlistener("controls/MFD[2]/button-pressed", func (node) {
    var button = getprop("controls/MFD[2]/button-pressed");
    if (button == 1) {#LOCK
        gps = 0;
        if (lock_tgp) {
            lock_tgp = 0;
            armament.contactPoint = nil;
            return;
        }
        var x = -2.5856;
        var y =  0.8536;
        var z = -1.4121;
        var pos = aircraftToCart({x:-x, y:y, z: -z});
        var coordA = geo.Coord.new();
        coordA.set_xyz(pos.x, pos.y, pos.z);
        var matrixMath = 0;
        if (matrixMath) {
            var dirCoord = geo.Coord.new(coordA);
            var vHead = getprop("sim/current-view/heading-offset-deg");
            var vPitch = getprop("sim/current-view/pitch-offset-deg");

            var vectorF = vector.Math.eulerToCartesian3X(-getprop("orientation/heading-deg"),getprop("orientation/pitch-deg"),getprop("orientation/roll-deg"));
            var vectorL = vector.Math.eulerToCartesian3Y(-getprop("orientation/heading-deg"),getprop("orientation/pitch-deg"),getprop("orientation/roll-deg"));
            var vectorU = vector.Math.eulerToCartesian3Z(-getprop("orientation/heading-deg"),getprop("orientation/pitch-deg"),getprop("orientation/roll-deg"));
            var viewM   = vector.Math.viewMatrix(vectorF,vectorL,vectorU);
            var pitchM = vector.Math.pitchMatrix(vPitch);
            var yawM   = vector.Math.yawMatrix(-vHead);
            var rotation = vector.Math.multiplyMatrices(pitchM, yawM);#heading, pitch
            var viewGlobal = vector.Math.multiplyMatrices4(viewM, vector.Math.to4x4(rotation));#order?
            #viewGlobal = vector.Math.multiplyMatrices4(viewGlobal,vector.Math.mirrorMatrix);
            #var vectorA = [viewGlobal[2],viewGlobal[6],viewGlobal[10]];
            var vectorA = vector.Math.normalize(vector.Math.xFromView(viewGlobal));
            #vectorA = vector.Math.multiplyMatrixWithVector(rotation, vectorF);
            print(vector.Math.format(vectorA));
            var set = vector.Math.cartesianToEuler(vectorA);
           
            #if (set[0] == nil) {print("0 heading");return;}
            #printf("%d heading %d pitch",set[0],set[1]);
            dirCoord.apply_course_distance(set[0],50);
            var up = math.tan(set[1]*D2R)*50;
            dirCoord.set_alt(coordA.alt()+up);
        }

        # get quaternion for view rotation:
        var q = [getprop("sim/current-view/debug/orientation-w"),getprop("sim/current-view/debug/orientation-x"),getprop("sim/current-view/debug/orientation-y"),getprop("sim/current-view/debug/orientation-z")];

        var V = [2 * (q[1] * q[3] - q[0] * q[2]), 2 * (q[2] * q[3] + q[0] * q[1]),1 - 2 * (q[1] * q[1] + q[2] * q[2])];
        var w= q[0];
        var x= q[1];
        var y= q[2];
        var z= q[3];

        #rotate from x axis using the quaternion:
        V = [1 - 2 * (y*y + z*z),2 * (x*y + w*z),2 * (x*z - w*y)];

        var xyz          = {"x":coordA.x(),                "y":coordA.y(),               "z":coordA.z()};
        #var directionLOS = {"x":dirCoord.x()-coordA.x(),   "y":dirCoord.y()-coordA.y(),  "z":dirCoord.z()-coordA.z()};
        var directionLOS = {"x":V[0],   "y":V[1],  "z":V[2]};

        # Check for terrain between own weapon and target:
        var terrainGeod = get_cart_ground_intersection(xyz, directionLOS);
        if (terrainGeod == nil) {
            #print("0 terrain");
            return;
        } else {
            var terrain = geo.Coord.new();
            terrain.set_latlon(terrainGeod.lat, terrainGeod.lon, terrainGeod.elevation);
            var ut = nil;
            foreach (u ; awg_9.completeList) {
                if (terrain.direct_distance_to(u.get_Coord(0))<45) {
                    ut = u;
                    break;
                }
            }
            if (ut!=nil) {
                var contact = awg_9.Target.new(ut.propNode);
                contact.setClass(awg_9.POINT);
                contact.setVirtual(1);
                contact.unique = rand();
                armament.contactPoint = contact;
            } else {
                armament.contactPoint = fc.ContactTGP.new("TGP-Spot",terrain,1);
            }
            #flir_updater.click_coord_cam = terrain;
            #setprop("/aircraft/flir/target/auto-track", 1);
            #interpolate("f16/avionics/lock-flir",1,1.5);
            #flir_updater.offsetP = 0;
            #flir_updater.offsetH = 0;# commented so we get back to where we were when unlocking
            lock_tgp = 1;
        }
    } elsif (button == 20) {#BACK
        setprop("sim/current-view/view-number",0);
        #setprop("/aircraft/flir/target/auto-track", 0);
        #lock.hide();
        #setprop("f16/avionics/lock-flir",0.05);
    } elsif (button == 6) {#TV/IR
        ir = !ir;
    } elsif (button == 11) {#UP
        if (lock_tgp) return;
        gps = 0;
        var fov = getprop("sim/current-view/field-of-view");
        if (getprop("/aircraft/flir/target/auto-track")) {
            flir_updater.offsetP += fov/100;
        } else {
            setprop("sim/current-view/pitch-offset-deg",getprop("sim/current-view/pitch-offset-deg")+fov/5);
        }
    } elsif (button == 12) {#DOWN
        if (lock_tgp) return;
        gps = 0;
        var fov = getprop("sim/current-view/field-of-view");
        if (getprop("/aircraft/flir/target/auto-track")) {
            flir_updater.offsetP -= fov/100;
        } else {
            setprop("sim/current-view/pitch-offset-deg",getprop("sim/current-view/pitch-offset-deg")-fov/5);
        }
    } elsif (button == 14) {#LEFT
        if (lock_tgp) return;
        gps = 0;
        var fov = getprop("sim/current-view/field-of-view");
        if (getprop("/aircraft/flir/target/auto-track")) {
            flir_updater.offsetH -= fov/100;
        } else {
            setprop("sim/current-view/heading-offset-deg",getprop("sim/current-view/heading-offset-deg")+fov/5);
        }
    } elsif (button == 15) {#RGHT
        if (lock_tgp) return;
        gps = 0;
        var fov = getprop("sim/current-view/field-of-view");
        if (getprop("/aircraft/flir/target/auto-track")) {
            flir_updater.offsetH += fov/100;
        } else {
            setprop("sim/current-view/heading-offset-deg",getprop("sim/current-view/heading-offset-deg")-fov/5);
        }
    } elsif (button == 13) {#WIDE/NARO
        wide = !wide;       
    } elsif (button == 2) {#ZOOM
        zoomlvl += 1;
        if (zoomlvl > 4) {
            zoomlvl = 1;
        }
    }# elsif (button == 3) {#RDR
     #   if (!getprop("/aircraft/flir/target/auto-track") and awg_9.active_u != nil) {
     #       flir_updater.offsetP = 0;
     #       flir_updater.offsetH = 0;
     #       flir_updater.click_coord_cam = awg_9.active_u.get_Coord();
     #       flir_updater.aim();
     #       flir_updater.click_coord_cam = nil;
     #   }
     #}
});

var steerlock = 0;

var fast_loop = func {
  var viewName = getprop("/sim/current-view/name");
    if (viewName == "TGP" and (getprop("gear/gear/wow") or !getprop("f16/stores/tgp-mounted"))) {
        # deselect view back to pilot default
        setprop("sim/current-view/view-number",0);
        setprop("sim/rendering/als-filters/use-IR-vision", 0);
        setprop("sim/view[105]/enabled", 0);
    } elsif (viewName == "TGP") {
        # FLIR TGP stuff:
        setprop("aircraft/flir/target/view-enabled", viewName == "TGP");
        setprop("sim/rendering/als-filters/use-filtering", viewName == "TGP");
        setprop("sim/rendering/als-filters/use-IR-vision", viewName == "TGP" and ir);
        setprop("sim/rendering/als-filters/use-night-vision", 0);
       
        var x = getprop("sim/gui/canvas/size[0]");
        var y = getprop("sim/gui/canvas/size[1]");
               
        var degs = 3.6/zoomlvl;
        if (wide) {           
            line13.setText("WIDE");
        } else {
            degs = 1.0/zoomlvl;
            line13.setText("NARO");
        }
        var fov = degs*(x/y);
        var format = (x/y)/2.25;#16/9 = 1.777
        var scale = format*20/fov;# we take into account that different pilots have different screen formats so the height of the MFD in screen stays same relative.
        setprop("sim/current-view/field-of-view-scale",scale);
        setprop("sim/current-view/field-of-view",fov);

        zoom.setText(sprintf("%.1fX",zoomlvl));
       
        line6.setText(ir==1?"WHOT":"TV");
       
        if (getprop("/aircraft/flir/target/auto-track") and flir_updater.click_coord_cam != nil) {
            var dist = flir_updater.click_coord_cam.direct_distance_to(geo.aircraft_position())*M2NM;
            bott.setText(sprintf("%2.1f  CMBT  %04d",dist,lasercode));
        } else {
            bott.setText(sprintf("      CMBT  %04d",lasercode));
        }
        if (!getprop("/aircraft/flir/target/auto-track") or flir_updater.click_coord_cam == nil) {
            setprop("sim/view[105]/heading-offset-deg", -getprop("sim/current-view/heading-offset-deg"));
            setprop("sim/view[105]/pitch-offset-deg", getprop("sim/current-view/pitch-offset-deg"));
        }
    } else {
        # remove FLIR effects and disable TGP view
        setprop("sim/rendering/als-filters/use-IR-vision", 0);
        setprop("sim/view[105]/enabled", 0);#!getprop("gear/gear/wow"));
        #lock.hide();
        #setprop("f16/avionics/lock-flir",0.05);
    }
   
    callsign = nil;
    steerlock = 0;
    var follow = 0;
    if (armament.contactPoint !=nil and armament.contactPoint.get_range()>35 and armament.contactPoint.get_Callsign() != "GPS-Spot") {
        armament.contactPoint = nil;
    }
    var gpps = 0;
    if (armament.contactPoint == nil) {
        # no TGP lock
        if (armament.contact == nil) {# we do not check for get_display here since as long as something is selected we dont show steerpoint.
            if (getprop("autopilot/route-manager/active") == 1 and getprop("autopilot/route-manager/current-wp") != nil and getprop("autopilot/route-manager/current-wp") > -1) {
                # TGP follow steerpoint
                var idx = getprop("autopilot/route-manager/current-wp");
                var ele = getprop("autopilot/route-manager/route/wp["~idx~"]/altitude-ft");
                var lat = getprop("autopilot/route-manager/route/wp["~idx~"]/latitude-deg");
                var lon = getprop("autopilot/route-manager/route/wp["~idx~"]/longitude-deg");
                if (ele == nil) {
                    ele = 0;
                }
                ele *= FT2M;
                var ele2 = geo.elevation(lat,lon);
                if (ele2 != nil) {
                    ele = ele2;
                }               
                var sp = geo.Coord.new();
                sp.set_latlon(lat,lon,ele);
                flir_updater.click_coord_cam = sp;
                setprop("/aircraft/flir/target/auto-track", 1);
                if (callsign != lat~lon) {
                    # we switched steerpoint or from radar to steerpoint
                    flir_updater.offsetP = 0;
                    flir_updater.offsetH = 0;
                }
                callsign = lat~lon;
                steerlock = 1;
                steer = 1;
            } else {
                # TGP not follow, locked from aircraft
                setprop("/aircraft/flir/target/auto-track", 0);
                flir_updater.click_coord_cam = nil;
                flir_updater.offsetP = 0;
                flir_updater.offsetH = 0;
                steer = 0;
                callsign = nil;
            }
        } elsif (armament.contact != nil and armament.contact.get_display()) {
            # TGP follow radar lock
            flir_updater.click_coord_cam = armament.contact.get_Coord();
            setprop("/aircraft/flir/target/auto-track", 1);
            if (callsign != armament.contact.getUnique()) {
                flir_updater.offsetP = 0;
                flir_updater.offsetH = 0;
            }
            callsign = armament.contact.getUnique();
            steer = 0;
        } else {
            setprop("/aircraft/flir/target/auto-track", 0);
            flir_updater.click_coord_cam = nil;
            callsign = nil;
            flir_updater.offsetP = 0;
            flir_updater.offsetH = 0;
            steer = 0;
        }
        lock_tgp = 0;
        gps = 0;
    } else {
        # TGP lock
        var vis = 1;
        gpss = armament.contactPoint.get_Callsign() == "GPS-Spot";# GPS-Spot only used by "program GPS dialog"
        if (armament.contactPoint.get_Callsign() != "TGP-Spot" and !gps and !gpss and !steer) {
            # we do not check for visibility if:
            # - following steerpoint
            # - a GPS coord has been entered manually by "program GPS dialog"
            follow = 1;
            vis = awg_9.TerrainManager.IsVisible(armament.contactPoint.propNode, nil);
        }
        if (!vis) {
            setprop("/aircraft/flir/target/auto-track", 0);
            flir_updater.click_coord_cam = nil;
            callsign = nil;
            flir_updater.offsetP = 0;
            flir_updater.offsetH = 0;
            lock_tgp = 0;
            armament.contactPoint = nil;
        } else {
            lock_tgp = 1;
            flir_updater.click_coord_cam = armament.contactPoint.get_Coord();
            callsign = armament.contactPoint.getUnique();
            setprop("/aircraft/flir/target/auto-track", 1);
            #flir_updater.offsetP = 0;
            #flir_updater.offsetH = 0;# commented so we get back to where we were when unlocking
        }
    }
    setprop("f16/avionics/tgp-lock", lock_tgp);#used in HUD
       
    if (getprop("f16/stores/tgp-mounted")) {
        if (lock_tgp and !lock_tgp_last) {
            interpolate("f16/avionics/lock-flir",1,1.5);
        } elsif (!lock_tgp) {
            setprop("f16/avionics/lock-flir",0.05);
        }
        lock_tgp_last = lock_tgp;
        if (lock_tgp) {
            line1box.show();
            line11.hide();
            line12.hide();
            line14.hide();
            line15.hide();
        } else {
            line1box.hide();
            line11.show();
            line12.show();
            line14.show();
            line15.show();
        }
        if (lock_tgp and gps) {
            midl.setText(sprintf("%s      %s", "GPS", getprop("controls/armament/laser-arm-dmd")?"L":""));
        } elsif (lock_tgp and follow) {
            midl.setText(sprintf("%s POINT %s", gps?"GPS":(ir==1?"IR":"TV"), getprop("controls/armament/laser-arm-dmd")?"L":""));
        } elsif (lock_tgp) {
            midl.setText(sprintf("%s AREA  %s", gps?"GPS":(ir==1?"IR":"TV"), getprop("controls/armament/laser-arm-dmd")?"L":""));
        } elsif (getprop("/aircraft/flir/target/auto-track") and flir_updater.click_coord_cam != nil and steerlock) {
            midl.setText(sprintf("  STEER  %s", getprop("controls/armament/laser-arm-dmd")?"L":""));
        } elsif (getprop("/aircraft/flir/target/auto-track") and flir_updater.click_coord_cam != nil) {
            midl.setText(sprintf("  RADAR  %s", getprop("controls/armament/laser-arm-dmd")?"L":""));
        } else {
            midl.setText(sprintf("         %s", getprop("controls/armament/laser-arm-dmd")?"L":""));
        }
       
        var scaleLock = getprop("f16/avionics/lock-flir");
        lock.setScale(scaleLock,scaleLock);
        lock.setStrokeLineWidth(1/scaleLock);
        if (scaleLock != 0.05) {
            lock.show();
        } else {
            lock.hide();
        }
        lock.update();
   
        # animate the LANTIRN camera:
        var b = geo.normdeg180(getprop("sim/view[105]/heading-offset-deg"));
        var p = getprop("sim/view[105]/pitch-offset-deg");
        var polarL = math.sqrt(p*p+b*b);
        var polarD = polarL!=0 and b!=0?math.atan2(p,b)*R2D:-90;
        setprop("aircraft/flir/swivel/pitch-deg",polarL);
        setprop("aircraft/flir/swivel/roll-deg",polarD);
    }
    settimer(fast_loop,0);
}


var line1 = nil;
var line1box = nil;
var line2 = nil;
var line3 = nil;
var line4 = nil;
var line6 = nil;
var line7 = nil;
var line11 = nil;
var line12 = nil;
var line13 = nil;
var line14 = nil;
var line15 = nil;
var line20 = nil;
var cross = nil;
var lock = nil;
var zoom = nil;
var bott = nil;
var midl = nil;
var ir = 1;
var lasercode = int(rand()*10000);setprop("f16/avionics/laser-code",lasercode);
var callsign = nil;
var lock_tgp = 0;
var lock_tgp_last = 0;
var wide = 1;
var zoomlvl = 1.0;
var gps = 0;# set from Program GPS dialog
var steer = 0;

var callInit = func {
  var canvasMFDext = canvas.new({
        "name": "MFD-EXT",
        "size": [256, 256],
        "view": [256, 256],
        "mipmapping": 1
  });
     
  canvasMFDext.addPlacement({"node": "MFDimage3", "texture": "tranbg.png"});
  canvasMFDext.setColorBackground(1.00, 1.00, 1.00, 0.00);

  dedGroup = canvasMFDext.createGroup();
  dedGroup.show();
  var color = [1,1,1,1];
  line1 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("left-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("LOCK")
        .setTranslation(5, 256*0.20);
  line1box = dedGroup.createChild("path")
        .moveTo(0,-7)
        .vert(14)
        .horiz(35)
        .vert(-14)
        .horiz(-35)
        .setStrokeLineWidth(1)
        .setColor(1,1,1)
        .hide()
        .setTranslation(5, 256*0.20);
  line2 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("left-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("ZOOM")
        .setTranslation(5, 256*0.35);
  line3 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("left-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("ZOOM")
        .hide()       
        .setTranslation(5, 256*0.50);
  line4 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("left-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("")
        .setTranslation(5, 256*0.65);
  line6 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("right-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("WHOT")
        .setTranslation(256-5, 256*0.2);
  line7 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("right-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("XFER")
        .hide()
        .setTranslation(256-5, 256*0.35);
  line11 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("UP")
        .setTranslation(256*0.2, 5);
  line12 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("DOWN")
        .setTranslation(256*0.35, 5);
  line13 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("WIDE")
        .setTranslation(256*0.50, 5);
  line14 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("LEFT")
        .setTranslation(256*0.65, 5);
  line15 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("RGHT")
        .setTranslation(256*0.8, 5);
  line20 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-bottom")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("BACK")
        .setTranslation(256*0.8, 256-5);

    zoom = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(1,1,1)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("1.0X")
        .setTranslation(256*0.5, 20);
    midl = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(1,1,1)
        .setAlignment("center-bottom")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("IR POINT    L")
        .setTranslation(256*0.5, 256*0.8);
    bott = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(1,1,1)
        .setAlignment("center-bottom")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("13.0  CMBT  1538")
        .setTranslation(256*0.5, 256*0.9);

  cross = dedGroup.createChild("path")
            .moveTo(128,0)
            .vert(120)
            .moveTo(128,256)
            .vert(-120)
            .moveTo(0,128)
            .horiz(120)
            .moveTo(256,128)
            .horiz(-120)
            .setStrokeLineWidth(1)
            .setColor(1,1,1);
    lock = dedGroup.createChild("path")
            #.setCenter(128,128)
            .moveTo(48,48)
            .vert(-96)
            .horiz(-96)
            .vert(96)
            .horiz(96)
            .hide()
            .setTranslation(128,128)
            .setStrokeLineWidth(1)
            .setColor(1,1,1);
};

callInit();
fast_loop();
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2108
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: F-16 upgraded to 'production' status

Postby Thorsten » Thu Oct 31, 2019 9:08 am

The script you posted is no-op for me - using it I can't move the view at all, clicking on up/down/left right does nothing, wide/narrow or zoom level and lock buttons work fine though.

***

Small afterthought - the Maverick is, I believe, not a laser-guided weapon. When targeting it, you are not looking through a target pod lens but through the weapons's own TV or IR sensor (dependent on what variant of the missile that is). So when the weapon is equipped, it should be possible to target it without a mounted pod or laser active.
Thorsten
 
Posts: 11642
Joined: Mon Nov 02, 2009 8:33 am

Re: F-16 upgraded to 'production' status

Postby Necolatis » Thu Oct 31, 2019 2:07 pm

Thorsten wrote in Thu Oct 31, 2019 9:08 am:The script you posted is no-op for me - using it I can't move the view at all, clicking on up/down/left right does nothing, wide/narrow or zoom level and lock buttons work fine though.


Strange, will look into it.

Thorsten wrote in Thu Oct 31, 2019 9:08 am:Small afterthought - the Maverick is, I believe, not a laser-guided weapon. When targeting it, you are not looking through a target pod lens but through the weapons's own TV or IR sensor (dependent on what variant of the missile that is). So when the weapon is equipped, it should be possible to target it without a mounted pod or laser active.


Yeah, true. But you can pair it with the TGP, so that whatever the target pod looks at the agm will look, so you can use the target pod to lock with instead of using the AGMs own sensor directly.
In FG F-16 you dont need laser armed to use AGM65, if thats the case for you its a bug.
As for targeting without POD, yes in real life you can, but we have cut some corners, this is one of them.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2108
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: F-16 upgraded to 'production' status

Postby Necolatis » Thu Oct 31, 2019 3:37 pm

Fixed.

tgp.nas:
Code: Select all
# Copyright (C) 2016  onox
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Lines below FLIRCameraUpdater has been modified/added by Nikolai V. Chr.
#
# Position of the FLIR camera ([z (back), x (right), y (up)])
var coords_cam = [
    getprop("/sim/view[105]/config/z-offset-m"),
    getprop("/sim/view[105]/config/x-offset-m"),
    getprop("/sim/view[105]/config/y-offset-m")
];
io.include("Aircraft/Generic/updateloop.nas");
#io.load_nasal(getprop("/sim/fg-root") ~ "/Aircraft/c172p/Nasal/generic/math_ext.nas","math_ext");
var FLIRCameraUpdater = {

    new: func {
        var m = {
            parents: [FLIRCameraUpdater, Updatable]
        };
        m.loop = UpdateLoop.new(components: [m], update_period: 0.0);

        # Create a function to update the position of the FLIR camera
        m.update_cam = me._get_flir_auto_updater(180.0);

        # Create a function to update the position using an input device
        m.manual_update_cam = me._get_flir_updater(180.0, m.update_cam);

        m.click_coord_cam = nil;

        m.listeners = std.Vector.new();

        m.offsetP = 0;
        m.offsetH = 0;

        return m;
    },

    enable: func {
        #me.loop.reset();
        me.loop.enable();
    },

    disable: func {
        #me.remove_listeners();
        me.loop.disable();
    },

    enable_or_disable: func (enable) {
        if (enable) {
            me.enable();
        }
        else {
            me.disable();
        }
    },

    remove_listeners: func {
        foreach (var listener; me.listeners.vector) {
            removelistener(listener);
        }
        me.listeners.clear();
    },

    reset: func {
        #print("reset called?!?!");
        return;
        me.remove_listeners();
        me.listeners.append(setlistener("/sim/signals/click", func {
            var lat = getprop("/sim/input/click/latitude-deg");
            var lon = getprop("/sim/input/click/longitude-deg");
            var elev = getprop("/sim/input/click/elevation-m");

            var click_position = geo.Coord.new().set_latlon(lat, lon, elev);

            var origin_position = geo.aircraft_position();
            var distance_m = origin_position.direct_distance_to(click_position);

            if (getprop("/aircraft/flir/locks/auto-track")) {
                me.click_coord_cam = click_position;
                setprop("/aircraft/flir/target/auto-track", 1);
                logger.screen.white(sprintf("New tracking position at %d meter distance", distance_m));
            }
            else {
                setprop("/aircraft/flir/target/auto-track", 0);
                me.click_coord_cam = nil;
                logger.screen.red("Press F6 to enable automatic tracking by FLIR camera");
            }
        }));

        me.listeners.append(setlistener("/aircraft/flir/locks/auto-track", func (n) {
            setprop("/aircraft/flir/target/auto-track", 0);
            me.click_coord_cam = nil;
            if (n.getBoolValue()) {
                logger.screen.green("Automatic tracking by FLIR camera enabled. Click on the terrain to start tracking.");
            }
            else {
                logger.screen.red("Automatic tracking by FLIR camera disabled");
            }
        }));
    },

    update: func (dt) {
        var roll_deg  = getprop("/orientation/roll-deg");
        var pitch_deg = getprop("/orientation/pitch-deg");
        var heading   = getprop("/orientation/heading-deg");

        var computer = me._get_flir_computer(roll_deg, pitch_deg, heading);

        if (getprop("/aircraft/flir/target/auto-track") and me.click_coord_cam != nil) {
            var (yaw, pitch, distance) = computer(coords_cam, me.click_coord_cam);
            if (lock_tgp) {
                me.update_cam(roll_deg, pitch_deg, yaw, pitch);
            } else {
                me.update_cam(roll_deg, pitch_deg, yaw+me.offsetH, pitch+me.offsetP);
            }
        }
#        else {
#            me.manual_update_cam(roll_deg, pitch_deg);
#        }
    },

    aim: func () {
        var roll_deg  = getprop("/orientation/roll-deg");
        var pitch_deg = getprop("/orientation/pitch-deg");
        var heading   = getprop("/orientation/heading-deg");

        var computer = me._get_flir_computer(roll_deg, pitch_deg, heading);

        if (getprop("sim/current-view/view-number") ==12 and me.click_coord_cam != nil) {
            var (yaw, pitch, distance) = computer(coords_cam, me.click_coord_cam);
            me.update_cam(roll_deg, pitch_deg, yaw, pitch);
        }
    },

    ######################################################################
    # Gyro stabilization                                                 #
    ######################################################################

    _get_flir_updater: func (offset, updater) {
        return func (roll_deg, pitch_deg) {
            var yaw   = getprop("/aircraft/flir/input/yaw-deg") + (180.0 - offset);
            var pitch = getprop("/aircraft/flir/input/pitch-deg");

            updater(roll_deg, pitch_deg, yaw, pitch);
        };
    },

    ######################################################################
    # Automatic tracking computation                                     #
    ######################################################################

    _get_flir_auto_updater: func (offset) {
        return func (roll_deg, pitch_deg, yaw, pitch) {
            (yaw, pitch) = math_ext.get_yaw_pitch_body(roll_deg, pitch_deg, yaw, pitch, offset);

            setprop("/aircraft/flir/target/yaw-deg", yaw);
            setprop("/aircraft/flir/target/pitch-deg", pitch);
            if (getprop("sim/current-view/view-number") ==12) {
                setprop("/sim/current-view/goal-heading-offset-deg", -yaw);
                setprop("/sim/current-view/goal-pitch-offset-deg", pitch);
            }
            setprop("sim/view[105]/heading-offset-deg", yaw);
            setprop("sim/view[105]/pitch-offset-deg", pitch);
        };
    },

    _get_flir_computer: func (roll_deg, pitch_deg, heading) {
        return func (coords, target) {
            var (position_2d, position) = math_ext.get_point(coords[0], coords[1], coords[2], roll_deg, pitch_deg, heading);
            return math_ext.get_yaw_pitch_distance_inert(position_2d, position, target, heading);
        }
    }

};

math_ext.get_yaw_pitch_distance_inert = func (position_2d, position, target_position, heading, f=nil) {
    # Does the same as Onox's version, except takes curvature of Earth into account.
    var heading_deg = positioned.courseAndDistance(position_2d, target_position)[0] - heading;
    var pitch_deg   = vector.Math.getPitch(position, target_position);
    var distance_m  = position.direct_distance_to(target_position);
    return [heading_deg, pitch_deg, distance_m];
}

var flir_updater = FLIRCameraUpdater.new();

setlistener("/sim/signals/fdm-initialized", func {
    setlistener("/aircraft/flir/target/view-enabled", func (node) {
        flir_updater.enable_or_disable(node.getBoolValue());
    }, 1, 0);
});

setlistener("controls/MFD[2]/button-pressed", func (node) {
    var button = getprop("controls/MFD[2]/button-pressed");
    if (button == 1) {#LOCK
        gps = 0;
        if (lock_tgp) {
            lock_tgp = 0;
            armament.contactPoint = nil;
            return;
        }
        var x = -2.5856;
        var y =  0.8536;
        var z = -1.4121;
        var pos = aircraftToCart({x:-x, y:y, z: -z});
        var coordA = geo.Coord.new();
        coordA.set_xyz(pos.x, pos.y, pos.z);
        var matrixMath = 0;
        if (matrixMath) {
            var dirCoord = geo.Coord.new(coordA);
            var vHead = getprop("sim/current-view/heading-offset-deg");
            var vPitch = getprop("sim/current-view/pitch-offset-deg");

            var vectorF = vector.Math.eulerToCartesian3X(-getprop("orientation/heading-deg"),getprop("orientation/pitch-deg"),getprop("orientation/roll-deg"));
            var vectorL = vector.Math.eulerToCartesian3Y(-getprop("orientation/heading-deg"),getprop("orientation/pitch-deg"),getprop("orientation/roll-deg"));
            var vectorU = vector.Math.eulerToCartesian3Z(-getprop("orientation/heading-deg"),getprop("orientation/pitch-deg"),getprop("orientation/roll-deg"));
            var viewM   = vector.Math.viewMatrix(vectorF,vectorL,vectorU);
            var pitchM = vector.Math.pitchMatrix(vPitch);
            var yawM   = vector.Math.yawMatrix(-vHead);
            var rotation = vector.Math.multiplyMatrices(pitchM, yawM);#heading, pitch
            var viewGlobal = vector.Math.multiplyMatrices4(viewM, vector.Math.to4x4(rotation));#order?
            #viewGlobal = vector.Math.multiplyMatrices4(viewGlobal,vector.Math.mirrorMatrix);
            #var vectorA = [viewGlobal[2],viewGlobal[6],viewGlobal[10]];
            var vectorA = vector.Math.normalize(vector.Math.xFromView(viewGlobal));
            #vectorA = vector.Math.multiplyMatrixWithVector(rotation, vectorF);
            print(vector.Math.format(vectorA));
            var set = vector.Math.cartesianToEuler(vectorA);
           
            #if (set[0] == nil) {print("0 heading");return;}
            #printf("%d heading %d pitch",set[0],set[1]);
            dirCoord.apply_course_distance(set[0],50);
            var up = math.tan(set[1]*D2R)*50;
            dirCoord.set_alt(coordA.alt()+up);
        }

        # get quaternion for view rotation:
        var q = [getprop("sim/current-view/debug/orientation-w"),getprop("sim/current-view/debug/orientation-x"),getprop("sim/current-view/debug/orientation-y"),getprop("sim/current-view/debug/orientation-z")];

        var V = [2 * (q[1] * q[3] - q[0] * q[2]), 2 * (q[2] * q[3] + q[0] * q[1]),1 - 2 * (q[1] * q[1] + q[2] * q[2])];
        var w= q[0];
        var x= q[1];
        var y= q[2];
        var z= q[3];

        #rotate from x axis using the quaternion:
        V = [1 - 2 * (y*y + z*z),2 * (x*y + w*z),2 * (x*z - w*y)];

        var xyz          = {"x":coordA.x(),                "y":coordA.y(),               "z":coordA.z()};
        #var directionLOS = {"x":dirCoord.x()-coordA.x(),   "y":dirCoord.y()-coordA.y(),  "z":dirCoord.z()-coordA.z()};
        var directionLOS = {"x":V[0],   "y":V[1],  "z":V[2]};

        # Check for terrain between own weapon and target:
        var terrainGeod = get_cart_ground_intersection(xyz, directionLOS);
        if (terrainGeod == nil) {
            #print("0 terrain");
            return;
        } else {
            var terrain = geo.Coord.new();
            terrain.set_latlon(terrainGeod.lat, terrainGeod.lon, terrainGeod.elevation);
            var ut = nil;
            foreach (u ; awg_9.completeList) {
                if (terrain.direct_distance_to(u.get_Coord(0))<45) {
                    ut = u;
                    break;
                }
            }
            if (ut!=nil) {
                var contact = awg_9.Target.new(ut.propNode);
                contact.setClass(awg_9.POINT);
                contact.setVirtual(1);
                contact.unique = rand();
                armament.contactPoint = contact;
            } else {
                armament.contactPoint = fc.ContactTGP.new("TGP-Spot",terrain,1);
            }
            #flir_updater.click_coord_cam = terrain;
            #setprop("/aircraft/flir/target/auto-track", 1);
            #interpolate("f16/avionics/lock-flir",1,1.5);
            #flir_updater.offsetP = 0;
            #flir_updater.offsetH = 0;# commented so we get back to where we were when unlocking
            lock_tgp = 1;
        }
    } elsif (button == 20) {#BACK
        setprop("sim/current-view/view-number",0);
        #setprop("/aircraft/flir/target/auto-track", 0);
        #lock.hide();
        #setprop("f16/avionics/lock-flir",0.05);
    } elsif (button == 6) {#TV/IR
        ir = !ir;
    } elsif (button == 11) {#UP
        if (lock_tgp) return;
        gps = 0;
        var fov = getprop("sim/current-view/field-of-view");
        if (getprop("/aircraft/flir/target/auto-track")) {
            flir_updater.offsetP += fov/100;
        } else {
            setprop("sim/current-view/pitch-offset-deg",getprop("sim/current-view/pitch-offset-deg")+fov/5);
        }
    } elsif (button == 12) {#DOWN
        if (lock_tgp) return;
        gps = 0;
        var fov = getprop("sim/current-view/field-of-view");
        if (getprop("/aircraft/flir/target/auto-track")) {
            flir_updater.offsetP -= fov/100;
        } else {
            setprop("sim/current-view/pitch-offset-deg",getprop("sim/current-view/pitch-offset-deg")-fov/5);
        }
    } elsif (button == 14) {#LEFT
        if (lock_tgp) return;
        gps = 0;
        var fov = getprop("sim/current-view/field-of-view");
        if (getprop("/aircraft/flir/target/auto-track")) {
            flir_updater.offsetH -= fov/100;
        } else {
            setprop("sim/current-view/heading-offset-deg",getprop("sim/current-view/heading-offset-deg")+fov/5);
        }
    } elsif (button == 15) {#RGHT
        if (lock_tgp) return;
        gps = 0;
        var fov = getprop("sim/current-view/field-of-view");
        if (getprop("/aircraft/flir/target/auto-track")) {
            flir_updater.offsetH += fov/100;
        } else {
            setprop("sim/current-view/heading-offset-deg",getprop("sim/current-view/heading-offset-deg")-fov/5);
        }
    } elsif (button == 13) {#WIDE/NARO
        wide = !wide;       
    } elsif (button == 2) {#ZOOM
        zoomlvl += 1;
        if (zoomlvl > 4) {
            zoomlvl = 1;
        }
    }# elsif (button == 3) {#RDR
     #   if (!getprop("/aircraft/flir/target/auto-track") and awg_9.active_u != nil) {
     #       flir_updater.offsetP = 0;
     #       flir_updater.offsetH = 0;
     #       flir_updater.click_coord_cam = awg_9.active_u.get_Coord();
     #       flir_updater.aim();
     #       flir_updater.click_coord_cam = nil;
     #   }
     #}
});

var steerlock = 0;

var fast_loop = func {
  var viewName = getprop("/sim/current-view/name");
    if (viewName == "TGP" and (getprop("gear/gear/wow") or !getprop("f16/stores/tgp-mounted"))) {
        # deselect view back to pilot default
        setprop("sim/current-view/view-number",0);
        setprop("sim/rendering/als-filters/use-IR-vision", 0);
        setprop("sim/view[105]/enabled", 0);
    } elsif (viewName == "TGP") {
        # FLIR TGP stuff:
        setprop("aircraft/flir/target/view-enabled", viewName == "TGP");
        setprop("sim/rendering/als-filters/use-filtering", viewName == "TGP");
        setprop("sim/rendering/als-filters/use-IR-vision", viewName == "TGP" and ir);
        setprop("sim/rendering/als-filters/use-night-vision", 0);
       
        var x = getprop("sim/gui/canvas/size[0]");
        var y = getprop("sim/gui/canvas/size[1]");
               
        var degs = 3.6/zoomlvl;
        if (wide) {           
            line13.setText("WIDE");
        } else {
            degs = 1.0/zoomlvl;
            line13.setText("NARO");
        }
        var fov = degs*(x/y);
        var format = (x/y)/2.25;#16/9 = 1.777
        var scale = format*20/fov;# we take into account that different pilots have different screen formats so the height of the MFD in screen stays same relative.
        setprop("sim/current-view/field-of-view-scale",scale);
        setprop("sim/current-view/field-of-view",fov);

        zoom.setText(sprintf("%.1fX",zoomlvl));
       
        line6.setText(ir==1?"WHOT":"TV");
       
        if (getprop("/aircraft/flir/target/auto-track") and flir_updater.click_coord_cam != nil) {
            var dist = flir_updater.click_coord_cam.direct_distance_to(geo.aircraft_position())*M2NM;
            bott.setText(sprintf("%2.1f  CMBT  %04d",dist,lasercode));
        } else {
            bott.setText(sprintf("      CMBT  %04d",lasercode));
        }
        if (!getprop("/aircraft/flir/target/auto-track") or flir_updater.click_coord_cam == nil) {
            setprop("sim/view[105]/heading-offset-deg", -getprop("sim/current-view/heading-offset-deg"));
            setprop("sim/view[105]/pitch-offset-deg", getprop("sim/current-view/pitch-offset-deg"));
        }
    } else {
        # remove FLIR effects and disable TGP view
        setprop("sim/rendering/als-filters/use-IR-vision", 0);
        setprop("sim/view[105]/enabled", 0);#!getprop("gear/gear/wow"));
        #lock.hide();
        #setprop("f16/avionics/lock-flir",0.05);
    }
   
    #callsign = nil;
    steerlock = 0;
    var follow = 0;
    if (armament.contactPoint !=nil and armament.contactPoint.get_range()>35 and armament.contactPoint.get_Callsign() != "GPS-Spot") {
        armament.contactPoint = nil;
    }
    var gpps = 0;
    if (armament.contactPoint == nil) {
        # no TGP lock
        if (armament.contact == nil) {# we do not check for get_display here since as long as something is selected we dont show steerpoint.
            if (getprop("autopilot/route-manager/active") == 1 and getprop("autopilot/route-manager/current-wp") != nil and getprop("autopilot/route-manager/current-wp") > -1) {
                # TGP follow steerpoint
                var idx = getprop("autopilot/route-manager/current-wp");
                var ele = getprop("autopilot/route-manager/route/wp["~idx~"]/altitude-ft");
                var lat = getprop("autopilot/route-manager/route/wp["~idx~"]/latitude-deg");
                var lon = getprop("autopilot/route-manager/route/wp["~idx~"]/longitude-deg");
                if (ele == nil) {
                    ele = 0;
                }
                ele *= FT2M;
                var ele2 = geo.elevation(lat,lon);
                if (ele2 != nil) {
                    ele = ele2;
                }               
                var sp = geo.Coord.new();
                sp.set_latlon(lat,lon,ele);
                flir_updater.click_coord_cam = sp;
                setprop("/aircraft/flir/target/auto-track", 1);
                if (callsign != lat~lon) {
                    # we switched steerpoint or from radar to steerpoint
                    flir_updater.offsetP = 0;
                    flir_updater.offsetH = 0;
                }
                callsign = lat~lon;
                steerlock = 1;
                steer = 1;
            } else {
                # TGP not follow, locked from aircraft
                setprop("/aircraft/flir/target/auto-track", 0);
                flir_updater.click_coord_cam = nil;
                flir_updater.offsetP = 0;
                flir_updater.offsetH = 0;
                steer = 0;
                callsign = nil;
            }
        } elsif (armament.contact != nil and armament.contact.get_display()) {
            # TGP follow radar lock
            flir_updater.click_coord_cam = armament.contact.get_Coord();
            setprop("/aircraft/flir/target/auto-track", 1);
            if (callsign != armament.contact.getUnique()) {
                flir_updater.offsetP = 0;
                flir_updater.offsetH = 0;
            }
            callsign = armament.contact.getUnique();
            steer = 0;
        } else {
            setprop("/aircraft/flir/target/auto-track", 0);
            flir_updater.click_coord_cam = nil;
            callsign = nil;
            flir_updater.offsetP = 0;
            flir_updater.offsetH = 0;
            steer = 0;
        }
        lock_tgp = 0;
        gps = 0;
    } else {
        # TGP lock
        var vis = 1;
        gpss = armament.contactPoint.get_Callsign() == "GPS-Spot";# GPS-Spot only used by "program GPS dialog"
        if (armament.contactPoint.get_Callsign() != "TGP-Spot" and !gps and !gpss and !steer) {
            # we do not check for visibility if:
            # - following steerpoint
            # - a GPS coord has been entered manually by "program GPS dialog"
            follow = 1;
            vis = awg_9.TerrainManager.IsVisible(armament.contactPoint.propNode, nil);
        }
        if (!vis) {
            setprop("/aircraft/flir/target/auto-track", 0);
            flir_updater.click_coord_cam = nil;
            callsign = nil;
            flir_updater.offsetP = 0;
            flir_updater.offsetH = 0;
            lock_tgp = 0;
            armament.contactPoint = nil;
        } else {
            lock_tgp = 1;
            flir_updater.click_coord_cam = armament.contactPoint.get_Coord();
            callsign = armament.contactPoint.getUnique();
            setprop("/aircraft/flir/target/auto-track", 1);
            #flir_updater.offsetP = 0;
            #flir_updater.offsetH = 0;# commented so we get back to where we were when unlocking
        }
    }
    setprop("f16/avionics/tgp-lock", lock_tgp);#used in HUD
       
    if (getprop("f16/stores/tgp-mounted")) {
        if (lock_tgp and !lock_tgp_last) {
            interpolate("f16/avionics/lock-flir",1,1.5);
        } elsif (!lock_tgp) {
            setprop("f16/avionics/lock-flir",0.05);
        }
        lock_tgp_last = lock_tgp;
        if (lock_tgp) {
            line1box.show();
            line11.hide();
            line12.hide();
            line14.hide();
            line15.hide();
        } else {
            line1box.hide();
            line11.show();
            line12.show();
            line14.show();
            line15.show();
        }
        if (lock_tgp and gps) {
            midl.setText(sprintf("%s      %s", "GPS", getprop("controls/armament/laser-arm-dmd")?"L":""));
        } elsif (lock_tgp and follow) {
            midl.setText(sprintf("%s POINT %s", gps?"GPS":(ir==1?"IR":"TV"), getprop("controls/armament/laser-arm-dmd")?"L":""));
        } elsif (lock_tgp) {
            midl.setText(sprintf("%s AREA  %s", gps?"GPS":(ir==1?"IR":"TV"), getprop("controls/armament/laser-arm-dmd")?"L":""));
        } elsif (getprop("/aircraft/flir/target/auto-track") and flir_updater.click_coord_cam != nil and steerlock) {
            midl.setText(sprintf("  STEER  %s", getprop("controls/armament/laser-arm-dmd")?"L":""));
        } elsif (getprop("/aircraft/flir/target/auto-track") and flir_updater.click_coord_cam != nil) {
            midl.setText(sprintf("  RADAR  %s", getprop("controls/armament/laser-arm-dmd")?"L":""));
        } else {
            midl.setText(sprintf("         %s", getprop("controls/armament/laser-arm-dmd")?"L":""));
        }
       
        var scaleLock = getprop("f16/avionics/lock-flir");
        lock.setScale(scaleLock,scaleLock);
        lock.setStrokeLineWidth(1/scaleLock);
        if (scaleLock != 0.05) {
            lock.show();
        } else {
            lock.hide();
        }
        lock.update();
   
        # animate the LANTIRN camera:
        var b = geo.normdeg180(getprop("sim/view[105]/heading-offset-deg"));
        var p = getprop("sim/view[105]/pitch-offset-deg");
        var polarL = math.sqrt(p*p+b*b);
        var polarD = polarL!=0 and b!=0?math.atan2(p,b)*R2D:-90;
        setprop("aircraft/flir/swivel/pitch-deg",polarL);
        setprop("aircraft/flir/swivel/roll-deg",polarD);
    }
    settimer(fast_loop,0);
}


var line1 = nil;
var line1box = nil;
var line2 = nil;
var line3 = nil;
var line4 = nil;
var line6 = nil;
var line7 = nil;
var line11 = nil;
var line12 = nil;
var line13 = nil;
var line14 = nil;
var line15 = nil;
var line20 = nil;
var cross = nil;
var lock = nil;
var zoom = nil;
var bott = nil;
var midl = nil;
var ir = 1;
var lasercode = int(rand()*10000);setprop("f16/avionics/laser-code",lasercode);
var callsign = nil;
var lock_tgp = 0;
var lock_tgp_last = 0;
var wide = 1;
var zoomlvl = 1.0;
var gps = 0;# set from Program GPS dialog
var steer = 0;

var callInit = func {
  var canvasMFDext = canvas.new({
        "name": "MFD-EXT",
        "size": [256, 256],
        "view": [256, 256],
        "mipmapping": 1
  });
     
  canvasMFDext.addPlacement({"node": "MFDimage3", "texture": "tranbg.png"});
  canvasMFDext.setColorBackground(1.00, 1.00, 1.00, 0.00);

  dedGroup = canvasMFDext.createGroup();
  dedGroup.show();
  var color = [1,1,1,1];
  line1 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("left-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("LOCK")
        .setTranslation(5, 256*0.20);
  line1box = dedGroup.createChild("path")
        .moveTo(0,-7)
        .vert(14)
        .horiz(35)
        .vert(-14)
        .horiz(-35)
        .setStrokeLineWidth(1)
        .setColor(1,1,1)
        .hide()
        .setTranslation(5, 256*0.20);
  line2 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("left-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("ZOOM")
        .setTranslation(5, 256*0.35);
  line3 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("left-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("ZOOM")
        .hide()       
        .setTranslation(5, 256*0.50);
  line4 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("left-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("")
        .setTranslation(5, 256*0.65);
  line6 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("right-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("WHOT")
        .setTranslation(256-5, 256*0.2);
  line7 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("right-center")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("XFER")
        .hide()
        .setTranslation(256-5, 256*0.35);
  line11 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("UP")
        .setTranslation(256*0.2, 5);
  line12 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("DOWN")
        .setTranslation(256*0.35, 5);
  line13 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("WIDE")
        .setTranslation(256*0.50, 5);
  line14 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("LEFT")
        .setTranslation(256*0.65, 5);
  line15 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("RGHT")
        .setTranslation(256*0.8, 5);
  line20 = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(color)
        .setAlignment("center-bottom")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("BACK")
        .setTranslation(256*0.8, 256-5);

    zoom = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(1,1,1)
        .setAlignment("center-top")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("1.0X")
        .setTranslation(256*0.5, 20);
    midl = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(1,1,1)
        .setAlignment("center-bottom")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("IR POINT    L")
        .setTranslation(256*0.5, 256*0.8);
    bott = dedGroup.createChild("text")
        .setFontSize(13, 1)
        .setColor(1,1,1)
        .setAlignment("center-bottom")
        .setFont("LiberationFonts/LiberationMono-Bold.ttf")
        .setText("13.0  CMBT  1538")
        .setTranslation(256*0.5, 256*0.9);

  cross = dedGroup.createChild("path")
            .moveTo(128,0)
            .vert(120)
            .moveTo(128,256)
            .vert(-120)
            .moveTo(0,128)
            .horiz(120)
            .moveTo(256,128)
            .horiz(-120)
            .setStrokeLineWidth(1)
            .setColor(1,1,1);
    lock = dedGroup.createChild("path")
            #.setCenter(128,128)
            .moveTo(48,48)
            .vert(-96)
            .horiz(-96)
            .vert(96)
            .horiz(96)
            .hide()
            .setTranslation(128,128)
            .setStrokeLineWidth(1)
            .setColor(1,1,1);
};

callInit();
fast_loop();
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2108
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: F-16 upgraded to 'production' status

Postby Thorsten » Fri Nov 01, 2019 9:41 am

In the latest iteration of the script, the direction buttons again work fine, and I confirm that zoom or wide/narrow changes leave the view pointed at the same spot.

However, locking the view and releasing it again makes it move back to pointing directly at the waypoint rather than bringing it into the state right before it was locked.

It's definitely workable - I got all six missiles locked and fired before 6 miles to target, which seems a modestly safe distance - but the waypoint has to be chosen carefully...
Thorsten
 
Posts: 11642
Joined: Mon Nov 02, 2009 8:33 am

PreviousNext

Return to Aircraft

Who is online

Users browsing this forum: YandexBot [Bot] and 6 guests