Hi there again, after almost 2 months i deliver as promised a post about scene/textrure mouse interactivity. Sorry for the delay folks i didn’t really have enough time back in US then it was christmas time and then i got to resolve some personal stuff. But don’t worry this doesn’t mean i didn’t work on Agile3D, it just means that i didn’t write about it. But back to the scene interactivity stuff.
Lets get to one of the most problematic parts of scene interactivity and thats how to identify face/object under mouse. If you read my previous post on this topic you already have a basic idea what the options will be, but lets summarize possible render options for face.
1. Render each face as a separate sprite instance.
2. Render all faces into one display object.
3. Render each face as a separate shape instance
Handling interactivity of option 1. is easy and the most straightforward since each sprite which means each face in this instance will generate their mouse events directly and once you have references from the sprite instance to the face instance you are pretty much done. However as always the most straightforward solution is always the worst one, downside to this is that its really slow all those InteractiveObject instances firing events clog the FPS a lot. Other downside is that it consumes the most memory of the three, since sprites are DisplayObjectContainters as well which is unnecessary for us anyway. So unless you really want to simplify your engine and sacrifice the performance i wouldn’t recommend doing it this way.
Lets look at option 2. Chronologically it was the first option i tried since it required almost zero changes to my ViewPort class, obviously becouse without interactivity I already was rendering all faces into one shape. But what now, there is no native way we will get the face under cursor so this is where some math comes into play. First thing trying to raycast from mouse to the scene, but this is unecessary complex operation since we can just work with already projected faces and do all the calculations in 2D. Here its a matter of detecting point inside a triangle which lets face it is not as quick as we would like so another optimalizations are needed this is the point where you can unleash you potential. Here are some of the things that i tried. I used bounding circles not the escribed circle since that would need additional calculation but the fastest one which is from random point with the radius of the longer triangle line this way possible intersection was just a simple distance check. Next i even used quadtree for space lookup optimalizations before actual distance checks… I am not going to the math details here its not the point of this article, but suffice to say this method proved to be real improvement over option 1. But this is not where i stopped ;)
Option 3. and let me say it this is the one that is currently implemented in the updated version of Agile3D. Here were are creating multiple Shape instances which means that the whole scene is not rendered into a single shape but each face has its own FaceShape instance. There is no slowdown of the option 1. since we are not using Sprite instances, the memory usage is not of the roof as well. But you ask whats the point since we don’t have the mouse event possibilities of the Sprite class. The point is that this option opens another possible solutions that are not available in option 2. and were rather pointless in option 1. (since the slowdown). First thing that comes to mind is the good oldfashioned hitTestPoint method. Its a native way of finding whether a display object collides with a specified point, yay ideal. This proved to be way faster than option 1. and it rivalled with the optimized option 2. but depends on the optimalizations. Still, this is not the solution that Agile3D uses after all.
The final one do indeed comes from option 3. but doesn’t use hitTestPoint. What i use is one method that honestly i never did use before because i never needed it at all, but here its the perfect one. Its DisplayObjectContainer’s getObjectsUnderPoint method, the pure genius of one call to get all you need, no repetitive testing, nothing just a native function call.
This is by far the fastest method i could came up with, i am not going to say its the best one since i am not the all knowing being but i can atleast doubt that there is a faster way. If anyone out there has a potentially fastest way just drop me a word about it i am all ear. ;)
Thats all folks, if there are any questions just ask, after all half of the fun is to get the knowledge and the other half is to share it. Next post will be about what comes next, how we get the correct scene/texture coordinates and how we propagate the event to the interactive texture if there is some.
Thanks, and drop me a line.