Board index FlightGear Development New features

Virtual Camera?

Discussion and requests for new features. Please note that FlightGear developers are volunteers and may or may not be able to consider these requests.

Re: Virtual Camera?

Postby Marius_A » Wed Dec 04, 2013 6:04 pm

... I was wondering if it would be possible to get something like a 3Dvirtual camera in FligthGear, something like Ezdok ...


This script smoothly moves camera position inside cockpit (save as fgcamera.nas and put to "../FlightGear/data/Nasal" directory):
Code: Select all
##############################################
#            fgcamera.nas
##############################################

###
# Preset view transition speed (increase to slow down camera movement)
# Use fgcamera.changePoint(vn) to switch preset views. "vn" is preset view (usually in aircraft's *-set.xml file)  number.
# Example:
# fgcamera.changePoint(0) will move camera to default position,
# fgcamera.changePoint(101) will move camera to position described in <PropertyList> ... <view n="101"> ... </view> ... </PropertyList>
var time = 0.5;

###
# Adjustable linear and angular velocities (increase if view moves too slow).
# Recommendation: x = y = z, h = p = r.
var velocity = {
      "x": 2.0,
      "y": 2.0,
      "z": 2.0,
      "h": 180.0,
      "p": 180.0,
      "r": 180.0
   };
###
# Adjustable linear and angular accelerations (increase to reduce view "floating" effect).
# Recommendation: x = y = z, h = p = r.
var acceleration = {
      "x": 0.1,
      "y": 0.1,
      "z": 0.1,
      "h": 10.0,
      "p": 10.0,
      "r": 10.0
   };
#################################################################################################
#Main script:
#
var camera = {
      "current": {
         "x": getprop("/sim/view[0]/config/x-offset-m"),
         "y": getprop("/sim/view[0]/config/y-offset-m"),
         "z": getprop("/sim/view[0]/config/z-offset-m"),
         "h": getprop("/sim/view[0]/config/heading-offset-deg"),
         "p": getprop("/sim/view[0]/config/pitch-offset-deg"),
         "r": getprop("/sim/view[0]/config/roll-offset-deg")
      },
      "from": {
         "x": getprop("/sim/view[0]/config/x-offset-m"),
         "y": getprop("/sim/view[0]/config/y-offset-m"),
         "z": getprop("/sim/view[0]/config/z-offset-m"),
         "h": getprop("/sim/view[0]/config/heading-offset-deg"),
         "p": getprop("/sim/view[0]/config/pitch-offset-deg"),
         "r": getprop("/sim/view[0]/config/roll-offset-deg")
      },      
      "to": {
         "x": getprop("/sim/view[0]/config/x-offset-m"),
         "y": getprop("/sim/view[0]/config/y-offset-m"),
         "z": getprop("/sim/view[0]/config/z-offset-m"),
         "h": getprop("/sim/view[0]/config/heading-offset-deg"),
         "p": getprop("/sim/view[0]/config/pitch-offset-deg"),
         "r": getprop("/sim/view[0]/config/roll-offset-deg")
      },
      "blend": {
         "x": -1.0,
         "y": -1.0,
         "z": -1.0,
         "h": -1.0,
         "p": -1.0,
         "r": -1.0
      },
      "delta": {
         "x": -1.0,
         "y": -1.0,
         "z": -1.0,
         "h": -1.0,
         "p": -1.0,
         "r": -1.0
      },      
      "velocity": {
         "current": {
            "x": 0.0,
            "y": 0.0,
            "z": 0.0,
            "h": 0.0,
            "p": 0.0,
            "r": 0.0
         },
         "target": {
            "x": 0.0,
            "y": 0.0,
            "z": 0.0,
            "h": 0.0,
            "p": 0.0,
            "r": 0.0
         }
      },
      "acceleration": {
         "x": 0.0,
         "y": 0.0,
         "z": 0.0,
         "h": 0.0,
         "p": 0.0,
         "r": 0.0
      }
   };
