SuperMap iObjects for C++ 构建三维场景与加载模型数据

 

       在前一篇SuperMap C++ 组件开发环境快速搭建(VS + Qt)中,讲述了如何进行SuperMap iObjects for C++ 二次开发工程的配置,以及创建地图窗口显示地图。本篇将介绍如何创建三维场景窗口,打开三维场景,以及加载模型数据。本篇仅以VS开发为例。

1. 创建一个基于对话框的MFC的应用项目FirstSuperMap3D

    工程配置此处就不再详细讲述了,使用三维需增加三维的链接库,如下:

SuGeometry3Dd.lib
SuGraphics3Dd.lib
SuRenderd.lib
SuScened.lib
SuSceneEditord.lib
SuFMELicensed.lib
SuNetToolkitd.lib

2. 创建三维场景类: SceneControl

       SceneControl 主要用于封装 SuperMap 的场景,实现通用的功能,以方便在不同的窗口类中加载。

SeneControl.h 的部分内容如下所示:

#ifndef SCENECONTROL_H
#define SCENECONTROL_H

#include "MapEditor/UGMapEditorWnd.h"
#include "Graphics/UGGraphicsManager.h"
#include "Drawing/UGDrawParamaters.h"
#include "Scene/UGScene3D.h"
#include "SceneEditor/UGSceneEditorWnd.h"
#include "Scene/UGRoot3D.h"
#include "Graphics3D/UGRenderTarget.h"
#include "Scene/UGLayer3Ds.h"

using namespace UGC;

class  SceneControl
{
	//Constructor
public:
	/*
	 *@en
	 *@pWndHandle  window's handle, (HWND)CWnd::m_hWnd in MFC, (HWND)QWidget::winId() in Qt
	 *@dpiX        logical dpi in horizontal
	 *@dpiY        logical dpi in vertical
	*/
	SceneControl(void* pWndHandle, int dpiX, int dpiY);
	virtual ~SceneControl();

	// members
private:
	//@en the handle of view which providing a window for scene
	void* m_pWnd;

...

SceneControl.cpp 的部分内容如下:

#include "stdafx.h"
#include "SceneControl.h"

SceneControl::SceneControl(void* pWndHandle, int dpiX, int dpiY)
{
	m_pUGSceneWnd = NULL;
	//m_pRoot3D = NULL;
	m_pCameraWorld = NULL;

	m_IsMinSized = false;

	Initialize(pWndHandle, dpiX, dpiY);

	m_pInnerWorkspace = new UGWorkspace();
	m_pWorkspace = NULL;
	SetWorkspace(m_pInnerWorkspace);

	mIsInWorkspace = false;
}

...

3. 将 SceneControl 添加到窗口类 FirstSuperMap3DDlg 

      需要注意的是,三维场景的绘制,需要一个定时器,来定时刷新场景,并且在界面需要显示,才需要刷新场景,所以我们在OnSize()函数中开启定时器。

    (1)  在 FirstSuperMap3DDlg.h 头文件中引入需要的头文件,定义需要的变量、绘制函数和鼠标事件函数等等,如下所示

#include "SceneControl.h"

// 定义TimerID
class TimerIDs
{
public:
	static const UINT_PTR ID_RENDER3D = 1;
	static const UINT  PERIOD_RENDER3D = 30;
};

...

	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void OnSize(UINT nType, int cx, int cy);

	DECLARE_MESSAGE_MAP()

private:
	SceneControl* m_pSceneControl;
	UINT_PTR mRender3DTimerID;
	bool mIsVisible;

public:
	SceneControl* GetSceneControl();
	void RenderInTimer();

    (2) FirstSuperMap3DDlg.cpp 中实现上述函数,部分内容如下:

... 

void CALLBACK TimerRender3D(HWND hWnd, UINT nMsg, UINT_PTR nTimerid, DWORD dwTime)
{

	if (hWnd != NULL)
	{
		CWnd* pWnd = CWnd::FromHandle(hWnd);
		string targetName = "class SceneView";
		string wndName = typeid(*pWnd).name();
		if (typeid(*pWnd) == typeid(FirstSuperMap3DDlg))
		{
			FirstSuperMap3DDlg* pDlg = (FirstSuperMap3DDlg*)pWnd;
			pDlg->RenderInTimer();
		}
	}
}

// Message Handlers


void FirstSuperMap3DDlg::OnPaint()
{

	CPaintDC dc(this); // device context for painting
	CRect rect;
	GetClientRect(&rect);
	m_pSceneControl->OnDraw(rect.left, rect.top, rect.right, rect.bottom, dc.m_hDC);

	CDialogEx::OnPaint();

}


...

