К основному контенту

Интеграция 3D-мыши в Renga


Примерно неделю назад Александр Ершов - любитель новых технологий и двигатель прогресса в нашей команде - опубликовал статью на Хабре о том, как он интегрировал 3D-мышь в Renga. Для тех, кто еще не читал эту статью, но как Александр интересуется новыми технологиями, публикуем его статью в нашем блоге.
image   
3D-манипуляторы - это средства взаимодействия пользователя с программным обеспечением, которые обеспечивают интуитивную навигацию в трехмерном пространстве и возможность работать двумя руками одновременно. Инженеры-проектировщики и компании, которые внедрили 3D-манипуляторы, сообщают о внушительном приросте производительности. Речь в статье пойдет о 3D-мыши от компании 3DСonnexion. Вот так она выглядит (картинка из интернетов): 
image 
У 3D-мышки 6 степеней свободы: смещение по осям X, Y, Z, а также поворот вокруг осей, соответственно: Roll, Pitch, Yaw. 
image 
Степени свободы мышки: 
image 
Для интеграции 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;
}
На этом подключение мышки к нашему приложению завершено. Ссылка на полный код примера.

Комментарии

Популярные сообщения из этого блога

Под крышей дома моего....

Крыша - это главный атрибут любого дома, а особенно частного загородного дома, коттеджа. Она не только призвана защищать его от дождя, снега и палящего солнца, но и является украшением дома и улицы, притягивает взгляд соседей и прохожих.
В Renga Architecture инструмент Крыша позволяет строить самые разные модели крыши с помощью небольшого набора команд, но с первого взгляда не всегда ясно, как сделать её той или иной формы. Поэтому мы, Арина Соболева (инженер тех.поддержки) и Анастасия Тян (технический писатель), решили рассказать о разных тонкостях и нюансах работы с этим инструментом на примере нескольких загородных домов -  от простого к сложному. Проще всего в Renga Architecture создать четырехскатную вальмовую крышу. Здесь не надо менять никаких параметров, крыша строится по точкам, непрерывно (Рисунок 1). Чтобы её создать, один раз задаем Параметры сегмента (Рисунок 2) и указываем 4 точки по углам здания на 3D Виде. Построение крыши всегда завершается нажатием клавиши ENTER или совм…

Renga в реальных примерах

Сегодня хотим поговорить о примерах проектов, выполненных в Renga. Когда присматриваешься к новой программе, всегда хочется знать, на что она способна, а наши системы довольно молодые, найти в открытом доступе модели и чертежи, выполненные в ней, не просто. Быть может, даже не все текущие пользователи Renga знают, что в поставке систем Renga Architecture и Renga Structure есть примеры таких проектов. Они лежат в папке Samples, которую можно найти в папке установки программы. Если вы уже установили Renga, но еще не видели этих проектов, рекомендуем заглянуть в эту папочку. Помимо этих примеров на сайте Grabcad.com есть пара десятков небольших проектов, выполненных нами в процессе работы над Renga. Там выложены проекты разной степени проработанности и детализации, но тем не менее они наглядно демонстрируют возможности Renga. Найти их можно по запросу renga в поиске grabcad.com. Все модели можно скачать в формате rnp, открыть в Renga и посмотреть, как они сделаны. Тем, кто совсем не зна…

Виртуальная реальность в Renga

Возможно, тот, кто посещал мероприятия АСКОН и Renga Software, обратил внимание, что модели зданий, созданные в Renga, демонстрировались всем желающим в шлеме виртуальной реальности Oculus Rift. Уже осенью пользователи Renga смогут сами смотреть и показывать заказчикам свои проекты в шлеме. Есть только один минус ㅡ придется приобрести Oculus Rift. А подключить его к Renga Architecture или Renga Structure не составит труда: В настройках приложения появится новая опция ㅡ Отображать команду “Виртуальная реальность” на 3D Виде. Её нужно включить. Кроме того, в настройках можно перейти в режим навигации Управление камерой, чтобы было удобнее ходить по зданию.После этого в нижнем левом углу Renga появится кнопочка Виртуальная реальность, если её нажать, то изображение преобразится.И voilà, можно надевать шлем и путешествовать по модели. При этом можно передвигаться по зданию как с помощью обычной мышки и клавиатуры, так и с помощью 3D-мыши.
Вот и все премудрости. А о технических подробност…