Updated WalkView:
- Added support for additional manager objects, e.g. for animating a 3d model or move a JSBSim pointmass. - Improved the documentation. - Some bugs removed.
This commit is contained in:
parent
8fd716f2ca
commit
049d98ad8e
1 changed files with 74 additions and 26 deletions
|
@ -11,7 +11,7 @@
|
|||
|
||||
# Global API. Automatically selects the right walker for the current view.
|
||||
|
||||
# NOTE: Coordinates are always 3 component lists: [x, y, z].
|
||||
# NOTE: Coordinates are always 3 component lists: [x, y, z] in meters.
|
||||
# The coordinate system is the same as the main 3d model one.
|
||||
# X - back, Y - right and Z - up.
|
||||
|
||||
|
@ -58,10 +58,17 @@ var active_walker = func {
|
|||
# Class for a moving view.
|
||||
#
|
||||
# CONSTRUCTOR:
|
||||
# walker.new(<view name>, <constraints>);
|
||||
# walker.new(<view name>, <constraints>, <managers>);
|
||||
#
|
||||
# view name ... The name of the view : string
|
||||
# constraints ... The movement constraints : constraint hash
|
||||
# Determines where the view can go.
|
||||
# managers ... Optional list of custom managers. A manager is a
|
||||
# a hash that contains an update function of the type
|
||||
# func(walker instance). The update function
|
||||
# of each manager will be called as the last part of
|
||||
# each walker update. Intended for controlling a
|
||||
# a 3d model or similar.
|
||||
#
|
||||
# METHODS:
|
||||
# active() : bool
|
||||
|
@ -82,7 +89,7 @@ var active_walker = func {
|
|||
# get_eye_height() : int (meter)
|
||||
#
|
||||
# set_constraints(constraints)
|
||||
# get_constraints() : contraint hash
|
||||
# get_constraints() : constraint hash
|
||||
#
|
||||
# EXAMPLE:
|
||||
# var constraint =
|
||||
|
@ -95,10 +102,11 @@ var active_walker = func {
|
|||
# walk view should not have any other view manager.
|
||||
#
|
||||
var walker = {
|
||||
new : func (view_name, constraints = nil) {
|
||||
new : func (view_name, constraints = nil, managers = nil) {
|
||||
var obj = { parents : [walker] };
|
||||
obj.view = view.views[view.indexof(view_name)];
|
||||
obj.constraints = constraints;
|
||||
obj.managers = managers;
|
||||
obj.position = [
|
||||
obj.view.getNode("config/z-offset-m").getValue(),
|
||||
obj.view.getNode("config/x-offset-m").getValue(),
|
||||
|
@ -108,7 +116,6 @@ var walker = {
|
|||
obj.view.getNode("config/heading-offset-deg").getValue();
|
||||
obj.speed_fwd = 0.0;
|
||||
obj.speed_side = 0.0;
|
||||
obj.id = 0;
|
||||
obj.isactive = 0;
|
||||
obj.eye_height = 1.60;
|
||||
obj.goal_height = obj.position[2] + obj.eye_height;
|
||||
|
@ -135,7 +142,7 @@ var walker = {
|
|||
me.position[2] = pos[2];
|
||||
},
|
||||
get_pos : func {
|
||||
return me.position;
|
||||
return [me.position[0], me.position[1], me.position[2]];
|
||||
},
|
||||
set_eye_height : func (h) {
|
||||
me.eye_height = h;
|
||||
|
@ -157,13 +164,11 @@ var walker = {
|
|||
me.last_time = getprop("/sim/time/elapsed-sec") - 0.0001;
|
||||
me.update();
|
||||
me.position[2] = me.goal_height;
|
||||
settimer(func { me._loop_(me.id); }, 0.0);
|
||||
},
|
||||
stop : func {
|
||||
me.isactive = 0;
|
||||
me.id += 1;
|
||||
},
|
||||
# Internals.
|
||||
# The update function is called by the view manager when the view is active.
|
||||
update : func {
|
||||
var t = getprop("/sim/time/elapsed-sec");
|
||||
var dt = t - me.last_time;
|
||||
|
@ -173,11 +178,11 @@ var walker = {
|
|||
me.heading = cur.getNode("heading-offset-deg").getValue();
|
||||
|
||||
me.position[0] -=
|
||||
me.speed_fwd * dt * math.cos(me.heading * RAD) +
|
||||
me.speed_side * dt * math.sin(me.heading * RAD);
|
||||
me.speed_fwd * dt * math.cos(me.heading * TO_RAD) +
|
||||
me.speed_side * dt * math.sin(me.heading * TO_RAD);
|
||||
me.position[1] -=
|
||||
me.speed_fwd * dt * math.sin(me.heading * RAD) -
|
||||
me.speed_side * dt * math.cos(me.heading * RAD);
|
||||
me.speed_fwd * dt * math.sin(me.heading * TO_RAD) -
|
||||
me.speed_side * dt * math.cos(me.heading * TO_RAD);
|
||||
|
||||
var cur_height = me.position[2];
|
||||
if (me.constraints != nil) {
|
||||
|
@ -198,19 +203,23 @@ var walker = {
|
|||
cur.getNode("x-offset-m").setValue(me.position[1]);
|
||||
cur.getNode("y-offset-m").setValue(me.position[2]);
|
||||
|
||||
me.last_time = t;
|
||||
},
|
||||
_loop_ : func (id) {
|
||||
if (me.id != id) return;
|
||||
me.update();
|
||||
settimer(func { me._loop_(id); }, 0.0);
|
||||
if (me.managers != nil) {
|
||||
foreach(var m; me.managers) {
|
||||
m.update(me);
|
||||
}
|
||||
}
|
||||
|
||||
me.last_time = t;
|
||||
return 0.0;
|
||||
},
|
||||
};
|
||||
|
||||
###############################################################################
|
||||
# Constraint classes.
|
||||
# Constraint classes. Determines where the view can walk.
|
||||
|
||||
# Assumes that the constraints are convex.
|
||||
# The union of two constraints.
|
||||
# c1, c2 - the constraints : constraint
|
||||
# NOTE: Assumes that the constraints are convex.
|
||||
var unionConstraint = {
|
||||
new : func (c1, c2) {
|
||||
var obj = { parents : [unionConstraint] };
|
||||
|
@ -236,6 +245,7 @@ var unionConstraint = {
|
|||
};
|
||||
|
||||
# Build a unionConstraint hierarchy from a list of constraints.
|
||||
# cs - list of constraints : [constraint]
|
||||
var makeUnionConstraint = func (cs) {
|
||||
if (size(cs) < 2) return cs[0];
|
||||
|
||||
|
@ -247,8 +257,8 @@ var makeUnionConstraint = func (cs) {
|
|||
}
|
||||
|
||||
# Mostly aligned plane sloping along the X axis.
|
||||
# minp - the X,Y minimum point
|
||||
# maxp - the X,Y maximum point
|
||||
# minp - the X,Y minimum point : position (meter)
|
||||
# maxp - the X,Y maximum point : position (meter)
|
||||
var slopingYAlignedPlane = {
|
||||
new : func (minp, maxp) {
|
||||
var obj = { parents : [slopingYAlignedPlane] };
|
||||
|
@ -270,8 +280,8 @@ var slopingYAlignedPlane = {
|
|||
|
||||
# Action constraint
|
||||
# Triggers an action when entering or exiting the constraint.
|
||||
# contraint - the area in question.
|
||||
# on_enter - function that is called when the walker enters the area.
|
||||
# constraint - the area in question : constraint
|
||||
# on_enter() - function that is called when the walker enters the area.
|
||||
# on_exit(x, y) - function that is called when the walker leaves the area.
|
||||
# x and y are <0, 0 or >0 depending on in which direction(s)
|
||||
# the walker left the constraint.
|
||||
|
@ -305,11 +315,49 @@ var actionConstraint = {
|
|||
}
|
||||
};
|
||||
|
||||
###############################################################################
|
||||
# Manager classes.
|
||||
|
||||
# JSBSim pointmass manager.
|
||||
# Moves a pointmass representing the crew member together with the view.
|
||||
# CONSTRUCTOR:
|
||||
# JSBSimPointmass.new(<pointmass index>);
|
||||
#
|
||||
# pointmass index ... The index of the pointmass : int
|
||||
# offsets ... [x, y ,z] position in meter of the origin of the
|
||||
# JSBSim structural frame in the 3d model frame.
|
||||
#
|
||||
# NOTE: Only supports aligned frames (yet).
|
||||
#
|
||||
var JSBSimPointmass = {
|
||||
new : func (index, offsets = nil) {
|
||||
var base = props.globals.getNode("fdm/jsbsim/inertia");
|
||||
var prefix = "pointmass-location-";
|
||||
var postfix = "-inches[" ~ index ~"]";
|
||||
var obj = { parents : [JSBSimPointmass] };
|
||||
obj.pos_ft =
|
||||
[
|
||||
base.getNode(prefix ~ "X" ~ postfix),
|
||||
base.getNode(prefix ~ "Y" ~ postfix),
|
||||
base.getNode(prefix ~ "Z" ~ postfix)
|
||||
];
|
||||
obj.offset = (offsets == nil) ? [0.0, 0.0, 0.0] : offsets;
|
||||
return obj;
|
||||
},
|
||||
update : func (walker) {
|
||||
var pos = walker.get_pos();
|
||||
pos[2] += walker.get_eye_height()/2;
|
||||
forindex (var i; pos) {
|
||||
me.pos_ft[i].setValue((pos[i] - me.offset[i])*M2FT*12);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
###############################################################################
|
||||
# Module implementation below
|
||||
|
||||
var RAD = math.pi/180;
|
||||
var DEG = 180/math.pi;
|
||||
var TO_RAD = math.pi/180;
|
||||
var TO_DEG = 180/math.pi;
|
||||
|
||||
var walkers = {};
|
||||
|
||||
|
|
Loading…
Reference in a new issue