6.4. Texture Management

TerrainViz also manages a tree of textures via the SbTVizTextureList class. SbTVizTextureList handles a list of textures (SbTVizTexture classes) sorted to fit a quadtree. The level of the texture is the depth level in this quadtree. Level n has 2 2n textures. The position of a texture within the quadtree is specified by two values between 0 and 2 2n-1. It is not necessary to provide all textures. Some patches can remain empty. Full resolution textures are the leaves of the tree (see Figure 6.5, “ TerrainViz texture quadtree”).

The textures displayed are chosen according to the point of view. The highest resolution texture is displayed for the region in which the camera is located along with its direct neighborhood (of the same level). Then concentric neighborhoods decrease in texture level. So the most refined textures are around the point of view and texture quality decreases as we move away from it (see Figure 6.4, “ Texture neighborhood with level information”).

Texture neighborhood with level information

Figure 6.4.  Texture neighborhood with level information


TerrainViz texture quadtree

Figure 6.5.  TerrainViz texture quadtree


[Warning]

In previous versions of TerrainViz (1.0 and 1.1), the coordinate system was oriented differently. Altitudes were along the Y-axis, longitudes along X, and latitudes along -Z. The origin in the texture quadtree was on the top left corner. See Section 6.7.1, “SoTVizRender and SoTVizViewer”.

An SbTVizTexture stores an image buffer given by pointer or loaded from a texture file (image file) in any of the formats supported by Open Inventor. It also manages the attributes of the texture to fit the texture quadtree. Each texture is characterized by its level in the texture list quadtree, its position in this level, the number of color components, and its pixel size.

The following example loads a 3-level tree of textures (21 files), and maps it to the regular grid.

TerrainViz texture mapping

Figure 6.6. TerrainViz texture mapping


Example 6.3.  A simple example using textures

#include <Inventor/Xt/viewers/SoXtExaminerViewer.h>
#include <Inventor/nodes/SoSeparator.h>
#include <TerrainViz/nodes/SoTViz.h>
#include <TerrainViz/nodes/SoTVizRender.h>
#include <TerrainViz/SbTVizTextureList.h>
#include <TerrainViz/SbTVizRegularGridData.h>
  
  int
  main(int argc, char **argv)
  {
  // Initialize Inventor. This returns a main window to use.
  // If unsuccessful, exit.
    Widget mainWindow = SoXt::init(argv[0]);    // pass the app name
    if (mainWindow == NULL) exit(1);

  // Initialize TerrainViz
    SoTViz::init();

    SoXtExaminerViewer *mainViewer = new SoXtExaminerViewer(mainWindow);
    SoSeparator *mainRoot = new SoSeparator;

    mainViewer->setSceneGraph(mainRoot);

    SoTVizRender *dtmRender = new SoTVizRender();

    mainRoot->addChild(dtmRender);

  // The data file is 4097*4097

    SbTVizRegularGridData *data = new SbTVizRegularGridData();
    data->loadDataFile("data/africa_binary.dat",
                           SbVec3d(1./4097., 1./4097., 0.136/4097.),
                           SbVec3d(0., 0., 0.));
    dtmRender->setData(data);
    texList->addTexture("data/africa_1_1.png", 0, SbVec2s(0,0));
    texList->addTexture("data/africa_1_4.png", 1, SbVec2s(0,0), SbVec2s(1,1));
    texList->addTexture("data/africa_2_4.png", 1, SbVec2s(1,0), SbVec2s(1,1));
    texList->addTexture("data/africa_3_4.png", 1, SbVec2s(0,1), SbVec2s(1,1));
    texList->addTexture("data/africa_4_4.png", 1, SbVec2s(1,1), SbVec2s(1,1));
    texList->addTexture("data/africa_01_16.png", 2, SbVec2s(0,0), SbVec2s(1,1));
    texList->addTexture("data/africa_02_16.png", 2, SbVec2s(1,0), SbVec2s(1,1));
    texList->addTexture("data/africa_03_16.png", 2, SbVec2s(2,0), SbVec2s(1,1));
    texList->addTexture("data/africa_04_16.png", 2, SbVec2s(3,0), SbVec2s(1,1));
    texList->addTexture("data/africa_05_16.png", 2, SbVec2s(0,1), SbVec2s(1,1));
    texList->addTexture("data/africa_06_16.png", 2, SbVec2s(1,1), SbVec2s(1,1));
    texList->addTexture("data/africa_07_16.png", 2, SbVec2s(2,1), SbVec2s(1,1));
    texList->addTexture("data/africa_08_16.png", 2, SbVec2s(3,1), SbVec2s(1,1));
    texList->addTexture("data/africa_09_16.png", 2, SbVec2s(0,2), SbVec2s(1,1));
    texList->addTexture("data/africa_10_16.png", 2, SbVec2s(1,2), SbVec2s(1,1));
    texList->addTexture("data/africa_11_16.png", 2, SbVec2s(2,2), SbVec2s(1,1));
    texList->addTexture("data/africa_12_16.png", 2, SbVec2s(3,2), SbVec2s(1,1));
    texList->addTexture("data/africa_13_16.png", 2, SbVec2s(0,3), SbVec2s(1,1));
    texList->addTexture("data/africa_14_16.png", 2, SbVec2s(1,3), SbVec2s(1,1));
    texList->addTexture("data/africa_15_16.png", 2, SbVec2s(2,3), SbVec2s(1,1));
    texList->addTexture("data/africa_16_16.png", 2, SbVec2s(3,3), SbVec2s(1,1));

    dtmRender->setTextureList(texList);
    dtmRender->maxRenderedTriangles = 10000;

    mainViewer->show();
    mainViewer->viewAll();

    SoXt::show(mainWindow);    // Display main window

    SoXt::mainLoop();          // Main Inventor event loop
    return 0;
  }