From owner-fgfs-devel@flightgear.org  Thu Sep 23 11:38:24 1999
X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
	["7909" "Thu" "23" "September" "1999" "11:28:17" "-0500" "Stephen J Baker" "sjbaker@hti.com" nil "216" "RE: [FGFS-Devel] 3D Cockpit" "^From:" nil nil "9" nil nil nil nil nil]
	nil)
Received: from mailhub.woodsoup.org (root@anduin.physics.iastate.edu [129.186.82.1])
	by mail.me.umn.edu (8.9.3/8.9.3) with ESMTP id LAA13129
	for <curt@me.umn.edu>; Thu, 23 Sep 1999 11:38:24 -0500 (CDT)
	(envelope-from owner-fgfs-devel@flightgear.org)
Received: from majordom by mailhub.woodsoup.org with local (Exim 1.92 #1)
	for fgfs-devel-outgoing@flightgear.org
	id 11UBsa-00077t-00; Thu, 23 Sep 1999 11:37:56 -0500
Received: from sunmgr.hti.com ([130.210.206.69] helo=issun6.hti.com)
	by mailhub.woodsoup.org with esmtp (Exim 1.92 #1)
	for fgfs-devel@flightgear.org
	id 11UBsY-00077j-00; Thu, 23 Sep 1999 11:37:54 -0500
Received: from issun5.hti.com ([130.210.202.3]) by issun6.hti.com
          (Netscape Messaging Server 3.6)  with ESMTP id AAA39F2
          for <fgfs-devel@flightgear.org>; Thu, 23 Sep 1999 11:37:23 -0500
Received: from sutcliffe.bgm.link.com ([130.210.63.42]) by issun5.hti.com
          (Netscape Messaging Server 3.6)  with SMTP id AAA5387
          for <fgfs-devel@flightgear.org>; Thu, 23 Sep 1999 11:37:22 -0500
X-Sender: steve@sutcliffe.bgm.link.com
In-Reply-To: <000201bf05cd$2494a860$1d02c8c0@JON>
Message-ID: <Pine.SGI.3.96.990923103938.11230A-100000@sutcliffe.bgm.link.com>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
Precedence: bulk
Reply-To: fgfs-devel@flightgear.org
From: "Stephen J Baker" <sjbaker@hti.com>
Sender: owner-fgfs-devel@flightgear.org
To: fgfs-devel@flightgear.org
Subject: RE: [FGFS-Devel] 3D Cockpit
Date: Thu, 23 Sep 1999 11:28:17 -0500 (CDT)

On Thu, 23 Sep 1999, Jon S. Berndt wrote:

> > I vote that we build a "codeless" way to implement basic
> > electro-mechanical/pneumatic instruments - and admit that glass
> > cockpit instruments will require lots of custom code - and probably
> > a special version of FGFS for that aircraft type. (Caveat: we can do
> > glass cockpit instruments that simply emulate electro-mechanical/
> > pneumatic instruments)
> 
> I agree with pretty much all that you said prior to this. But, what do you
> mean, 'codeless'?

I mean that once the system is basically implemented, you would not need
to write any new code to implement a different kind of electro-mechanical/
pneumatic instrument...unless it's something especially weird.

> Do you mean generic? Do you mean an instrument base class
> from which specialized instruments descend and are instantiated based on
> config file parameters and drawn with ssg and a 3D description file?

Almost.  I don't anticipate a need for config file parameters since all
that stuff can be inside the 3D description.

> To me 'codeless' means a binary dll.

Sorry - that's not what I mean at all.

> I still think the best way for FGFS to
> maintain some level of abstraction and generality (and maximum expandability
> and versatility) is a smart class hierarchy (perhaps something like a base
> FGInstrument and from that a single level of inheritance to FGAltimeter,
> FGAirspeed, FGHsi, etc.) drawn by SSG, with specific aircraft-unique
> instrument characteristics given in a config file.
 
I don't think it needs to be so specific.

OK - I'm going to explain this ONE more time...in yet more
detail!

Stop thinking about a total "instrument" for a moment and think about
individual "indicators" - the minute hand of a clock, the numbers in
an odometer, the bubble in a turn/slip indicator.

Each one of those kinds of indicators would be a class - descended
from an SSG node of some kind.  Each indicator would know how to
manipulate the 3D geometry beneath it to display some value.

The simplest would be the "needle".

class fgfsNeedle : public ssgTransform
{
  float modulo ;
  float scale ;
  float offset ;
  float minclamp ;
  float maxclamp ;
  float *data ;

public:

  ....stuff....

  void update ()
  {
    float angle = ( *data % modulo ) * scale + offset ;

    if ( angle < minclamp ) angle = minclamp ;
    if ( angle > maxclamp ) angle = maxclamp ;

    sgCoord c ; sgSetCoord ( &c, 0, 0, 0, 0, 0, angle ) ;

    setTransform ( &c ) ;
  }
} ;

...OK, let's model a clock.  In AC3D (or some other 3D editor),
we make a clock face with all the numbers textured onto it,
and in the middle, we model the two hands of the clock and
make each be an "object" in the modelling tool - perhaps
two white triangles for each hand on the clock. Attached to
each "object", the modeller allows a comment field. We
hijack that for our own uses:

  Short hand:

      @FGFS NEEDLE "time_of_day" M=43200 S=0.833333 O=0

  Long hand:

      @FGFS NEEDLE "time_of_day" M=3600 S=0.1 O=0

OK, we are done. We have "clock.ac" - a complete clock
instrument.  Now we go into the modeller again, and in
the "navion_interior.ac" we cut out a hole in the
dashboard and insert a purple polygon object, which is
the right size and in the right place for the Navions'
clock.  Attached to it's comment field we have:

     @FGFS INSTRUMENT "clock.ac"

The standard ssgLoadAC model loader is invoked to
load up the instrument panel "navion_interior.ac".
The ssgLoadAC function can be told to call an
application-specific function in FGFS whenever it
sees a comment field....so in that function we see
that a comment starting with the magic "@FGFS" string
is present and that there is an instrument here.

We delete the purple polygon (which was only a placeholder
so you could see where the clock would appear while you
were modelling the cockpit interior) - and call the
ssgLoadAC function again to load up "clock.ac".

Once again, we hit two comment fields - one for each hand
of the clock. This time, the "NEEDLE" string tells our
comment parser to change the ssgBranch node that the
loader would have created for that hand of the clock
and to replace it with an fgfsNeedle object (see above).

It also sees that this particular needle is displaying
"time_of_day" - so it searches a table inside FGFS of
variables that the FDM and other FGFS modules will keep
populated with various things that instruments might
care about. There are entries like "oil_pressure_engine_1"
and "altitude" and "indicated_airspeed".

The 'data' member of fgfsNeedle is set to the address of
the table entry that contains the current time of day
in seconds since midnight.

The same routine will set the "modulo" member function
to be 43200 for the short hand and 3600 for the long
hand (43200 is the number of seconds in 12 hours,
3600 is the number of seconds in one hour)...the
"scale" member is similarly set so that the short
hand rotates through 360 degrees over 12 hours and
the long hand through 360 degrees over 1 hour.

Finally, the fgfsNeedle is added to a list of all
the indicators that FGFS has currently loaded.

After that, FGFS calls "fgfsNeedle::update" frequently
enough to rotate each needle at a reasonable rate.
The update routine reads the value of the time of
day, and (in the case of the hour hand) takes the
time of day in seconds, modulo 12 hours, scales
it so that 12 hours==360 degrees of rotation,
and rotates the 3D geometry beneath it to place
the triangles that represent the hand.

The next time the clock is inside our field of
view, SSG will draw it for us.

OK, so we have a clock.  Now, suppose the clock in
a Cessna has a second hand.  All we need to do is
to fire up the old modeller again, hack in another
hand - longer and thinner than the minute hand,
and with a different comment:

      @FGFS NEEDLE "time_of_day" M=60 S=6 O=0

...and save the resulting file as "clock_with_second_hand.ac".
In the "cessna_interior.ac" we add another purple polygon
that points to the new clock model.

Voila!  We added a new kind of clock with no programming
at all.

The same fgfsNeedle class can do any kind of instrument
that has a rotating hand. The exact same code that drives
our clock could do an oil pressure gauge, some parts of
the altimeter, the rate-of-ascent/descent indicator...
whatever.

The hands on the clock don't even have to be white
triangles. You could have ornate brass hands with
angels and vine leaves engraved on them. The fgfsNeedle
class doesn't care - it'll rotate any set of polygons
you place beneath it in the modeller.

All that changes for each instrument is the comments
and 3D geometry in the ".ac" file.

Now, the *real* fgfsNeedle class can be made more
complex with limited rate-of-change, damping,
failure modes, etc.

You'll also need to look at some real aircraft
instruments and look for other common indicators.
Imagine: fgfsSevenSegmentLED - it would work
exactly the same way as the fgfsNeedle except
that instead of rotating a couple triangles around,
it would select between 10 different digits depending
on the result of a similar (*data%modulo)*scale+offset
calculation.

Each digit of the indicator would then be a separate
fgfsSevenSegmentLED.

Now you have built the code for that indicator, you
can use it for the radio frequency dial, some kind
of digital engine temperature readout, etc.

So long as you can break it up into simple indicators,
all complex instruments can use the exact same code.

Steve Baker                (817)619-2657 (Vox/Vox-Mail)
Raytheon Systems Inc.      (817)619-2466 (Fax)
Work: sjbaker@hti.com      http://www.hti.com
Home: sjbaker1@airmail.net http://web2.airmail.net/sjbaker1


--
Please visit the FGFS web page:  http://www.flightgear.org
For help on using this list (especially unsubscribing), send a message to
"fgfs-devel-request@flightgear.org" with a single line of text: "help".

