CGTalk > Software Specific Forums > Maxon Cinema 4D
Login register
Thread Closed share thread « Previous Thread | Next Thread »
 
Thread Tools Search this Thread Display Modes
Old 01-03-2013, 11:47 PM   #16
Cairyn
Fur Stylist
 
Cairyn's Avatar
Robert Gruenweiss
Germany
 
Join Date: Dec 2005
Posts: 357
Quote:
Originally Posted by selmo
1. You register with windows to receive RAWINPUTDEVICE (page 1/ usage 8) messages, which will come in as WM_INPUT messages.


Yep. Well, strictly speaking I open a new window first, which is invisible and has the C4D dialog window as parent. This window then registers for the raw input. But that is nothing of your concern if you just want to generate the messages from your device driver.

Quote:
Originally Posted by selmo
2. The space navigator sends WM_INPUT messages with a RAWINPUT structure in the lParam.


Yep. Well, strictly speaking the 3Dconnexion driver checks for the hardware events and then feeds WM_INPUT messages to the system (anyone who has registered for the raw input, which happens to be the CollieMouse window). That's the point where you would need to generate WM_INPUT messages yourself if you want CollieMouse to do anything.

Quote:
Originally Posted by selmo
3. You receive the WM_INPUT, and if it's an HID with a VendorID of 0x46d, you forward it to your method DetermineMovement(). Otherwise you ignore it (or error out)


Yep. Well, DetermineMovement does all the checking, as shown in the code above, but that's just a matter of internal code structure.

Quote:
Originally Posted by selmo
5. DetermineMovement() looks at the RAWINPUT HID RawData[0] to determine if it's a translation (1) or rotation (2). The 3 axes are stored in the next three data elements, as shorts.


Yep. As shown in the code snippets. Since it's all raw data, the interpretation of that data has to match whatever 3Dconnexion defined. Is there a point 4?

Quote:
Originally Posted by selmo
6. You then pass that along to whatever postprocessing you do and make the C4D API calls to move the camera.


Yep. The postprocessing involves multiplying the movement input with a default factor, the user factor, and the speedup; then determining the pivot, the navigation mode, and the camera projection... and so on, and so on...

Quote:
Originally Posted by selmo
So by sending your HWND an WM_INPUT with a RAWINPUT structure that reports as an HID Vendor ID 0x46d, CollieMouse should not know the difference between my inputs and a real space navigator.... This may end up being easier since many devices, incl DirectInput stuff, actually use the rawinput stuff at a lower layer anyway.


As long as you don't have a real Space Navigator that already sends messages like this. If more than one device sends messages, you lose.

You may actually benefit from switching on the "debug" checkbox of CollieMouse. Then the plugin will show error messages in the console if the received message is not recognized.

Quote:
Originally Posted by selmo
Some quick questions:
- Where is the "line" between your backend and front end?


The functions "Rotate" and "Translate". Everything before (window opening, raw input reception and processing) is system dependent and would need to be reprogrammed for a Mac version. Everything after is only C4D dependent.

Quote:
Originally Posted by selmo
- Is your standalone window the HWND that receives the WM_INPUT, and therefore where I should direct my WM_INPUT messages? Or perhaps since you've already registered to listen, maybe I just generate the WM_INPUT messages system wide and let windows direct them to your registered listener window....


The latter. My window is already posed to read WM_INPUT, you won't see that window anyway. The hardware can't know what applications are listening, and should not, anyway. WM_INPUT goes to the system, and Windows OS will take care of the propagation of the message.

No, I don't have an example for sending WM_INPUT to the system since that's what the 3Dconnexion driver is supposed to do.

The window is not standalone btw, it's a child of the C4D dialog. (This may somehow be connected to the hanging process in R14... but that's another question.)

Quote:
Originally Posted by selmo
-What are the expected ranges for the 3 axes?


Switch on the debug mode for CollieMouse. The console will show you the calls for Translate and Rotate. Since the values are deltas, there's also the question how often you will send a message.

Quote:
Originally Posted by selmo
-Having another backend emulate vendor ID 0x46d is probably OK for testing, but likely to cause problems in the long run, so if this works out, you probably want to expose the expected ID via the GUI.


Yes. Unfortunately these are vendor IDs that are probably like C4D's plugin IDs -- need to be unique worldwide, perhaps even across OS borders. Maybe you'd need to register a new ID with Microsoft? Of course you might also just select a random ID that's not in use on your system if CollieMouse supports a dynamic ID.

