Implementing interface to accept key and mouse input from clientside generated events

This is in reference to a question I had before:



http://hub.jmonkeyengine.org/groups/networking/forum/topic/jmonkeyengine-linked-to-servlet/#post-179392



My current goal is to take input events from a Facelets page and send the resulting DOM event types (keyUp, keyDown, mouseUp, mouseDown, mouseMove, etc.), keycodes, and some information on where inside my canvas element the mouse was clicked (for x and y coordinates of MouseButtonEvent). I’ve got all this info from the JSF side I need to create new InputEvent objects. The problem I’m having is finding specifically either what class I should extend or what interface I should implement in order to have jMonkeyEngine’s MouseButtonEvent and KeyInputEvent objects generated so that I can then register Triggers with ActionListener or AnalogListener objects via InputManager’s addMapping() and addListener() methods. I don’t think consuming events would do any good because no InputEvent objects have been created at this point. I’m a little skittish about modifying InputManager as I’m passing a reference to a class that extends SimpleApplication to com.aurellem.capture.Capture.captureVideo(), and I’m unsure what effects replacing a SimpleApplication based class’ inputManager member would have on the captureVideo() method. This may be a non-issue though and I could be worrying about nothing. Either way, I still need to know where I should pass InputEvent classes to in order to register Triggers with ActionListener/AnalogListener objects. Thoughts anyone? Code snippets preferably?

Man that last sentence made me almost not answer :stuck_out_tongue: Why do you want to go through the input system? Just abstract your event system so that it can get input from the input system or the network. This way you also don’t have to workaround the limits of the input system which is made for local input and not network input.

If you really want to do things your own way then you can just write a JmeContext wrapper that would expose the input events in the KeyInput / MouseInput implementations. This would be the correct way of doing it at least … The other option is to just directly initialize InputManager with your own implementations of those classes but then the flyCam which was created before that won’t work (of course you can still disable the old and create a new fly cam)

1 Like

Can I be “that guy” and ask what the point of this is?



Is it going to be only one client at a time? Or have you figured out how your are going to share OpenGL across multiple clients? What kind of infrastructure are you thinking about for the back-end, etc.? Are you trying to provide continuous updates or are you going to do one-shot rendering every so often and completely rearrange the scene graph for each client?



Once you answer the really critical design and infrastructure questions then I think the rest falls into place on its own.

@Momoko_Fan, I’ll give JMEContext a look and see what I can make of it. Thanks for the to the point advice. @pspeed,We are trying to keep this servlet based so content can be accessed from a central server if one is available or the viewer application can be run in an embedded web server a la Jetty if no network connection is available. Please don’t ask me why it has to be this way as I am not at liberty to comment on that, simply know that I’ve been tasked to do such. As I stated in the post referenced in the first post of this thread, applets aren’t really an option due to the code signing issue. It might only be one client connected at a time (i.e. program being run on embedded web server), but it could very well handle multiple connections if needed. As for how many individuals will actually be viewing an individual scene node, that will be just one, this isn’t a “multi-viewer” application. In other words, many viewers may be able to connect to a central server at once, but they are not going to be viewing the same scene graph, nor will they be sending input to manipulate the same scene graph. OpenGL will not have to be “shared” as you put it, because no scene graph will have to be reconstructed across every user’s box (this will be a lot more like OnLive than a traditional MMO in that the user just submits input and gets sent back a frame and MAYBE some audio every so often, the server does the bulk of the work). Put simply, the client side should have no business updating the scene graph, rendering frames, etc. The updates will be continuous though (Probably will be done via an Ajax push mechanism or preferably Websockets if I can lighten the requirements on browser versions to be supported, not that this has anything to do with JME ).@normen, I don’t see anything particularly offensive about that last sentence, and am sorry if you took it that way as it wasn’t intended. Unfortunately, and I don’t mean to be rude (just pragmatic) “just abstract your event system” is vague and doesn’t give me a whole lot to go off of. Something a bit more solid like, “If you really want to do things your own way then you can just write a JmeContext wrapper that would expose the input events in the KeyInput / MouseInput implementations” does. And by the way, thanks for downvoting this post; great way to get new people to contribute to a project.

But there is only one OpenGL on the box. You will have to share the graphics card somehow. Or is each web server its own process.



JME is pretty single-process oriented so if you have multiple clients then you will likely have to be switching different scene graphs in and out of a single JME. You will have to keep camera, etc. state for the other clients while swapping one scene out for another… and that state is really what’s being manipulated by the client input. InputManager doesn’t really come into play because you don’t really have a single client.

@pspeed, the way servlet containers work is essentially (without going into a whole lot of depth) every client connecting to the web server will get their own version of the application started inside it’s own servlet context (i.e. it’s own process if you will). A whole lot of things that the JME networking API (particularly almost everything related to RMI) does is pretty much handled for you inside the servlet container via IOC (i.e. you don’t even have to write a main method; you define what you want the program to do inside a no argument constructor and it is smart enough to handle a lot of stuff all by itself). This is one of the beauties of servlet containers and JSF more specifically. This is partly why I’m surprised at all the confusion as to why I want to go this route. Yes graphics cards may have to be shared, but I’m not trying to load tons of super high poly models that use quite a few shaders and even use render to texture or ray tracing for really vivid effects. These scenes are going to be mid-poly level with not a whole lot of models, simple textures, and maybe a few particle effects (all of which will be rendered with good old Phong method). I really don’t see why people think this going to be so terrible in terms of performance. Heck if I was super worried about code efficiency I’d be coding this in C++ anyway.

C++ wouldn’t matter anyway as the graphics card will be your bottleneck. And none of this has anything to do with JME networking so I’m not sure what that comes up.



