![]() |
VR-Forces 4.0.4 Class Documentation
|
The Modify Terrain example demonstrates the following:
This example demonstrates how to programmatically modify an existing GDB (VR-Forces native format) terrain database. It manipulates the polygons in a terrain database.
(in bin directory)
modifyTerrainDb
To run the example:
In step 1, a simple terrain database named data\terrain\simpleTerrain.gdb will be created. This database is flat area (altitude zero everywhere). The modifyTerrainDb loads this database, and manipulates several of the polygons to form a depression in one corner. It saves the modified terrain database as data\terrain\modifiedSimpleTerrain.gdb. To view the terrain, open the database in TDBTool or vrfGui. The altitude of the terrain will vary.
/******************************************************************************* ** Copyright (c) 2003 MAK Technologies, Inc. ** All rights reserved. *******************************************************************************/ /******************************************************************************* ** $RCSfile: main.cxx,v $ $Revision: 1.12 $ $State: Exp $ *******************************************************************************/ #include "gdb/terrainDb.h" #include "terrainCS/ser_utm.h" #include "geometry/point.h" #include "geometry/surface.h" #include "gdb/triInd.h" #include <vlutil/vlPrint.h> #include "gdb/allPoly.h" #include "geometry/chord.h" #include "gdb/gdbChordIntersectionRecord.h" #include "terrainDbFactory/tdbManager.h" // This example demonstrates how to use the terrain API to modify a simple // terrain database in code. It takes a simple terrain database and creates a // divot in the terrain in the lower right quandrant of the terrain database. // It reads in the ..\data\terrain\\simpleTerrain.gdb created by the // createTerrainDb example, and saves out the modified terrain database to the // file ..\data\terrain\modifiedTerrain.gdb. int main(int argc, char** argv) { DtTdbManager manager; // Load the terrain database using a terrain reader that knows how to load // MAK gdb terrain files. if(!manager.load("..\\data\\terrain\\simpleTerrain.gdb")) { DtWarn("Couldn't load terrain database file -- please run the createTerrainDb example to create simpleTerrain.gdb\n"); return 1; } // (The simpleTerrain.gdb file is a 1000 meter x 1000 meter square UTM database, // comprised of 8 - 500 x 500 meters square triangles, with zero elevations, // forming 4 quadrants. // Triangles and Polygons in the terrain database are all indirect, either // DtTriangleIndirect or DtPolygonIndirect. // // We will be removing the lower-right quadrant in the terrain (two triangles // comprising a 500 x 500 meter square area.) We'll do intersection tests // to find the triangles. // Get the closest intersection to the specified x,y locations, // along the up/down direction, // (750, 200). // (750, 300). // Try to intersect the terrain to get the left triangle // Note, we can use closestIntersection because we know that there is only // one intersection. If we needed the topmost intersection point if multiple // levels of terrain existed, we would have to create a chord and use it for // intersection tests manually. DtGdbChordIntersectionRecord intersectionRecord; if(!manager.terrainDatabase()->closestIntersection(DtVector(750,200,0), intersectionRecord)) { // Unlikely to happen - we know the geometry of simpleTerrain.gdb DtWarn("Intersection test failed!\n"); return 1; } // Try to intersect the terrain again to get the right triangle. DtGdbChordIntersectionRecord intersectionRecord2; if(!manager.terrainDatabase()->closestIntersection(DtVector(750, 300, 0), intersectionRecord2)) { // Unlikely to happen - we know the geometry of simpleTerrain.gdb DtWarn("Intersection test failed!\n"); return 1; } // Get the polygons (we know they're triangles) from // the chord intersection records. DtAllTypesPolygon* leftPolygon = intersectionRecord.polygon(); DtAllTypesPolygon* rightPolygon = intersectionRecord2.polygon(); if(!leftPolygon || !rightPolygon) { // Again, this is unlikely to happen - we know the geometry of // simpleTerrain.gdb DtWarn("At least one polygon not found at intersection!\n"); return 1; } // This vertex will be the vertex at the base of the divot. DtPoint baseVertex(750.0, 250.0, -60.0); // We will be replacing the polygon we intersected with 4 new ones. The // new polygons will be triangles attached to where the old polgon tied // in to the database, with a common vertex at the base of the hole (60 // meters deep, at x-y location (750, 250). // Get the vertices of the polygon we're going to remove DtPoint vertex0; DtPoint vertex1; DtPoint vertex2; DtPoint vertex3; leftPolygon->getVertex(vertex0, 0); leftPolygon->getVertex(vertex1, 1); leftPolygon->getVertex(vertex2, 2); rightPolygon->getVertex(vertex3, 2); DtSurface surface; surface.setIsGround(true); surface.setIsSoftSoil(true); // Different color than existing terrain created in createTerrainDb project... surface.setColor(DtColor(110, 95, 90, 0)); // Create new polygons making up the depression in the terrain. DtTriangleIndirect* newTri0 = NULL; DtTriangleIndirect* newTri1 = NULL; DtTriangleIndirect* newTri2 = NULL; DtTriangleIndirect* newTri3 = NULL; // Create a new polygon (a triangle) with one side formed by edge of old // polygon and with one vertex at baseVertex (bottom of our new hole). newTri0 = manager.terrainDatabase()->createTriangle(vertex0, vertex1, baseVertex, surface); // Repeat for rest of the new polygons making up the hole. newTri1 = manager.terrainDatabase()->createTriangle(vertex1, vertex2, baseVertex, surface); newTri2 = manager.terrainDatabase()->createTriangle(vertex2, vertex3, baseVertex, surface); newTri3 = manager.terrainDatabase()->createTriangle(vertex3, vertex0, baseVertex, surface); if (newTri0 == NULL || newTri1 == NULL || newTri2 == NULL || newTri3 == NULL) { DtWarn("Couldn't create new indirect triangles for divit in the ground.\n"); return 1; } // remove old triangles from database manager.terrainDatabase()->removeTerrainNode(leftPolygon); manager.terrainDatabase()->removeTerrainNode(rightPolygon); // Eliminates duplicate vertices (introduced by the triangles we just added). // Specify tolerance of 0.01 meters - vertices within 0.01 meters of each // other are considered duplicates of each other and compacted into one vertex. manager.terrainDatabase()->eliminateDuplicateVertices(0.01); // Eliminates duplicate surfaces in the same manner as eliminating duplicate // vertices. No tolerance is used as surfaces are either equal or not. manager.terrainDatabase()->eliminateDuplicateSurfaces(); // Save new terrain database to gdb format file manager.save("..\\data\\terrain\\modifiedSimpleTerrain.gdb"); DtInfo << "Creating terrain " << DtFilename("..\\data\\terrain\\modifiedSimpleTerrain.gdb").c_str() << std::endl; return 0; }