##
# Normalize angle to  -180 <= angle < 180
#
var normdeg = func(a) {
   while (a >= 180)
      a -= 360;
   while (a < -180)
      a += 360;
   return a;
}
var changePoint_loop_running = 0;
var changePoint = func(vn) {
   camera.current.x = getprop("/sim/current-view/x-offset-m");
   camera.current.y = getprop("/sim/current-view/y-offset-m");
   camera.current.z = getprop("/sim/current-view/z-offset-m");
   camera.current.h = normdeg(getprop("/sim/current-view/heading-offset-deg"));
   camera.current.p = normdeg(getprop("/sim/current-view/pitch-offset-deg"));
   camera.current.r = normdeg(getprop("/sim/current-view/roll-offset-deg"));
   camera.to.x = getprop(sprintf("/sim/view[%d]/config/x-offset-m", vn));
   camera.to.y = getprop(sprintf("/sim/view[%d]/config/y-offset-m", vn));
   camera.to.z = getprop(sprintf("/sim/view[%d]/config/z-offset-m", vn));
   camera.to.h = normdeg(getprop(sprintf("/sim/view[%d]/config/heading-offset-deg", vn)));
   camera.to.p = normdeg(getprop(sprintf("/sim/view[%d]/config/pitch-offset-deg", vn)));
   camera.to.r = 0.0;
   foreach(var a; keys(camera.current)) {
      camera.from[a] = camera.current[a];
      camera.velocity.current[a] = camera.velocity.target[a] = camera.acceleration[a] = 0;
      camera.blend[a] = -1;
   }
   if (!changePoint_loop_running) changePoint_loop();
}
var changePoint_loop = func {
   changePoint_loop_running = 0;
   var dt = getprop("/sim/time/delta-realtime-sec");
   foreach(var a; keys(camera.current)) {
      if (camera.current[a] != camera.to[a]) {
         camera.blend[a] += dt/time;
         if (camera.blend[a] > 1)
            camera.blend[a] = 1;
         var b = (math.sin(camera.blend[a] * math.pi / 2) + 1) / 2; # range 0 .. 1
         camera.current[a] = camera.from[a] + b * (camera.to[a] - camera.from[a]);
         if (camera.blend[a] == 1) {
            camera.blend[a] = -1;
            camera.current[a] = camera.to[a];
         } else changePoint_loop_running = 1;
      }
   }
   setprop("/sim/current-view/x-offset-m", camera.current.x);
   setprop("/sim/current-view/y-offset-m", camera.current.y);
   setprop("/sim/current-view/z-offset-m", camera.current.z);
   setprop("/sim/current-view/heading-offset-deg", camera.current.h);
   setprop("/sim/current-view/pitch-offset-deg", camera.current.p);
   setprop("/sim/current-view/roll-offset-deg", camera.current.r);
   if (changePoint_loop_running) settimer(changePoint_loop, 0);
}
var adjustPoint_loop_running = 0;
var adjustPoint = func (arg) {
   foreach (var a; keys(arg)) {
      if (arg[a] != nil) {
         camera.velocity.target[a] = velocity[a] * arg[a];
      }
   }
   if (!adjustPoint_loop_running) adjustPoint_loop();
}
var adjustPoint_loop = func {
   adjustPoint_loop_running = 0;
   var dt = getprop("/sim/time/delta-realtime-sec");
   foreach (var a; keys(camera.current)) {
      camera.acceleration[a] = acceleration[a];
      if (camera.velocity.target[a] < camera.velocity.current[a]) {
         camera.acceleration[a] = acceleration[a] * -1;
      }
      if (camera.velocity.target[a] == camera.velocity.current[a]) {
         camera.acceleration[a] = 0;
      }
      if ( (camera.velocity.target[a] * camera.velocity.current[a]) < 0 ) {
         camera.acceleration[a] *= 2;
      }
      var velocity_old = camera.velocity.current[a];
      camera.velocity.current[a] += camera.acceleration[a] * dt;
      if (camera.velocity.target[a] < 0) {
         if (camera.velocity.current[a] < camera.velocity.target[a]) {
            camera.velocity.current[a] = camera.velocity.target[a];
         }
      }
      if (camera.velocity.target[a] > 0) {
         if (camera.velocity.current[a] > camera.velocity.target[a]) {
            camera.velocity.current[a] = camera.velocity.target[a];
         }
      }      
      if (camera.velocity.target[a] == 0) {
         if ( (camera.velocity.current[a] * velocity_old) <= 0 ) {
            camera.velocity.current[a] = 0;
         }
      }
      camera.delta[a] = camera.velocity.current[a] * dt;
      if (camera.velocity.target[a] != camera.velocity.current[a])
         adjustPoint_loop_running = 1;
   }
   var heading_offset = getprop("/sim/current-view/heading-offset-deg") * math.pi / 180;
   var x = camera.delta.x * math.cos(heading_offset) + camera.delta.z * math.sin(heading_offset);
   var z = camera.delta.z * math.cos(heading_offset) - camera.delta.x * math.sin(heading_offset);
   camera.delta.x = x;
   camera.delta.z = z;
   if (changePoint_loop_running) {
      foreach (var a; keys(camera.current)) {
         camera.current[a] += camera.delta[a];
         camera.to[a] += camera.delta[a];
         camera.from[a] += camera.delta[a];      
      }
   } else {
      setprop("/sim/current-view/x-offset-m", getprop("/sim/current-view/x-offset-m") + camera.delta.x);
      setprop("/sim/current-view/y-offset-m", getprop("/sim/current-view/y-offset-m") + camera.delta.y);
      setprop("/sim/current-view/z-offset-m", getprop("/sim/current-view/z-offset-m") + camera.delta.z);
      setprop("/sim/current-view/heading-offset-deg", getprop("/sim/current-view/heading-offset-deg") + camera.delta.h);
      setprop("/sim/current-view/pitch-offset-deg", getprop("/sim/current-view/pitch-offset-deg") + camera.delta.p);
      setprop("/sim/current-view/roll-offset-deg", getprop("/sim/current-view/roll-offset-deg") + camera.delta.r);   
      }
   if (adjustPoint_loop_running) settimer(adjustPoint_loop, 0);
}

