1
0
Fork 0

Separated 3D model-handling code from main.cxx out into its own

subsystem, FGAircraftModel.
This commit is contained in:
david 2002-02-23 21:20:00 +00:00
parent a9a30bfd80
commit d61ce30c12
4 changed files with 239 additions and 145 deletions

View file

@ -47,6 +47,7 @@ fgfs_SOURCES = \
fg_props.cxx fg_props.hxx \
fgfs.cxx fgfs.hxx \
globals.cxx globals.hxx \
model.cxx model.hxx \
options.cxx options.hxx \
splash.cxx splash.hxx \
viewer.cxx viewer.hxx \

View file

@ -151,6 +151,7 @@ sgVec3 rway_ols;
#include "splash.hxx"
#include "viewmgr.hxx"
#include "options.hxx"
#include "model.hxx"
#ifdef macintosh
# include <console.h> // -dw- for command line dialog
@ -173,14 +174,6 @@ void fgReshape( int width, int height );
ssgRoot *scene = NULL;
ssgBranch *terrain = NULL;
// aircraft model stuff
ssgSelector *acmodel_selector = NULL;
ssgTransform *acmodel_pos = NULL;
ssgSelector *prop_selector = NULL;
ssgSelector *flaps_selector = NULL;
int acmodel_npropsettings;
int acmodel_proprpms[4][2]; // different propeller settings
ssgRoot *lighting = NULL;
ssgBranch *ground = NULL;
ssgBranch *airport = NULL;
@ -675,57 +668,7 @@ void fgRenderFrame( void ) {
ssgSetNearFar( 0.5f, 120000.0f );
}
if ( globals->get_viewmgr()->get_current() == 0 ) {
// disable aircraft model
acmodel_selector->select(0);
} else {
// enable aircraft model and set up its position and orientation
acmodel_selector->select(1);
FGViewerRPH *pilot_view =
(FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
sgMat4 sgTRANS;
sgMakeTransMat4( sgTRANS, pilot_view->get_view_pos() );
sgVec3 ownship_up;
sgSetVec3( ownship_up, 0.0, 0.0, 1.0);
sgMat4 sgROT;
sgMakeRotMat4( sgROT, -90.0, ownship_up );
// sgMat4 sgTMP;
// sgMat4 sgTUX;
// sgMultMat4( sgTMP, sgROT, pilot_view.VIEW_ROT );
// sgMultMat4( sgTUX, sgTMP, sgTRANS );
// sgTUX = ( sgROT * pilot_view.VIEW_ROT ) * sgTRANS
sgMat4 sgTUX;
sgCopyMat4( sgTUX, sgROT );
sgPostMultMat4( sgTUX, pilot_view->get_VIEW_ROT() );
sgPostMultMat4( sgTUX, sgTRANS );
sgCoord tuxpos;
sgSetCoord( &tuxpos, sgTUX );
acmodel_pos->setTransform( &tuxpos );
// set up moving parts
if (flaps_selector != NULL) {
flaps_selector->select( (globals->get_controls()->get_flaps() > 0.5f) ? 1 : 2 );
}
if (prop_selector != NULL) {
int propsel_mask = 0;
double rpm = fgGetDouble("/engines/engine[0]/rpm");
for (int i = 0; i < acmodel_npropsettings; i++) {
if (rpm >= acmodel_proprpms[i][0] &&
rpm <= acmodel_proprpms[i][1]) {
propsel_mask |= 1 << i;
}
}
prop_selector->select(propsel_mask);
}
}
current_model.update(0); // FIXME: use real delta time
// $$$ begin - added VS Renganthan 17 Oct 2K
fgUpdateDCS();
@ -1621,92 +1564,7 @@ int mainLoop( int argc, char **argv ) {
// ADA
// temporary visible aircraft "own ship"
acmodel_selector = new ssgSelector;
acmodel_pos = new ssgTransform;
ssgEntity *acmodel_obj = NULL;
if (fgGetString("/sim/flight-model") == "ada") {
// ada exteranl aircraft model loading
if( !ship_pos[0]->getKid(0) ) {
// fall back to default
ssgEntity *acmodel_obj = ssgLoad( (char *)"glider.ac" );
if( !acmodel_obj ) {
SG_LOG( SG_GENERAL, SG_ALERT, "FAILED to LOAD an AC model! ..." );
exit(-1);
}
acmodel_pos->addKid( acmodel_obj );
} else {
acmodel_obj = ship_pos[0]->getKid(0);
}
} else {
// default aircraft model loading
// Get the model location, and load textures from the same
// directory. Use an absolute path for the model to avoid
// incompatibilities in different versions of PLIB.
string acmodel_path =
fgGetString("/sim/model/path", "Models/Geometry/glider.ac");
SGPath full_model = globals->get_fg_root();
full_model.append(acmodel_path);
ssgTexturePath( (char *)full_model.dir().c_str() );
acmodel_obj = ssgLoad( (char *)full_model.c_str() );
if( !acmodel_obj ) {
// fall back to default
acmodel_obj = ssgLoad( (char *)"Models/Geometry/glider.ac" );
if( !acmodel_obj ) {
SG_LOG( SG_GENERAL, SG_ALERT, "FAILED to LOAD an AC model! ..." );
exit(-1);
}
}
}
// find moving parts (if this is an MDL model)
flaps_selector = (ssgSelector*)fgFindNode( acmodel_obj, "FLAPS" );
prop_selector = (ssgSelector*)fgFindNode( acmodel_obj, "PROP" );
acmodel_npropsettings = 0;
if (prop_selector != NULL) {
for (ssgEntity* kid = prop_selector->getKid(0); kid != NULL;
kid = prop_selector->getNextKid()) {
int prop_low, prop_high;
if ( sscanf(kid->getName(), "PROP_%d_%d",
&prop_low, &prop_high) == 2 ) {
prop_low = (int)((float)prop_low * (5000.0f / 32767.0f));
prop_high = (int)((float)prop_high * (5000.0f / 32767.0f));
acmodel_proprpms[acmodel_npropsettings][0] = prop_low ;
acmodel_proprpms[acmodel_npropsettings][1] = prop_high;
acmodel_npropsettings++;
SG_LOG( SG_GENERAL, SG_INFO, "PROPELLER SETTING " << prop_low <<
" " << prop_high );
}
}
}
// align the model properly for FGFS
ssgTransform *acmodel_align = new ssgTransform;
acmodel_align->addKid(acmodel_obj);
sgMat4 rot_matrix;
sgMat4 off_matrix;
sgMat4 res_matrix;
float h_rot = fgGetFloat("/sim/model/heading-offset-deg", 0.0);
float p_rot = fgGetFloat("/sim/model/roll-offset-deg", 0.0);
float r_rot = fgGetFloat("/sim/model/pitch-offset-deg", 0.0);
float x_off = fgGetFloat("/sim/model/x-offset-m", 0.0);
float y_off = fgGetFloat("/sim/model/y-offset-m", 0.0);
float z_off = fgGetFloat("/sim/model/z-offset-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);
acmodel_align->setTransform(res_matrix);
acmodel_pos->addKid( acmodel_align );
acmodel_selector->addKid( acmodel_pos );
//ssgFlatten( acmodel_obj );
//ssgStripify( acmodel_selector );
acmodel_selector->clrTraversalMaskBits( SSGTRAV_HOT );
scene->addKid( acmodel_selector );
current_model.init();
#ifdef FG_NETWORK_OLK
// Do the network intialization

191
src/Main/model.cxx Normal file
View file

@ -0,0 +1,191 @@
// 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
#include <plib/sg.h>
#include <plib/ssg.h>
#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/exception.hxx>
#include "globals.hxx"
#include "fg_props.hxx"
#include "viewmgr.hxx"
#include "model.hxx"
extern unsigned long int fgSimTime; // FIXME: this is ugly
extern ssgRoot * scene; // FIXME: from main.cxx
FGAircraftModel current_model; // FIXME: add to globals
static ssgEntity *
find_named_node (ssgEntity * node, const string &name)
{
char * node_name = node->getName();
if (node_name != 0 && name == node_name)
return node;
else if (node->isAKindOf(ssgTypeBranch())) {
int nKids = node->getNumKids();
for (int i = 0; i < nKids; i++) {
ssgEntity * result =
find_named_node(((ssgBranch*)node)->getKid(i), name);
if (result != 0)
return result;
}
return 0;
}
}
FGAircraftModel::FGAircraftModel ()
: _object(0),
_selector(new ssgSelector),
_position(new ssgTransform),
_prop_position(0)
{
}
FGAircraftModel::~FGAircraftModel ()
{
// since the nodes are attached to the scene graph, they'll be
// deleted automatically
}
void
FGAircraftModel::init ()
{
// TODO: optionally load an XML file with a pointer to the 3D object
// and placement and animation info
// Load the 3D aircraft object itself
SGPath path = globals->get_fg_root();
path.append(fgGetString("/sim/model/path", "Models/Geometry/glider.ac"));
ssgTexturePath((char *)path.dir().c_str());
_object = ssgLoad((char *)path.c_str());
if (_object == 0) {
_object = ssgLoad((char *)"Models/Geometry/glider.ac");
if (_object == 0)
throw sg_exception("Failed to load an aircraft model");
}
// Find the propeller
ssgEntity * prop_node = find_named_node(_object, "Propeller");
if (prop_node != 0) {
std::cout << "Found propeller node" << std::endl;
std::cout << "User data is " << int(prop_node->getUserData()) << std::endl;
_prop_position = new ssgTransform;
int nParents = prop_node->getNumParents();
_prop_position->addKid(prop_node);
std::cout << "Found " << nParents << " parent(s)" << std::endl;
for (int i = 0; i < nParents; i++) {
ssgBranch * parent = prop_node->getParent(i);
parent->replaceKid(prop_node, _prop_position);
}
} else {
std::cout << "Did not find propeller node" << std::endl;
}
// Set up the alignment node
ssgTransform * align = new ssgTransform;
align->addKid(_object);
sgMat4 rot_matrix;
sgMat4 off_matrix;
sgMat4 res_matrix;
float h_rot = fgGetFloat("/sim/model/heading-offset-deg", 0.0);
float p_rot = fgGetFloat("/sim/model/roll-offset-deg", 0.0);
float r_rot = fgGetFloat("/sim/model/pitch-offset-deg", 0.0);
float x_off = fgGetFloat("/sim/model/x-offset-m", 0.0);
float y_off = fgGetFloat("/sim/model/y-offset-m", 0.0);
float z_off = fgGetFloat("/sim/model/z-offset-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);
align->setTransform(res_matrix);
// Set up the position node
_position->addKid(align);
// Set up the selector node
_selector->addKid(_position);
_selector->clrTraversalMaskBits(SSGTRAV_HOT);
scene->addKid(_selector);
}
void
FGAircraftModel::bind ()
{
}
void
FGAircraftModel::unbind ()
{
}
void
FGAircraftModel::update (int dt)
{
// START TEMPORARY KLUDGE
static float prop_rotation = 0;
static sgMat4 prop_matrix;
_current_timestamp.stamp();
long ms = (_current_timestamp - _last_timestamp) / 1000;
_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
&& !fgGetBool("/sim/model/enable-interior")) {
_selector->select(false);
} else {
// TODO: use correct alignment in pilot
// view.
_selector->select(true);
FGViewerRPH *pilot_view =
(FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
sgMat4 sgTRANS;
sgMakeTransMat4( sgTRANS, pilot_view->get_view_pos() );
sgVec3 ownship_up;
sgSetVec3( ownship_up, 0.0, 0.0, 1.0);
sgMat4 sgROT;
sgMakeRotMat4( sgROT, -90.0, ownship_up );
sgMat4 sgTUX;
sgCopyMat4( sgTUX, sgROT );
sgPostMultMat4( sgTUX, pilot_view->get_VIEW_ROT() );
sgPostMultMat4( sgTUX, sgTRANS );
sgCoord tuxpos;
sgSetCoord( &tuxpos, sgTUX );
_position->setTransform( &tuxpos );
// START TEMPORARY KLUDGE
if (_prop_position != 0) {
double offset = fgGetDouble("/tmp/offset", -.75);
sgMat4 tmp;
sgMakeTransMat4(prop_matrix, 0, 0, offset);
sgMakeRotMat4(tmp, 0, 0, prop_rotation);
sgPostMultMat4(prop_matrix, tmp);
sgMakeTransMat4(tmp, 0, 0, -offset);
sgPostMultMat4(prop_matrix, tmp);
_prop_position->setTransform(prop_matrix);
}
// END_TEMPORARY KLUDGE
}
}
// end of model.cxx

44
src/Main/model.hxx Normal file
View file

@ -0,0 +1,44 @@
// model.hxx - manage a 3D aircraft model.
// Written by David Megginson, started 2002.
//
// This file is in the Public Domain, and comes with no warranty.
#ifndef __MODEL_HXX
#define __MODEL_HXX 1
#ifndef __cplusplus
# error This library requires C++
#endif
#include "fgfs.hxx"
#include <simgear/timing/timestamp.hxx>
class FGAircraftModel : public FGSubsystem
{
public:
FGAircraftModel ();
virtual ~FGAircraftModel ();
virtual void init ();
virtual void bind ();
virtual void unbind ();
virtual void update (int dt);
private:
ssgEntity * _object;
ssgSelector * _selector;
ssgTransform * _position;
SGTimeStamp _last_timestamp;
SGTimeStamp _current_timestamp;
ssgTransform * _prop_position;
};
extern FGAircraftModel current_model;
#endif // __MODEL_HXX