diff --git a/simgear/magvar/magvar.cxx b/simgear/magvar/magvar.cxx index 095c9718..2744e20e 100644 --- a/simgear/magvar/magvar.cxx +++ b/simgear/magvar/magvar.cxx @@ -50,7 +50,7 @@ void SGMagVar::update( double lon, double lat, double alt_m, double jd ) { void SGMagVar::update( const SGGeod& geod, double jd ) { - update(geod.getLongitudeDeg(), geod.getLatitudeDeg(), + update(geod.getLongitudeRad(), geod.getLatitudeRad(), geod.getElevationM(), jd); } @@ -62,3 +62,10 @@ double sgGetMagVar( double lon, double lat, double alt_m, double jd ) { double field[6]; return calc_magvar( lat, lon, alt_m / 1000.0, (long)jd, field ); } + +double sgGetMagVar( const SGGeod& pos, double jd ) +{ + return sgGetMagVar(pos.getLongitudeRad(), pos.getLatitudeRad(), + pos.getElevationM(), jd); +} + diff --git a/simgear/magvar/magvar.hxx b/simgear/magvar/magvar.hxx index 6a97e5ea..605bece7 100644 --- a/simgear/magvar/magvar.hxx +++ b/simgear/magvar/magvar.hxx @@ -103,5 +103,9 @@ public: */ double sgGetMagVar( double lon, double lat, double alt_m, double jd ); +/** + * overload version of the above to take a SGGeod + */ +double sgGetMagVar( const SGGeod& pos, double jd ); #endif // _MAGVAR_HXX diff --git a/simgear/scene/material/Effect.cxx b/simgear/scene/material/Effect.cxx index b4c010f4..787a9ce2 100644 --- a/simgear/scene/material/Effect.cxx +++ b/simgear/scene/material/Effect.cxx @@ -671,6 +671,11 @@ InstallAttributeBuilder textureUnitBuilder("texture-unit"); // Shader key, used both for shaders with relative and absolute names typedef pair ShaderKey; +inline ShaderKey makeShaderKey(SGPropertyNode_ptr& ptr, Shader::Type shaderType) +{ + return ShaderKey(ptr->getStringValue(), shaderType); +} + struct ProgramKey { typedef pair AttribKey; @@ -709,6 +714,7 @@ typedef tr1::unordered_map, boost::hash, ProgramKey::EqualTo> ProgramMap; ProgramMap programMap; +ProgramMap resolvedProgramMap; // map with resolved shader file names typedef tr1::unordered_map, boost::hash > ShaderMap; @@ -767,24 +773,13 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass, PropertyList pFragShaders = prop->getChildren("fragment-shader"); PropertyList pAttributes = prop->getChildren("attribute"); ProgramKey prgKey; - for (PropertyList::iterator itr = pVertShaders.begin(), - e = pVertShaders.end(); - itr != e; - ++itr) - prgKey.shaders.push_back(ShaderKey((*itr)->getStringValue(), - Shader::VERTEX)); - for (PropertyList::iterator itr = pGeomShaders.begin(), - e = pGeomShaders.end(); - itr != e; - ++itr) - prgKey.shaders.push_back(ShaderKey((*itr)->getStringValue(), - Shader::GEOMETRY)); - for (PropertyList::iterator itr = pFragShaders.begin(), - e = pFragShaders.end(); - itr != e; - ++itr) - prgKey.shaders.push_back(ShaderKey((*itr)->getStringValue(), - Shader::FRAGMENT)); + std::back_insert_iterator > inserter(prgKey.shaders); + transform(pVertShaders.begin(), pVertShaders.end(), inserter, + bind(makeShaderKey, _1, Shader::VERTEX)); + transform(pGeomShaders.begin(), pGeomShaders.end(), inserter, + bind(makeShaderKey, _1, Shader::GEOMETRY)); + transform(pFragShaders.begin(), pFragShaders.end(), inserter, + bind(makeShaderKey, _1, Shader::FRAGMENT)); for (PropertyList::iterator itr = pAttributes.begin(), e = pAttributes.end(); itr != e; @@ -805,62 +800,74 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass, ProgramMap::iterator pitr = programMap.find(prgKey); if (pitr != programMap.end()) { program = pitr->second.get(); - } else { - program = new Program; - // Add vertex shaders, then fragment shaders - PropertyList& pvec = pVertShaders; - Shader::Type stype = Shader::VERTEX; - for (int i = 0; i < 3; ++i) { - for (PropertyList::iterator nameItr = pvec.begin(), e = pvec.end(); - nameItr != e; - ++nameItr) { - string shaderName = (*nameItr)->getStringValue(); - string fileName = osgDB::findDataFile(shaderName, options); - if (fileName.empty()) - throw BuilderException(string("couldn't find shader ") + - shaderName); - ShaderKey skey(fileName, stype); - ShaderMap::iterator sitr = shaderMap.find(skey); - if (sitr != shaderMap.end()) { - program->addShader(sitr->second.get()); - } else { - ref_ptr shader = new Shader(stype); - if (shader->loadShaderSourceFromFile(fileName)) { - program->addShader(shader.get()); - shaderMap.insert(ShaderMap::value_type(skey, shader)); - } - } - } - if (i == 0) { - pvec = pGeomShaders; - stype = Shader::GEOMETRY; - } else { - pvec = pFragShaders; - stype = Shader::FRAGMENT; - } - } - BOOST_FOREACH(const ProgramKey::AttribKey& key, prgKey.attributes) { - program->addBindAttribLocation(key.first, key.second); - } - const SGPropertyNode* pGeometryVerticesOut = getEffectPropertyChild(effect, prop, "geometry-vertices-out"); - if ( pGeometryVerticesOut ) { - program->setParameter( GL_GEOMETRY_VERTICES_OUT_EXT, pGeometryVerticesOut->getIntValue() ); - } - const SGPropertyNode* pGeometryInputType = getEffectPropertyChild(effect, prop, "geometry-input-type"); - if ( pGeometryInputType ) { - GLint type; - findAttr( geometryInputType, pGeometryInputType->getStringValue(), type ); - program->setParameter( GL_GEOMETRY_INPUT_TYPE_EXT, type ); - } - const SGPropertyNode* pGeometryOutputType = getEffectPropertyChild(effect, prop, "geometry-output-type"); - if ( pGeometryOutputType ) { - GLint type; - findAttr( geometryOutputType, pGeometryOutputType->getStringValue(), type ); - program->setParameter( GL_GEOMETRY_OUTPUT_TYPE_EXT, type ); - } - - programMap.insert(ProgramMap::value_type(prgKey, program)); + pass->setAttributeAndModes(program); + return; } + // The program wasn't in the map using the load path passed in with + // the options, but it might have already been loaded using a + // different load path i.e., its shaders were found in the fg data + // directory. So, resolve the shaders' file names and look in the + // resolvedProgramMap for a program using those shaders. + ProgramKey resolvedKey; + resolvedKey.attributes = prgKey.attributes; + BOOST_FOREACH(const ShaderKey& shaderKey, prgKey.shaders) + { + const string& shaderName = shaderKey.first; + Shader::Type stype = shaderKey.second; + string fileName = osgDB::findDataFile(shaderName, options); + if (fileName.empty()) + throw BuilderException(string("couldn't find shader ") + + shaderName); + resolvedKey.shaders.push_back(ShaderKey(fileName, stype)); + } + ProgramMap::iterator resitr = resolvedProgramMap.find(resolvedKey); + if (resitr != resolvedProgramMap.end()) { + program = resitr->second.get(); + programMap.insert(ProgramMap::value_type(prgKey, program)); + pass->setAttributeAndModes(program); + return; + } + program = new Program; + BOOST_FOREACH(const ShaderKey& skey, resolvedKey.shaders) + { + const string& fileName = skey.first; + Shader::Type stype = skey.second; + ShaderMap::iterator sitr = shaderMap.find(skey); + if (sitr != shaderMap.end()) { + program->addShader(sitr->second.get()); + } else { + ref_ptr shader = new Shader(stype); + if (shader->loadShaderSourceFromFile(fileName)) { + program->addShader(shader.get()); + shaderMap.insert(ShaderMap::value_type(skey, shader)); + } + } + } + BOOST_FOREACH(const ProgramKey::AttribKey& key, prgKey.attributes) { + program->addBindAttribLocation(key.first, key.second); + } + const SGPropertyNode* pGeometryVerticesOut + = getEffectPropertyChild(effect, prop, "geometry-vertices-out"); + if (pGeometryVerticesOut) + program->setParameter(GL_GEOMETRY_VERTICES_OUT_EXT, + pGeometryVerticesOut->getIntValue()); + const SGPropertyNode* pGeometryInputType + = getEffectPropertyChild(effect, prop, "geometry-input-type"); + if (pGeometryInputType) { + GLint type; + findAttr(geometryInputType, pGeometryInputType->getStringValue(), type); + program->setParameter(GL_GEOMETRY_INPUT_TYPE_EXT, type); + } + const SGPropertyNode* pGeometryOutputType + = getEffectPropertyChild(effect, prop, "geometry-output-type"); + if (pGeometryOutputType) { + GLint type; + findAttr(geometryOutputType, pGeometryOutputType->getStringValue(), + type); + program->setParameter(GL_GEOMETRY_OUTPUT_TYPE_EXT, type); + } + programMap.insert(ProgramMap::value_type(prgKey, program)); + resolvedProgramMap.insert(ProgramMap::value_type(resolvedKey, program)); pass->setAttributeAndModes(program); } diff --git a/simgear/structure/subsystem_mgr.cxx b/simgear/structure/subsystem_mgr.cxx index ee9c15d1..26f026cd 100644 --- a/simgear/structure/subsystem_mgr.cxx +++ b/simgear/structure/subsystem_mgr.cxx @@ -104,7 +104,9 @@ void SGSubsystem::stamp(const string& name) // Implementation of SGSubsystemGroup. //////////////////////////////////////////////////////////////////////// -SGSubsystemGroup::SGSubsystemGroup () +SGSubsystemGroup::SGSubsystemGroup () : + _fixedUpdateTime(-1.0), + _updateTimeRemainder(0.0) { } @@ -157,18 +159,31 @@ SGSubsystemGroup::unbind () void SGSubsystemGroup::update (double delta_time_sec) { - for (unsigned int i = 0; i < _members.size(); i++) - { - SGTimeStamp timeStamp = SGTimeStamp::now(); - _members[i]->update(delta_time_sec); // indirect call - timeStamp = timeStamp - SGTimeStamp::now(); - double b = timeStamp.toUSecs(); - _members[i]->updateExecutionTime(b); - double threshold = _members[i]->getTimeWarningThreshold(); - if (( b > threshold ) && (b > 10000)) { - _members[i]->printTimingInformation(b); - } + int loopCount = 1; + // if dt == 0.0, we are paused, so we need to run one iteration + // of our members; if we have a fixed update time, we compute a + // loop count, and locally adjust dt + if ((delta_time_sec > 0.0) && (_fixedUpdateTime > 0.0)) { + double localDelta = delta_time_sec + _updateTimeRemainder; + loopCount = SGMiscd::roundToInt(localDelta / _fixedUpdateTime); + _updateTimeRemainder = delta_time_sec - (loopCount * _fixedUpdateTime); + delta_time_sec = _fixedUpdateTime; } + + while (loopCount-- > 0) { + for (unsigned int i = 0; i < _members.size(); i++) + { + SGTimeStamp timeStamp = SGTimeStamp::now(); + _members[i]->update(delta_time_sec); // indirect call + timeStamp = timeStamp - SGTimeStamp::now(); + double b = timeStamp.toUSecs(); + _members[i]->updateExecutionTime(b); + double threshold = _members[i]->getTimeWarningThreshold(); + if (( b > threshold ) && (b > 10000)) { + _members[i]->printTimingInformation(b); + } + } + } // of multiple update loop } void @@ -233,6 +248,12 @@ SGSubsystemGroup::remove_subsystem (const string &name) } } +void +SGSubsystemGroup::set_fixed_update_time(double dt) +{ + _fixedUpdateTime = dt; +} + void SGSubsystemGroup::Member::printTimingStatistics () { diff --git a/simgear/structure/subsystem_mgr.hxx b/simgear/structure/subsystem_mgr.hxx index a751d306..87654d9c 100644 --- a/simgear/structure/subsystem_mgr.hxx +++ b/simgear/structure/subsystem_mgr.hxx @@ -317,6 +317,10 @@ public: void collectDebugTiming(bool collect); + /** + * + */ + void set_fixed_update_time(double fixed_dt); private: class Member { @@ -345,6 +349,9 @@ private: Member * get_member (const string &name, bool create = false); vector _members; + + double _fixedUpdateTime; + double _updateTimeRemainder; }; @@ -376,6 +383,7 @@ public: enum GroupType { INIT = 0, GENERAL, + FDM, ///< flight model, autopilot, instruments that run coupled MAX_GROUPS };