I wouldn’t even be having this discussion except that the questions you are asking seem to be kind of irrelevant for your architecture. But if you’ve found a way to isolate separate JVMs into their own servlet context then you may have a way forward where it is relevant. Otherwise, I think you will find that JME (and probably because of LWJGL) won’t play nice in this case.



Anyway, good luck with it. I’ll check out of this conversation before I get “schooled” on other technologies I already used more than 10 years ago. :wink:

Considering that JSF 1.0 didn’t even come out until 2004 I find it hard to believe you’ve been coding in it for over 10 years :wink: Unless of course you are referring to servlet coding in general, which then yeah maybe. But if so, why did you ask me if each server is being run in it’s own process? You should already know the answer to that. More over, I fail to see why I would truly need to have to load a whole separate JVM instance for each user in a servlet environment. I also fail to see how the question of registering InputEvent objects created through my own factory is irrelevant to getting client side generated events to work with something primarily intended to be run on a standalone machine. That actually seems to be a VERY pertinent question considering the architecture I have described. I’m also checking out of this conversation as well as any attempt to explain myself is apparently taken as “schooling” and any request for actual code snippets as to how to go about modifying the input system instead of vague general advice that doesn’t mean anything apparently merits a downvote. Great pedagogy JME community; You’ve officially made me NOT want to use or promote your software. @Momoko_Fan, this last comment doesn’t apply to you and I do appreciate what help you offered, but I refuse to put up with other people with such fragile egos. Grow up people.

JSF != Servlets and you can configure them to run in separate processes or not. Again, you do not need to do the detour over the input system. See the input system and network events as equal, you have to do something with this input. Routing the network data via the input system is like scanning snailmail you get and sending it to your own email address to read it instead of just opening the letter.

Sheesh, man. I put a little smiley after that comment… who is being sensitive exactly? I just thought it was funny that you were explaining how to use something that has been around a long time. I did servlet programming back in 1999 or 2000 or something. I followed struts from the early days and even traded e-mails with Craig Mcclanahan on that list as he was developing JSF for Sun. So your message really did make me chuckle a little but not in a mean way.



The problem is when approaching these threads is that I don’t know when I’m talking to someone who is an expert and communicating poorly or is not an expert and has yet to encounter the hundred problems they will encounter with a particular approach. So I ask questions.



OpenGL is pretty single threaded on a process level. You are going to have trouble getting around that. You will find that out the first time you try to create more than one SimpleApplication instance or more than one GL context. But I felt that maybe I shouldn’t assume you didn’t already know that so I asked if you’d found a way to run in multiple process since that’s the only solution that doesn’t require sharing a single GL context. And if you actually did find a way to do it in multiple processes then your question for how to inject events is valid.



Otherwise, you will have to find a way to share a single JME across servlet contexts and use some kind of rendering request queue or something. The servlet (on behalf of a client) will have to package state (including that client’s scene) for some background rendering thread (the single OpenGL thread in this case). So, in that case, the servlet doesn’t have to forward things to JME’s input manager because the input manager is run as part of the single OpenGL thread and expects there to be only one process. Since you are having to keep state separately for each client then any inputs will need to manipulate that state and they won’t necessarily trigger a render at all.



Swapping in and out different scenes once per update pass will be pretty inefficient but there isn’t much way around that. How inefficient and whether it’s too inefficient largely depend on the hardware your packing and what your tolerance is. One or two frames a second for a handful of clients is what I might expect on average hardware. And maybe that’s within your target.

I think you should reconsider applets. You DO NOT need to sign them in order to deploy them, that assumption of yours is false. You can try it yourself using the jME3 SDK “applet deployment” option. The only excuse not to use applets is if you must have compatibility with every computer that will open that servlet, as some may have outdated drivers or missing drivers.

@pspeed said:
OpenGL is pretty single threaded on a process level. You are going to have trouble getting around that. You will find that out the first time you try to create more than one SimpleApplication instance or more than one GL context. But I felt that maybe I shouldn't assume you didn't already know that so I asked if you'd found a way to run in multiple process since that's the only solution that doesn't require sharing a single GL context. And if you actually did find a way to do it in multiple processes then your question for how to inject events is valid.

Otherwise, you will have to find a way to share a single JME across servlet contexts and use some kind of rendering request queue or something. The servlet (on behalf of a client) will have to package state (including that client's scene) for some background rendering thread (the single OpenGL thread in this case). So, in that case, the servlet doesn't have to forward things to JME's input manager because the input manager is run as part of the single OpenGL thread and expects there to be only one process. Since you are having to keep state separately for each client then any inputs will need to manipulate _that_ state and they won't necessarily trigger a render at all.

Swapping in and out different scenes once per update pass will be pretty inefficient but there isn't much way around that. How inefficient and whether it's too inefficient largely depend on the hardware your packing and what your tolerance is. One or two frames a second for a handful of clients is what I might expect on average hardware. And maybe that's within your target.


So, apparently I'm wrong on this and it's possible to create any number of SimpleApplication subclass instances if you swap out for an off-screen surface. (Note: to most readers, usually this is the wrong thing to do and this case is unique... don't try this at home.) Supposedly it only takes one line of code to do it. (Though I have no idea what that line is)... then I'd think using inputManager.onXXXEvent methods to inject your events should be entirely possible. Though, like Normen, I still recommend handling input separately.

At any rate, it doesn't change the fact that my questions and responses came from a place of trying to help and not a place of badgering or ignorance on my part (the above not withstanding). I genuinely thought the lesson on servlet containers was kind of funny for my own reasons. Given the direction the answers had gone (into territory I felt others could help more), I decided to wish you luck and bow out of the conversation.