# DEMO示例

# 简介

材质在产品中使用的效果基于具体引擎对材质数据的表现能力,同时材质从通过SDK下载下来到在实际场景中渲染出效果是一个比较复杂的过程。本篇章给出的demo程序,简单演示了用户如何通过SDK下载并缓存材质数据及如何自定义材质库网页版界面之后通过SDK创建材质库对话框,最后给出一些效果图以说明材质在真实的产品中对场景表现效果的影响。

# 准备工作

  • 点击下载SDKDemo.zip
  • 解压SDKDemo.zip到本地任意目录,如F:/Source/,则文件目录如下: demo文件
  • 双击SDK文件夹中的Install_1.1.0.9784.exe文件安装材质库本地系统服务;
  • 获取用户token;此步可参考材质库快速启动
  • 获取产品库id(由产品管理员通过材质库后台管理工具创建产品库);

注意

demo运行环境为Visual Studio 2017,依赖QT5.6.3,仅支持64位Release版本运行。

# 材质数据下载演示demo

此demo以单元测试的方式演示了如何调用SDK对外提供的接口,包括获取材质分类信息、获取某分类对应的材质信息、下载材质、下载缩略图等。

1.demo演示效果

demo成功运行之后,在路径Demo1\Source\Example\TestFiles下可查看到材质json文件、缩略图、纹理等缓存文件: demo2演示效果

2.关键点说明

key1:参数设置

使用准备工作中获取到的用户token及产品库id替换main.cpp中对应变量的值。

  // main.cpp
  const QString CTestHelper::m_libId = "d52604fa6fbc4782b9c1d43e6869dfbc"; //测试库的id
  const QString CTestHelper::m_token = "cn-e7cbe91b-2ec7-455e-bd5c-26c8ce148c43"; //用户token

1
2
3
4

key2:修改测试用例

目前demo中访问的库是开发者根据 材质库快速启动 开通材质库服务之后创建的测试库,测试案例中下载数据对象都属于此库,用户需根据自定义的产品库在对应的案例中修改需要下载的数据对象。

TEST(MaterialRequestHandler, RequestMaterialListByCategoryTest)
{
    ...
    categoryId = "18df72509769411488d505c3fcce4970"; // 用户自定义产品库中具体某一级分类id
    ...
}

TEST(MaterialRequestHandler, DownloadThumbnailsByIdTest)
{
    ...
    // 设置用户自定义产品库中多个材质的id,以分号分隔
    QString matIds = "6bb43bb081f2405d84a5c91501f7817f;013299660c82550c35176b6135a123627ba941eb;2d552e53cf97dda5ef8150e80f40a9e5483e40d9";
    ...
}
 
TEST(MaterialRequestHandler, DownloadMaterialTest)
{
    ...
    matId = "6797812f7ce43c4efb2b789cddd6e7bc"; // 设置用户自定义产品库中某个材质的id
    ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

:::

key3:重新实现回调类

从云端获取数据的接口为异步调用,当调用返回时会调用回调方法执行后续操作。SDK提供了纯虚回调基类IViewAdapter,需要产品端继承实现其中的回调方法,参考demo中的CTestClientAdapter类,在回调方法中可对返回的数据进行操作,触发UI更新等,如:

void CTestClientAdapter::onThumbnailLoadProgress(const QString& result)
{
    EXPECT_TRUE(!result.isEmpty());

    QString filePath = GetFilePath(result, "Thumbnails", CTestHelper::m_engineType);
    ASSERT_TRUE(!filePath.isEmpty());

    qDebug() << "SDK: Get thumbnail succeed!" << endl;
}
1
2
3
4
5
6
7
8
9

# 自定义用户界面演示demo

此demo给出了用户自定义网页版材质库界面之后如何通过SDK创建材质库对话框,同时演示了产品库所有材质的缩略图展示效果与单击预览功能。

1.demo演示效果

demo2演示效果

2.关键点说明

key1:参数设置

使用准备工作中获取到的用户token及产品库id替换main.cpp中对应变量的值。

  // main.cpp
    QString userToken = "cn-7ae9062a-f3d0-4ab5-a08c-4b6fb6889197";
    QString libIdList = "d52604fa6fbc4782b9c1d43e6869dfbc";
1
2
3

key2:自定义UI

用户自定义材质库界面基于CEF实现,参考Demo2\Source\UI,使用VSCode打开该文件夹,点击左下角build按钮,会在Demo2\Source目录下生成Material.jsui文件;

注意

自定义材质库网页版UI,需要具备js、html5、css等开发技能,了解Vue框架,此外还需要对CEF中js与C++的通信机制比较了解。

key3:实现材质库对话框

此处以QT的QDialog作为父窗口举例说明。

  1. 继承并实现QDialog作为材质库对话框最外成的父窗口,一般无边框模式下需要自己实现窗口拖动、缩放等功能,参考GMaterialLibraryDialog.cpp;
  2. 通常UI文件Material.jsui会拷贝到应用程序exe所在目录,在代码中获取全路径作为参数调用SDK的CreateChildWindow接口创建子窗口并返回其句柄,将其嵌入到父窗口QDialog中即可,具体实现参考CMaterialLibDialog构造函数,关键代码如下:
CMaterialLibDialog::CMaterialLibDialog(const QString& htmlZipPath, const QString& token,
    const QString& libIdList, const QString& productCode, const QString& engineType, QWidget* parent)
{
    if (m_handler != nullptr && m_handler->GetSharedMemoryError() == QSharedMemory::NoError)
    {
        QString res = m_handler->CreateChildWindow("GGP", htmlZipPath, (HWND)this->winId());
        m_child = HWND(res.toLongLong());
        if (m_child != nullptr)
        {
            QWindow* window = QWindow::fromWinId(WId(m_child));
            QWidget* childWidget = nullptr;
            if (window)
            {
                window->setFlags(window->flags() | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
                childWidget = QWidget::createWindowContainer(window, this, Qt::Widget);
                layout->addWidget(childWidget);
            }
        }
    }
    this->setLayout(layout);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

key4:父子窗口通信

  1. 父窗口通过SendMessage方法向子窗口发送消息,参考SendUserMessage函数的实现,子窗口接收到消息之后会直接转发给js,因此该函数的参数param1为js中监听事件名,param2为包含所需传递参数的Json字符串:
// messageType一般等于"SendCustomizedEvent"
void CMaterialLibDialog::SendUserMessage(const QString& messageType, const QString& param1, const QString& param2)
{
  //具体实现见demo
}
1
2
3
4
5
  1. 父窗口重新实现QWidget的nativeEvent函数,接受并处理子窗口发送过来的消息。消息来自js的invokeMethod方法,在子窗口中包装后转发到父窗口,通常包含消息类型及需要携带的参数:
bool CMaterialLibDialog::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    if (eventType == "windows_generic_MSG")
    {
        MSG* msg = reinterpret_cast<MSG*>(message);
        if (msg->message == WM_COPYDATA)
        {
            COPYDATASTRUCT *data = reinterpret_cast<COPYDATASTRUCT*>(msg->lParam);
            QString recevice = QString::fromUtf8((char*)data->lpData, (int)data->cbData);

            // 解析消息,并响应相关事件
            ...

            return true;
        }
    }
    return QWidget::nativeEvent(eventType, message, result);//交给Qt处理
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 产品使用案例

材质库在BIMDeco产品中的实际应用。

注:BIMDeco产品同时集成了图形平台Falcon渲染器,材质库本身已经支持Falcon渲染器;因此BIMDeco可以把应用材质数据的场景无缝导入Falcon渲染器,实现更好的效果展示。

  • 未使用材质的效果 未使用材质库

  • 使用材质库,应用材质数据 使用材质库

  • 使用材质后的效果 使用材质库效果

  • 场景导入Falcon渲染器的效果 Falcon效果

  • 在线客服

  • 意见反馈