Пример #1
0
void EnviroFrame::CarveTerrainToFitNode(osg::Node *node)
{
	vtTerrain *terr = g_App.GetCurrentTerrain();
	if (!terr)
		return;
	vtDynTerrainGeom *dyn = terr->GetDynTerrain();
	if (!dyn)
		return;

	FSphere sph;
	GetBoundSphere(node, sph, true);

	int changed = 0;
	int cols, rows;
	dyn->GetDimensions(cols, rows);
	const FPoint3 yvec(0,100,0);

	for (int c = 0; c < cols; c++)
	{
		for (int r = 0; r < rows; r++)
		{
			FPoint3 wpos;
			dyn->GetWorldLocation(c, r, wpos);

			if (wpos.x < (sph.center.x - sph.radius))
				continue;
			if (wpos.x > (sph.center.x + sph.radius))
				continue;
			if (wpos.z < (sph.center.z - sph.radius))
				continue;
			if (wpos.z > (sph.center.z + sph.radius))
				continue;

			// Shoot a ray upwards through the terrain surface point
			vtHitList HitList;
			int iNumHits = vtIntersect(node, wpos - yvec, wpos + yvec, HitList);
			if (iNumHits)
			{
				FPoint3 pos = HitList.front().point;

				dyn->SetElevation(c, r, pos.y);
				changed++;
			}
		}
	}
	if (changed != 0)
	{
		wxString msg;
		msg.Printf(_T("Adjusted %d heixels.  Re-shade the terrain?"), changed);
		int res = wxMessageBox(msg, _T(""), wxYES_NO, this);

		if (res == wxYES)
		{
			// Update the (entire) shading and culture
			EnableContinuousRendering(false);
			OpenProgressDialog(_("Recalculating Shading"), _T(""), false, this);

			terr->ReshadeTexture(vtGetTS()->GetSunLightTransform(), progress_callback);
			DRECT area;
			area.SetToZero();
			terr->RedrapeCulture(area);

			CloseProgressDialog();
			EnableContinuousRendering(true);
		}
	}
}
Пример #2
0
void EnviroFrame::OnChar(wxKeyEvent& event)
{
	static NavType prev = NT_Normal;
	vtTerrain *pTerr = g_App.GetCurrentTerrain();
	long key = event.GetKeyCode();

	// Keyboard shortcuts ("accelerators")
	switch (key)
	{
	case 27:
		// Esc: cancel a building or linear we're making
		if (g_App.m_mode == MM_BUILDINGS && g_App.IsMakingElastic())
			g_App.CancelElastic();
		else if (g_App.m_mode == MM_LINEARS && g_App.IsMakingElastic())
			g_App.CancelElastic();
		else	// or exit the application
		{
			// It's not safe to close immediately, as that will kill the canvas,
			//  and it might some Canvas event that caused us to close.  So,
			//  simply stop rendering, and delay closing until the next Idle event.
			m_canvas->m_bRunning = false;
			m_bCloseOnIdle = true;
		}
		break;

	case ' ':
		if (g_App.m_state == AS_Terrain)
			ToggleNavigate();
		break;

	case 'f':
		ChangeFlightSpeed(1.8f);
		break;
	case 's':
		ChangeFlightSpeed(1.0f / 1.8f);
		break;
	case 'a':
		g_App.SetMaintain(!g_App.GetMaintain());
		break;

	case '+':
		SetTerrainDetail(GetTerrainDetail()+1000);
		break;
	case '-':
		SetTerrainDetail(GetTerrainDetail()-1000);
		break;

	case 'd':
		// Toggle grab-pivot
		if (g_App.m_nav == NT_Grab)
			g_App.SetNavType(prev);
		else
		{
			prev = g_App.m_nav;
			g_App.SetNavType(NT_Grab);
		}
		break;

	case 'w':
		m_bAlwaysMove = !m_bAlwaysMove;
		if (g_App.m_pTFlyer != NULL)
			g_App.m_pTFlyer->SetAlwaysMove(m_bAlwaysMove);
		break;

	case '[':
		{
			float exag = pTerr->GetVerticalExag();
			exag /= 1.01;
			pTerr->SetVerticalExag(exag);
		}
		break;
	case ']':
		{
			float exag = pTerr->GetVerticalExag();
			exag *= 1.01;
			pTerr->SetVerticalExag(exag);
		}
		break;

	case 'e':
		m_bEarthLines = !m_bEarthLines;
		g_App.ShowEarthLines(m_bEarthLines);
		break;

	case 'y':
		// Example code: modify the terrain by using the (slow) approach of using
		//  vtTerrain methods GetInitialGrid and UpdateElevation.
		{
			vtTerrain *pTerr = g_App.GetCurrentTerrain();
			if (pTerr && pTerr->GetParams().GetValueBool(STR_ALLOW_GRID_SCULPTING))
			{
				vtElevationGrid	*grid = pTerr->GetInitialGrid();
				if (grid)
				{
					clock_t t1 = clock();
					// Raise an area of the terrain
					int cols, rows;
					grid->GetDimensions(cols, rows);
					for (int i  = cols / 4; i < cols / 2; i++)
						for (int j = rows / 4; j < rows / 2; j++)
						{
							grid->SetFValue(i, j, grid->GetFValue(i, j) + 40);
						}
					pTerr->UpdateElevation();
					clock_t t2 = clock();
					VTLOG(" Modify1: %.3f sec\n", (float)(t2-t1)/CLOCKS_PER_SEC);

					// Update the shading and culture
					pTerr->ReshadeTexture(vtGetTS()->GetSunLightTransform());
					DRECT area;
					area.SetToZero();
					pTerr->RedrapeCulture(area);
				}
			}
		}
		break;
	case 'Y':
		// Example code: modify the terrain by using the (fast) approach of using
		//  vtDynTerrainGeom::SetElevation.
		{
			vtTerrain *pTerr = g_App.GetCurrentTerrain();
			if (pTerr)
			{
				vtDynTerrainGeom *dyn = pTerr->GetDynTerrain();
				if (dyn)
				{
					clock_t t1 = clock();
					// Raise an area of the terrain
					int cols, rows;
					dyn->GetDimensions(cols, rows);
					for (int i  = cols / 4; i < cols / 2; i++)
						for (int j = rows / 4; j < rows / 2; j++)
						{
							dyn->SetElevation(i, j, dyn->GetElevation(i, j) + 40);
						}
					clock_t t2 = clock();
					VTLOG(" Modify2: %.3f sec\n", (float)(t2-t1)/CLOCKS_PER_SEC);

					// Update the shading and culture
					pTerr->ReshadeTexture(vtGetTS()->GetSunLightTransform());
					DRECT area;
					area.SetToZero();
					pTerr->RedrapeCulture(area);
				}
			}
		}
		break;
	case 'u':
		// Example code: modify a small area of terrain around the mouse pointer.
		{
			vtTerrain *pTerr = g_App.GetCurrentTerrain();
			if (pTerr)
			{
				vtDynTerrainGeom *dyn = pTerr->GetDynTerrain();
				if (dyn)
				{
					// Get 3D cursor location in grid coordinates
					FPoint3 fpos;
					g_App.m_pTerrainPicker->GetCurrentPoint(fpos);
					IPoint2 ipos;
					dyn->WorldToGrid(fpos, ipos);
					for (int x  = -4; x < 4; x++)
						for (int y = -4; y < 4; y++)
						{
							float val = dyn->GetElevation(ipos.x + x, ipos.y + y);
							dyn->SetElevation(ipos.x + x, ipos.y + y, val + 40);
						}

					// Update the (entire) shading and culture
					pTerr->ReshadeTexture(vtGetTS()->GetSunLightTransform());
					DRECT area;
					area.SetToZero();
					pTerr->RedrapeCulture(area);
				}
			}
		}
		break;
	case 'D':	// Shift-D
		// dump camera info
		g_App.DumpCameraInfo();
		break;

	case 2:	// Ctrl-B
		// toggle demo
		g_App.ToggleDemo();
		break;

	case WXK_F11:
		DoTestCode();
		break;

	case WXK_F12:
		m_pSceneGraphDlg->Show(true);
		break;

	case WXK_DELETE:
		DeleteAllSelected();
		break;

	default:
		event.Skip();
		break;
	}
}
Пример #3
0
bool vtElevLayer::ImportFromFile(const wxString &strFileName,
	bool progress_callback(int), vtElevError *err)
{
	// Avoid trouble with '.' and ',' in Europe - all the file readers assume
	//  the default "C" locale.
	ScopedLocale normal_numbers(LC_NUMERIC, "C");

	wxString strExt = strFileName.AfterLast('.');
	vtString fname = (const char *) strFileName.mb_str(wxConvUTF8);

	VTLOG("ImportFromFile '%s'\n", (const char *) fname);

	if (!strExt.CmpNoCase(_T("gz")))
	{
		// ignore .gz, look at extension under it
		wxString dropped = strFileName.Left(strFileName.Len()-3);
		strExt = dropped.AfterLast('.');
	}

	if (!strExt.CmpNoCase(_T("bz2")))
	{
		// ignore .bz2, look at extension under it
		wxString dropped = strFileName.Left(strFileName.Len()-4);
		strExt = dropped.AfterLast('.');
	}

	// The first character in the file is useful for telling which format
	// the file really is.
	FILE *fp = vtFileOpen(fname, "rb");
	char first = fgetc(fp);
	fclose(fp);

	bool success = false;

	if (!strExt.CmpNoCase(_T("dxf")))
	{
		m_pTin = new vtTin2d;
		success = m_pTin->ReadDXF(fname, progress_callback);
	}
	else
	if (!strFileName.Right(6).CmpNoCase(_T("xy.adf")))
	{
		m_pTin = new vtTin2d;
		success = m_pTin->ReadADF(fname, progress_callback);
	}
	else
	if (!strFileName.Right(4).CmpNoCase(_T(".tin")))
	{
		m_pTin = new vtTin2d;
		success = m_pTin->ReadGMS(fname, progress_callback);
	}
	else
	if (!strFileName.Right(4).CmpNoCase(_T(".ply")))
	{
		m_pTin = new vtTin2d;
		success = m_pTin->ReadPLY(fname, progress_callback);
	}
	else
	{
		if (m_pGrid == NULL)
			m_pGrid = new vtElevationGrid;
	}

	if (!strExt.CmpNoCase(_T("3tx")))
	{
		success = m_pGrid->LoadFrom3TX(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("dem")))
	{
		// If there is a .hdr file in the same place, it is most likely
		//  a GTOPO30/SRTM30 file
		vtString hdr_fname = ChangeFileExtension(fname, ".hdr");
		if (vtFileExists(hdr_fname))
			success = m_pGrid->LoadFromGTOPO30(hdr_fname, progress_callback);
		else
		{
			if (first == '*')
				success = m_pGrid->LoadFromMicroDEM(fname, progress_callback);
			else
				success = m_pGrid->LoadFromDEM(fname, progress_callback, err);
		}
	}
	else if (!strExt.CmpNoCase(_T("asc")))
	{
		success = m_pGrid->LoadFromASC(fname, progress_callback);
		// vtElevationGrid does have its own ASC reader, but use GDAL instead
//		success = m_pGrid->LoadWithGDAL(strFileName.mb_str(wxConvUTF8), progress_callback, err);
	}
	else if (!strExt.CmpNoCase(_T("bil")))
	{
		success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
	}
	else if (!strExt.CmpNoCase(_T("mem")))
	{
		success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
	}
	else if (!strExt.CmpNoCase(_T("ter")))
	{
		success = m_pGrid->LoadFromTerragen(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("cdf")))
	{
		success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
	}
	else if (!strExt.CmpNoCase(_T("hdr")))
	{
		success = m_pGrid->LoadFromGTOPO30(fname, progress_callback);
		if (!success)
			success = m_pGrid->LoadFromGLOBE(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("dte")) ||
			!strExt.CmpNoCase(_T("dt0")) ||
			!strExt.CmpNoCase(_T("dt1")) ||
			!strExt.CmpNoCase(_T("dt2")))
	{
		success = m_pGrid->LoadFromDTED(fname, progress_callback);
	}
	else if (!strExt.Left(3).CmpNoCase(_T("pgm")))
	{
		success = m_pGrid->LoadFromPGM(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("grd")))
	{
		// might by CDF, might be Surfer GRD
		if (first == 'D')
		{
			VTLOG("First character is 'D', attempting load as a Surfer Grid file.\n");
			success = m_pGrid->LoadFromGRD(fname, progress_callback);
		}
		else
		{
			VTLOG("First character is not 'D', attempting load as a netCDF file.\n");
			success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
		}
		if (!success)
		{
			VTLOG("Didn't load successfully, attempting load with GDAL.\n");
			// Might be 'Arc Binary Grid', try GDAL
			success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
		}
	}
	else if (!strFileName.Right(8).CmpNoCase(_T("catd.ddf")) ||
			!strExt.Left(3).CmpNoCase(_T("tif")) ||
			!strExt.Left(3).CmpNoCase(_T("png")) ||
			!strExt.Left(3).CmpNoCase(_T("img")) ||
			!strExt.CmpNoCase(_T("adf")))
	{
		if (m_pGrid)
			success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
	}
	else if (!strExt.CmpNoCase(_T("raw")))
	{
		RawDlg dlg(NULL, -1, _("Raw Elevation File"));

		dlg.m_iBytes = 2;
		dlg.m_iWidth = 100;
		dlg.m_iHeight = 100;
		dlg.m_fVUnits = 1.0f;
		dlg.m_fSpacing = 30.0f;
		dlg.m_bBigEndian = false;
		dlg.m_extents.SetToZero();
		g_bld->GetProjection(dlg.m_original);

		if (dlg.ShowModal() == wxID_OK)
		{
			success = m_pGrid->LoadFromRAW(fname, dlg.m_iWidth,
					dlg.m_iHeight, dlg.m_iBytes, dlg.m_fVUnits, dlg.m_bBigEndian,
					progress_callback);
		}
		if (success)
		{
			m_pGrid->SetEarthExtents(dlg.m_extents);
			m_pGrid->SetProjection(dlg.m_proj);
		}
	}
	else if (!strExt.CmpNoCase(_T("ntf")))
	{
		success = m_pGrid->LoadFromNTF5(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("txt")) ||
		!strExt.CmpNoCase(_T("xyz")))
	{
		success = m_pGrid->LoadFromXYZ(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("hgt")))
	{
		success = m_pGrid->LoadFromHGT(fname, progress_callback);
	}
	else if (!strExt.Left(2).CmpNoCase(_T("db")))
	{
		success = ImportFromDB(fname, progress_callback);
	}
	if (!success)
		return false;

	vtProjection *pProj;
	if (m_pGrid)
		pProj = &m_pGrid->GetProjection();
	else
		pProj = &m_pTin->m_proj;

	// We should ask for a CRS before asking for extents
	if (!g_bld->ConfirmValidCRS(pProj))
	{
		if (err)
		{
			err->type = vtElevError::CANCELLED;
			err->message = "Cancelled";
		}
		return false;
	}

	if (m_pGrid != NULL)
	{
		if (m_pGrid->GetEarthExtents().IsEmpty())
		{
			// No extents.
			wxString msg = _("File lacks geographic location (extents). Would you like to specify extents?\n Yes - specify extents\n No - use some default values\n");
			int res = wxMessageBox(msg, _("Elevation Import"), wxYES_NO | wxCANCEL);
			if (res == wxYES)
			{
				DRECT ext;
				ext.SetToZero();
				ExtentDlg dlg(NULL, -1, _("Elevation Grid Extents"));
				dlg.SetArea(ext, (pProj->IsGeographic() != 0));
				if (dlg.ShowModal() == wxID_OK)
					m_pGrid->SetEarthExtents(dlg.m_area);
				else
					return false;
			}
			if (res == wxNO)
			{
				// Just make up some fake extents, assuming a regular even grid
				int xsize, ysize;
				m_pGrid->GetDimensions(xsize, ysize);

				DRECT ext;
				ext.left = ext.bottom = 0;
				if (pProj->IsGeographic())
				{
					ext.right = xsize * (1.0/3600);	// arc second
					ext.top = ysize * (1.0/3600);
				}
				else
				{
					ext.right = xsize * 10;	// 10 linear units (meters, feet..)
					ext.top = ysize * 10;
				}
				m_pGrid->SetEarthExtents(ext);
			}
			if (res == wxCANCEL)
			{
				if (err)
				{
					err->type = vtElevError::CANCELLED;
					err->message = "Cancelled";
				}
				return false;
			}
		}
		m_pGrid->SetupLocalCS(1.0f);
	}
	return true;
}