1
0
Fork 0

Started support for animations. Currently, the only supported type

(other than "none") is "spin", which must be tied to a property giving
a value in RPM.  This gets the DC-3 propellers turning.  The next type
will be "rotation", which will allow the flaps, elevators, ailerons,
and rudders to move (and even gear, eventually).  Later, I'll add
"shift" for sliding things around, and will figure something out for
blinking lights.
This commit is contained in:
david 2002-02-26 00:10:06 +00:00
parent 3d4bec275b
commit fe7fbdf532
2 changed files with 130 additions and 43 deletions

View file

@ -47,10 +47,9 @@ find_named_node (ssgEntity * node, const string &name)
FGAircraftModel::FGAircraftModel () FGAircraftModel::FGAircraftModel ()
: _props(new SGPropertyNode), : _props(new SGPropertyNode),
_object(0), _model(0),
_selector(new ssgSelector), _selector(new ssgSelector),
_position(new ssgTransform), _position(new ssgTransform)
_prop_position(0)
{ {
} }
@ -67,6 +66,8 @@ FGAircraftModel::init ()
// TODO: optionally load an XML file with a pointer to the 3D object // TODO: optionally load an XML file with a pointer to the 3D object
// and placement and animation info // and placement and animation info
SG_LOG(SG_INPUT, SG_INFO, "Initializing aircraft 3D model");
// Load the 3D aircraft object itself // Load the 3D aircraft object itself
SGPath path = globals->get_fg_root(); SGPath path = globals->get_fg_root();
path.append(fgGetString("/sim/model/path", "Models/Geometry/glider.ac")); path.append(fgGetString("/sim/model/path", "Models/Geometry/glider.ac"));
@ -83,28 +84,23 @@ FGAircraftModel::init ()
} }
ssgTexturePath((char *)path.dir().c_str()); ssgTexturePath((char *)path.dir().c_str());
_object = ssgLoad((char *)path.c_str()); _model = ssgLoad((char *)path.c_str());
if (_object == 0) { if (_model == 0) {
_object = ssgLoad((char *)"Models/Geometry/glider.ac"); _model = ssgLoad((char *)"Models/Geometry/glider.ac");
if (_object == 0) if (_model == 0)
throw sg_exception("Failed to load an aircraft model"); throw sg_exception("Failed to load an aircraft model");
} }
// Find the propeller // Load animations
ssgEntity * prop_node = find_named_node(_object, "Propeller"); vector<SGPropertyNode *> animation_nodes =
if (prop_node != 0) { _props->getChildren("animation");
_prop_position = new ssgTransform; for (int i = 0; i < animation_nodes.size(); i++) {
int nParents = prop_node->getNumParents(); _animations.push_back(read_animation(animation_nodes[i]));
_prop_position->addKid(prop_node);
for (int i = 0; i < nParents; i++) {
ssgBranch * parent = prop_node->getParent(i);
parent->replaceKid(prop_node, _prop_position);
}
} }
// Set up the alignment node // Set up the alignment node
ssgTransform * align = new ssgTransform; ssgTransform * align = new ssgTransform;
align->addKid(_object); align->addKid(_model);
sgMat4 rot_matrix; sgMat4 rot_matrix;
sgMat4 off_matrix; sgMat4 off_matrix;
sgMat4 res_matrix; sgMat4 res_matrix;
@ -141,23 +137,16 @@ FGAircraftModel::unbind ()
void void
FGAircraftModel::update (int dt) FGAircraftModel::update (int dt)
{ {
// START TEMPORARY KLUDGE
static float prop_rotation = 0;
static sgMat4 prop_matrix;
_current_timestamp.stamp(); _current_timestamp.stamp();
long ms = (_current_timestamp - _last_timestamp) / 1000; long elapsed_ms = (_current_timestamp - _last_timestamp) / 1000;
_last_timestamp.stamp(); _last_timestamp.stamp();
double rpms = fgGetDouble("/engines/engine[0]/rpm") / 60000.0;
prop_rotation += (ms * rpms * 360);
while (prop_rotation >= 360)
prop_rotation -= 360;
// END TEMPORARY KLUDGE
if (globals->get_viewmgr()->get_current() == 0) { if (globals->get_viewmgr()->get_current() == 0) {
_selector->select(false); _selector->select(false);
} else { } else {
for (int i = 0; i < _animations.size(); i++)
do_animation(_animations[i], elapsed_ms);
_selector->select(true); _selector->select(true);
FGViewerRPH *pilot_view = FGViewerRPH *pilot_view =
(FGViewerRPH *)globals->get_viewmgr()->get_view( 0 ); (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
@ -179,19 +168,88 @@ FGAircraftModel::update (int dt)
sgCoord tuxpos; sgCoord tuxpos;
sgSetCoord( &tuxpos, sgTUX ); sgSetCoord( &tuxpos, sgTUX );
_position->setTransform( &tuxpos ); _position->setTransform( &tuxpos );
}
// START TEMPORARY KLUDGE }
if (_prop_position != 0) {
double offset = -.75; FGAircraftModel::Animation
sgMat4 tmp; FGAircraftModel::read_animation (const SGPropertyNode * node)
sgMakeTransMat4(prop_matrix, 0, 0, offset); {
sgMakeRotMat4(tmp, 0, 0, prop_rotation); Animation animation;
sgPostMultMat4(prop_matrix, tmp);
sgMakeTransMat4(tmp, 0, 0, -offset); // Figure out the animation type
sgPostMultMat4(prop_matrix, tmp); string type_name = node->getStringValue("type");
_prop_position->setTransform(prop_matrix); if (type_name == "spin") {
} SG_LOG(SG_INPUT, SG_INFO, "Reading spin animation");
// END_TEMPORARY KLUDGE animation.type = Animation::Spin;
} else {
animation.type = Animation::None;
SG_LOG(SG_INPUT, SG_ALERT, "Unknown animation type " << type_name);
return animation;
}
// Find the object to be animated
string object_name = node->getStringValue("object-name");
ssgEntity * target = find_named_node(_model, object_name);
if (target != 0) {
SG_LOG(SG_INPUT, SG_INFO, " Target object is " << object_name);
} else {
animation.type = Animation::None;
SG_LOG(SG_INPUT, SG_ALERT, "Object " << object_name
<< " not found in model");
return animation;
}
// Splice a transform node into the tree
animation.transform = new ssgTransform;
int nParents = target->getNumParents();
animation.transform->addKid(target);
for (int i = 0; i < nParents; i++) {
ssgBranch * parent = target->getParent(i);
parent->replaceKid(target, animation.transform);
}
// Get the node
animation.prop =
fgGetNode(node->getStringValue("property", "/null"), true);
// Get the center and axis
animation.center_x = node->getFloatValue("center/x-m", 0);
animation.center_y = node->getFloatValue("center/y-m", 0);
animation.center_z = node->getFloatValue("center/z-m", 0);
animation.axis_x = node->getFloatValue("axis/x", 0);
animation.axis_y = node->getFloatValue("axis/y", 1);
animation.axis_z = node->getFloatValue("axis/z", 0);
return animation;
}
void
FGAircraftModel::do_animation (Animation &animation, long elapsed_ms)
{
switch (animation.type) {
case Animation::None:
return;
case Animation::Spin: {
float velocity_rpms = animation.prop->getDoubleValue() / 60000.0;
animation.position += (elapsed_ms * velocity_rpms * 360);
while (animation.position >= 360)
animation.position -= 360;
sgMakeTransMat4(animation.matrix, -animation.center_x,
-animation.center_y, -animation.center_z);
sgVec3 axis;
sgSetVec3(axis, animation.axis_x, animation.axis_y, animation.axis_z);
sgMat4 tmp;
sgMakeRotMat4(tmp, animation.position, axis);
sgPostMultMat4(animation.matrix, tmp);
sgMakeTransMat4(tmp, animation.center_x,
animation.center_y, animation.center_z);
sgPostMultMat4(animation.matrix, tmp);
animation.transform->setTransform(animation.matrix);
return;
}
default:
return;
} }
} }

View file

@ -10,6 +10,12 @@
# error This library requires C++ # error This library requires C++
#endif #endif
#include <string>
#include <vector>
SG_USING_STD(string);
SG_USING_STD(vector);
#include "fgfs.hxx" #include "fgfs.hxx"
#include <simgear/misc/props.hxx> #include <simgear/misc/props.hxx>
#include <simgear/timing/timestamp.hxx> #include <simgear/timing/timestamp.hxx>
@ -28,15 +34,38 @@ public:
private: private:
struct Animation
{
enum Type {
None,
Spin
};
string name;
Type type;
ssgTransform * transform;
sgMat4 matrix;
SGPropertyNode * prop;
float position;
float center_x;
float center_y;
float center_z;
float axis_x;
float axis_y;
float axis_z;
};
Animation read_animation (const SGPropertyNode * node);
void do_animation (Animation &animation, long elapsed_ms);
SGPropertyNode * _props; SGPropertyNode * _props;
ssgEntity * _object; ssgEntity * _model;
ssgSelector * _selector; ssgSelector * _selector;
ssgTransform * _position; ssgTransform * _position;
SGTimeStamp _last_timestamp; SGTimeStamp _last_timestamp;
SGTimeStamp _current_timestamp; SGTimeStamp _current_timestamp;
ssgTransform * _prop_position; vector<Animation> _animations;
}; };