... 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.