For most users, that would be a quite confusing option since it's worth nothing without your alternative driver-intermediates.

Also, of course this system is far from universal. It only controls the camera, it can only support a single input device, and it's not possible to hook another plugin or expression into it. I'm wondering... naturally one could break up the plugin where Translate and Rotate are called, and instead generate C4D internal messages, which can be read by separate message plugins. That could even support multiple sources by moving the vendor ID dependency. But I digress... probably too complicated, and non-programmer users wouldn't benefit.
 
Old 01-05-2013, 06:03 AM   #17
selmo
Veteran
portfolio
Lars Norpchen
Octopus Motor
Pacifica, USA
 
Join Date: Sep 2009
Posts: 45
Well, I got as far as reading the joystick via RawInput and successfully sending messages to CollieMouse before I hit a dead end. Unfortunately, the WM_INPUT message uses a HANDLE to pass data to the receiver, and it's not possible to create such a HANDLE from userspace. So I can't emulate the space navigator's messages to you unless I write a proper device driver (way more effort than it's worth).

So I guess we're done with that idea. It's unfortunate, as I discovered this is a recurring stumbling block for anyone looking to redirect or remap RAWINPUT events (for supporting handicap users or simulating devices for development, for example). Everything else looked promising and seemed to be working. Thanks for the help, it was an interesting experiment.

If you are interested in extending CollieMouse to support other input devices like we discussed at some point in the future, I had an idea for a relatively easy workaround: use WM_INPUT for the navigator driver, but also define one or more additional WM_USER messages that feed directly into your DetermineMovement method. Like what you do for WM_INPUT, but instead of RAWINPUT, the message would provide you the movement information in a convenient form via the wParam / lParam fields (similar to a WM_MOUSEMOVE message). DetermineMovement() seems to be the logical entry point for any and all movement messages (for a potential mac version as well)

Thanks again for CollieMouse.
 
Old 01-05-2013, 01:25 PM   #18
Cairyn
Fur Stylist
 
Cairyn's Avatar
Robert Gruenweiss
Germany
 
Join Date: Dec 2005
Posts: 357
Quote:
Originally Posted by selmo
Well, I got as far as reading the joystick via RawInput and successfully sending messages to CollieMouse before I hit a dead end. Unfortunately, the WM_INPUT message uses a HANDLE to pass data to the receiver, and it's not possible to create such a HANDLE from userspace.


I see, the construction of the HRAWINPUT handle seems to be the issue. (I'm curious, did you use BroadcastSystemMessage() to send the message?)

So, if you want to send WM_USER messages, you'd need to use RegisterWindowMessage() on a string that we agree on (since it's cross-app), and then use a different structure (not a handle) as LPARAM. I guess I could even make the registration string modifiable, although that's not really necessary for a test...

Will you try sending WM_USER? If the setup works from your side, I can pretty easily add that to the message loop...

(Also, who is going to own the LPARAM if it's a pointer? I don't want to clean up here, so I guess you do, in which case the asynchronous call order may be important...)
 
Old 01-05-2013, 09:33 PM   #19
selmo
Veteran
portfolio
Lars Norpchen
Octopus Motor
Pacifica, USA
 
Join Date: Sep 2009
Posts: 45
I sent the message directly to your HWND, which CollieMouse reported as being received and logged in the debug console. So I know that much works. Unfortunately, it also logged that GetRawInputData failed, which I determined was due to the HANDLE issue. WM_INPUT is one of the few messages that are not injectable at the userspace level. The canonical way to do it is via SendInput(), but that doesn't work for us here because it only sends input messages to a window if it has focus, and doesn't fully support HID devices.

Sending a WM_USER can be done directly to your HWND as well, which you get in your win_proc like any other message. I'm not sure registering the WM_USER message is even necessary if the message is being sent directly to your HWND. It's an internal contract between the sender and recipient and windows knows to not mess with messages defined as WM_USER and above.

