Earth3D
 

Earth3D Library

In the following I will explain how you can use the "earth3dlib" program to embed a 3D view of the earth in your own application and how you can add your own content. The project uses Trolltech's QT for network access, GUI widgets, XML parsing and mouse and keyboard interaction.

Building

The build process is similar on all platforms, but has some different prerequisites:

Prerequisites

  • Linux
    You need QT4 development packages, libpng and OpenGL development packages installed.
  • Windows
    I used Visual C++ 2003, but I think it will work with mingw, too.
    • First you have to compile and install QT 4. The lib directory of the QT installation needs to be added to the PATH (to be able to run QT 4 applications).
    • glext.h has to be added to the include directory e.g. "Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include\gl".
    • libpng has to be copied to e.g. "C:\lib" or the project file earth3dlib.pro has to be changed to point to the correct location. You can download the binaries here and copy the files that are in the zip file in the lib directory to "C:\lib". If have tested it using version 1.2.24.
  • MacOS X
    The build process is similar to the Linux build process. Install and compile QT 4.

Downloading

The sourcecode can be either checked out from Sourceforge's CVS or downloaded as a Snapshot.

Compiling

To compile run the following commands:

  • Linux, MacOS X:

    $QTDIR/bin/qmake earth3dlib.pro
    make

  • Windows:

    %QTDIR%/bin/qmake earth3dlib.pro
    nmake

Running

Run the application (when using Linux or MacOS X, you find it as "earth3dlib" in the project's directory, under Windows it's in the "debug" or "release" subdirectory. You should get the following window:

Earth3d Lib Window

Embedding the library.

To see how the library can be used in own programs let's take a look at the main method:

int main( int argc, char ** argv ) {
  QApplication a(argc, argv);

#ifdef MYMACOS
  a.addLibraryPath(a.applicationDirPath() + "/../PlugIns");
#endif

  QFrame mainForm;
  Earth3dWidget earth(&mainForm);
  earth.setNavigator(new MouseNavigator(&earth));

  QVBoxLayout vboxlayout;
  vboxlayout.addWidget(&earth);

  mainForm.setLayout(&vboxlayout);
  mainForm.setMinimumSize(QSize(640, 480));
  mainForm.show();

  return a.exec();
}
            

That's all to create a window with a view of the earth that can be moved/rotated and zoomed with the mouse and the keyboard. Earth3dWidget is the widget that displays the earth. The navigator is an object that handles mouse and keyboard events to interact with the displayed earth.

Extending the view.

It it very easy to add new visuals to the 3D view. You just have to implement a class that inherits the Draw class and add it to the view using Earth3dWidget::addDrawObject(). In the 3D scene the earth has a radius of 1 and is placed in the center of the coordinate system. It is static and it is not rotated. When the user moves the earth with the mouse, the camera moves, not the earth. So it is very easy to place objects on fixed coordinates or calculate coordinates for moving objects.

The Earth3dWidget view is painted in three phases:

  • Phase 0, background
  • Phase 1, earth. After this phase the Z coordinates for rotating the earth are retrieved.
  • Phase 2, objects on and above earth's surface
  • Phase 3, head up display, no transformation

Normally you will use phase 2 for your own graphics. Phase 0 should be used for the background and should not change the Z buffer. It can be used e.g. to display stars in the background.

In Phase 1 the earth is displayed and the Z depth coordinates for every pixel are saved. This depth information is used to "grab" the earth with the mouse and move this specific point of the surface around. So it is important to have a point on the surface and not some custom object like e.g. a satellite.

In phase 2 you can display everything that is on and over the surface like signs, buildings, clouds or satellites.

Phase 3 is used to display head up information, i.e. information that is displayed heading to the user. Everything that is displayed in this phase is fixed to the camera, not to the earth. So if the user moves around, objects displayed in phase 3 move with him. An example would be the small earth that can be seen in the middle of this Video in the upper right corner.

Draw Objects

A Draw object is an object that is called once for every phase during the rendering of one frame. You can inherit from the existing Draw class and you only have to implement one method:

virtual void draw(Point3D *viewer, bool viewculling, QGLWidget *widget, Point3D direction, int layer) = 0;
                

You get the position of the camera (viewer), the direction into which the camera looks, the OpenGL widget where you have to paint to, a boolean if viewculling is turned on and the layer (the phase) that is currently painted.

Normally inside this draw method you will first check if the layer is 2 and otherwise return. When layer is 2 you can start drawing your visuals to the QGLWidget. For many applications the camera is not important as they want to display information that is fixed to the earth or it only moves by time. The earth is fixed in the center of the coordinate system and is never moved. So you only have to display your objects at the same coordinates all the time.

When you have implemented your Draw object, add it to the scene in the main method:

Earth3dWidget earth(&mainForm);
earth.setNavigator(new MouseNavigator(&earth));
earth.addDrawObject(mydrawobject);
                

A simple Draw object, that displays a sphere at the GPS coordinate "0 North 0 East", would look like this:

void DrawTest::draw(Point3D *viewer, bool viewculling, QGLWidget *widget, Point3D direction, int phase) {
  if (phase!=2) return;

  glPushMatrix();

  // put a sphere at 0N, 0E, i.e. (x,y,z) = (-1, 0, 0)
  glTranslatef(-1,0,0);
  glutSolidSphere(0.1, 10, 10);

  glPopMatrix();
}