 运行效果,如下图所示:

3. 打开工作空间和三维场景

     这里我们打开iDesktop 提供的示例数据CBD,在 OnSize() 函数中初始化 SceneControl 后,打开CBD工作空间,打开其保存的场景,如下所示:

// Open workspace file
UGString wkPath = _U("F:\\JunSuperMap\\2 SuperMapData\\iDesktop\\10i\\SampleData\\3D\\CBDDataset\\CBD.smwu");

UGWorkspaceConnection wkCon;

wkCon.m_strServer = wkPath;
wkCon.m_nWorkspaceType = UGWorkspace::WS_Version_SMWU;

UGWorkspace* pWorkspace = m_pSceneControl->GetWorkspace();
if (pWorkspace->Open(wkCon))
{
	UGString sceneName = pWorkspace->m_SceneStorages.GetNameAt(0);

	m_pSceneControl->OpenScene(sceneName);
			
}

 运行后如图所示:

4. 添加模型数据集

    有时我们可能需要添加自己的模型数据集,如我们打开一个空场景,然后添加一个模型数据集。因此我们将前面的打开场景,改为添加一个模型数据集。代码如下:

// 添加模型数据集
UGString ugDatasourceName = pWorkspace->m_DataSources.GetAliasAt(0);
UGDataset* pDataset = pWorkspace->GetDataSource(ugDatasourceName)->GetDataset(_U("Building"));
UGString ugDatasetName = pDataset->GetName();
UGString ugLayerName = ugDatasetName + _U("@") + ugDatasourceName; // 数据集名@数据源名,图层默认命名格式,也是通过该格式的名称获得关联数据

UGDataset::DatasetType datasetType = pDataset->GetType();
UGLayer3D* pLayer = m_pSceneControl->GetSceneEditWnd()->GetScene3D()->m_Layers.AddLayer(ugLayerName);
		
if (pLayer != NULL)
{
	// 显示到数据集范围
	m_pSceneControl->GetSceneEditWnd()->GetScene3D()->GetCamera(_U("Camera"))->FlyToBounds(pLayer->GetBounds(), 1);
	if (datasetType == UGDataset::/*DatasetType::*/Model || datasetType == UGDataset::/*DatasetType::*/CAD)
	{
		// 此处仅设置一个三维风格,以达到启用目的
		// 其他风格可根据需要设置
		UGStyle3D style3D;
		style3D.SetFill3DMode(UGC::/*UGFill3DMode::*/FILL_FACE);
		pLayer->SetStyle3D(style3D);
	}
}

运行效果如图所示:

5. 添加倾斜摄影

     同样,我们使用 iDesktop 提供的示例数据(OSGB),直接将.scp文件添加到场景中。因为是添加倾斜摄影数据,有scp配置文件即可,就不用打开工作空间文件了。将前面的代码修改为:

// 添加倾斜摄影数据,使用scp配置文件
UGString scp(_U("F:\\JunSuperMap\\2 SuperMapData\\iDesktop\\10i\\SampleData\\3D\\OSGB\\compressed.scp"));

UGLayer3D* pLayerSCP = m_pSceneControl->GetSceneEditWnd()->GetScene3D()->m_Layers.AddLayer(scp);
if (pLayerSCP != NULL)
{
	// 显示到数据集范围
	m_pSceneControl->GetSceneEditWnd()->GetScene3D()->GetCamera(_U("Camera"))->FlyToBounds(pLayerSCP->GetBounds(), 1);
}

运行效果如图所示:

 

        以上就是本篇的内容,希望通过本文的介绍,能帮助有需要使用SuperMap iObjects for C++ 产品进行开发的朋友,快速搭建起三维开发的环境。文中提到的数据,都来自 iDesktop 的示例数据,并且文件较大,这里就不提供了,有需要的朋友可以在超图软件的“技术资源中心”下载。当然,使用自己的数据也是可以的。示例程序请通过页面上方的资源下载。

更多功能,请参考GitHub项目https://github.com/Jun0x01/JunSuCpp

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值