As far as the contents of the message, I think it's better to avoid pointers, not only for the potential for ownership scope and leaks, but also because you then have to deal with cross process memory marshalling. It's a relatively small chunk of data we're passing around, so it could be encoded in the wParam and lParams directly, which is more convenient as there are no scope or context or marshalling issues. If you look at WM_MOUSEMOVE, I'm thinking something similar. The wParam could define the type of message similar to how hid.rawData[0] is used in your current code ( translate, rotate, buttons, etc) and then the lParam is the data packed into 32 bits. You currently expect 3 shorts from RawInput, but in this case we would need to make that chars ( which is ok for joysticks, as they usually send only 8 bits anyway, and even the space mouse only appears to be using 10 bits). Or we could do three ten bit fields. Or if having 16 or 32 bits matters, the command could be made more specific, sending each axis as a separate command (either different wParam values or different WM_USER messages). For buttons, it's just a simple 1 bit for each button mapping. Between the wParam and lParam, we've got 48 bits to slice however we like, as long as we keep all the information in the message itself and not use pointers or handles.
 
Old 01-06-2013, 02:01 PM   #20
Cairyn
Fur Stylist
 
Cairyn's Avatar
Robert Gruenweiss
Germany
 
Join Date: Dec 2005
Posts: 357
Quote:
Originally Posted by selmo
Sending a WM_USER can be done directly to your HWND as well, which you get in your win_proc like any other message.
As far as the contents of the message, I think it's better to avoid pointers


Yeah, if you don't broadcast but target the window directly (care to tell me how you find it?), then we don't need a systemwide unique message and can use WM_APP. (WM_USER may collide with internal control messages.)

So, I prepared a test file. You will find the release builds for 32 and 64 bits at the same place where the official zip is, under the name of CollieMouse_Test.zip. Contains only the cdls!

These versions obey the WM_APP in the message loop and invoke a very simplified method:

