1
0
Fork 0
flightgear/src/Scenery/tileentry.hxx
curt 27158525a9 Restructure the way tile freeing is handled. When a tile is removed from
the tile cache it's ssg elements are disconnected from the main ssg scene
graph, and then the tile is thrown on the end of a delete queue.  The
tilemgr->update() routine runs every frame.  It looks at this queue and if
it is non-empty, it incrementally frees the compents of the first tile
on the queue.  When the tile is completely free it is removed from the queue.

The amount of time to free the memory for even a single tile can be quite
substantial, especially with the increased overhead of dynamic/random
ground objects.  This change allows the system to spread the work of freeing
tile memory out over many frames so you don't get a noticable single frame
hit or stutter.
2002-07-25 23:59:04 +00:00

301 lines
8.3 KiB
C++

// tileentry.hxx -- routines to handle an individual scenery tile
//
// Written by Curtis Olson, started May 1998.
//
// Copyright (C) 1998 - 2001 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$
#ifndef _TILEENTRY_HXX
#define _TILEENTRY_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
#include <GL/glut.h>
#include <GL/gl.h>
#include <simgear/compiler.h>
#include <vector>
#include STL_STRING
#include <plib/ssg.h> // plib includes
#include <simgear/bucket/newbucket.hxx>
#include <simgear/math/point3d.hxx>
#include <simgear/misc/sg_path.hxx>
#if defined( sgi )
#include <strings.h>
#endif
SG_USING_STD(string);
SG_USING_STD(vector);
typedef vector < Point3D > point_list;
typedef point_list::iterator point_list_iterator;
typedef point_list::const_iterator const_point_list_iterator;
class FGTileEntry;
/**
* A class to hold deferred model loading info
*/
class FGDeferredModel {
private:
string model_path;
string texture_path;
FGTileEntry *tile;
ssgTransform *obj_trans;
public:
inline FGDeferredModel() { }
inline FGDeferredModel( const string mp, const string tp,
FGTileEntry *t, ssgTransform *ot )
{
model_path = mp;
texture_path = tp;
tile = t;
obj_trans = ot;
}
inline ~FGDeferredModel() { }
inline string get_model_path() const { return model_path; }
inline string get_texture_path() const { return texture_path; }
inline FGTileEntry *get_tile() const { return tile; }
inline ssgTransform *get_obj_trans() const { return obj_trans; }
};
/**
* A class to encapsulate everything we need to know about a scenery tile.
*/
class FGTileEntry {
public:
/* CLO123 FROM HERE TO THE CORRESPONDING MARKER ARE THINGS THAT
CAN BE DELETED AFTER WE DROP THE ASCII SCENERY FORMAT */
typedef vector < sgVec3 * > free_vec3_list;
typedef vector < sgVec2 * > free_vec2_list;
typedef vector < unsigned short * > free_index_list;
// node list
point_list nodes;
int ncount;
/* CLO123 MARKER */
// global tile culling data
Point3D center;
double bounding_radius;
Point3D offset;
// this tile's official location in the world
SGBucket tile_bucket;
// list of pointers to memory chunks that need to be freed when
// tile entry goes away
free_vec3_list vec3_ptrs;
free_vec2_list vec2_ptrs;
free_index_list index_ptrs;
private:
// ssg tree structure for this tile is as follows:
// ssgRoot(scene)
// - ssgBranch(terrain)
// - ssgTransform(tile)
// - ssgRangeSelector(tile)
// - ssgEntity(tile)
// - kid1(fan)
// - kid2(fan)
// ...
// - kidn(fan)
// pointer to ssg transform for this tile
ssgTransform *terra_transform;
ssgTransform *rwy_lights_transform;
ssgTransform *gnd_lights_transform;
// pointer to ssg range selector for this tile
ssgRangeSelector *terra_range;
ssgRangeSelector *rwy_lights_range;
ssgRangeSelector *gnd_lights_range;
// we create several preset brightness and can choose which one we
// want based on lighting conditions.
ssgSelector *gnd_lights_brightness;
// ADA --->
// Runway centre coords.
Point3D rway_center; // Reqd. for switching as function of distance from runway center
//pointers for Runway lights
ssgTransform *lightmaps_transform; // branch for runway lights
ssgRangeSelector *lightmaps_range; // tried to maintain same structure as Curt's ground
ssgSelector *lightmaps_brightness; // selector node for points/ lightmaps
ssgSimpleState *lightmap_state; // OpenGL state of the polygons that make up runway lights
ssgVertexArray *light_points; // array of runway light coords.
// <--- ADA
/**
* Indicates this tile has been loaded from a file and connected
* into the scene graph. Note that this may be set asynchronously
* by another thread.
*/
volatile bool loaded;
/**
* Count of pending models to load for this tile. This tile
* cannot be removed until this number reaches zero (i.e. no
* pending models to load for this tile.)
*/
volatile int pending_models;
bool obj_load( const std::string& path,
ssgBranch* geometry,
ssgBranch* rwy_lights,
ssgVertexArray* gound_lights,
bool is_base );
ssgLeaf* gen_lights( ssgVertexArray *lights, int inc, float bright );
double timestamp;
// this variable tracks the status of the incremental memory freeing.
enum {
NODES = 0x01,
VEC_PTRS = 0x02,
TERRA_NODE = 0x04,
GROUND_LIGHTS = 0x08,
RWY_LIGHTS = 0x10,
LIGHTMAPS = 0x20
};
int free_tracker;
public:
// ADA --->
ssgTransform *ols_transform; // transform node for flols simulation
ssgSelector *lightmaps_sequence; // selector node for points/ lightmaps
ssgBranch* gen_runway_lights(ssgVertexArray *points,ssgVertexArray *normal, ssgVertexArray *dir, int *type);
// <--- ADA
// Constructor
FGTileEntry( const SGBucket& b );
// Destructor
~FGTileEntry();
#ifdef WISH_PLIB_WAS_THREADED // but it isn't
// Schedule tile to be freed/removed
void sched_removal();
#endif
// Clean up the memory used by this tile and delete the arrays
// used by ssg as well as the whole ssg branch. This does a
// partial clean up and exits so we can spread the load across
// multiple frames. Returns false if work remaining to be done,
// true if dynamically allocated memory used by this tile is
// completely freed.
bool free_tile();
// Calculate this tile's offset
void SetOffset( const Point3D& p)
{
offset = center - p;
}
// Return this tile's offset
inline Point3D get_offset() const { return offset; }
// Update the ssg transform node for this tile so it can be
// properly drawn relative to our (0,0,0) point
void prep_ssg_node( const Point3D& p, sgVec3 up, float vis);
/**
* Load tile data from a file.
* @param base name of directory containing tile data file.
* @param is_base is this a base terrain object for which we should generate
* random ground light points */
void load( const SGPath& base, bool is_base );
/**
* Return true if the tile entry is loaded, otherwise return false
* indicating that the loading thread is still working on this.
*/
inline bool is_loaded() const { return loaded; }
/**
* decrement the pending models count
*/
inline void dec_pending_models() { pending_models--; }
/**
* return the number of remaining pending models for this tile
*/
inline int get_pending_models() const { return pending_models; }
/**
* Return the "bucket" for this tile
*/
inline SGBucket get_tile_bucket() const { return tile_bucket; }
/**
* Add terrain mesh and ground lighting to scene graph.
*/
void add_ssg_nodes( ssgBranch* terrain_branch,
ssgBranch* gnd_lights_branch,
ssgBranch* rwy_lights_branch );
/**
* disconnect terrain mesh and ground lighting nodes from scene
* graph for this tile.
*/
void disconnect_ssg_nodes();
/**
* return the SSG Transform node for the terrain
*/
inline ssgTransform *get_terra_transform() { return terra_transform; }
void set_timestamp(double time_ms) { timestamp = time_ms; }
inline double get_timestamp() const { return timestamp; }
};
#endif // _TILEENTRY_HXX