From 83b414482f9b1f74939221469fefc9b8b48e54d7 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 31 Jul 2005 09:04:18 +0000 Subject: [PATCH] Harald JOHNSEN: I did some profiling of the code and found a few interessant things. Some corrections are obvious like the one in the multiplayer code, the fps is no more divided by 2 or 3 when another plane is on screen. Other things like collision detection and computation of agl can not really be optimized. I changed a few things in hitlist.cxx but this only give a very low increase of fps. The groundcache eats a lot of cpu but I think that the real way to do it is to use a real collision system like OPCODE or something like that. And I added an option to disable the recording of replay data. It takes more cpu than we can think. Changes ======= - panel.cxx : moved the computation of the instruments diffuse color outside the texturelayer code since this is constant during a frame, this is a big speedup for 2D panels ; - hitlist.cxx : changed the computation of the intersection between ray and triangle, optimized the sphere culling by using a normalized direction vector. This can give a 35% speedup on the computation of elevation in some situations ; - renderer.cxx, acmodel.cxx : call ssgDrawAndCull with plane scene graph in external or internal view, calling ssgDrawAndCull with the root scene graph was drawing other players plane a second time in multiplayer mode ; - mplayer.cxx : removed the calls to ssgFlatten and ssgStripify because it was degenerating models, causing a massive drop in frame rate ; - replay.cxx : added an option to disable the recording of the flight - fgclouds.cxx : changed the path of cloudlayer properties to match preferences.xml ; set the altitude of clouds from scenarios to a more correct value if metar is not enabled ; --- src/Environment/fgclouds.cxx | 12 ++-- src/Main/renderer.cxx | 14 +---- src/Model/acmodel.cxx | 5 ++ src/MultiPlayer/mpplayer.cxx | 6 +- src/Replay/replay.cxx | 7 ++- src/Replay/replay.hxx | 1 + src/Scenery/hitlist.cxx | 109 ++++++++++++++++++++++++++++++++--- 7 files changed, 124 insertions(+), 30 deletions(-) diff --git a/src/Environment/fgclouds.cxx b/src/Environment/fgclouds.cxx index b61a55101..044fb885f 100644 --- a/src/Environment/fgclouds.cxx +++ b/src/Environment/fgclouds.cxx @@ -108,8 +108,8 @@ void FGClouds::buildLayer(SGCloudField *layer, string name, double alt, double c int CloudVarietyCount = 0; double totalCount = 0.0; - SGPropertyNode *cloud_def_root = fgGetNode("/environment/config/cloudlayers/clouds", false); - SGPropertyNode *layer_def_root = fgGetNode("/environment/config/cloudlayers/layers", false); + SGPropertyNode *cloud_def_root = fgGetNode("/environment/cloudlayers/clouds", false); + SGPropertyNode *layer_def_root = fgGetNode("/environment/cloudlayers/layers", false); layer->clear(); // when we don't generate clouds the layer is rendered in 2D @@ -395,8 +395,12 @@ void FGClouds::buildScenario( string scenario ) { string station = fgGetString("/environment/metar/station-id", "XXXX"); // fetch station elevation if exists - FGAirport a = globals->get_airports()->search( station ); - station_elevation_ft = a.getElevation(); + if( station == "XXXX" ) + station_elevation_ft = fgGetDouble("/position/ground-elev-m", 0.0); + else { + FGAirport a = globals->get_airports()->search( station ); + station_elevation_ft = a.getElevation(); + } for(int iLayer = 0 ; iLayer < thesky->get_cloud_layer_count(); iLayer++) { thesky->get_cloud_layer(iLayer)->get_layer3D()->clear(); diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index fe79a0425..05b85037b 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -383,7 +383,7 @@ FGRenderer::update( bool refresh_camera_settings ) { */ static SGSkyColor scolor; - FGLight *l = (FGLight *)(globals->get_subsystem("lighting")); +// FGLight *l = (FGLight *)(globals->get_subsystem("lighting")); scolor.sky_color = l->sky_color(); scolor.fog_color = l->adj_fog_color(); @@ -711,17 +711,7 @@ FGRenderer::update( bool refresh_camera_settings ) { globals->get_aircraft_model()->select( true ); globals->get_model_mgr()->draw(); globals->get_aircraft_model()->draw(); - // If the view is internal, the previous line draw the - // cockpit with modified near/far clip planes and deselect - // the aircraft in the global scenegraph - // Otherwise, it just enables the aircraft: The scenegraph - // must be drawn again to see the plane. - ssgBranch *branch = globals->get_scenery()->get_aircraft_branch(); - // in external view the shadows are drawn before the transparent parts of the ac - if( ! is_internal ) - branch->setTravCallback( SSG_CALLBACK_POSTTRAV, SGShadowVolume::ACpostTravCB); - ssgCullAndDraw( globals->get_scenery()->get_scene_graph() ); - branch->setTravCallback( SSG_CALLBACK_POSTTRAV, 0); + FGTileMgr::set_tile_filter( true ); sgSetModelFilter( true ); globals->get_aircraft_model()->select( true ); diff --git a/src/Model/acmodel.cxx b/src/Model/acmodel.cxx index 662a4a4b8..e28e10045 100644 --- a/src/Model/acmodel.cxx +++ b/src/Model/acmodel.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #include
#include
@@ -133,6 +134,10 @@ FGAircraftModel::draw () _selector->select(0); } else { _selector->select(1); + // in external view the shadows are drawn before the transparent parts of the ac + _scene->setTravCallback( SSG_CALLBACK_POSTTRAV, SGShadowVolume::ACpostTravCB); + ssgCullAndDraw(_scene); + _scene->setTravCallback( SSG_CALLBACK_POSTTRAV, 0); } } diff --git a/src/MultiPlayer/mpplayer.cxx b/src/MultiPlayer/mpplayer.cxx index 90a4f8e48..8a97280a3 100644 --- a/src/MultiPlayer/mpplayer.cxx +++ b/src/MultiPlayer/mpplayer.cxx @@ -146,7 +146,7 @@ void MPPlayer::Close(void) { // Flush the model loader so that it erases the model from its list of // models. - globals->get_model_lib()->flush1(); +// globals->get_model_lib()->flush1(); // Assume that plib/ssg deletes the model and transform as their // refcounts should be zero. @@ -263,10 +263,6 @@ void MPPlayer::LoadModel(void) { // Add model to transform m_ModelTrans->addKid( m_Model ); - // Optimise model and transform - ssgFlatten( m_Model ); - ssgStripify( m_ModelTrans ); - // Place on scene under aircraft branch globals->get_scenery()->get_aircraft_branch()->addKid( m_ModelTrans ); globals->get_scenery()->register_placement_transform( m_ModelTrans); diff --git a/src/Replay/replay.cxx b/src/Replay/replay.cxx index c91b41c48..b9475c6ec 100644 --- a/src/Replay/replay.cxx +++ b/src/Replay/replay.cxx @@ -84,7 +84,7 @@ void FGReplay::init() { */ void FGReplay::bind() { - // nothing to bind + disable_replay = fgGetNode( "/sim/replay/disable", true ); } @@ -105,6 +105,9 @@ void FGReplay::update( double dt ) { static SGPropertyNode *replay_master = fgGetNode( "/sim/freeze/replay", true ); + if( disable_replay->getBoolValue() ) + return; + if ( replay_master->getBoolValue() ) { // don't record the replay session return; @@ -259,7 +262,7 @@ static FGReplayData interpolate( double time, FGReplayData f1, FGReplayData f2 ) result.fdm.A_Y_pilot = weight( fdm1.A_Y_pilot, fdm2.A_Y_pilot, ratio ); result.fdm.A_Z_pilot = weight( fdm1.A_Z_pilot, fdm2.A_Z_pilot, ratio ); - int i; + unsigned int i; // Engine status for ( i = 0; i < fdm1.num_engines; ++i ) { diff --git a/src/Replay/replay.hxx b/src/Replay/replay.hxx index 90367beb0..a2a8deee7 100644 --- a/src/Replay/replay.hxx +++ b/src/Replay/replay.hxx @@ -94,6 +94,7 @@ private: replay_list_type short_term; replay_list_type medium_term; replay_list_type long_term; + SGPropertyNode_ptr disable_replay; }; diff --git a/src/Scenery/hitlist.cxx b/src/Scenery/hitlist.cxx index fa5781c61..310d06190 100644 --- a/src/Scenery/hitlist.cxx +++ b/src/Scenery/hitlist.cxx @@ -240,6 +240,85 @@ FGHitList::FGHitList() : FGHitList::~FGHitList() {} +// http://www.cs.lth.se/home/Tomas_Akenine_Moller/raytri/raytri.c +// http://little3d.free.fr/ressources/jgt%20Fast,%20Minumum%20Storage%20Ray-Triangle%20Intersection.htm +// http://www.acm.org/jgt/papers/MollerTrumbore97/ + +/* Ray-Triangle Intersection Test Routines */ +/* Different optimizations of my and Ben Trumbore's */ +/* code from journals of graphics tools (JGT) */ +/* http://www.acm.org/jgt/ */ +/* by Tomas Moller, May 2000 */ + +/* code rewritten to do tests on the sign of the determinant */ +/* the division is at the end in the code */ +// cosmetics change by H.J : +// make u & v locals since we don't use them, use sg functions +static bool intersect_triangle(const double orig[3], const double dir[3], + const double vert0[3], const double vert1[3], const double vert2[3], + double *t) +{ + double u, v; + double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; + + const SGDfloat eps = 1e-4; + + /* find vectors for two edges sharing vert0 */ + sgdSubVec3(edge1, vert1, vert0); + sgdSubVec3(edge2, vert2, vert0); + + /* begin calculating determinant - also used to calculate U parameter */ + sgdVectorProductVec3(pvec, dir, edge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + double det = sgdScalarProductVec3(edge1, pvec); + + if (det > eps) + { + /* calculate distance from vert0 to ray origin */ + sgdSubVec3(tvec, orig, vert0); + + /* calculate U parameter and test bounds */ + u = sgdScalarProductVec3(tvec, pvec); + if (u < 0.0 || u > det) + return false; + + /* prepare to test V parameter */ + sgdVectorProductVec3(qvec, tvec, edge1); + + /* calculate V parameter and test bounds */ + v = sgdScalarProductVec3(dir, qvec); + if (v < 0.0 || u + v > det) + return false; + + } + else if(det < -eps) + { + /* calculate distance from vert0 to ray origin */ + sgdSubVec3(tvec, orig, vert0); + + /* calculate U parameter and test bounds */ + u = sgdScalarProductVec3(tvec, pvec); + if (u > 0.0 || u < det) + return false; + + /* prepare to test V parameter */ + sgdVectorProductVec3(qvec, tvec, edge1); + + /* calculate V parameter and test bounds */ + v = sgdScalarProductVec3(dir, qvec) ; + if (v > 0.0 || u + v < det) + return false; + } + else return false; /* ray is parallell to the plane of the triangle */ + + /* calculate t, ray intersects triangle */ + *t = sgdScalarProductVec3(edge2, qvec) / det; + + return true; +} + + /* Find the intersection of an infinite line with a leaf the line being defined by a point and direction. @@ -280,7 +359,21 @@ int FGHitList::IntersectLeaf( ssgLeaf *leaf, sgdMat4 m, sgdSetVec3( tri[0], leaf->getVertex( i1 ) ); sgdSetVec3( tri[1], leaf->getVertex( i2 ) ); sgdSetVec3( tri[2], leaf->getVertex( i3 ) ); - +#if 1 + sgdFloat t; + if( intersect_triangle( orig, dir, tri[0], tri[1], tri[2], &t) ) { + sgdVec4 plane; + sgdMakePlane( plane, tri[0], tri[1], tri[2] ); + // t is the distance to the triangle plane + // so P = Orig + t*dir + sgdVec3 point; + sgdAddScaledVec3( point, orig, dir, t ); + sgdXformPnt3( point, point, m ); + sgdXformPnt4(plane,plane,m); + add(leaf,i,point,plane); + num_hits++; + } +#else if( isZeroAreaTri( tri ) ) continue; @@ -292,11 +385,12 @@ int FGHitList::IntersectLeaf( ssgLeaf *leaf, sgdMat4 m, if( fgdPointInTriangle( point, tri ) ) { // transform point into passed into desired coordinate frame sgdXformPnt3( point, point, m ); - sgdXformPnt4(plane,plane,m); + sgdXformPnt4(plane,plane,m); add(leaf,i,point,plane); num_hits++; } } +#endif } return num_hits; } @@ -443,18 +537,18 @@ void FGHitList::IntersectBranch( ssgBranch *branch, sgdMat4 m, && !kid->getBSphere()->isEmpty() ) { sgdVec3 center; + const sgFloat *BSCenter = kid->getBSphere()->getCenter(); sgdSetVec3( center, - kid->getBSphere()->getCenter()[0], - kid->getBSphere()->getCenter()[1], - kid->getBSphere()->getCenter()[2] ); + BSCenter[0], + BSCenter[1], + BSCenter[2] ); sgdXformPnt3( center, m ) ; // sgdClosestPointToLineDistSquared( center, orig, dir ) // inlined here because because of profiling results sgdVec3 u, u1, v; sgdSubVec3(u, center, orig); - sgdScaleVec3( u1, dir, sgdScalarProductVec3(u,dir) - / sgdScalarProductVec3(dir,dir) ); + sgdScaleVec3( u1, dir, sgdScalarProductVec3(u,dir) ); sgdSubVec3(v, u, u1); // double because of possible overflow @@ -533,6 +627,7 @@ bool fgCurrentElev( sgdVec3 abs_view_pos, double max_alt_m, sgdCopyVec3(orig, view_pos ); sgdCopyVec3(dir, abs_view_pos ); + sgdNormaliseVec3( dir ); hit_list->Intersect( globals->get_scenery()->get_terrain_branch(), orig, dir );