Code:
bool DetermineMovementExt (HWND hwnd, WPARAM wParam, LPARAM lParam) { BaseContainer* storage = CollieMousePrefs::GetCurrentSettings(); Bool l_bDebugOutput = storage->GetBool (IDD_SPACEMOUSEDIALOG_DEBUGOUTPUT, STORAGEDEFAULT_DEBUGOUTPUT); if (l_bDebugOutput) GePrint("WM_APP message received for 3D mouse dialog"); int movement = static_cast<int>(wParam); int amount = static_cast<int>(lParam); if (l_bDebugOutput) GePrint("Movement code: " + movement); if (l_bDebugOutput) GePrint("Movement amount: " + amount); switch (movement) { case 1: return Translate(amount, 0, 0); // Translate X case 2: return Translate(0, amount, 0); // Translate Y case 3: return Translate(0, 0, amount); // Translate Z case 4: return Rotate(amount, 0, 0); // Rotate H case 5: return Rotate(0, amount, 0); // Rotate P case 6: return Rotate(0, 0, amount); // Rotate B default: ; } return false; }


As you see, it interprets WPARAM and LPARAM as int; this should work for 32 and 64 bit systems. (Since Win32, WPARAM and LPARAM have both the same length, which is the system's pointer length, which again should be the same length as the default integer on both 32 and 64 bit systems. If that doesn't work and you get any issues with the sign, I can still cast differently depending on the system's pointer width, but try this first.)

This interpretation will void the option "Dominant only" of course, since now only one axis will be forwarded anyway. If your hardware sends multiple axes in one go, we might still compress three axes and put it into the same WPARAM/LPARAM pair. But let's keep it simple first.
 
Old 01-07-2013, 02:42 AM   #21
selmo
Veteran
portfolio
Lars Norpchen
Octopus Motor
Pacifica, USA
 
Join Date: Sep 2009
Posts: 45
Quote:
Originally Posted by Cairyn
Yeah, if you don't broadcast but target the window directly (care to tell me how you find it?)


by WndClass plus Title:
Code:
FindWindow(_T("3dconnexion_controller_window"),_T("Space Mouse Receiver"));


There's some work to do in making that more robust, but it works fine for testing. Ultimately I need to guarantee I'm talking to the right HWND. I could potentially find someone else's window with the same wndclass and title. That would normally be unlikely, but I'm guessing those strings are straight from 3dconnection and therefore might collide with someone else's space navigator receiver.

Finding the window by class and name doesn't support multiple instances of C4D without special handling (an unusual use case, but still....). Hmm. I'm not sure if that still be an issue with a registered broadcast message...do you filter within CollieMouse to only listen when the app has focus, or is that filtering done at a higher level?


Quote:
Originally Posted by Cairyn
So, I prepared a test file. You will find the release builds for 32 and 64 bits at the same place where the official zip is, under the name of CollieMouse_Test.zip. Contains only the cdls!


Yup, it works (both 32 and 64 bit). Thanks! I've got to add something for a UI and options, etc. but I'm moving the camera around with a joystick, so the proof of concept is there. Are you happy with the current message structure, or do you want to change it ? Button support is probably worth adding (even for the space navigator!) although it would take some thought as to how best present the UI for assigning button controls (keyboard emulation?)
 
Old 01-14-2013, 07:14 PM   #22
jayse
dirty
portfolio
Jayse Hansen
Freelancer
www.jayse.us
Las Vegas, USA
 
Join Date: Apr 2005
Posts: 42
Send a message via AIM to jayse
Fantastic work. I wish it were for mac as well - My navigators are in a drawer somewhere. Perhaps you should sell your work to them - they're awful when it comes to 3d connexion support.

Great that you were able to tackle it! Much needed!
__________________
-----------------------------
UI stuff for film
www.jayse.tv
 
Old 01-15-2013, 03:30 PM   #23
joeski4d
PRO
 
joeski4d's Avatar
portfolio
Joe Ski
designer
Washington, DC, USA
 
Join Date: Mar 2005
Posts: 175
I would like to see this compiled for Mac, too.

I'm surprised to hear so many Space Navigator's are collecting dust. While I realize there's lots of room for improvement, as this plugin seems to prove, I really love using mine with C4D R14.

-Joe
 
Old 01-15-2013, 05:10 PM   #24
jayse
dirty
portfolio
Jayse Hansen
Freelancer
www.jayse.us
Las Vegas, USA
 
Join Date: Apr 2005
Posts: 42
Send a message via AIM to jayse
well... last I checked there was really no mac support for the buttons... so if you just want to orbit that's fine - but then to do any shortcuts you have to move your hand to the keyboard. When that's the case I find it's just faster to do it all via keyboard/mouse. Unless that's changed?
__________________
-----------------------------
UI stuff for film
www.jayse.tv
 
Old 01-15-2013, 09:47 PM   #25
Cairyn
Fur Stylist
 
Cairyn's Avatar
Robert Gruenweiss
Germany
 
Join Date: Dec 2005
Posts: 357
Quote:
Originally Posted by jayse
well... last I checked there was really no mac support for the buttons... so if you just want to orbit that's fine - but then to do any shortcuts you have to move your hand to the keyboard. When that's the case I find it's just faster to do it all via keyboard/mouse. Unless that's changed?

Really, no button support from the 3Dconnexion driver? Or do you just expect the settings in C4D itself?

Here is what I do to use a button:
1. define a keyboard shortcut in C4D, no matter how cryptic; multi-key preferred, e.g. #SN1
2. go into the 3Dconnexion driver, select settings for a button, let the button trigger the multi-key shortcut that you just defined in C4D.

Of course it would not be a big issue to trigger functions through CollieMouse. Just one more tab with settings. (What's the maximum number of buttons on a 3Dconnexion device?)

But, you know, no Mac so far...
 
Old 01-15-2013, 11:39 PM   #26
jayse
dirty
portfolio
Jayse Hansen
Freelancer
www.jayse.us
Las Vegas, USA
 
Join Date: Apr 2005
Posts: 42
Send a message via AIM to jayse
from what I understood before the keys were just plain dead... I'd be all over it if they could be remapped. Amazing eh? Sold as mac supported - but not the case. Several posts in their forums confirmed they kind of didn't really plan on doing much development on it. C'est la vie.
__________________
-----------------------------
UI stuff for film
www.jayse.tv
 
Old 01-16-2013, 05:01 PM   #27
joeski4d
PRO
 
joeski4d's Avatar
portfolio
Joe Ski
designer
Washington, DC, USA
 
Join Date: Mar 2005
Posts: 175
Hi Jayse, do you have the latest drivers from 3dconnexion?

I'm able to map the buttons specific to each app and it all works fine. Here's a screenshot of my driver prefs: http://c.joeski.com/image/2F2c1G380l1h


Quote:
Originally Posted by jayse
from what I understood before the keys were just plain dead... I'd be all over it if they could be remapped. Amazing eh? Sold as mac supported - but not the case. Several posts in their forums confirmed they kind of didn't really plan on doing much development on it. C'est la vie.
 
Old 01-16-2013, 05:01 PM   #28
CGTalk Moderation
Lord of the posts
CGTalk Forum Leader
 
Join Date: Sep 2003
Posts: 1,066,481
Thread automatically closed

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
__________________
CGTalk Policy/Legalities
Note that as CGTalk Members, you agree to the terms and conditions of using this website.
 
Thread Closed share thread


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 02:18 PM.


Powered by vBulletin
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd.