Spheriosity and Efficiency

July 12, 2008

I spent some time today trying to add, what I think, would be a neat feature in Spheriosity. The feature would let you see the line or circle you are about to create when you are trying to make new lines and circles. Currently you just select the end points and then the program draws the line. With this feature, after you select the first point Spheriosity will show you were the line or circle will end up after you place the second point.

I figured this would be pretty simple and that I wouldn’t run into any of the efficiency issues I constantly worry about. Unfortunately I did… This took me completely by surprise because with the point moving feature everything seems to happen quite smoothly! So it was tough for me to believe that now this feature was slow.

I further inspected the code to find that the difference was in how point moving vs. how this feature was implemented. The way the code is currently structured is that all user related activities are fed through a state machine. The different states are like MovePointState , DrawPointState etc.. Each state extends a base class with 6 or 7 (can’t remember exact number) abstract functions. The class which receives all mouse related events then forwards the appropriate data to the functions of the current. Any given state can ignore functions it does not need by simply implementing them as an empty function block:

public void addPoint(Point3f newPt) {}

The function I currently use to get data from the mouse have the following function headers:

 * @param mouseEvent - MouseEvent sent by Java
 * @param worldLoc   - Pointer location mapped to the surface of the sphere
public void newMouseLoc(MouseEvent mouseEvent, Point3f worldLoc);

Java can give you the new location of the mouse in one of two different ways, but now both at once. By implementing the MouseMotionListener interface there are two functions. mouseDragged and mouseMoved. Even though the mouse is being moved while you are dragging in Java choose to implement it such that only one function or the other is called at once. So both mouseMoved and mouseDragged call my function [newMouseLoc]  . In mouseMoved I house the code which determines what lines or points get highlighted depending on the current state. In mouse dragged I simply pass right along the data to newMouseLoc.

So, the MovePointState gets the data from mouseDragged where the only overhead is the calculation I have to do in order to convert the mouse location to the surface of the sphere (quite a large calculation…) Where as in mouseMoved I did the same calculation as in mouseDragged and also did an intersection test with Java3D to see what, if anything, needed to be highlighted. Since part of that intersection test probably involved math that was already done to map the the user click to the sphere… Now… if this calculation was just happening once or twice I’m sure you would never notice. Unfortunately it happens every time the cursor moves. That in itself doesn’t make the the program lag though. Also added to the mix is that to draw each line we really make a bunch of small lines (100 to be exact) because a line on the sphere isn’t the same as the Euclidean version Java3D provides. So now we have that calculation coupled with the code that figures out the end points for the 100 lines and at the very least a for loop with 100 iterations … all each time the cursor moves!

This is why I worry about optimizing Spheriosity. I do my best to keep the code clean, but no one wants to use a slow program.

In terms of a solution to this problem… I moved some of the calculations around so I am doing less math to figure out what to highlight or not, and that seems to solve most of the issues. I still want to optimize it some more as I think I am approaching a dangerous threshold for minimum requirements 🙂 to run the program.