From 525d2df3ccbf80152492a8632267f228a41ac393 Mon Sep 17 00:00:00 2001 From: curt Date: Tue, 6 May 2003 23:40:43 +0000 Subject: [PATCH] - Moved some property specific code into simgear/props/ - Split out the condition code from fgfs/src/Main/fg_props and put it in it's own source file in simgear/props/ - Created a scene subdirectory for scenery, model, and material property related code. - Moved location.[ch]xx into simgear/scene/model/ - The location and condition code had dependencies on flightgear's global state (all the globals-> stuff, the flightgear property tree, etc.) SimGear code can't depend on it so that data has to be passed as parameters to the functions/methods/constructors. --- configure.ac | 3 + simgear/Makefile.am | 2 + simgear/misc/Makefile.am | 14 +- simgear/misc/commands.cxx | 3 +- simgear/misc/commands.hxx | 2 +- simgear/props/Makefile.am | 24 ++ simgear/props/condition.cxx | 435 +++++++++++++++++++++++++ simgear/props/condition.hxx | 176 ++++++++++ simgear/{misc => props}/props.cxx | 2 +- simgear/{misc => props}/props.hxx | 0 simgear/{misc => props}/props_io.cxx | 2 +- simgear/{misc => props}/props_io.hxx | 2 +- simgear/{misc => props}/props_test.cxx | 0 simgear/scene/Makefile.am | 13 + simgear/scene/model/Makefile.am | 11 + simgear/scene/model/location.cxx | 283 ++++++++++++++++ simgear/scene/model/location.hxx | 187 +++++++++++ 17 files changed, 1145 insertions(+), 14 deletions(-) create mode 100644 simgear/props/Makefile.am create mode 100644 simgear/props/condition.cxx create mode 100644 simgear/props/condition.hxx rename simgear/{misc => props}/props.cxx (99%) rename simgear/{misc => props}/props.hxx (100%) rename simgear/{misc => props}/props_io.cxx (99%) rename simgear/{misc => props}/props_io.hxx (97%) rename simgear/{misc => props}/props_test.cxx (100%) create mode 100644 simgear/scene/Makefile.am create mode 100644 simgear/scene/model/Makefile.am create mode 100644 simgear/scene/model/location.cxx create mode 100644 simgear/scene/model/location.hxx diff --git a/configure.ac b/configure.ac index 7d0e5354..eeab41a4 100644 --- a/configure.ac +++ b/configure.ac @@ -415,7 +415,10 @@ AC_CONFIG_FILES([ \ simgear/math/Makefile \ simgear/metar/Makefile \ simgear/misc/Makefile \ + simgear/props/Makefile \ simgear/route/Makefile \ + simgear/scene/Makefile \ + simgear/scene/model/Makefile \ simgear/screen/Makefile \ simgear/serial/Makefile \ simgear/sky/Makefile \ diff --git a/simgear/Makefile.am b/simgear/Makefile.am index 8a2c435c..ccdcf2bf 100644 --- a/simgear/Makefile.am +++ b/simgear/Makefile.am @@ -23,7 +23,9 @@ SUBDIRS = \ magvar \ math \ $(METAR_DIRS) \ + props \ route \ + scene \ screen \ serial \ sky \ diff --git a/simgear/misc/Makefile.am b/simgear/misc/Makefile.am index 6f4e3828..8c6d70da 100644 --- a/simgear/misc/Makefile.am +++ b/simgear/misc/Makefile.am @@ -5,8 +5,6 @@ lib_LIBRARIES = libsgmisc.a include_HEADERS = \ commands.hxx \ exception.hxx \ - props.hxx \ - props_io.hxx \ sg_path.hxx \ sgstream.hxx \ stopwatch.hxx \ @@ -18,8 +16,6 @@ include_HEADERS = \ libsgmisc_a_SOURCES = \ commands.cxx \ exception.cxx \ - props.cxx \ - props_io.cxx \ sg_path.cxx \ sgstream.cxx \ strutils.cxx \ @@ -27,12 +23,12 @@ libsgmisc_a_SOURCES = \ texcoord.cxx \ zfstream.cxx -noinst_PROGRAMS = props_test tabbed_value_test - -props_test_SOURCES = props_test.cxx -props_test_LDADD = libsgmisc.a ../xml/libsgxml.a ../debug/libsgdebug.a +noinst_PROGRAMS = tabbed_value_test tabbed_value_test_SOURCES = tabbed_values_test.cxx -tabbed_value_test_LDADD = libsgmisc.a ../xml/libsgxml.a ../debug/libsgdebug.a +tabbed_value_test_LDADD = \ + $(top_builddir)/simgear/misc/libsgmisc.a \ + $(top_builddir)/simgear/xml/libsgxml.a \ + $(top_builddir)/simgear/debug/libsgdebug.a INCLUDES = -I$(top_srcdir) diff --git a/simgear/misc/commands.cxx b/simgear/misc/commands.cxx index 88869848..2e2c5921 100644 --- a/simgear/misc/commands.cxx +++ b/simgear/misc/commands.cxx @@ -4,8 +4,9 @@ // // $Id$ +#include + #include "commands.hxx" -#include "props_io.hxx" diff --git a/simgear/misc/commands.hxx b/simgear/misc/commands.hxx index 55f193b4..4ab28a09 100644 --- a/simgear/misc/commands.hxx +++ b/simgear/misc/commands.hxx @@ -17,7 +17,7 @@ #include #include -#include "props.hxx" +#include SG_USING_STD(string); SG_USING_STD(map); diff --git a/simgear/props/Makefile.am b/simgear/props/Makefile.am new file mode 100644 index 00000000..3195e69d --- /dev/null +++ b/simgear/props/Makefile.am @@ -0,0 +1,24 @@ +includedir = @includedir@/props + +lib_LIBRARIES = libsgprops.a + +include_HEADERS = \ + condition.hxx \ + props.hxx \ + props_io.hxx + +libsgprops_a_SOURCES = \ + condition.cxx \ + props.cxx \ + props_io.cxx + +noinst_PROGRAMS = props_test + +props_test_SOURCES = props_test.cxx +props_test_LDADD = \ + $(top_builddir)/simgear/props/libsgprops.a \ + $(top_builddir)/simgear/xml/libsgxml.a \ + $(top_builddir)/simgear/misc/libsgmisc.a \ + $(top_builddir)/simgear/debug/libsgdebug.a + +INCLUDES = -I$(top_srcdir) diff --git a/simgear/props/condition.cxx b/simgear/props/condition.cxx new file mode 100644 index 00000000..d50f461a --- /dev/null +++ b/simgear/props/condition.cxx @@ -0,0 +1,435 @@ +// condition.hxx - Declarations and inline methods for property conditions. +// Written by David Megginson, started 2000. +// CLO May 2003 - Split out condition specific code. +// +// This file is in the Public Domain, and comes with no warranty. +// +// $Id$ + +#ifdef HAVE_CONFIG_H +# include +#endif + +// #include STL_IOSTREAM + +#include + +#include "props.hxx" + +#include "condition.hxx" + +SG_USING_STD(istream); +SG_USING_STD(ostream); + + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGCondition. +//////////////////////////////////////////////////////////////////////// + +FGCondition::FGCondition () +{ +} + +FGCondition::~FGCondition () +{ +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGPropertyCondition. +//////////////////////////////////////////////////////////////////////// + +FGPropertyCondition::FGPropertyCondition ( SGPropertyNode *prop_root, + const char *propname ) + : _node( prop_root->getNode(propname, true) ) +{ + cout << "FGPropertyCondition::FGPropertyCondition()" << endl; + cout << " prop_root = " << prop_root << endl; + cout << " propname = " << propname << endl; + _node = prop_root->getNode(propname, true); + cout << " _node = " << _node << endl; +} + +FGPropertyCondition::~FGPropertyCondition () +{ +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGNotCondition. +//////////////////////////////////////////////////////////////////////// + +FGNotCondition::FGNotCondition (FGCondition * condition) + : _condition(condition) +{ +} + +FGNotCondition::~FGNotCondition () +{ + delete _condition; +} + +bool +FGNotCondition::test () const +{ + return !(_condition->test()); +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGAndCondition. +//////////////////////////////////////////////////////////////////////// + +FGAndCondition::FGAndCondition () +{ +} + +FGAndCondition::~FGAndCondition () +{ + for (unsigned int i = 0; i < _conditions.size(); i++) + delete _conditions[i]; +} + +bool +FGAndCondition::test () const +{ + int nConditions = _conditions.size(); + for (int i = 0; i < nConditions; i++) { + if (!_conditions[i]->test()) + return false; + } + return true; +} + +void +FGAndCondition::addCondition (FGCondition * condition) +{ + _conditions.push_back(condition); +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGOrCondition. +//////////////////////////////////////////////////////////////////////// + +FGOrCondition::FGOrCondition () +{ +} + +FGOrCondition::~FGOrCondition () +{ + for (unsigned int i = 0; i < _conditions.size(); i++) + delete _conditions[i]; +} + +bool +FGOrCondition::test () const +{ + int nConditions = _conditions.size(); + for (int i = 0; i < nConditions; i++) { + if (_conditions[i]->test()) + return true; + } + return false; +} + +void +FGOrCondition::addCondition (FGCondition * condition) +{ + _conditions.push_back(condition); +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGComparisonCondition. +//////////////////////////////////////////////////////////////////////// + +static int +doComparison (const SGPropertyNode * left, const SGPropertyNode *right) +{ + switch (left->getType()) { + case SGPropertyNode::BOOL: { + bool v1 = left->getBoolValue(); + bool v2 = right->getBoolValue(); + if (v1 < v2) + return FGComparisonCondition::LESS_THAN; + else if (v1 > v2) + return FGComparisonCondition::GREATER_THAN; + else + return FGComparisonCondition::EQUALS; + break; + } + case SGPropertyNode::INT: { + int v1 = left->getIntValue(); + int v2 = right->getIntValue(); + if (v1 < v2) + return FGComparisonCondition::LESS_THAN; + else if (v1 > v2) + return FGComparisonCondition::GREATER_THAN; + else + return FGComparisonCondition::EQUALS; + break; + } + case SGPropertyNode::LONG: { + long v1 = left->getLongValue(); + long v2 = right->getLongValue(); + if (v1 < v2) + return FGComparisonCondition::LESS_THAN; + else if (v1 > v2) + return FGComparisonCondition::GREATER_THAN; + else + return FGComparisonCondition::EQUALS; + break; + } + case SGPropertyNode::FLOAT: { + float v1 = left->getFloatValue(); + float v2 = right->getFloatValue(); + if (v1 < v2) + return FGComparisonCondition::LESS_THAN; + else if (v1 > v2) + return FGComparisonCondition::GREATER_THAN; + else + return FGComparisonCondition::EQUALS; + break; + } + case SGPropertyNode::DOUBLE: { + double v1 = left->getDoubleValue(); + double v2 = right->getDoubleValue(); + if (v1 < v2) + return FGComparisonCondition::LESS_THAN; + else if (v1 > v2) + return FGComparisonCondition::GREATER_THAN; + else + return FGComparisonCondition::EQUALS; + break; + } + case SGPropertyNode::STRING: + case SGPropertyNode::NONE: + case SGPropertyNode::UNSPECIFIED: { + string v1 = left->getStringValue(); + string v2 = right->getStringValue(); + if (v1 < v2) + return FGComparisonCondition::LESS_THAN; + else if (v1 > v2) + return FGComparisonCondition::GREATER_THAN; + else + return FGComparisonCondition::EQUALS; + break; + } + } + throw sg_exception("Unrecognized node type"); + return 0; +} + + +FGComparisonCondition::FGComparisonCondition (Type type, bool reverse) + : _type(type), + _reverse(reverse), + _left_property(0), + _right_property(0), + _right_value(0) +{ +} + +FGComparisonCondition::~FGComparisonCondition () +{ + delete _right_value; +} + +bool +FGComparisonCondition::test () const +{ + // Always fail if incompletely specified + if (_left_property == 0 || + (_right_property == 0 && _right_value == 0)) + return false; + + // Get LESS_THAN, EQUALS, or GREATER_THAN + int cmp = + doComparison(_left_property, + (_right_property != 0 ? _right_property : _right_value)); + if (!_reverse) + return (cmp == _type); + else + return (cmp != _type); +} + +void +FGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root, + const char * propname ) +{ + _left_property = prop_root->getNode(propname, true); +} + +void +FGComparisonCondition::setRightProperty( SGPropertyNode *prop_root, + const char * propname ) +{ + delete _right_value; + _right_value = 0; + _right_property = prop_root->getNode(propname, true); +} + +void +FGComparisonCondition::setRightValue (const SGPropertyNode *node) +{ + _right_property = 0; + delete _right_value; + _right_value = new SGPropertyNode(*node); +} + + + +//////////////////////////////////////////////////////////////////////// +// Read a condition and use it if necessary. +//////////////////////////////////////////////////////////////////////// + + // Forward declaration +static FGCondition * readCondition( SGPropertyNode *prop_root, + const SGPropertyNode *node ); + +static FGCondition * +readPropertyCondition( SGPropertyNode *prop_root, + const SGPropertyNode *node ) +{ + return new FGPropertyCondition( prop_root, node->getStringValue() ); +} + +static FGCondition * +readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node ) +{ + int nChildren = node->nChildren(); + for (int i = 0; i < nChildren; i++) { + const SGPropertyNode * child = node->getChild(i); + FGCondition * condition = readCondition(prop_root, child); + if (condition != 0) + return new FGNotCondition(condition); + } + SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition"); + return 0; +} + +static FGCondition * +readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node ) +{ + FGAndCondition * andCondition = new FGAndCondition; + int nChildren = node->nChildren(); + for (int i = 0; i < nChildren; i++) { + const SGPropertyNode * child = node->getChild(i); + FGCondition * condition = readCondition(prop_root, child); + if (condition != 0) + andCondition->addCondition(condition); + } + return andCondition; +} + +static FGCondition * +readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node ) +{ + FGOrCondition * orCondition = new FGOrCondition; + int nChildren = node->nChildren(); + for (int i = 0; i < nChildren; i++) { + const SGPropertyNode * child = node->getChild(i); + FGCondition * condition = readCondition(prop_root, child); + if (condition != 0) + orCondition->addCondition(condition); + } + return orCondition; +} + +static FGCondition * +readComparison( SGPropertyNode *prop_root, + const SGPropertyNode *node, + FGComparisonCondition::Type type, + bool reverse) +{ + FGComparisonCondition * condition = new FGComparisonCondition(type, reverse); + condition->setLeftProperty(prop_root, node->getStringValue("property[0]")); + if (node->hasValue("property[1]")) + condition->setRightProperty(prop_root, node->getStringValue("property[1]")); + else + condition->setRightValue(node->getChild("value", 0)); + + return condition; +} + +static FGCondition * +readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node ) +{ + const string &name = node->getName(); + if (name == "property") + return readPropertyCondition(prop_root, node); + else if (name == "not") + return readNotCondition(prop_root, node); + else if (name == "and") + return readAndConditions(prop_root, node); + else if (name == "or") + return readOrConditions(prop_root, node); + else if (name == "less-than") + return readComparison(prop_root, node, FGComparisonCondition::LESS_THAN, + false); + else if (name == "less-than-equals") + return readComparison(prop_root, node, FGComparisonCondition::GREATER_THAN, + true); + else if (name == "greater-than") + return readComparison(prop_root, node, FGComparisonCondition::GREATER_THAN, + false); + else if (name == "greater-than-equals") + return readComparison(prop_root, node, FGComparisonCondition::LESS_THAN, + true); + else if (name == "equals") + return readComparison(prop_root, node, FGComparisonCondition::EQUALS, + false); + else if (name == "not-equals") + return readComparison(prop_root, node, FGComparisonCondition::EQUALS, true); + else + return 0; +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGConditional. +//////////////////////////////////////////////////////////////////////// + +FGConditional::FGConditional () + : _condition (0) +{ +} + +FGConditional::~FGConditional () +{ + delete _condition; +} + +void +FGConditional::setCondition (FGCondition * condition) +{ + delete _condition; + _condition = condition; +} + +bool +FGConditional::test () const +{ + return ((_condition == 0) || _condition->test()); +} + + + +// The top-level is always an implicit 'and' group +FGCondition * +fgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node ) +{ + return readAndConditions(prop_root, node); +} + + +// end of fg_props.cxx diff --git a/simgear/props/condition.hxx b/simgear/props/condition.hxx new file mode 100644 index 00000000..3da63712 --- /dev/null +++ b/simgear/props/condition.hxx @@ -0,0 +1,176 @@ +// condition.hxx - Declarations and inline methods for property conditions. +// Written by David Megginson, started 2000. +// CLO May 2003 - Split out condition specific code. +// +// This file is in the Public Domain, and comes with no warranty. + +#ifndef __SG_CONDITION_HXX +#define __SG_CONDITION_HXX + +#include +#include +#include + + +//////////////////////////////////////////////////////////////////////// +// Conditions. +//////////////////////////////////////////////////////////////////////// + + +/** + * An encoded condition. + * + * This class encodes a single condition of some sort, possibly + * connected with properties. + * + * This class should migrate to somewhere more general. + */ +class FGCondition +{ +public: + FGCondition (); + virtual ~FGCondition (); + virtual bool test () const = 0; +}; + + +/** + * Condition for a single property. + * + * This condition is true only if the property returns a boolean + * true value. + */ +class FGPropertyCondition : public FGCondition +{ +public: + FGPropertyCondition ( SGPropertyNode *prop_root, + const char * propname ); + virtual ~FGPropertyCondition (); + virtual bool test () const { return _node->getBoolValue(); } +private: + const SGPropertyNode * _node; +}; + + +/** + * Condition for a 'not' operator. + * + * This condition is true only if the child condition is false. + */ +class FGNotCondition : public FGCondition +{ +public: + // transfer pointer ownership + FGNotCondition (FGCondition * condition); + virtual ~FGNotCondition (); + virtual bool test () const; +private: + FGCondition * _condition; +}; + + +/** + * Condition for an 'and' group. + * + * This condition is true only if all of the conditions + * in the group are true. + */ +class FGAndCondition : public FGCondition +{ +public: + FGAndCondition (); + virtual ~FGAndCondition (); + virtual bool test () const; + // transfer pointer ownership + virtual void addCondition (FGCondition * condition); +private: + vector _conditions; +}; + + +/** + * Condition for an 'or' group. + * + * This condition is true if at least one of the conditions in the + * group is true. + */ +class FGOrCondition : public FGCondition +{ +public: + FGOrCondition (); + virtual ~FGOrCondition (); + virtual bool test () const; + // transfer pointer ownership + virtual void addCondition (FGCondition * condition); +private: + vector _conditions; +}; + + +/** + * Abstract base class for property comparison conditions. + */ +class FGComparisonCondition : public FGCondition +{ +public: + enum Type { + LESS_THAN, + GREATER_THAN, + EQUALS + }; + FGComparisonCondition (Type type, bool reverse = false); + virtual ~FGComparisonCondition (); + virtual bool test () const; + virtual void setLeftProperty( SGPropertyNode *prop_root, + const char * propname ); + virtual void setRightProperty( SGPropertyNode *prop_root, + const char * propname ); + // will make a local copy + virtual void setRightValue (const SGPropertyNode * value); +private: + Type _type; + bool _reverse; + const SGPropertyNode * _left_property; + const SGPropertyNode * _right_property; + const SGPropertyNode * _right_value; +}; + + +/** + * Base class for a conditional components. + * + * This class manages the conditions and tests; the component should + * invoke the test() method whenever it needs to decide whether to + * active itself, draw itself, and so on. + */ +class FGConditional +{ +public: + FGConditional (); + virtual ~FGConditional (); + // transfer pointer ownership + virtual void setCondition (FGCondition * condition); + virtual const FGCondition * getCondition () const { return _condition; } + virtual bool test () const; +private: + FGCondition * _condition; +}; + + +/** + * Global function to make a condition out of properties. + * + * The top-level is always an implicit 'and' group, whatever the + * node's name (it should usually be "condition"). + * + * @param node The top-level condition node (usually named "condition"). + * @return A pointer to a newly-allocated condition; it is the + * responsibility of the caller to delete the condition when + * it is no longer needed. + */ +FGCondition * fgReadCondition( SGPropertyNode *prop_root, + const SGPropertyNode *node ); + + +#endif // __SG_CONDITION_HXX + diff --git a/simgear/misc/props.cxx b/simgear/props/props.cxx similarity index 99% rename from simgear/misc/props.cxx rename to simgear/props/props.cxx index 0af19b43..790aa05c 100644 --- a/simgear/misc/props.cxx +++ b/simgear/props/props.cxx @@ -1726,7 +1726,7 @@ SGPropertyNode::getNode (const char * relative_path, bool create) if (result != 0) _path_cache->put(relative_path, result); } - + return result; } diff --git a/simgear/misc/props.hxx b/simgear/props/props.hxx similarity index 100% rename from simgear/misc/props.hxx rename to simgear/props/props.hxx diff --git a/simgear/misc/props_io.cxx b/simgear/props/props_io.cxx similarity index 99% rename from simgear/misc/props_io.cxx rename to simgear/props/props_io.cxx index 36ea2b7e..e808e0b6 100644 --- a/simgear/misc/props_io.cxx +++ b/simgear/props/props_io.cxx @@ -5,9 +5,9 @@ #include #include +#include #include -#include "sg_path.hxx" #include "props.hxx" #include "props_io.hxx" diff --git a/simgear/misc/props_io.hxx b/simgear/props/props_io.hxx similarity index 97% rename from simgear/misc/props_io.hxx rename to simgear/props/props_io.hxx index 83e84c5a..d541e1ce 100644 --- a/simgear/misc/props_io.hxx +++ b/simgear/props/props_io.hxx @@ -13,7 +13,7 @@ #define __PROPS_IO_HXX #include -#include +#include #include diff --git a/simgear/misc/props_test.cxx b/simgear/props/props_test.cxx similarity index 100% rename from simgear/misc/props_test.cxx rename to simgear/props/props_test.cxx diff --git a/simgear/scene/Makefile.am b/simgear/scene/Makefile.am new file mode 100644 index 00000000..494d96c6 --- /dev/null +++ b/simgear/scene/Makefile.am @@ -0,0 +1,13 @@ +includedir = @includedir@/scene + +SUBDIRS = model + +# lib_LIBRARIES = libsgscene.a + +# noinst_HEADERS = + +# include_HEADERS = + +# libsgscene_a_SOURCES = + +INCLUDES = -I$(top_srcdir) diff --git a/simgear/scene/model/Makefile.am b/simgear/scene/model/Makefile.am new file mode 100644 index 00000000..26de102c --- /dev/null +++ b/simgear/scene/model/Makefile.am @@ -0,0 +1,11 @@ +includedir = @includedir@/scene/model + +lib_LIBRARIES = libsgmodel.a + +noinst_HEADERS = + +include_HEADERS = location.hxx + +libsgmodel_a_SOURCES = location.cxx + +INCLUDES = -I$(top_srcdir) diff --git a/simgear/scene/model/location.cxx b/simgear/scene/model/location.cxx new file mode 100644 index 00000000..033cf613 --- /dev/null +++ b/simgear/scene/model/location.cxx @@ -0,0 +1,283 @@ +// location.cxx -- class for determining model location in the flightgear world. +// +// Written by Jim Wilson, David Megginson, started April 2002. +// Based largely on code by Curtis Olson and Norman Vine. +// +// Copyright (C) 2002 Curtis L. Olson - curt@flightgear.org +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ + + +#include + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include + +// #include +// #include "globals.hxx" + +#include "location.hxx" + + +/** + * make model transformation Matrix - based on optimizations by NHV + */ +static void MakeTRANS( sgMat4 dst, const double Theta, + const double Phi, const double Psi, + const sgMat4 UP) +{ + SGfloat cosTheta = (SGfloat) cos(Theta); + SGfloat sinTheta = (SGfloat) sin(Theta); + SGfloat cosPhi = (SGfloat) cos(Phi); + SGfloat sinPhi = (SGfloat) sin(Phi); + SGfloat sinPsi = (SGfloat) sin(Psi) ; + SGfloat cosPsi = (SGfloat) cos(Psi) ; + + sgMat4 tmp; + + tmp[0][0] = cosPhi * cosTheta; + tmp[0][1] = sinPhi * cosPsi + cosPhi * -sinTheta * -sinPsi; + tmp[0][2] = sinPhi * sinPsi + cosPhi * -sinTheta * cosPsi; + + tmp[1][0] = -sinPhi * cosTheta; + tmp[1][1] = cosPhi * cosPsi + -sinPhi * -sinTheta * -sinPsi; + tmp[1][2] = cosPhi * sinPsi + -sinPhi * -sinTheta * cosPsi; + + tmp[2][0] = sinTheta; + tmp[2][1] = cosTheta * -sinPsi; + tmp[2][2] = cosTheta * cosPsi; + + float a = UP[0][0]; + float b = UP[1][0]; + float c = UP[2][0]; + dst[2][0] = a*tmp[0][0] + b*tmp[0][1] + c*tmp[0][2] ; + dst[1][0] = a*tmp[1][0] + b*tmp[1][1] + c*tmp[1][2] ; + dst[0][0] = -(a*tmp[2][0] + b*tmp[2][1] + c*tmp[2][2]) ; + dst[3][0] = SG_ZERO ; + + a = UP[0][1]; + b = UP[1][1]; + c = UP[2][1]; + dst[2][1] = a*tmp[0][0] + b*tmp[0][1] + c*tmp[0][2] ; + dst[1][1] = a*tmp[1][0] + b*tmp[1][1] + c*tmp[1][2] ; + dst[0][1] = -(a*tmp[2][0] + b*tmp[2][1] + c*tmp[2][2]) ; + dst[3][1] = SG_ZERO ; + + a = UP[0][2]; + c = UP[2][2]; + dst[2][2] = a*tmp[0][0] + c*tmp[0][2] ; + dst[1][2] = a*tmp[1][0] + c*tmp[1][2] ; + dst[0][2] = -(a*tmp[2][0] + c*tmp[2][2]) ; + dst[3][2] = SG_ZERO ; + + dst[2][3] = SG_ZERO ; + dst[1][3] = SG_ZERO ; + dst[0][3] = SG_ZERO ; + dst[3][3] = SG_ONE ; + +} + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGLocation. +//////////////////////////////////////////////////////////////////////// + +// Constructor +FGLocation::FGLocation( void ): + _dirty(true), + _lon_deg(0), + _lat_deg(0), + _alt_ft(0), + _roll_deg(0), + _pitch_deg(0), + _heading_deg(0), + _cur_elev_m(0), + _tile_center(0) +{ + sgdZeroVec3(_absolute_view_pos); + sgZeroVec3(_relative_view_pos); + sgZeroVec3(_zero_elev_view_pos); + sgMakeRotMat4( UP, 0.0, 0.0, 0.0 ); + sgMakeRotMat4( TRANS, 0.0, 0.0, 0.0 ); +} + + +// Destructor +FGLocation::~FGLocation( void ) { +} + +void +FGLocation::init () +{ +} + +void +FGLocation::bind () +{ +} + +void +FGLocation::unbind () +{ +} + +void +FGLocation::setPosition (double lon_deg, double lat_deg, double alt_ft) +{ + _dirty = true; + _lon_deg = lon_deg; + _lat_deg = lat_deg; + _alt_ft = alt_ft; +} + +void +FGLocation::setOrientation (double roll_deg, double pitch_deg, double heading_deg) +{ + _dirty = true; + _roll_deg = roll_deg; + _pitch_deg = pitch_deg; + _heading_deg = heading_deg; +} + +double * +FGLocation::get_absolute_view_pos( const Point3D scenery_center ) +{ + if ( _dirty ) { + recalc( scenery_center ); + } + return _absolute_view_pos; +} + +float * +FGLocation::getRelativeViewPos( const Point3D scenery_center ) +{ + if ( _dirty ) { + recalc( scenery_center ); + } + return _relative_view_pos; +} + +float * +FGLocation::getZeroElevViewPos( const Point3D scenery_center ) +{ + if ( _dirty ) { + recalc( scenery_center ); + } + return _zero_elev_view_pos; +} + + +// recalc() is done every time one of the setters is called (making the +// cached data "dirty") on the next "get". It calculates all the outputs +// for viewer. +void +FGLocation::recalc( const Point3D scenery_center ) +{ + + recalcPosition( _lon_deg, _lat_deg, _alt_ft, scenery_center ); + + // Make the world up rotation matrix for eye positioin... + sgMakeRotMat4( UP, _lon_deg, 0.0, -_lat_deg ); + + + // get the world up radial vector from planet center for output + sgSetVec3( _world_up, UP[0][0], UP[0][1], UP[0][2] ); + + // Creat local matrix with current geodetic position. Converting + // the orientation (pitch/roll/heading) to vectors. + MakeTRANS( TRANS, _pitch_deg * SG_DEGREES_TO_RADIANS, + _roll_deg * SG_DEGREES_TO_RADIANS, + -_heading_deg * SG_DEGREES_TO_RADIANS, + UP); + + // Given a vector pointing straight down (-Z), map into onto the + // local plane representing "horizontal". This should give us the + // local direction for moving "south". + sgVec3 minus_z; + sgSetVec3( minus_z, 0.0, 0.0, -1.0 ); + + sgmap_vec_onto_cur_surface_plane(_world_up, _relative_view_pos, minus_z, + _surface_south); + sgNormalizeVec3(_surface_south); + + // now calculate the surface east vector + sgVec3 world_down; + sgNegateVec3(world_down, _world_up); + sgVectorProductVec3(_surface_east, _surface_south, world_down); + + set_clean(); +} + +void +FGLocation::recalcPosition( double lon_deg, double lat_deg, double alt_ft, + const Point3D scenery_center ) const +{ + double sea_level_radius_m; + double lat_geoc_rad; + + + // Convert from geodetic to geocentric + // coordinates. + sgGeodToGeoc(lat_deg * SGD_DEGREES_TO_RADIANS, + alt_ft * SG_FEET_TO_METER, + &sea_level_radius_m, + &lat_geoc_rad); + + // Calculate the cartesian coordinates + // of point directly below at sea level. + // aka Zero Elevation Position + Point3D p = Point3D(lon_deg * SG_DEGREES_TO_RADIANS, + lat_geoc_rad, + sea_level_radius_m); + Point3D tmp = sgPolarToCart3d(p) - _tile_center; + sgSetVec3(_zero_elev_view_pos, tmp[0], tmp[1], tmp[2]); + + // Calculate the absolute view position + // in fgfs coordinates. + // aka Absolute View Position + p.setz(p.radius() + alt_ft * SG_FEET_TO_METER); + tmp = sgPolarToCart3d(p); + sgdSetVec3(_absolute_view_pos, tmp[0], tmp[1], tmp[2]); + + // Calculate the relative view position + // from the scenery center. + // aka Relative View Position + + // FIXME: view position should ONLY be calculated in the viewer... + // Anything else should calculate their own positions relative to the + // viewer's tile_center. + sgdVec3 center; + sgdSetVec3( center, + scenery_center.x(), scenery_center.y(), scenery_center.z() ); + sgdVec3 view_pos; + sgdSubVec3(view_pos, _absolute_view_pos, center); + sgSetVec3(_relative_view_pos, view_pos); + +} + +void +FGLocation::update (int dt) +{ +} diff --git a/simgear/scene/model/location.hxx b/simgear/scene/model/location.hxx new file mode 100644 index 00000000..0cba6378 --- /dev/null +++ b/simgear/scene/model/location.hxx @@ -0,0 +1,187 @@ +// location.hxx -- class for determining model location in the flightgear world. +// +// Written by Jim Wilson, David Megginson, started April 2002. +// +// Copyright (C) 2002 Jim Wilson, David Megginson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ + + +#ifndef _LOCATION_HXX +#define _LOCATION_HXX + + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#include +#include +#include + +#include // plib include + +// #include "fgfs.hxx" + + +// Define a structure containing view information +class FGLocation +{ + +public: + + // Constructor + FGLocation( void ); + + // Destructor + virtual ~FGLocation( void ); + + ////////////////////////////////////////////////////////////////////// + // Part 1: standard FGSubsystem implementation. + ////////////////////////////////////////////////////////////////////// + + virtual void init (); + virtual void bind (); + virtual void unbind (); + void update (int dt); + + + ////////////////////////////////////////////////////////////////////// + // Part 2: user settings. + ////////////////////////////////////////////////////////////////////// + + // Geodetic position of model... + virtual double getLongitude_deg () const { return _lon_deg; } + virtual double getLatitude_deg () const { return _lat_deg; } + virtual double getAltitudeASL_ft () const { return _alt_ft; } + virtual void setPosition (double lon_deg, double lat_deg, double alt_ft); + + + // Reference orientation rotations... + // These are rotations that represent the plane attitude effect on + // the view (in Pilot view). IE The view frustrum rotates as the plane + // turns, pitches, and rolls. + // In model view (lookat/chaseview) these end up changing the angle that + // the eye is looking at the ojbect (ie the model). + // FIXME: the FGModel class should have its own version of these so that + // it can generate it's own model rotations. + virtual double getRoll_deg () const { return _roll_deg; } + virtual double getPitch_deg () const {return _pitch_deg; } + virtual double getHeading_deg () const {return _heading_deg; } + virtual void setOrientation (double roll_deg, double pitch_deg, double heading_deg); + + + ////////////////////////////////////////////////////////////////////// + // Part 3: output vectors and matrices in FlightGear coordinates. + ////////////////////////////////////////////////////////////////////// + + // Vectors and positions... + + // Get zero view_pos + virtual float * get_view_pos() { return _relative_view_pos; } + // Get the absolute view position in fgfs coordinates. + virtual double * get_absolute_view_pos( const Point3D scenery_center ); + // Get zero elev + virtual float * get_zero_elev() { return _zero_elev_view_pos; } + // Get world up vector + virtual float *get_world_up() { return _world_up; } + // Get the relative (to scenery center) view position in fgfs coordinates. + virtual float * getRelativeViewPos( const Point3D scenery_center ); + // Get the absolute zero-elevation view position in fgfs coordinates. + virtual float * getZeroElevViewPos( const Point3D scenery_center ); + // Get surface east vector + virtual float *get_surface_east() { return _surface_east; } + // Get surface south vector + virtual float *get_surface_south() { return _surface_south; } + // Elevation of ground under location (based on scenery output)... + void set_cur_elev_m ( double elev ) { _cur_elev_m = elev; } + inline double get_cur_elev_m () { return _cur_elev_m; } + // Interface to current buckets for use with tilemgr... + void set_tile_center ( Point3D tile_center ) { _tile_center = tile_center; } + inline Point3D get_tile_center () { return _tile_center; } + + // Matrices... + virtual const sgVec4 *getTransformMatrix( const Point3D scenery_center ) { + if ( _dirty ) { + recalc( scenery_center ); + } + return TRANS; + } + virtual const sgVec4 *getCachedTransformMatrix() { return TRANS; } + virtual const sgVec4 *getUpMatrix( const Point3D scenery_center ) { + if ( _dirty ) { + recalc( scenery_center ); + } + return UP; + } + virtual const sgVec4 *getCachedUpMatrix() { return UP; } + + +private: + + ////////////////////////////////////////////////////////////////// + // private data // + ////////////////////////////////////////////////////////////////// + + // flag forcing a recalc of derived view parameters + bool _dirty; + + mutable sgdVec3 _absolute_view_pos; + mutable sgVec3 _relative_view_pos; + mutable sgVec3 _zero_elev_view_pos; + + double _lon_deg; + double _lat_deg; + double _alt_ft; + + double _roll_deg; + double _pitch_deg; + double _heading_deg; + + // elevation of ground under this location... + double _cur_elev_m; + Point3D _tile_center; + + // surface vector heading south + sgVec3 _surface_south; + + // surface vector heading east (used to unambiguously align sky + // with sun) + sgVec3 _surface_east; + + // world up vector (normal to the plane tangent to the earth's + // surface at the spot we are directly above + sgVec3 _world_up; + + // sg versions of our friendly matrices + sgMat4 TRANS, UP; + + ////////////////////////////////////////////////////////////////// + // private functions // + ////////////////////////////////////////////////////////////////// + + void recalc( const Point3D scenery_center ); + void recalcPosition( double lon_deg, double lat_deg, double alt_ft, + const Point3D scenery_center ) const; + + inline void set_dirty() { _dirty = true; } + inline void set_clean() { _dirty = false; } + +}; + + +#endif // _LOCATION_HXX -- 2.39.5