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.
|
# 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.
|
# The coordinate system is the same as the main 3d model one.
|
||||||
# X - back, Y - right and Z - up.
|
# X - back, Y - right and Z - up.
|
||||||
|
|
||||||
|
@ -58,10 +58,17 @@ var active_walker = func {
|
||||||
# Class for a moving view.
|
# Class for a moving view.
|
||||||
#
|
#
|
||||||
# CONSTRUCTOR:
|
# CONSTRUCTOR:
|
||||||
# walker.new(<view name>, <constraints>);
|
# walker.new(<view name>, <constraints>, <managers>);
|
||||||
#
|
#
|
||||||
# view name ... The name of the view : string
|
# view name ... The name of the view : string
|
||||||
# constraints ... The movement constraints : constraint hash
|
# 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:
|
# METHODS:
|
||||||
# active() : bool
|
# active() : bool
|
||||||
|
@ -82,7 +89,7 @@ var active_walker = func {
|
||||||
# get_eye_height() : int (meter)
|
# get_eye_height() : int (meter)
|
||||||
#
|
#
|
||||||
# set_constraints(constraints)
|
# set_constraints(constraints)
|
||||||
# get_constraints() : contraint hash
|
# get_constraints() : constraint hash
|
||||||
#
|
#
|
||||||
# EXAMPLE:
|
# EXAMPLE:
|
||||||
# var constraint =
|
# var constraint =
|
||||||
|
@ -95,10 +102,11 @@ var active_walker = func {
|
||||||
# walk view should not have any other view manager.
|
# walk view should not have any other view manager.
|
||||||
#
|
#
|
||||||
var walker = {
|
var walker = {
|
||||||
new : func (view_name, constraints = nil) {
|
new : func (view_name, constraints = nil, managers = nil) {
|
||||||
var obj = { parents : [walker] };
|
var obj = { parents : [walker] };
|
||||||
obj.view = view.views[view.indexof(view_name)];
|
obj.view = view.views[view.indexof(view_name)];
|
||||||
obj.constraints = constraints;
|
obj.constraints = constraints;
|
||||||
|
obj.managers = managers;
|
||||||
obj.position = [
|
obj.position = [
|
||||||
obj.view.getNode("config/z-offset-m").getValue(),
|
obj.view.getNode("config/z-offset-m").getValue(),
|
||||||
obj.view.getNode("config/x-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.view.getNode("config/heading-offset-deg").getValue();
|
||||||
obj.speed_fwd = 0.0;
|
obj.speed_fwd = 0.0;
|
||||||
obj.speed_side = 0.0;
|
obj.speed_side = 0.0;
|
||||||
obj.id = 0;
|
|
||||||
obj.isactive = 0;
|
obj.isactive = 0;
|
||||||
obj.eye_height = 1.60;
|
obj.eye_height = 1.60;
|
||||||
obj.goal_height = obj.position[2] + obj.eye_height;
|
obj.goal_height = obj.position[2] + obj.eye_height;
|
||||||
|
@ -135,7 +142,7 @@ var walker = {
|
||||||
me.position[2] = pos[2];
|
me.position[2] = pos[2];
|
||||||
},
|
},
|
||||||
get_pos : func {
|
get_pos : func {
|
||||||
return me.position;
|
return [me.position[0], me.position[1], me.position[2]];
|
||||||
},
|
},
|
||||||
set_eye_height : func (h) {
|
set_eye_height : func (h) {
|
||||||
me.eye_height = h;
|
me.eye_height = h;
|
||||||
|
@ -157,13 +164,11 @@ var walker = {
|
||||||
me.last_time = getprop("/sim/time/elapsed-sec") - 0.0001;
|
me.last_time = getprop("/sim/time/elapsed-sec") - 0.0001;
|
||||||
me.update();
|
me.update();
|
||||||
me.position[2] = me.goal_height;
|
me.position[2] = me.goal_height;
|
||||||
settimer(func { me._loop_(me.id); }, 0.0);
|
|
||||||
},
|
},
|
||||||
stop : func {
|
stop : func {
|
||||||
me.isactive = 0;
|
me.isactive = 0;
|
||||||
me.id += 1;
|
|
||||||
},
|
},
|
||||||
# Internals.
|
# The update function is called by the view manager when the view is active.
|
||||||
update : func {
|
update : func {
|
||||||
var t = getprop("/sim/time/elapsed-sec");
|
var t = getprop("/sim/time/elapsed-sec");
|
||||||
var dt = t - me.last_time;
|
var dt = t - me.last_time;
|
||||||
|
@ -173,11 +178,11 @@ var walker = {
|
||||||
me.heading = cur.getNode("heading-offset-deg").getValue();
|
me.heading = cur.getNode("heading-offset-deg").getValue();
|
||||||
|
|
||||||
me.position[0] -=
|
me.position[0] -=
|
||||||
me.speed_fwd * dt * math.cos(me.heading * RAD) +
|
me.speed_fwd * dt * math.cos(me.heading * TO_RAD) +
|
||||||
me.speed_side * dt * math.sin(me.heading * RAD);
|
me.speed_side * dt * math.sin(me.heading * TO_RAD);
|
||||||
me.position[1] -=
|
me.position[1] -=
|
||||||
me.speed_fwd * dt * math.sin(me.heading * RAD) -
|
me.speed_fwd * dt * math.sin(me.heading * TO_RAD) -
|
||||||
me.speed_side * dt * math.cos(me.heading * RAD);
|
me.speed_side * dt * math.cos(me.heading * TO_RAD);
|
||||||
|
|
||||||
var cur_height = me.position[2];
|
var cur_height = me.position[2];
|
||||||
if (me.constraints != nil) {
|
if (me.constraints != nil) {
|
||||||
|
@ -198,19 +203,23 @@ var walker = {
|
||||||
cur.getNode("x-offset-m").setValue(me.position[1]);
|
cur.getNode("x-offset-m").setValue(me.position[1]);
|
||||||
cur.getNode("y-offset-m").setValue(me.position[2]);
|
cur.getNode("y-offset-m").setValue(me.position[2]);
|
||||||
|
|
||||||
me.last_time = t;
|
if (me.managers != nil) {
|
||||||
},
|
foreach(var m; me.managers) {
|
||||||
_loop_ : func (id) {
|
m.update(me);
|
||||||
if (me.id != id) return;
|
|
||||||
me.update();
|
|
||||||
settimer(func { me._loop_(id); }, 0.0);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = {
|
var unionConstraint = {
|
||||||
new : func (c1, c2) {
|
new : func (c1, c2) {
|
||||||
var obj = { parents : [unionConstraint] };
|
var obj = { parents : [unionConstraint] };
|
||||||
|
@ -236,6 +245,7 @@ var unionConstraint = {
|
||||||
};
|
};
|
||||||
|
|
||||||
# Build a unionConstraint hierarchy from a list of constraints.
|
# Build a unionConstraint hierarchy from a list of constraints.
|
||||||
|
# cs - list of constraints : [constraint]
|
||||||
var makeUnionConstraint = func (cs) {
|
var makeUnionConstraint = func (cs) {
|
||||||
if (size(cs) < 2) return cs[0];
|
if (size(cs) < 2) return cs[0];
|
||||||
|
|
||||||
|
@ -247,8 +257,8 @@ var makeUnionConstraint = func (cs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Mostly aligned plane sloping along the X axis.
|
# Mostly aligned plane sloping along the X axis.
|
||||||
# minp - the X,Y minimum point
|
# minp - the X,Y minimum point : position (meter)
|
||||||
# maxp - the X,Y maximum point
|
# maxp - the X,Y maximum point : position (meter)
|
||||||
var slopingYAlignedPlane = {
|
var slopingYAlignedPlane = {
|
||||||
new : func (minp, maxp) {
|
new : func (minp, maxp) {
|
||||||
var obj = { parents : [slopingYAlignedPlane] };
|
var obj = { parents : [slopingYAlignedPlane] };
|
||||||
|
@ -270,8 +280,8 @@ var slopingYAlignedPlane = {
|
||||||
|
|
||||||
# Action constraint
|
# Action constraint
|
||||||
# Triggers an action when entering or exiting the constraint.
|
# Triggers an action when entering or exiting the constraint.
|
||||||
# contraint - the area in question.
|
# constraint - the area in question : constraint
|
||||||
# on_enter - function that is called when the walker enters the area.
|
# 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.
|
# 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)
|
# x and y are <0, 0 or >0 depending on in which direction(s)
|
||||||
# the walker left the constraint.
|
# 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
|
# Module implementation below
|
||||||
|
|
||||||
var RAD = math.pi/180;
|
var TO_RAD = math.pi/180;
|
||||||
var DEG = 180/math.pi;
|
var TO_DEG = 180/math.pi;
|
||||||
|
|
||||||
var walkers = {};
|
var walkers = {};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue