Всем привет! Я работаю в компании Renga Software (совместное предприятие АСКОН и фирмы «1С»), которая занимается разработкой BIM-систем: Renga Architecture — для архитектурно-строительного проектирования и Renga Structure — для проектирования конструктивной части зданий и сооружений.
В этой статье хочу поделиться опытом интеграции 3D-мыши в систему Renga.

3D-манипуляторы — это средства взаимодействия пользователя с программным обеспечением, которые обеспечивают интуитивную навигацию в трехмерном пространстве и возможность работать двумя руками одновременно. Инженеры-проектировщики и компании, которые внедрили 3D-манипуляторы, сообщают о внушительном приросте производительности.
Речь в статье пойдет о 3D-мыши от компании 3DСonnexion. Вот так она выглядит (картинка из интернетов):

У 3D-мышки 6 степеней свободы: смещение по осям X, Y, Z, а также поворот вокруг осей, соответственно: Roll, Pitch, Yaw.

Степени свободы мышки:

Для интеграции 3D-мыши в ваше приложение компания 3DСonnexion предоставляет SDK. Его можно скачать с сайта производителя после регистрации.
Продемонстрирую способ интеграции 3D-мыши в приложение на основе Qt5.
Создадим простое Qt приложение с помощью мастера новых проектов в Visual Studio.
Для работы с 3D-мышью нужно включить несколько заголовочных файлов из SDK:
Для того чтобы мышка заработала, ей нужно передать handle окна, куда мышка будет присылать сообщения. Напишем код инициализации мышки. Он будет выглядеть как-то так:
Теперь мышка подключена к нашему приложению и будет присылать в message loop нашего окна сообщения. Сообщение от мышки имеет следующую структуру:
Нас интересует тип события — SiSpwEvent::type. И SiSpwData::spwData — там находится информация о нажатых кнопках, перемещении и вращении по осям.
Наша задача отфильтровать сообщения от мышки. Для этого установим наш класс в качестве фильтра событий. Отнаследуемся от QAbstractNativeEventFilter и переопределим функцию nativeEventFilter:
На этом подключение мышки к нашему приложению завершено. Ссылка на полный код примера.
В этой статье хочу поделиться опытом интеграции 3D-мыши в систему Renga.

Подробнее о семействе продуктов Renga (Осторожно маркетинг!)
Renga Architecture – система для архитектурно-строительного проектирования. Программа создана для максимальной помощи проектировщику в решении его задач: создание архитектурного облика здания, информационной модели и быстрая компоновка чертежей согласно стандартам СПДС и многое другое.
Renga Structure — cистема для проектирования конструктивной части зданий/сооружений. Программа для инженеров-конструкторов и проектировщиков по созданию информационной модели здания или сооружения и получению чертежей марок КР/КЖ/КЖИ/КМ/АС.
Семейство продуктов Renga предназначено для проектирования по технологии BIM. Высокая производительность систем позволяет работать с большими проектами без видимого снижения качества работы с 3D-моделью:
Объектное проектирование
Создание в Renga 3D-модели здания/сооружения инструментами объектного проектирования (стена, колонна, окно и т.д.)
Коллективная работа
Обмен хранение и управление данными осуществляется с помощью BIM-Server Pilot
Взаимодействие со сметными системами
Интеграция Renga по средством API со сметными системами 1С-смета и ABC-смета для взаимодействия проектного и сметного отделов.
Обмен данными
Renga позволяет обмениваться данными с другими системами через различные форматы (.ifc, .dwg, .dxf, .obj, .dae, .stl, .3ds, .lwo и .csv)
Автоматизация получения спецификаций и ведомостей
В Renga реализована функция получения отчетов для формирования спецификаций, ведомостей и экспликаций.
Автоматизация получения чертежей
По данным 3D-модели автоматически получаются виды (фасады, разрезы и планы) и размещаются на чертежах в заданных масштабах.
Renga Structure — cистема для проектирования конструктивной части зданий/сооружений. Программа для инженеров-конструкторов и проектировщиков по созданию информационной модели здания или сооружения и получению чертежей марок КР/КЖ/КЖИ/КМ/АС.
Семейство продуктов Renga предназначено для проектирования по технологии BIM. Высокая производительность систем позволяет работать с большими проектами без видимого снижения качества работы с 3D-моделью:
Объектное проектирование
Создание в Renga 3D-модели здания/сооружения инструментами объектного проектирования (стена, колонна, окно и т.д.)
Коллективная работа
Обмен хранение и управление данными осуществляется с помощью BIM-Server Pilot
Взаимодействие со сметными системами
Интеграция Renga по средством API со сметными системами 1С-смета и ABC-смета для взаимодействия проектного и сметного отделов.
Обмен данными
Renga позволяет обмениваться данными с другими системами через различные форматы (.ifc, .dwg, .dxf, .obj, .dae, .stl, .3ds, .lwo и .csv)
Автоматизация получения спецификаций и ведомостей
В Renga реализована функция получения отчетов для формирования спецификаций, ведомостей и экспликаций.
Автоматизация получения чертежей
По данным 3D-модели автоматически получаются виды (фасады, разрезы и планы) и размещаются на чертежах в заданных масштабах.
3D-манипуляторы — это средства взаимодействия пользователя с программным обеспечением, которые обеспечивают интуитивную навигацию в трехмерном пространстве и возможность работать двумя руками одновременно. Инженеры-проектировщики и компании, которые внедрили 3D-манипуляторы, сообщают о внушительном приросте производительности.
Речь в статье пойдет о 3D-мыши от компании 3DСonnexion. Вот так она выглядит (картинка из интернетов):

