From b51fb81a1e90d39ee598ab6117de5c4df00ed82e Mon Sep 17 00:00:00 2001 From: david Date: Wed, 27 Feb 2002 12:46:38 +0000 Subject: [PATCH] - added an 'offset' parameter for animations (it's applied before 'factor') - incorporated changes from Norman Vine to avoid expensive matrix operations --- src/Main/model.cxx | 127 ++++++++++++++++++++++++++++----------------- src/Main/model.hxx | 11 ++-- 2 files changed, 84 insertions(+), 54 deletions(-) diff --git a/src/Main/model.cxx b/src/Main/model.cxx index d1b4233f4..4359a2e31 100644 --- a/src/Main/model.cxx +++ b/src/Main/model.cxx @@ -46,8 +46,7 @@ find_named_node (ssgEntity * node, const string &name) } FGAircraftModel::FGAircraftModel () - : _props(new SGPropertyNode), - _model(0), + : _model(0), _selector(new ssgSelector), _position(new ssgTransform) { @@ -55,7 +54,6 @@ FGAircraftModel::FGAircraftModel () FGAircraftModel::~FGAircraftModel () { - delete _props; // since the nodes are attached to the scene graph, they'll be // deleted automatically } @@ -66,6 +64,8 @@ FGAircraftModel::init () // TODO: optionally load an XML file with a pointer to the 3D object // and placement and animation info + SGPropertyNode props; + SG_LOG(SG_INPUT, SG_INFO, "Initializing aircraft 3D model"); // Load the 3D aircraft object itself @@ -73,10 +73,10 @@ FGAircraftModel::init () path.append(fgGetString("/sim/model/path", "Models/Geometry/glider.ac")); if (path.str().substr(path.str().size() - 4, 4) == ".xml") { - readProperties(path.str(), _props); - if (_props->hasValue("/path")) { + readProperties(path.str(), &props); + if (props.hasValue("/path")) { path = path.dir();; - path.append(_props->getStringValue("/path")); + path.append(props.getStringValue("/path")); } else { path = globals->get_fg_root(); path.append("Models/Geometry/glider.ac"); @@ -93,7 +93,7 @@ FGAircraftModel::init () // Load animations vector animation_nodes = - _props->getChildren("animation"); + props.getChildren("animation"); for (int i = 0; i < animation_nodes.size(); i++) { _animations.push_back(read_animation(animation_nodes[i])); } @@ -104,12 +104,12 @@ FGAircraftModel::init () sgMat4 rot_matrix; sgMat4 off_matrix; sgMat4 res_matrix; - float h_rot = _props->getFloatValue("/offsets/heading-deg", 0.0); - float p_rot = _props->getFloatValue("/offsets/roll-deg", 0.0); - float r_rot = _props->getFloatValue("/offsets/pitch-deg", 0.0); - float x_off = _props->getFloatValue("/offsets/x-m", 0.0); - float y_off = _props->getFloatValue("/offsets/y-m", 0.0); - float z_off = _props->getFloatValue("/offsets/z-m", 0.0); + float h_rot = props.getFloatValue("/offsets/heading-deg", 0.0); + float p_rot = props.getFloatValue("/offsets/roll-deg", 0.0); + float r_rot = props.getFloatValue("/offsets/pitch-deg", 0.0); + float x_off = props.getFloatValue("/offsets/x-m", 0.0); + float y_off = props.getFloatValue("/offsets/y-m", 0.0); + float z_off = props.getFloatValue("/offsets/z-m", 0.0); sgMakeRotMat4(rot_matrix, h_rot, p_rot, r_rot); sgMakeTransMat4(off_matrix, x_off, y_off, z_off); sgMultMat4(res_matrix, off_matrix, rot_matrix); @@ -221,15 +221,18 @@ FGAircraftModel::read_animation (const SGPropertyNode * node) fgGetNode(node->getStringValue("property", "/null"), true); animation.position = node->getFloatValue("initial-position", 0); + animation.offset = node->getFloatValue("offset", 0); animation.factor = node->getFloatValue("factor", 1); // 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); + animation.center[0] = node->getFloatValue("center/x-m", 0); + animation.center[1] = node->getFloatValue("center/y-m", 0); + animation.center[2] = node->getFloatValue("center/z-m", 0); + animation.axis[0] = node->getFloatValue("axis/x", 0); + animation.axis[1] = node->getFloatValue("axis/y", 1); + animation.axis[2] = node->getFloatValue("axis/z", 0); + + sgNormalizeVec3(animation.axis); return animation; } @@ -240,38 +243,19 @@ FGAircraftModel::do_animation (Animation &animation, long elapsed_ms) switch (animation.type) { case Animation::None: return; - case Animation::Spin: { - float velocity_rpms = animation.prop->getDoubleValue() - * animation.factor / 60000.0; + case Animation::Spin: + { + float velocity_rpms = (animation.prop->getDoubleValue() + * animation.factor / 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); + animation.setRotation(); return; } case Animation::Rotate: { - animation.position = animation.prop->getFloatValue() * animation.factor; - 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); + animation.position = ((animation.prop->getFloatValue() + + animation.offset) + * animation.factor); + animation.setRotation(); return; } default: @@ -279,4 +263,53 @@ FGAircraftModel::do_animation (Animation &animation, long elapsed_ms) } } +/* + * Transform to rotate an object around its local axis + * from a relative frame of reference at center -- NHV + */ +void +FGAircraftModel::Animation::setRotation() +{ + float temp_angle = -position * SG_DEGREES_TO_RADIANS ; + + float s = (float) sin ( temp_angle ) ; + float c = (float) cos ( temp_angle ) ; + float t = SG_ONE - c ; + + // axis was normalized at load time + // hint to the compiler to put these into FP registers + float x = axis[0]; + float y = axis[1]; + float z = axis[2]; + + sgMat4 matrix; + matrix[0][0] = t * x * x + c ; + matrix[0][1] = t * y * x - s * z ; + matrix[0][2] = t * z * x + s * y ; + matrix[0][3] = SG_ZERO; + + matrix[1][0] = t * x * y + s * z ; + matrix[1][1] = t * y * y + c ; + matrix[1][2] = t * z * y - s * x ; + matrix[1][3] = SG_ZERO; + + matrix[2][0] = t * x * z - s * y ; + matrix[2][1] = t * y * z + s * x ; + matrix[2][2] = t * z * z + c ; + matrix[2][3] = SG_ZERO; + + // hint to the compiler to put these into FP registers + x = center[0]; + y = center[1]; + z = center[2]; + + matrix[3][0] = x - x*matrix[0][0] - y*matrix[1][0] - z*matrix[2][0]; + matrix[3][1] = y - x*matrix[0][1] - y*matrix[1][1] - z*matrix[2][1]; + matrix[3][2] = z - x*matrix[0][2] - y*matrix[1][2] - z*matrix[2][2]; + matrix[3][3] = SG_ONE; + + transform->setTransform(matrix); +} + + // end of model.cxx diff --git a/src/Main/model.hxx b/src/Main/model.hxx index 651462a3e..60e2c398d 100644 --- a/src/Main/model.hxx +++ b/src/Main/model.hxx @@ -47,19 +47,16 @@ private: sgMat4 matrix; SGPropertyNode * prop; float factor; + float offset; float position; - float center_x; - float center_y; - float center_z; - float axis_x; - float axis_y; - float axis_z; + sgVec3 center; + sgVec3 axis; + void setRotation (); }; Animation read_animation (const SGPropertyNode * node); void do_animation (Animation &animation, long elapsed_ms); - SGPropertyNode * _props; ssgEntity * _model; ssgSelector * _selector; ssgTransform * _position;