📜 ⬆️ ⬇️

3D mouse integration in Renga

Hello! I work at Renga Software (a joint venture between ASCON and 1C), which develops BIM systems: Renga Architecture for architectural and building design and Renga Structure for designing the structural part of buildings and structures.

In this article I want to share the experience of integrating a 3D mouse into the Renga system.
image

Read more about the Renga product family (Careful marketing!)
Renga Architecture - a system for architectural and construction design. The program was created for maximum assistance to the designer in solving his tasks: the creation of the architectural appearance of the building, the information model and the quick layout of the drawings according to the standards of SPDS and much more.

Renga Structure - a system for designing structural parts of buildings / structures. A program for design engineers and designers to create an information model of a building or structure and to obtain drawings of KR / KZh / KZH / KM / AU brands.
')
The Renga product family is designed for BIM design. High system performance allows you to work with large projects without a visible reduction in the quality of work with the 3D model:

Object Design
Creation in Renga of a 3D model of a building / structure with object design tools (wall, column, window, etc.)

Teamwork
Sharing storage and data management is carried out using BIM-Server Pilot
Interaction with estimated systems
Renga integration by means of API with 1C-estimate budget systems and ABC estimates for interaction between project and budget departments.

Data exchange
Renga allows you to exchange data with other systems through various formats (.ifc, .dwg, .dxf, .obj, .dae, .stl, .3ds, .lwo and .csv)

Automate the receipt of specifications and statements
Renga has the function of receiving reports for the formation of specifications, statements and explications.

Automation of drawing
According to the data of the 3D model, views are automatically obtained (facades, sections and plans) and placed on the drawings in the specified scales.


3D manipulators are the means of user interaction with software that provide intuitive navigation in three-dimensional space and the ability to work with both hands simultaneously. Design engineers and companies that have implemented 3D manipulators have reported impressive performance gains.

The article will focus on the 3D-mouse from the company 3DConnexion. This is how it looks (picture from the Internet):

image

The 3D mouse has 6 degrees of freedom: the displacement along the X, Y, Z axes, and the rotation around the axes, respectively: Roll, Pitch, Yaw.

image

Mouse degrees of freedom:

image

To integrate a 3D mouse into your application, 3DConnexion provides an SDK. It can be downloaded from the manufacturer’s site after registration.

I will demonstrate how to integrate a 3D mouse into a Qt5 based application.
Create a simple Qt application using the wizard of new projects in Visual Studio.

To work with a 3D mouse, you need to include several header files from the 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" 

In order for the mouse to work, it needs to transfer the window handle to where the mouse will send messages. We write the initialization code of the mouse. It will look something like this:

 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 */ } } 

Now the mouse is connected to our application and will send a message loop to the message loop of our window. The message from the mouse has the following structure:

 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; 

We are interested in the type of event - SiSpwEvent :: type . And SiSpwData :: spwData - there is information about the pressed buttons, movement and rotation along the axes.

Our task is to filter messages from the mouse. To do this, set our class as an event filter. Inherit from QAbstractNativeEventFilter and override the nativeEventFilter function:

 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; } 

This completes the connection of the mouse to our application. Link to the complete code of the example.

Source: https://habr.com/ru/post/332676/


All Articles