У 3D-мышки 6 степеней свободы: смещение по осям X, Y, Z, а также поворот вокруг осей, соответственно: Roll, Pitch, Yaw.

Степени свободы мышки:

Для интеграции 3D-мыши в ваше приложение компания 3DСonnexion предоставляет SDK. Его можно скачать с сайта производителя после регистрации.
Продемонстрирую способ интеграции 3D-мыши в приложение на основе Qt5.
Создадим простое Qt приложение с помощью мастера новых проектов в Visual Studio.
Для работы с 3D-мышью нужно включить несколько заголовочных файлов из SDK:
// Mouse 3D stuff #include <spwmacro.h> /* Common macros used by SpaceWare functions. */ #include <si.h> /* Required for any SpaceWare support within an app.*/ #include <siapp.h> /* Required for siapp.lib symbols */ #include "virtualkeys.hpp"
Для того чтобы мышка заработала, ей нужно передать handle окна, куда мышка будет присылать сообщения. Напишем код инициализации мышки. Он будет выглядеть как-то так:
bool init3DMouse() { SiOpenData oData; /*init the SpaceWare input library */ if (SiInitialize() == SPW_DLL_LOAD_ERROR) return false; SiOpenWinInit(&oData, (HWND)winId()); /* init Win. platform specific data */ SiSetUiMode(mouse3DHandle, SI_UI_ALL_CONTROLS); /* Config SoftButton Win Display */ /* open data, which will check for device type and return the device handle to be used by this function */ if ( (mouse3DHandle = SiOpen ("HabrahabrAnd3DMouse", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData)) == NULL) { SiTerminate(); /* called to shut down the SpaceWare input library */ return false; /* could not open device */ } else { return true; /* opened device succesfully */ } }
Теперь мышка подключена к нашему приложению и будет присылать в message loop нашего окна сообщения. Сообщение от мышки имеет следующую структуру:
typedef struct /* 3DxWare event */ { int type; /* Event type */ union { SiSpwData spwData; /* Button, motion, or combo data */ SiSpwOOB spwOOB; /* Out of band message */ SiOrientation spwOrientation; /* Which hand orientation is the device */ char exData[SI_MAXBUF]; /* Exception data. Driver use only */ SiKeyboardData spwKeyData; /* String for keyboard data */ SiSyncPacket siSyncPacket; /* GUI SyncPacket sent to applications */ SiHWButtonData hwButtonEvent; /* V3DKey that goes with * * SI_BUTTON_PRESS/RELEASE_EVENT */ SiAppCommandData appCommandData; /* Application command event function data that * * goes with an SI_APP_EVENT event */ SiDeviceChangeEventData deviceChangeEventData; /* Data for connecting/disconnecting devices */ SiCmdEventData cmdEventData; /* V3DCMD_* function data that * * goes with an SI_CMD_EVENT event */ } u; } SiSpwEvent;
Нас интересует тип события — SiSpwEvent::type. И SiSpwData::spwData — там находится информация о нажатых кнопках, перемещении и вращении по осям.
Наша задача отфильтровать сообщения от мышки. Для этого установим наш класс в качестве фильтра событий. Отнаследуемся от QAbstractNativeEventFilter и переопределим функцию nativeEventFilter:
bool HabrahabrAnd3DMouse::nativeEventFilter(const QByteArray &eventType, void *msg, long *) { if(!mouse3DHandle) return false; MSG* winMSG = (MSG*)msg; bool handled = SPW_FALSE; SiSpwEvent Event; /* SpaceWare Event */ SiGetEventData EData; /* SpaceWare Event Data */ /* init Window platform specific data for a call to SiGetEvent */ SiGetEventWinInit(&EData, winMSG->message, winMSG->wParam, winMSG->lParam); /* check whether msg was a 3D mouse event and process it */ if (SiGetEvent (mouse3DHandle, SI_AVERAGE_EVENTS, &EData, &Event) == SI_IS_EVENT) { if (Event.type == SI_MOTION_EVENT) { qDebug() << "delta by X coordinate = " << Event.u.spwData.mData[SI_TX] << "\n"; qDebug() << "delta by Y coordinate = " << Event.u.spwData.mData[SI_TY] << "\n"; qDebug() << "delta by Z coordinate = " << Event.u.spwData.mData[SI_TZ] << "\n"; qDebug() << "delta by Yaw = " << Event.u.spwData.mData[SI_RX] << "\n"; qDebug() << "delta by Pitch = " << Event.u.spwData.mData[SI_RY] << "\n"; qDebug() << "delta by Roll = " << Event.u.spwData.mData[SI_RZ] << "\n"; } else if (Event.type == SI_ZERO_EVENT) { // ZERO event } else if (Event.type == SI_BUTTON_EVENT) { // misc button events } handled = SPW_TRUE; /* 3D mouse event handled */ } return handled; }
На этом подключение мышки к нашему приложению завершено. Ссылка на полный код примера.