Keyboard configuration (save as fgcamera.xml and use as FlightGear config: in FlightGear Wizard select "Advanced..." and add path to this file (field "Config"):
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>

<!-- ########################################

       fgcamera.xml
      
   Usage options: 
   1) add the code to aircraft's  *-set.xml file;
   2) use this file as FlightGear config:
      in FlightGear Wizard select "Advanced..." and add path to this file (field "Config")
   
   Option (1) is recommended.
   
##########################################-->

 <PropertyList>
  <input>
    <keyboard>
      <key n="360">
      <name> PageUp </name>
      <desc>Camera Up</desc>
      <binding>
         <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": nil, "y": 1.0, "z": nil, "h": nil, "p": nil, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
      </binding>
      <mod-up>
         <binding>
            <command>nasal</command>
            <script>
            <![CDATA[
               var arg = {"x": nil, "y": 0.0, "z": nil, "h": nil, "p": nil, "r": nil};
               fgcamera.adjustPoint(arg);
            ]]>
            </script>
         </binding>
      </mod-up>
      </key>
   
   <key n="361">
   <name> PageDown </name>
   <desc>Camera Down</desc>
   <binding>
      <command>nasal</command>
      <script>
      <![CDATA[
         var arg = {"x": nil, "y": -1.0, "z": nil, "h": nil, "p": nil, "r": nil};
         fgcamera.adjustPoint(arg);
      ]]>
      </script>
   </binding>
   <mod-up>
      <binding>
         <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": nil, "y": 0.0, "z": nil, "h": nil, "p": nil, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
      </binding>
   </mod-up>
   </key>

   <key n="49">
   <name> 1 </name>
   <desc>Preset view 1</desc>
   <binding>
      <command>nasal</command>
      <script>
         fgcamera.changePoint(0);
      </script>
   </binding>
   </key>
   
   <key n="50">
   <name> 2 </name>
   <desc>Preset view 2</desc>
   <binding>
      <command>nasal</command>
      <script>
         fgcamera.changePoint(101);
      </script>
   </binding>
   </key>
   
   <key n="51">
   <name> 3 </name>
   <desc>Preset view 3</desc>
   <binding>
      <command>nasal</command>
      <script>
         fgcamera.changePoint(103);
      </script>
   </binding>
   </key>
   
   <key n="52">
   <name> 4 </name>
   <desc>Preset view 4</desc>
   <binding>
      <command>nasal</command>
      <script>
         fgcamera.changePoint(104);
      </script>
   </binding>
   
   </key>
   <key n="53">
   <name> 5 </name>
   <desc>Camera rotate left</desc>
   <binding>
      <command>nasal</command>
      <script>
      <![CDATA[
         var arg = {"x": nil, "y": nil, "z": nil, "h": 1.0, "p": nil, "r": nil};
         fgcamera.adjustPoint(arg);
      ]]>
      </script>
   </binding>
   <mod-up>
      <binding>
         <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": nil, "y": nil, "z": nil, "h": 0.0, "p": nil, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
      </binding>
   </mod-up>
   </key>
   
   <key n="54">
   <name> 6 </name>
   <desc>Camera rotate right</desc>
   <binding>
      <command>nasal</command>
      <script>
      <![CDATA[
         var arg = {"x": nil, "y": nil, "z": nil, "h": -1.0, "p": nil, "r": nil};
         fgcamera.adjustPoint(arg);
      ]]>
      </script>
   </binding>
   <mod-up>
      <binding>
         <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": nil, "y": nil, "z": nil, "h": 0.0, "p": nil, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
      </binding>
   </mod-up>
   </key>
   
   <key n="56">
   <name> 8 </name>
   <desc>Camera rotate up</desc>
   <binding>
      <command>nasal</command>
      <script>
      <![CDATA[
         var arg = {"x": nil, "y": nil, "z": nil, "h": nil, "p": 1.0, "r": nil};
         fgcamera.adjustPoint(arg);
      ]]>
      </script>
   </binding>
   <mod-up>
      <binding>
         <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": nil, "y": nil, "z": nil, "h": nil, "p": 0.0, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
      </binding>
   </mod-up>
   </key>
   
   <key n="55">
   <name> 7 </name>
   <desc>Camera rotate down</desc>
   <binding>
      <command>nasal</command>
      <script>
      <![CDATA[
         var arg = {"x": nil, "y": nil, "z": nil, "h": nil, "p": -1.0, "r": nil};
         fgcamera.adjustPoint(arg);
      ]]>
      </script>
   </binding>
   <mod-up>
      <binding>
         <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": nil, "y": nil, "z": nil, "h": nil, "p": 0.0, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
      </binding>
   </mod-up>
   </key>
   
   <key n="357">
   <name> Up </name>
   <desc>Camera forward</desc>
   <binding>
      <command>nasal</command>
      <script>
      <![CDATA[
         var arg = {"x": nil, "y": nil, "z": -1.0, "h": nil, "p": nil, "r": nil};
         fgcamera.adjustPoint(arg);
      ]]>
      </script>
   </binding>
   <mod-up>
      <binding>
         <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": nil, "y": nil, "z": 0.0, "h": nil, "p": nil, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
      </binding>
   </mod-up>
   </key>
   <key n="359">
   <name> Down </name>
   <desc>camera back</desc>
   <binding>
      <command>nasal</command>
      <script>
      <![CDATA[
         var arg = {"x": nil, "y": nil, "z": 1.0, "h": nil, "p": nil, "r": nil};
         fgcamera.adjustPoint(arg);
      ]]>
      </script>
   </binding>
   <mod-up>
      <binding>
         <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": nil, "y": nil, "z": 0.0, "h": nil, "p": nil, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
      </binding>
   </mod-up>
   </key>
   <key n="356">
   <name> Left </name>
   <desc>Camera left</desc>
   <binding>
      <command>nasal</command>
      <script>
      <![CDATA[
         var arg = {"x": -1.0, "y": nil, "z": nil, "h": nil, "p": nil, "r": nil};
         fgcamera.adjustPoint(arg);
      ]]>
      </script>
   </binding>
   <mod-up>
      <binding>
         <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": 0.0, "y": nil, "z": nil, "h": nil, "p": nil, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
      </binding>
   </mod-up>
   </key>
   <key n="358">
   <name> Right </name>
   <desc>Camera right</desc>
   <binding>
      <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": 1.0, "y": nil, "z": nil, "h": nil, "p": nil, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
   </binding>
   <mod-up>
      <binding>
         <command>nasal</command>
         <script>
         <![CDATA[
            var arg = {"x": 0.0, "y": nil, "z": nil, "h": nil, "p": nil, "r": nil};
            fgcamera.adjustPoint(arg);
         ]]>
         </script>
      </binding>
   </mod-up>
   </key>
   </keyboard>
</input>
</PropertyList>


Pre-configured keys:

arrow keys - moves camera front/back and left/right,
PageUp, PageDown - moves camera up/down,
5, 6 - rotates left/right,
7, 8 - rotates up/down,
1, 2, 3, 4 - smoothly moves to preset views.
Marius_A
 
Posts: 92
Joined: Wed Dec 04, 2013 3:20 pm

Re: Virtual Camera?

Postby Foxtrot15 » Sat May 21, 2016 10:10 am

Hi is this still working in FG 2016.1.1? It was previously working in 3.7 but after I upgraded it stopped working. Anyone know why?

Image
Foxtrot15
 
Posts: 378
Joined: Thu Aug 27, 2015 6:01 am
Location: Singapore
Callsign: Ice-99
Version: 2016.1.0
OS: OS X

Previous

Return to New features

Who is online

Users browsing this forum: No registered users and 4 guests