A River Runs Through It

River, Bridge and Ground
Since I wanted a river and bridge in the first map for Alpha Quest, I had to make it possible to make water. I needed to rewire the drawing routines to provide groups for both opaque and transparent surfaces, as well as provide a property on the BuildableMesh that lets me know the Material is transparent. In WPF, the transparent Materials need to be added to the scene graph later than opaque materials so that the opaque materials show up correctly.

This image also shows (in not too much detail) some use of the PanelSpace in the bridge and soil/grass cells on the far bank of the river. It also shows a little bit of very rough shadow in the river bed itself.


One MeshGeometry3D to Rule them All

I finished off the PanelCellSpace a few weeks ago, and got it pushed through to the service host, proxy client and client UI. One thing I noticed (since I was testing in a large outdoor space) was that the performance was absolutely crappy (client-side…the workshop rendering was mostly OK). I wanted to fix this right away; but knew it would take profiling, though spending $500 around tax time wasn’t a viable alternative. Thus I had to improvise.

Enter good old Debug.WriteLine() statements with timings. I soon narrowed down a major performance problem to calling the full map rendering method 3 times. Basically when anything changed I was redrawing the entire map, locators (game tokens) and overlay graphics (aiming cells and lines). By separating those functions and only calling them when needed, I reduced re-draw time from 4.5 seconds (after making a single 5 foot move) to 1.5 seconds. Pretty good, but I was certain it could go faster.

I toyed with several ideas including caching full frozen Geometry3D models (per thread), and having other mesh collapsing optimizations. I finally settled on an approach of rather than drawing each cell face into a cell Model3DGroup with copious amounts of (frozen) transforms, I’d build aggregate meshes for cell faces using the same material rather than separate models. I had to replace a parameter in my call chains (and retain the old group for those cells I didn’t want to “upgrade” to the new style just yet), and futz around with collecting cell Model3DGroups and the shared MeshGeometry3D, but the end result is about 0.3 seconds from action start on client, through to server processing and updating, back to notification, collection of new map display data (based on senses) and rendering.

Yay!