434 lines
15 KiB
TeX
434 lines
15 KiB
TeX
|
%
|
||
|
% `SceneryGeneration.tex' -- describes the scenery generation tool pipeline
|
||
|
%
|
||
|
% Written by Curtis Olson. Started February, 1999. curt@flightgear.org
|
||
|
%
|
||
|
% $Id$
|
||
|
%------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
\documentclass[12pt]{article}
|
||
|
|
||
|
\usepackage{anysize}
|
||
|
\papersize{11in}{8.5in}
|
||
|
\marginsize{1in}{1in}{1in}{1in}
|
||
|
|
||
|
\usepackage{amsmath}
|
||
|
|
||
|
\usepackage{epsfig}
|
||
|
|
||
|
\usepackage{setspace}
|
||
|
\onehalfspacing
|
||
|
|
||
|
\usepackage{url}
|
||
|
|
||
|
|
||
|
\begin{document}
|
||
|
|
||
|
|
||
|
\title{
|
||
|
Flight Gear Scenery Generation Tools.
|
||
|
}
|
||
|
|
||
|
|
||
|
\author{
|
||
|
Curtis L. Olson\\
|
||
|
(\texttt{curt@flightgear.org})
|
||
|
}
|
||
|
|
||
|
|
||
|
\maketitle
|
||
|
|
||
|
|
||
|
\section{Introduction}
|
||
|
|
||
|
This document gives a brief overview of the Flight Gear scenery
|
||
|
generation tools and how they fit together in a pipeline to produce
|
||
|
the runtime scenery from the raw data.
|
||
|
|
||
|
The first sections describe how the Flight Gear Earth is subdivided
|
||
|
and the coordinate systems that Flight Gear uses internally. The
|
||
|
remaining sections describe the tools that take diverse data sources
|
||
|
and produce the actual scenery.
|
||
|
|
||
|
|
||
|
\section{Internal Scenery Representation}
|
||
|
|
||
|
This section describes how FG represents, manipulates, and
|
||
|
transforms scenery internally.
|
||
|
|
||
|
Internal, all FG scenery is defined using a cartesian coordinate
|
||
|
system centered at the center of the earth. Please refer to the
|
||
|
Flight Gear CoordinateSystem document for more information. This
|
||
|
means that one of the scenery tools processing steps will be to
|
||
|
convert from the source data coordinate system to the internal Flight
|
||
|
Gear coordinate system.
|
||
|
|
||
|
|
||
|
\subsection{Scenery Partitioning}
|
||
|
|
||
|
Flight Gear splits the world up into tiles. This splits up the
|
||
|
immense scenery data base into chunks that are managable by the run
|
||
|
time simulator.
|
||
|
|
||
|
Tile edges are parallel to longitude and latitude lines. Tiles are
|
||
|
gauranteed to be at least 8 miles long in both width and height. As
|
||
|
we move towards the poles, the tiles get narrower, so at certain
|
||
|
predefined latitudes, the tile with is doubled. Figure \ref{fig:lats}
|
||
|
shows latitudes vs. tile widths. The southern hemisphere is a mirror
|
||
|
image of the northern hemisphere.
|
||
|
|
||
|
\begin{figure}[hbt]
|
||
|
\begin{center}
|
||
|
\begin{tabular}{||l|l||} \hline
|
||
|
Latitude Range & Tile Width \\ \hline
|
||
|
$[0, 22)$ & $\frac{1}{8}$ degree \\ \hline
|
||
|
$[22, 62)$ & $\frac{1}{4}$ degree \\ \hline
|
||
|
$[62, 76)$ & $\frac{1}{2}$ degree \\ \hline
|
||
|
$[76, 83)$ & $1$ degree \\ \hline
|
||
|
$[83, 86)$ & $2$ degrees \\ \hline
|
||
|
$[86, 88)$ & $4$ degrees \\ \hline
|
||
|
$[88, 89)$ & $8$ degrees \\ \hline
|
||
|
$[89, 90]$ & polar cap \\ \hline
|
||
|
\hline
|
||
|
\end{tabular}
|
||
|
\end{center}
|
||
|
|
||
|
\caption{Latitude vs. Tile Widths.}
|
||
|
\label{fig:lats}
|
||
|
\end{figure}
|
||
|
|
||
|
|
||
|
Since Flight Gear tiles are partitioned parallel to longitude and
|
||
|
latitude lines, they have a trapezium shape. Figure \ref{fig:trap}
|
||
|
shows an exaggerated scenery area.
|
||
|
|
||
|
\begin{figure}[hbt]
|
||
|
\centerline{
|
||
|
\psfig{file=trap.eps}
|
||
|
}
|
||
|
\caption{Basic Tile Shape}
|
||
|
\label{fig:trap}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsection{Reference Points}
|
||
|
|
||
|
Each scenery area will have a reference point at the center of its
|
||
|
area. This reference point (for purposes of avoiding floating point
|
||
|
precision problems) defines the origin of a local coordinate system
|
||
|
which. The local coordinate system is simply translated from the
|
||
|
global coordinate system by the distance of the tile's center
|
||
|
reference point from the center of the earth. Figure
|
||
|
\ref{fig:reference} demonstrates this better than I can explain it.
|
||
|
|
||
|
\begin{figure}[hbt]
|
||
|
\centerline{
|
||
|
\psfig{file=ref.eps}
|
||
|
}
|
||
|
\caption{Reference Points and Translations}
|
||
|
\label{fig:reference}
|
||
|
\end{figure}
|
||
|
|
||
|
All the objects for a specific scenery area will be defined based on
|
||
|
this local coordinate system. For each scenery area we define a
|
||
|
vector $\vec{\mathbf{a}}$ which represents the distance from the
|
||
|
center of the earth to the local coordinate system.
|
||
|
|
||
|
|
||
|
\subsection{Putting the pieces of scenery together}
|
||
|
|
||
|
To render a scene, the scenery manager will need to load all the
|
||
|
visible tiles. Before rendering each tile we translate it by
|
||
|
$\vec{\mathbf{a}}_{current} - \vec{\mathbf{a}}_{n}$. This moves all
|
||
|
the rendered tiles near to the origin, while maintaining the relative
|
||
|
positions and orientations. The of moving all the tiles near the
|
||
|
origin before rendering them is to try to reduce floating point round
|
||
|
off problems.
|
||
|
|
||
|
When rendering, it is straightforward to calculate the proper view
|
||
|
point and up vector so that the scenery will appear right side up when
|
||
|
it is rendered.
|
||
|
|
||
|
\subsection{Scenery file format}
|
||
|
|
||
|
Here is a very brief overview of the flight gear scenery file format.
|
||
|
Some of this format will have to change in the future, so I won't put
|
||
|
a lot of effort here right now. This description will be most
|
||
|
understandable if you reference an actual scenery tile file. If you
|
||
|
have questions, please ask!
|
||
|
|
||
|
\begin{itemize}
|
||
|
|
||
|
\item Coordinates are in (X, Y, Z) with (0, 0, 0) being the center of
|
||
|
the earth. Units are in meters.
|
||
|
|
||
|
\item ``gbs'' is the ``global bounding sphere'' specified by the
|
||
|
center reference point and a radius.
|
||
|
|
||
|
\item This is followed by a list of vertices prefaced by ``v''
|
||
|
specifying the offsets of the vertices from the gbs reference point.
|
||
|
|
||
|
\item Then follows the list of vertex normals ``vn''.
|
||
|
|
||
|
\item Then the sets of triangle strips are specifed:
|
||
|
|
||
|
\item ``usemtl'' points to a material property record in the materials
|
||
|
file and specifies the texture/color/etc. for this triangle strip.
|
||
|
|
||
|
\item ``bs'' specifies the bounding sphere for this particular tri
|
||
|
strip (for view frustum culling)
|
||
|
|
||
|
\item ``t'' is the start of a tri strip and the integer numbers are
|
||
|
just indices back into the vertex and vertex normal lists.
|
||
|
|
||
|
\item ``q'' is simply a continuation of the triangle strip.
|
||
|
\end{itemize}
|
||
|
|
||
|
I will eventually need to add texture coordinate support to this file
|
||
|
format, as well as a way to reference and position objects from an
|
||
|
external library.
|
||
|
|
||
|
|
||
|
\section{Scenery Generation}
|
||
|
|
||
|
This section is very fluid right now. I have implemented a first pass
|
||
|
at generating scenery. This was a good learning experience, but it
|
||
|
exposed several flaws and limitations in my original approach. I am
|
||
|
in the midst of a complete overhaul of these tools which is intended
|
||
|
to address all the short comings of my first attempt. At this point I
|
||
|
am simply outlining the plan. Much of this could change as my plan
|
||
|
continues to smack up against reality.
|
||
|
|
||
|
With that in mind, the scenery generation tools can be subdivided into
|
||
|
four major categories.
|
||
|
|
||
|
\begin{itemize}
|
||
|
|
||
|
\item Libraries which provide basic functionality used by the terrain
|
||
|
tools.
|
||
|
|
||
|
\item Preprocessing tools which convert data from it's original format
|
||
|
(as downloaded from the net) to something that is easier for the
|
||
|
scenery tools to process.
|
||
|
|
||
|
\item Scenery generation tools which assemble and massage the
|
||
|
resulting input data into the Flight Gear scenery format.
|
||
|
|
||
|
\item Miscellaneous utilities
|
||
|
|
||
|
\end{itemize}
|
||
|
|
||
|
\subsection{Libraries}
|
||
|
|
||
|
|
||
|
\subsubsection{GPC}
|
||
|
|
||
|
GPC is the ``Generic Polygon Clipper'' library. It is available from
|
||
|
|
||
|
\url{http://www.cs.man.ac.uk/aig/staff/alan/software}
|
||
|
|
||
|
Please be aware that the licensing terms for the gpc library clash
|
||
|
with the GPL and prevent the source code from being redistributed with
|
||
|
any GPL program. Therefore any developers interested in building the
|
||
|
scenery tools will have to fetch and install this library individually
|
||
|
on their own systems.
|
||
|
|
||
|
\subsubsection{GFC}
|
||
|
|
||
|
GFC is the ``Geographic Foundation Classes'' library. It is available
|
||
|
from:
|
||
|
|
||
|
\url{http://www.geog.psu.edu/~qian/gfc/index.html}
|
||
|
|
||
|
This library allows programs to process GIS shapefiles and extract out
|
||
|
the lon/lat coordinates of the GIS structures.
|
||
|
|
||
|
\subsubsection{DEM}
|
||
|
|
||
|
This is a library of routines distributed as part of Flight Gear.
|
||
|
This library has routines to parse the 3 arcsec DEM file format,
|
||
|
approximate the regular grid of height data, with an irregular grid,
|
||
|
and interpolate the elevation of any arbitrary point inside the grid.
|
||
|
|
||
|
An irregular grid can often represent the same level detail as a
|
||
|
regular grid with 4-6x fewer polygons. This is very desirable in a
|
||
|
flight sim where both detail and rendering speed is very important.
|
||
|
|
||
|
Another feature of an irregular grid is that it carries fewer
|
||
|
artifacts that could provide negative training value to pilots. For
|
||
|
instance a regular grid could give a pilot non-realistic cues for
|
||
|
determining north/south/east/west.
|
||
|
|
||
|
|
||
|
\subsubsection{Triangle}
|
||
|
|
||
|
Triangle can be built as a standalone binary, or as a library. For
|
||
|
our uses I am choosing to build it as a library. This library
|
||
|
impliments the delauney triangulation algorithm. It takes a set of
|
||
|
unorder points and finds the optimal triangulation of these points.
|
||
|
|
||
|
For our use we feed in a set of unordered height values and the
|
||
|
triangle library will output a set of triangles that can be rendered
|
||
|
as terrain.
|
||
|
|
||
|
The triangle library does a few more things that are useful. It will
|
||
|
subdivide triangles to ensure that they never get too long and
|
||
|
skinny. It will also let you set up boundaries and holes within the
|
||
|
triangulation area.
|
||
|
|
||
|
\subsection{Preprocessing tools}
|
||
|
|
||
|
\subsubsection{GenAirports}
|
||
|
|
||
|
This tools inputs an ascii specification of the airports of the world
|
||
|
that looks like the following:
|
||
|
|
||
|
\begin{verbatim}
|
||
|
KORD Chicago O Hare International
|
||
|
-087.917774 41.976778 13000 200 140 155154 14 R 668
|
||
|
-087.902380 41.969040 10141 150 90 154154 09 R 668
|
||
|
-087.903546 41.991918 10003 150 140 155154 14 L 668
|
||
|
-087.889594 41.961618 8071 150 41 154154 04 R 668
|
||
|
-087.903705 41.983954 7967 150 90 154154 09 L 668
|
||
|
-087.905138 41.989606 7500 150 39 142144 04 L 668
|
||
|
-087.900410 41.990086 5341 150 180 131131 18 x 668
|
||
|
\end{verbatim}
|
||
|
|
||
|
For each airport, a bounding polygon is generated, and written as a
|
||
|
clipping record for each intersecting tile in the scenery construction
|
||
|
area. The actual airport will belong to the tile containing it's
|
||
|
center point, but the airport will need to be clipped out of the base
|
||
|
terrain from any tiles it might spill over into.
|
||
|
|
||
|
\subsubsection{ShapeFile}
|
||
|
|
||
|
The ShapeFile tool will take the polygons from shapefiles (via GFC),
|
||
|
clip them to the appropriate tile boundares (via GPC) and write the
|
||
|
resulting polygons to the appropriate tile in the scenery work space.
|
||
|
|
||
|
|
||
|
\subsubsection{DemRaw2ascii}
|
||
|
|
||
|
This tool will input the 30 arcsec raw DEM format, split it up into 1
|
||
|
x 1 degree sections, and output the result into the 3 arcsec format so
|
||
|
it can be fed through the scenery pipeline.
|
||
|
|
||
|
\subsubsection{Dem2node}
|
||
|
|
||
|
This tool takes the raw DEM files and calls routines from libDEM.a to
|
||
|
create the irregular grid approximation of the original data. The
|
||
|
elevation data is writen to the to the appropriate tile in the scenery
|
||
|
work space.
|
||
|
|
||
|
\subsection{Scenery generation tools}
|
||
|
|
||
|
Issues:
|
||
|
|
||
|
Combining height data, polygon data.
|
||
|
|
||
|
Triangulating / tri-stripping / tri-fanning.
|
||
|
|
||
|
Matching vertices and normals along edges and at corners.
|
||
|
|
||
|
Resolving conflicts in data:
|
||
|
overlapping polygon areas.
|
||
|
conflicting height data between airports and DEM data
|
||
|
|
||
|
Here's the basic process to create scenery:
|
||
|
|
||
|
Dump the raw data into the appropriate tile areas in the work space.
|
||
|
This includes height data (DEM, airport) and polygon data (airport,
|
||
|
hydro-data, land use data, etc.)
|
||
|
|
||
|
For each tile, run the generic clipper on each polygon in order from
|
||
|
highest to lowest incrementally building an accumulation ``super''
|
||
|
polygon that comprises a union of all polygons we've processed so far
|
||
|
for this tile. For each polygon first clip against this
|
||
|
super-accumlation-polygon. What's left after the clip is the new
|
||
|
shape of the polygon. This is the scheme for eliminating overlapping
|
||
|
features on a priority basis.
|
||
|
|
||
|
For each polygon on a tile we must determine a point inside. We need
|
||
|
this for the triangulation step.
|
||
|
|
||
|
For each polygon, triangulate all the height fields in the tile.
|
||
|
Using the triangle library we can feed in all the polygon outlines
|
||
|
with the corresponding interior points. We can tell the triangulator
|
||
|
to start at every point except for the one we are working on and eat
|
||
|
away all the triangles until a polygon border is encountered. This
|
||
|
leaves us with the triangulation of each polygon.
|
||
|
|
||
|
Now we have a pile of height data and the triangulation for each
|
||
|
polygon. However, some of these hieght fields must be enforced
|
||
|
(airports) and some of this can be adjusted (base terrain). We might
|
||
|
also want to think about ensuring lakes are level, and rivers don't
|
||
|
run up and down hills. Anyways, with a flurry of handwaving, we have
|
||
|
adjusted all the heights.
|
||
|
|
||
|
The next thing we have to worry about is making sure each tile meshes
|
||
|
exactly with all it's neighbors. We do this by spliting the tile up
|
||
|
into it's 4 edges, 4 corners, and the remaining vertices. We write
|
||
|
these parts out as individual files if a neighboring tile hasn't been
|
||
|
processed first. In other words, the first tile to be process gets to
|
||
|
define the shared edge or corner. The neighbor must use this data if
|
||
|
it exists. Then we have to reassemble the tile using any pre-existing
|
||
|
edges from a neighbor tiles that were processed before us and
|
||
|
retriangulate since our node list has changed. <whew>
|
||
|
|
||
|
Unfortunately it's not quite this simple!
|
||
|
|
||
|
We need to be careful, because we have to make sure we also preserve
|
||
|
the polygon connections since lakes, rivers, and even airports often
|
||
|
span multiple tiles.
|
||
|
|
||
|
To do this I propose a scheme of assigning a unique integer id to each
|
||
|
polygon. When writing out the shared edge/corner pieces I also
|
||
|
associate this idea. So rather than disassembling, sharing, and
|
||
|
reassembling whole tiles, we need to do this on a per-polygon basis.
|
||
|
More handwaving and we are off to the next step.
|
||
|
|
||
|
Now, we need to take our 3d, triangulated polygons and tri-fan or
|
||
|
tri-strip them for rendering efficiency. We have been using a
|
||
|
freeware tool called ``stripe'' but it's a typical CSci hack job where
|
||
|
the author was more interested in demonstrating the theory, rather
|
||
|
than demonstrating bug free, robust, well written code. Oh well. I
|
||
|
think I will try to write a utility to combine triangles into fans.
|
||
|
This will help culling (smaller, centralized objects == better
|
||
|
culling) but will happen at the expense of more vertex
|
||
|
transformations. I'm hoping this will result in a net gain. Finger
|
||
|
crossed. :-)
|
||
|
|
||
|
Finally, we need to take our 3d, fan-ified polygons and convert them
|
||
|
to the FGFS scenery format and copy them from the work space directory
|
||
|
tree into the final scenery directory tree.
|
||
|
|
||
|
% \subsubsection{Areas}
|
||
|
% \subsubsection{AssemTris}
|
||
|
% \subsubsection{Clipper}
|
||
|
% \subsubsection{FixNode}
|
||
|
% \subsubsection{FixObj}
|
||
|
% \subsubsection{SplitTris}
|
||
|
% \subsubsection{Stripe\_w}
|
||
|
% \subsubsection{Tri2obj}
|
||
|
|
||
|
\subsection{Miscellaneous Utilities}
|
||
|
|
||
|
\subsubsection{DemInfo}
|
||
|
|
||
|
Reads the ``A'' record from a 3 arcsec DEM file and dumps some
|
||
|
pertinent information.
|
||
|
|
||
|
\subsubsection{tile-sizes.pl}
|
||
|
|
||
|
Generates the width of a 1/8 x 1/8 degree tile at various latitudes.
|
||
|
|
||
|
|
||
|
\end{document}
|
||
|
|
||
|
|
||
|
%------------------------------------------------------------------------
|
||
|
% $Log$
|
||
|
% Revision 1.1 1999/02/15 00:38:46 curt
|
||
|
% Initial revision.
|
||
|
%
|