2002-02-23 21:20:00 +00:00
|
|
|
|
// model.cxx - manage a 3D aircraft model.
|
|
|
|
|
// Written by David Megginson, started 2002.
|
|
|
|
|
//
|
|
|
|
|
// This file is in the Public Domain, and comes with no warranty.
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
# include <config.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-04-13 13:30:38 +00:00
|
|
|
|
#include <string.h> // for strcmp()
|
2002-03-30 21:24:19 +00:00
|
|
|
|
|
2002-02-23 21:20:00 +00:00
|
|
|
|
#include <plib/sg.h>
|
|
|
|
|
#include <plib/ssg.h>
|
|
|
|
|
|
|
|
|
|
#include <simgear/compiler.h>
|
|
|
|
|
#include <simgear/debug/logstream.hxx>
|
2002-04-20 14:07:34 +00:00
|
|
|
|
#include <simgear/math/interpolater.hxx>
|
2002-04-05 03:19:34 +00:00
|
|
|
|
#include <simgear/math/point3d.hxx>
|
|
|
|
|
#include <simgear/math/sg_geodesy.hxx>
|
2002-02-23 21:20:00 +00:00
|
|
|
|
#include <simgear/misc/exception.hxx>
|
2002-02-25 20:07:34 +00:00
|
|
|
|
#include <simgear/misc/sg_path.hxx>
|
2002-02-23 21:20:00 +00:00
|
|
|
|
|
2002-04-20 14:07:34 +00:00
|
|
|
|
#include <Main/fg_props.hxx>
|
2002-04-05 03:19:34 +00:00
|
|
|
|
#include <Main/globals.hxx>
|
2002-04-11 04:25:30 +00:00
|
|
|
|
#include <Main/location.hxx>
|
2002-04-05 03:19:34 +00:00
|
|
|
|
#include <Scenery/scenery.hxx>
|
2002-02-23 21:20:00 +00:00
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
#include "model.hxx"
|
3D panel support from Andy Ross:
+ The panel(s) are now an first-class SSG node inside the aircraft
scene graph. There's a little code added to model.cxx to handle the
parsing, but most of the changes are inside the new FGPanelNode
class (Model/panelnode.[ch]xx).
+ The old FGPanel source changed a lot, but mostly cosmetically. The
virtual-cockpit code moved out into FGPanelNode, and the core
rendering has been abstracted into a draw() method that doesn't try
to set any OpenGL state. I also replaced the old inter-layer offset
code with glPolygonOffset, as calculating the right Z values is hard
across the funky modelview matrix I need to use. The older virtual
panel code got away with it by disabling depth test, thus the "panel
draws on top of yoke" bug. PolygonOffset is really the appropriate
solution for this sort of task anyway.
+ The /sim/virtual-cockpit property is no more. The 2D panels are
still specified in the -set.xml file, but 3D panels are part of the
model file.
+ You can have as many 3D panels as you like.
Problems:
+ The mouse support isn't ready yet, so the 3D panels still aren't
interactive. Soon to come.
+ Being part of the same scene graph as the model, the 3D panels now
"jitter" in exactly the same way. While this makes the jitter of
the attitude gyro less noticeable, it's still *very* noticeable and
annoying. I looked hard for this, and am at this point convinced
that the problem is with the two orientation computations. We have
one in FGLocation that is used by the model code, and one in
FGViewer that is used at the top of the scene graph. My suspicion
is that they don't agree exactly, so the final orientation matrix is
the right answer plus the difference. I did rule out the FDMs
though. None of them show more than about 0.0001 degree of
orientation change between frames for a stopped aircraft. That's
within an order of magnitude of what you'd expect for the
orientation change due to the rotation of the earth (which we don't
model -- I cite it only as evidence of how small this is); far, far
less than one pixel on the screen.
[and later]
OK, this is fixed by the attached panel.cxx file. What's happened is
that the winding order for the text layer's polygons is wrong, so I
reverse it before drawing. That's largely a hatchet job to make
things work for now, though. We should figure out why the winding
order is wrong for only text layers and fix it. I checked the plib
sources -- they're definitely doing things CCW, as is all the rest of
the panel code.
Odd. I'm also not sure why the 2D panel doesn't care (it works in
both winding orders). But this will allow you to check in working
code, anyway. There's a big comment to this effect in there.
2002-06-28 14:17:40 +00:00
|
|
|
|
#include "panelnode.hxx"
|
2002-02-23 21:20:00 +00:00
|
|
|
|
|
|
|
|
|
|
2002-03-30 21:24:19 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Static utility functions.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2002-03-27 14:52:19 +00:00
|
|
|
|
|
2002-04-01 14:00:08 +00:00
|
|
|
|
/**
|
|
|
|
|
* Locate a named SSG node in a branch.
|
|
|
|
|
*/
|
2002-02-23 21:20:00 +00:00
|
|
|
|
static ssgEntity *
|
2002-03-30 21:24:19 +00:00
|
|
|
|
find_named_node (ssgEntity * node, const char * name)
|
2002-02-23 21:20:00 +00:00
|
|
|
|
{
|
|
|
|
|
char * node_name = node->getName();
|
2002-03-30 21:24:19 +00:00
|
|
|
|
if (node_name != 0 && !strcmp(name, node_name))
|
2002-02-23 21:20:00 +00:00
|
|
|
|
return node;
|
|
|
|
|
else if (node->isAKindOf(ssgTypeBranch())) {
|
|
|
|
|
int nKids = node->getNumKids();
|
|
|
|
|
for (int i = 0; i < nKids; i++) {
|
|
|
|
|
ssgEntity * result =
|
2002-04-13 13:30:38 +00:00
|
|
|
|
find_named_node(((ssgBranch*)node)->getKid(i), name);
|
2002-02-23 21:20:00 +00:00
|
|
|
|
if (result != 0)
|
2002-04-13 13:30:38 +00:00
|
|
|
|
return result;
|
2002-02-23 21:20:00 +00:00
|
|
|
|
}
|
2002-02-24 21:14:38 +00:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
2002-02-23 21:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-30 21:24:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* Splice a branch in between all child nodes and their parents.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
splice_branch (ssgBranch * branch, ssgEntity * child)
|
|
|
|
|
{
|
|
|
|
|
int nParents = child->getNumParents();
|
|
|
|
|
branch->addKid(child);
|
|
|
|
|
for (int i = 0; i < nParents; i++) {
|
|
|
|
|
ssgBranch * parent = child->getParent(i);
|
|
|
|
|
parent->replaceKid(child, branch);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set up the transform matrix for a spin or rotation.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
set_rotation (sgMat4 &matrix, double position_deg,
|
2002-04-13 13:30:38 +00:00
|
|
|
|
sgVec3 ¢er, sgVec3 &axis)
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
|
|
|
|
float temp_angle = -position_deg * 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];
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set up the transform matrix for a translation.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis)
|
|
|
|
|
{
|
|
|
|
|
sgVec3 xyz;
|
|
|
|
|
sgScaleVec3(xyz, axis, position_m);
|
|
|
|
|
sgMakeTransMat4(matrix, xyz);
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
|
2002-06-10 13:20:26 +00:00
|
|
|
|
/**
|
|
|
|
|
* Make an offset matrix from rotations and position offset.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
make_offsets_matrix (sgMat4 * result, double h_rot, double p_rot, double r_rot,
|
|
|
|
|
double x_off, double y_off, double z_off)
|
|
|
|
|
{
|
|
|
|
|
sgMat4 rot_matrix;
|
|
|
|
|
sgMat4 pos_matrix;
|
|
|
|
|
sgMakeRotMat4(rot_matrix, h_rot, p_rot, r_rot);
|
|
|
|
|
sgMakeTransMat4(pos_matrix, x_off, y_off, z_off);
|
|
|
|
|
sgMultMat4(*result, pos_matrix, rot_matrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-04-20 14:07:34 +00:00
|
|
|
|
/**
|
|
|
|
|
* Read an interpolation table from properties.
|
|
|
|
|
*/
|
|
|
|
|
static SGInterpTable *
|
|
|
|
|
read_interpolation_table (const SGPropertyNode * props)
|
|
|
|
|
{
|
|
|
|
|
const SGPropertyNode * table_node = props->getNode("interpolation");
|
|
|
|
|
if (table_node != 0) {
|
|
|
|
|
SGInterpTable * table = new SGInterpTable();
|
2002-05-11 00:59:26 +00:00
|
|
|
|
vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
|
2002-04-20 14:07:34 +00:00
|
|
|
|
for (int i = 0; i < entries.size(); i++)
|
|
|
|
|
table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
|
|
|
|
|
entries[i]->getDoubleValue("dep", 0.0));
|
|
|
|
|
return table;
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-03-30 21:24:19 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2002-04-05 03:19:34 +00:00
|
|
|
|
// Implementation of FG3DModel
|
2002-03-30 21:24:19 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2002-03-27 14:52:19 +00:00
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::FG3DModel ()
|
2002-06-10 13:20:26 +00:00
|
|
|
|
: _model(0)
|
2002-02-23 21:20:00 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::~FG3DModel ()
|
2002-02-23 21:20:00 +00:00
|
|
|
|
{
|
|
|
|
|
// since the nodes are attached to the scene graph, they'll be
|
|
|
|
|
// deleted automatically
|
2002-03-30 21:24:19 +00:00
|
|
|
|
|
2002-04-20 17:07:47 +00:00
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < _animations.size(); i++)
|
|
|
|
|
delete _animations[i];
|
2002-02-23 21:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::init (const string &path)
|
2002-02-23 21:20:00 +00:00
|
|
|
|
{
|
2002-02-27 12:46:38 +00:00
|
|
|
|
SGPropertyNode props;
|
|
|
|
|
|
2002-04-13 13:30:38 +00:00
|
|
|
|
// Load the 3D aircraft object itself
|
2002-03-20 22:40:11 +00:00
|
|
|
|
SGPath xmlpath = globals->get_fg_root();
|
2002-04-05 03:19:34 +00:00
|
|
|
|
SGPath modelpath = path;
|
2002-03-20 22:40:11 +00:00
|
|
|
|
xmlpath.append(modelpath.str());
|
|
|
|
|
|
2002-04-13 13:30:38 +00:00
|
|
|
|
// Check for an XML wrapper
|
2002-03-20 22:40:11 +00:00
|
|
|
|
if (xmlpath.str().substr(xmlpath.str().size() - 4, 4) == ".xml") {
|
|
|
|
|
readProperties(xmlpath.str(), &props);
|
2002-02-27 12:46:38 +00:00
|
|
|
|
if (props.hasValue("/path")) {
|
2002-03-20 22:40:11 +00:00
|
|
|
|
modelpath = modelpath.dir();
|
|
|
|
|
modelpath.append(props.getStringValue("/path"));
|
2002-02-25 20:07:34 +00:00
|
|
|
|
} else {
|
2002-06-19 03:25:40 +00:00
|
|
|
|
if (_model == 0)
|
|
|
|
|
_model = new ssgBranch;
|
2002-02-25 20:07:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-13 13:30:38 +00:00
|
|
|
|
// Assume that textures are in
|
|
|
|
|
// the same location as the XML file.
|
2002-06-19 03:25:40 +00:00
|
|
|
|
if (_model == 0) {
|
|
|
|
|
ssgTexturePath((char *)xmlpath.dir().c_str());
|
|
|
|
|
_model = (ssgBranch *)ssgLoad((char *)modelpath.c_str());
|
|
|
|
|
if (_model == 0)
|
|
|
|
|
throw sg_exception("Failed to load 3D model");
|
|
|
|
|
}
|
2002-02-23 21:20:00 +00:00
|
|
|
|
|
2002-04-13 13:30:38 +00:00
|
|
|
|
// Set up the alignment node
|
2002-02-23 21:20:00 +00:00
|
|
|
|
ssgTransform * align = new ssgTransform;
|
2002-04-20 17:07:47 +00:00
|
|
|
|
align->addKid(_model);
|
2002-02-23 21:20:00 +00:00
|
|
|
|
sgMat4 res_matrix;
|
2002-06-10 13:20:26 +00:00
|
|
|
|
make_offsets_matrix(&res_matrix,
|
|
|
|
|
props.getFloatValue("/offsets/heading-deg", 0.0),
|
|
|
|
|
props.getFloatValue("/offsets/roll-deg", 0.0),
|
|
|
|
|
props.getFloatValue("/offsets/pitch-deg", 0.0),
|
|
|
|
|
props.getFloatValue("/offsets/x-m", 0.0),
|
|
|
|
|
props.getFloatValue("/offsets/y-m", 0.0),
|
|
|
|
|
props.getFloatValue("/offsets/z-m", 0.0));
|
2002-02-23 21:20:00 +00:00
|
|
|
|
align->setTransform(res_matrix);
|
|
|
|
|
|
2002-04-20 17:07:47 +00:00
|
|
|
|
// Load animations
|
2002-05-11 00:59:26 +00:00
|
|
|
|
vector<SGPropertyNode_ptr> animation_nodes = props.getChildren("animation");
|
2002-04-20 17:07:47 +00:00
|
|
|
|
unsigned int i;
|
|
|
|
|
for (i = 0; i < animation_nodes.size(); i++) {
|
2002-05-11 00:59:26 +00:00
|
|
|
|
vector<SGPropertyNode_ptr> name_nodes =
|
2002-04-20 17:07:47 +00:00
|
|
|
|
animation_nodes[i]->getChildren("object-name");
|
|
|
|
|
if (name_nodes.size() < 1) {
|
|
|
|
|
Animation * animation = make_animation(0, animation_nodes[i]);
|
2002-06-19 02:58:06 +00:00
|
|
|
|
if (animation != 0)
|
|
|
|
|
_animations.push_back(animation);
|
2002-04-20 17:07:47 +00:00
|
|
|
|
} else {
|
|
|
|
|
for (unsigned int j = 0; j < name_nodes.size(); j++) {
|
|
|
|
|
Animation * animation =
|
|
|
|
|
make_animation(name_nodes[j]->getStringValue(), animation_nodes[i]);
|
|
|
|
|
if (animation != 0)
|
|
|
|
|
_animations.push_back(animation);
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-06-10 13:20:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
3D panel support from Andy Ross:
+ The panel(s) are now an first-class SSG node inside the aircraft
scene graph. There's a little code added to model.cxx to handle the
parsing, but most of the changes are inside the new FGPanelNode
class (Model/panelnode.[ch]xx).
+ The old FGPanel source changed a lot, but mostly cosmetically. The
virtual-cockpit code moved out into FGPanelNode, and the core
rendering has been abstracted into a draw() method that doesn't try
to set any OpenGL state. I also replaced the old inter-layer offset
code with glPolygonOffset, as calculating the right Z values is hard
across the funky modelview matrix I need to use. The older virtual
panel code got away with it by disabling depth test, thus the "panel
draws on top of yoke" bug. PolygonOffset is really the appropriate
solution for this sort of task anyway.
+ The /sim/virtual-cockpit property is no more. The 2D panels are
still specified in the -set.xml file, but 3D panels are part of the
model file.
+ You can have as many 3D panels as you like.
Problems:
+ The mouse support isn't ready yet, so the 3D panels still aren't
interactive. Soon to come.
+ Being part of the same scene graph as the model, the 3D panels now
"jitter" in exactly the same way. While this makes the jitter of
the attitude gyro less noticeable, it's still *very* noticeable and
annoying. I looked hard for this, and am at this point convinced
that the problem is with the two orientation computations. We have
one in FGLocation that is used by the model code, and one in
FGViewer that is used at the top of the scene graph. My suspicion
is that they don't agree exactly, so the final orientation matrix is
the right answer plus the difference. I did rule out the FDMs
though. None of them show more than about 0.0001 degree of
orientation change between frames for a stopped aircraft. That's
within an order of magnitude of what you'd expect for the
orientation change due to the rotation of the earth (which we don't
model -- I cite it only as evidence of how small this is); far, far
less than one pixel on the screen.
[and later]
OK, this is fixed by the attached panel.cxx file. What's happened is
that the winding order for the text layer's polygons is wrong, so I
reverse it before drawing. That's largely a hatchet job to make
things work for now, though. We should figure out why the winding
order is wrong for only text layers and fix it. I checked the plib
sources -- they're definitely doing things CCW, as is all the rest of
the panel code.
Odd. I'm also not sure why the 2D panel doesn't care (it works in
both winding orders). But this will allow you to check in working
code, anyway. There's a big comment to this effect in there.
2002-06-28 14:17:40 +00:00
|
|
|
|
// Load panels
|
|
|
|
|
vector<SGPropertyNode_ptr> panel_nodes = props.getChildren("panel");
|
|
|
|
|
for (i = 0; i < panel_nodes.size(); i++) {
|
|
|
|
|
printf("Reading a panel in model.cxx\n");
|
|
|
|
|
FGPanelNode * panel = new FGPanelNode(panel_nodes[i]);
|
|
|
|
|
_model->addKid(panel);
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-10 13:20:26 +00:00
|
|
|
|
// Load sub-models
|
|
|
|
|
vector<SGPropertyNode_ptr> model_nodes = props.getChildren("model");
|
|
|
|
|
for (i = 0; i < model_nodes.size(); i++) {
|
|
|
|
|
SGPropertyNode_ptr node = model_nodes[i];
|
|
|
|
|
ssgTransform * align = new ssgTransform;
|
|
|
|
|
sgMat4 res_matrix;
|
|
|
|
|
make_offsets_matrix(&res_matrix,
|
|
|
|
|
node->getFloatValue("offsets/heading-deg", 0.0),
|
|
|
|
|
node->getFloatValue("offsets/roll-deg", 0.0),
|
|
|
|
|
node->getFloatValue("offsets/pitch-deg", 0.0),
|
|
|
|
|
node->getFloatValue("offsets/x-m", 0.0),
|
|
|
|
|
node->getFloatValue("offsets/y-m", 0.0),
|
|
|
|
|
node->getFloatValue("offsets/z-m", 0.0));
|
|
|
|
|
align->setTransform(res_matrix);
|
|
|
|
|
FG3DModel * kid = new FG3DModel;
|
|
|
|
|
kid->init(node->getStringValue("path"));
|
|
|
|
|
align->addKid(kid->getSceneGraph());
|
|
|
|
|
_model->addKid(align);
|
|
|
|
|
_children.push_back(kid);
|
2002-04-20 17:07:47 +00:00
|
|
|
|
}
|
2002-02-23 21:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
void
|
2002-05-11 16:28:50 +00:00
|
|
|
|
FG3DModel::update (double dt)
|
2002-02-23 21:20:00 +00:00
|
|
|
|
{
|
2002-04-13 21:41:51 +00:00
|
|
|
|
unsigned int i;
|
|
|
|
|
|
2002-06-10 13:20:26 +00:00
|
|
|
|
for (i = 0; i < _children.size(); i++)
|
|
|
|
|
_children[i]->update(dt);
|
2002-04-13 21:41:51 +00:00
|
|
|
|
for (i = 0; i < _animations.size(); i++)
|
2002-04-05 03:19:34 +00:00
|
|
|
|
_animations[i]->update(dt);
|
2002-02-26 00:10:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::Animation *
|
|
|
|
|
FG3DModel::make_animation (const char * object_name,
|
2002-04-20 14:07:34 +00:00
|
|
|
|
SGPropertyNode * node)
|
2002-02-26 00:10:06 +00:00
|
|
|
|
{
|
2002-03-30 21:24:19 +00:00
|
|
|
|
Animation * animation = 0;
|
|
|
|
|
const char * type = node->getStringValue("type");
|
|
|
|
|
if (!strcmp("none", type)) {
|
|
|
|
|
animation = new NullAnimation();
|
2002-04-13 12:10:20 +00:00
|
|
|
|
} else if (!strcmp("range", type)) {
|
|
|
|
|
animation = new RangeAnimation();
|
2002-05-03 21:09:14 +00:00
|
|
|
|
} else if (!strcmp("billboard", type)) {
|
|
|
|
|
animation = new BillboardAnimation();
|
2002-04-01 14:00:08 +00:00
|
|
|
|
} else if (!strcmp("select", type)) {
|
|
|
|
|
animation = new SelectAnimation();
|
2002-03-30 21:24:19 +00:00
|
|
|
|
} else if (!strcmp("spin", type)) {
|
|
|
|
|
animation = new SpinAnimation();
|
|
|
|
|
} else if (!strcmp("rotate", type)) {
|
|
|
|
|
animation = new RotateAnimation();
|
|
|
|
|
} else if (!strcmp("translate", type)) {
|
|
|
|
|
animation = new TranslateAnimation();
|
2002-02-27 20:32:24 +00:00
|
|
|
|
} else {
|
2002-03-30 21:24:19 +00:00
|
|
|
|
animation = new NullAnimation();
|
|
|
|
|
SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type);
|
2002-02-27 20:32:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-20 17:07:47 +00:00
|
|
|
|
ssgEntity * object;
|
|
|
|
|
if (object_name != 0) {
|
|
|
|
|
object = find_named_node(_model, object_name);
|
|
|
|
|
if (object == 0) {
|
|
|
|
|
SG_LOG(SG_INPUT, SG_WARN, "Object " << object_name << " not found");
|
|
|
|
|
delete animation;
|
|
|
|
|
animation = 0;
|
|
|
|
|
}
|
2002-02-26 00:10:06 +00:00
|
|
|
|
} else {
|
2002-04-20 17:07:47 +00:00
|
|
|
|
object = _model;
|
2002-02-26 00:10:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-19 02:58:06 +00:00
|
|
|
|
if (animation != 0)
|
|
|
|
|
animation->init(object, node);
|
2002-03-30 21:24:19 +00:00
|
|
|
|
return animation;
|
|
|
|
|
}
|
2002-02-26 00:10:06 +00:00
|
|
|
|
|
|
|
|
|
|
2002-03-30 21:24:19 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2002-04-05 03:19:34 +00:00
|
|
|
|
// Implementation of FG3DModel::Animation
|
2002-03-30 21:24:19 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::Animation::Animation ()
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::Animation::~Animation ()
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2002-04-05 03:19:34 +00:00
|
|
|
|
// Implementation of FG3DModel::NullAnimation
|
2002-03-30 21:24:19 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::NullAnimation::NullAnimation ()
|
2002-04-01 14:00:08 +00:00
|
|
|
|
: _branch(new ssgBranch)
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
2002-02-26 14:30:04 +00:00
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::NullAnimation::~NullAnimation ()
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
2002-04-01 14:00:08 +00:00
|
|
|
|
_branch = 0;
|
2002-03-30 21:24:19 +00:00
|
|
|
|
}
|
2002-02-27 12:46:38 +00:00
|
|
|
|
|
2002-03-30 21:24:19 +00:00
|
|
|
|
void
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::NullAnimation::init (ssgEntity * object,
|
2002-04-13 13:30:38 +00:00
|
|
|
|
SGPropertyNode * props)
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
2002-04-01 14:00:08 +00:00
|
|
|
|
splice_branch(_branch, object);
|
|
|
|
|
_branch->setName(props->getStringValue("name", 0));
|
2002-02-26 00:10:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-05-11 16:28:50 +00:00
|
|
|
|
FG3DModel::NullAnimation::update (double dt)
|
2002-02-26 00:10:06 +00:00
|
|
|
|
{
|
2002-02-23 21:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-25 22:01:13 +00:00
|
|
|
|
|
2002-04-13 12:10:20 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FG3DModel::RangeAnimation
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
FG3DModel::RangeAnimation::RangeAnimation ()
|
|
|
|
|
: _branch(new ssgRangeSelector)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FG3DModel::RangeAnimation::~RangeAnimation ()
|
|
|
|
|
{
|
|
|
|
|
_branch = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FG3DModel::RangeAnimation::init (ssgEntity * object,
|
2002-04-13 13:30:38 +00:00
|
|
|
|
SGPropertyNode * props)
|
2002-04-13 12:10:20 +00:00
|
|
|
|
{
|
|
|
|
|
float ranges[2];
|
|
|
|
|
splice_branch(_branch, object);
|
|
|
|
|
_branch->setName(props->getStringValue("name", 0));
|
|
|
|
|
ranges[0] = props->getFloatValue("min-m", 0);
|
|
|
|
|
ranges[1] = props->getFloatValue("max-m", 5000);
|
|
|
|
|
_branch->setRanges(ranges, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-05-11 16:28:50 +00:00
|
|
|
|
FG3DModel::RangeAnimation::update (double dt)
|
2002-04-13 12:10:20 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-05-03 21:09:14 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FG3DModel::BillboardAnimation
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
FG3DModel::BillboardAnimation::BillboardAnimation ()
|
|
|
|
|
: _branch(0)
|
|
|
|
|
{
|
|
|
|
|
// Note: we cannot allocate the branch until we know whether
|
|
|
|
|
// it can rotate around the x axis as well as the z axis.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FG3DModel::BillboardAnimation::~BillboardAnimation ()
|
|
|
|
|
{
|
|
|
|
|
_branch = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FG3DModel::BillboardAnimation::init (ssgEntity * object,
|
|
|
|
|
SGPropertyNode * props)
|
|
|
|
|
{
|
|
|
|
|
_branch = new ssgCutout(props->getBoolValue("spherical", true));
|
|
|
|
|
splice_branch(_branch, object);
|
|
|
|
|
_branch->setName(props->getStringValue("name", 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-05-11 16:28:50 +00:00
|
|
|
|
FG3DModel::BillboardAnimation::update (double dt)
|
2002-05-03 21:09:14 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-04-01 14:00:08 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2002-04-05 03:19:34 +00:00
|
|
|
|
// Implementation of FG3DModel::SelectAnimation
|
2002-04-01 14:00:08 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::SelectAnimation::SelectAnimation ()
|
2002-04-01 14:00:08 +00:00
|
|
|
|
: _condition(0),
|
|
|
|
|
_selector(new ssgSelector)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::SelectAnimation::~SelectAnimation ()
|
2002-04-01 14:00:08 +00:00
|
|
|
|
{
|
|
|
|
|
delete _condition;
|
|
|
|
|
_selector = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::SelectAnimation::init (ssgEntity * object,
|
2002-04-13 13:30:38 +00:00
|
|
|
|
SGPropertyNode * props)
|
2002-04-01 14:00:08 +00:00
|
|
|
|
{
|
|
|
|
|
splice_branch(_selector, object);
|
|
|
|
|
_selector->setName(props->getStringValue("name", 0));
|
|
|
|
|
SGPropertyNode * node = props->getChild("condition");
|
|
|
|
|
if (node != 0) {
|
|
|
|
|
_condition = fgReadCondition(node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-05-11 16:28:50 +00:00
|
|
|
|
FG3DModel::SelectAnimation::update (double dt)
|
2002-04-01 14:00:08 +00:00
|
|
|
|
{
|
|
|
|
|
if (_condition != 0 && _condition->test())
|
|
|
|
|
_selector->select(0xffff);
|
|
|
|
|
else
|
|
|
|
|
_selector->select(0x0000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-03-25 22:01:13 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2002-04-05 03:19:34 +00:00
|
|
|
|
// Implementation of FG3DModel::SpinAnimation
|
2002-03-25 22:01:13 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::SpinAnimation::SpinAnimation ()
|
2002-03-30 21:24:19 +00:00
|
|
|
|
: _prop(0),
|
|
|
|
|
_factor(0),
|
|
|
|
|
_position_deg(0),
|
|
|
|
|
_transform(new ssgTransform)
|
2002-03-25 22:01:13 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::SpinAnimation::~SpinAnimation ()
|
2002-03-25 22:01:13 +00:00
|
|
|
|
{
|
2002-03-30 21:24:19 +00:00
|
|
|
|
_transform = 0;
|
2002-03-25 22:01:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-02-27 12:46:38 +00:00
|
|
|
|
void
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::SpinAnimation::init (ssgEntity * object,
|
2002-04-13 13:30:38 +00:00
|
|
|
|
SGPropertyNode * props)
|
2002-02-27 12:46:38 +00:00
|
|
|
|
{
|
2002-04-13 13:30:38 +00:00
|
|
|
|
// Splice in the new transform node
|
2002-03-30 21:24:19 +00:00
|
|
|
|
splice_branch(_transform, object);
|
2002-04-01 14:00:08 +00:00
|
|
|
|
_transform->setName(props->getStringValue("name", 0));
|
2002-03-30 21:24:19 +00:00
|
|
|
|
_prop = fgGetNode(props->getStringValue("property", "/null"), true);
|
|
|
|
|
_factor = props->getDoubleValue("factor", 1.0);
|
|
|
|
|
_position_deg = props->getDoubleValue("starting-position-deg", 0);
|
|
|
|
|
_center[0] = props->getFloatValue("center/x-m", 0);
|
|
|
|
|
_center[1] = props->getFloatValue("center/y-m", 0);
|
|
|
|
|
_center[2] = props->getFloatValue("center/z-m", 0);
|
|
|
|
|
_axis[0] = props->getFloatValue("axis/x", 0);
|
|
|
|
|
_axis[1] = props->getFloatValue("axis/y", 0);
|
|
|
|
|
_axis[2] = props->getFloatValue("axis/z", 0);
|
|
|
|
|
sgNormalizeVec3(_axis);
|
|
|
|
|
}
|
2002-02-27 12:46:38 +00:00
|
|
|
|
|
2002-03-30 21:24:19 +00:00
|
|
|
|
void
|
2002-05-11 16:28:50 +00:00
|
|
|
|
FG3DModel::SpinAnimation::update (double dt)
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
2002-05-11 16:28:50 +00:00
|
|
|
|
float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
|
2002-03-30 21:24:19 +00:00
|
|
|
|
_position_deg += (dt * velocity_rpms * 360);
|
|
|
|
|
while (_position_deg < 0)
|
|
|
|
|
_position_deg += 360.0;
|
|
|
|
|
while (_position_deg >= 360.0)
|
|
|
|
|
_position_deg -= 360.0;
|
|
|
|
|
set_rotation(_matrix, _position_deg, _center, _axis);
|
|
|
|
|
_transform->setTransform(_matrix);
|
|
|
|
|
}
|
2002-02-27 12:46:38 +00:00
|
|
|
|
|
|
|
|
|
|
2002-03-30 21:24:19 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2002-04-05 03:19:34 +00:00
|
|
|
|
// Implementation of FG3DModel::RotateAnimation
|
2002-03-30 21:24:19 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::RotateAnimation::RotateAnimation ()
|
2002-03-30 21:24:19 +00:00
|
|
|
|
: _prop(0),
|
|
|
|
|
_offset_deg(0.0),
|
|
|
|
|
_factor(1.0),
|
2002-04-20 14:07:34 +00:00
|
|
|
|
_table(0),
|
2002-03-30 21:24:19 +00:00
|
|
|
|
_has_min(false),
|
|
|
|
|
_min_deg(0.0),
|
|
|
|
|
_has_max(false),
|
|
|
|
|
_max_deg(1.0),
|
|
|
|
|
_position_deg(0.0),
|
|
|
|
|
_transform(new ssgTransform)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::RotateAnimation::~RotateAnimation ()
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
2002-04-20 14:07:34 +00:00
|
|
|
|
delete _table;
|
2002-03-30 21:24:19 +00:00
|
|
|
|
_transform = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::RotateAnimation::init (ssgEntity * object,
|
2002-04-20 14:07:34 +00:00
|
|
|
|
SGPropertyNode * props)
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
2002-04-13 13:30:38 +00:00
|
|
|
|
// Splice in the new transform node
|
2002-03-30 21:24:19 +00:00
|
|
|
|
splice_branch(_transform, object);
|
2002-04-01 14:00:08 +00:00
|
|
|
|
_transform->setName(props->getStringValue("name", 0));
|
2002-03-30 21:24:19 +00:00
|
|
|
|
_prop = fgGetNode(props->getStringValue("property", "/null"), true);
|
|
|
|
|
_offset_deg = props->getDoubleValue("offset-deg", 0.0);
|
|
|
|
|
_factor = props->getDoubleValue("factor", 1.0);
|
2002-04-20 14:07:34 +00:00
|
|
|
|
_table = read_interpolation_table(props);
|
2002-03-30 21:24:19 +00:00
|
|
|
|
if (props->hasValue("min-deg")) {
|
|
|
|
|
_has_min = true;
|
|
|
|
|
_min_deg = props->getDoubleValue("min-deg");
|
|
|
|
|
}
|
|
|
|
|
if (props->hasValue("max-deg")) {
|
|
|
|
|
_has_max = true;
|
|
|
|
|
_max_deg = props->getDoubleValue("max-deg");
|
|
|
|
|
}
|
|
|
|
|
_position_deg = props->getDoubleValue("starting-position-deg", 0);
|
|
|
|
|
_center[0] = props->getFloatValue("center/x-m", 0);
|
|
|
|
|
_center[1] = props->getFloatValue("center/y-m", 0);
|
|
|
|
|
_center[2] = props->getFloatValue("center/z-m", 0);
|
|
|
|
|
_axis[0] = props->getFloatValue("axis/x", 0);
|
|
|
|
|
_axis[1] = props->getFloatValue("axis/y", 0);
|
|
|
|
|
_axis[2] = props->getFloatValue("axis/z", 0);
|
|
|
|
|
sgNormalizeVec3(_axis);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-05-11 16:28:50 +00:00
|
|
|
|
FG3DModel::RotateAnimation::update (double dt)
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
2002-04-20 14:07:34 +00:00
|
|
|
|
if (_table == 0) {
|
|
|
|
|
_position_deg = (_prop->getDoubleValue() + _offset_deg) * _factor;
|
|
|
|
|
if (_has_min && _position_deg < _min_deg)
|
|
|
|
|
_position_deg = _min_deg;
|
|
|
|
|
if (_has_max && _position_deg > _max_deg)
|
|
|
|
|
_position_deg = _max_deg;
|
|
|
|
|
} else {
|
|
|
|
|
_position_deg = _table->interpolate(_prop->getDoubleValue());
|
|
|
|
|
}
|
2002-03-30 21:24:19 +00:00
|
|
|
|
set_rotation(_matrix, _position_deg, _center, _axis);
|
|
|
|
|
_transform->setTransform(_matrix);
|
2002-02-27 12:46:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-30 21:24:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2002-04-05 03:19:34 +00:00
|
|
|
|
// Implementation of FG3DModel::TranslateAnimation
|
2002-03-30 21:24:19 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::TranslateAnimation::TranslateAnimation ()
|
2002-03-30 21:24:19 +00:00
|
|
|
|
: _prop(0),
|
|
|
|
|
_offset_m(0.0),
|
|
|
|
|
_factor(1.0),
|
2002-04-20 14:07:34 +00:00
|
|
|
|
_table(0),
|
2002-03-30 21:24:19 +00:00
|
|
|
|
_has_min(false),
|
|
|
|
|
_min_m(0.0),
|
|
|
|
|
_has_max(false),
|
|
|
|
|
_max_m(1.0),
|
|
|
|
|
_position_m(0.0),
|
|
|
|
|
_transform(new ssgTransform)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::TranslateAnimation::~TranslateAnimation ()
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
2002-04-20 14:07:34 +00:00
|
|
|
|
delete _table;
|
2002-03-30 21:24:19 +00:00
|
|
|
|
_transform = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-04-05 03:19:34 +00:00
|
|
|
|
FG3DModel::TranslateAnimation::init (ssgEntity * object,
|
2002-04-20 14:07:34 +00:00
|
|
|
|
SGPropertyNode * props)
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
2002-04-13 13:30:38 +00:00
|
|
|
|
// Splice in the new transform node
|
2002-03-30 21:24:19 +00:00
|
|
|
|
splice_branch(_transform, object);
|
2002-04-01 14:00:08 +00:00
|
|
|
|
_transform->setName(props->getStringValue("name", 0));
|
2002-03-30 21:24:19 +00:00
|
|
|
|
_prop = fgGetNode(props->getStringValue("property", "/null"), true);
|
|
|
|
|
_offset_m = props->getDoubleValue("offset-m", 0.0);
|
|
|
|
|
_factor = props->getDoubleValue("factor", 1.0);
|
2002-04-20 14:07:34 +00:00
|
|
|
|
_table = read_interpolation_table(props);
|
2002-03-30 21:24:19 +00:00
|
|
|
|
if (props->hasValue("min-m")) {
|
|
|
|
|
_has_min = true;
|
|
|
|
|
_min_m = props->getDoubleValue("min-m");
|
|
|
|
|
}
|
|
|
|
|
if (props->hasValue("max-m")) {
|
|
|
|
|
_has_max = true;
|
|
|
|
|
_max_m = props->getDoubleValue("max-m");
|
|
|
|
|
}
|
|
|
|
|
_position_m = props->getDoubleValue("starting-position-m", 0);
|
|
|
|
|
_axis[0] = props->getFloatValue("axis/x", 0);
|
|
|
|
|
_axis[1] = props->getFloatValue("axis/y", 0);
|
|
|
|
|
_axis[2] = props->getFloatValue("axis/z", 0);
|
|
|
|
|
sgNormalizeVec3(_axis);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-05-11 16:28:50 +00:00
|
|
|
|
FG3DModel::TranslateAnimation::update (double dt)
|
2002-03-30 21:24:19 +00:00
|
|
|
|
{
|
2002-04-20 14:07:34 +00:00
|
|
|
|
if (_table == 0) {
|
|
|
|
|
_position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
|
|
|
|
|
if (_has_min && _position_m < _min_m)
|
|
|
|
|
_position_m = _min_m;
|
|
|
|
|
if (_has_max && _position_m > _max_m)
|
|
|
|
|
_position_m = _max_m;
|
|
|
|
|
} else {
|
|
|
|
|
_position_m = _table->interpolate(_prop->getDoubleValue());
|
|
|
|
|
}
|
2002-03-30 21:24:19 +00:00
|
|
|
|
set_translation(_matrix, _position_m, _axis);
|
|
|
|
|
_transform->setTransform(_matrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-06-10 13:20:26 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGModelPlacement.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
FGModelPlacement::FGModelPlacement ()
|
|
|
|
|
: _model(new FG3DModel),
|
|
|
|
|
_lon_deg(0),
|
|
|
|
|
_lat_deg(0),
|
|
|
|
|
_elev_ft(0),
|
|
|
|
|
_roll_deg(0),
|
|
|
|
|
_pitch_deg(0),
|
|
|
|
|
_heading_deg(0),
|
|
|
|
|
_selector(new ssgSelector),
|
|
|
|
|
_position(new ssgTransform),
|
|
|
|
|
_location(new FGLocation)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGModelPlacement::~FGModelPlacement ()
|
|
|
|
|
{
|
|
|
|
|
delete _model;
|
|
|
|
|
delete _selector;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::init (const string &path)
|
|
|
|
|
{
|
|
|
|
|
_model->init(path);
|
|
|
|
|
_position->addKid(_model->getSceneGraph());
|
|
|
|
|
_selector->addKid(_position);
|
|
|
|
|
_selector->clrTraversalMaskBits(SSGTRAV_HOT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::update (double dt)
|
|
|
|
|
{
|
|
|
|
|
_model->update(dt);
|
|
|
|
|
|
|
|
|
|
_location->setPosition( _lon_deg, _lat_deg, _elev_ft );
|
|
|
|
|
_location->setOrientation( _roll_deg, _pitch_deg, _heading_deg );
|
|
|
|
|
|
|
|
|
|
sgMat4 POS;
|
|
|
|
|
sgCopyMat4(POS, _location->getTransformMatrix());
|
|
|
|
|
|
|
|
|
|
sgVec3 trans;
|
|
|
|
|
sgCopyVec3(trans, _location->get_view_pos());
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < 4; i++) {
|
|
|
|
|
float tmp = POS[i][3];
|
|
|
|
|
for( int j=0; j<3; j++ ) {
|
|
|
|
|
POS[i][j] += (tmp * trans[j]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_position->setTransform(POS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
FGModelPlacement::getVisible () const
|
|
|
|
|
{
|
|
|
|
|
return (_selector->getSelect() != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::setVisible (bool visible)
|
|
|
|
|
{
|
|
|
|
|
_selector->select(visible);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::setLongitudeDeg (double lon_deg)
|
|
|
|
|
{
|
|
|
|
|
_lon_deg = lon_deg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::setLatitudeDeg (double lat_deg)
|
|
|
|
|
{
|
|
|
|
|
_lat_deg = lat_deg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::setElevationFt (double elev_ft)
|
|
|
|
|
{
|
|
|
|
|
_elev_ft = elev_ft;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::setPosition (double lon_deg, double lat_deg, double elev_ft)
|
|
|
|
|
{
|
|
|
|
|
_lon_deg = lon_deg;
|
|
|
|
|
_lat_deg = lat_deg;
|
|
|
|
|
_elev_ft = elev_ft;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::setRollDeg (double roll_deg)
|
|
|
|
|
{
|
|
|
|
|
_roll_deg = roll_deg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::setPitchDeg (double pitch_deg)
|
|
|
|
|
{
|
|
|
|
|
_pitch_deg = pitch_deg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::setHeadingDeg (double heading_deg)
|
|
|
|
|
{
|
|
|
|
|
_heading_deg = heading_deg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGModelPlacement::setOrientation (double roll_deg, double pitch_deg,
|
|
|
|
|
double heading_deg)
|
|
|
|
|
{
|
|
|
|
|
_roll_deg = roll_deg;
|
|
|
|
|
_pitch_deg = pitch_deg;
|
|
|
|
|
_heading_deg = heading_deg;
|
|
|
|
|
}
|
|
|
|
|
|
2002-02-23 21:20:00 +00:00
|
|
|
|
// end of model.cxx
|