This article describes the Windmaster wind system, which provides the Global Wind used by the Nemo sailboat in Second Life, It is intended to be an overview for those with a technical interest in how it works.
The Windmaster system started as an experiment in finding a way to implement wind shadow that had less lag and better accuracy than other implementations. Global Wind was invented during the early stages of development, and a basic form of this was implemented before wind shadow itself, some time in February 2011.
- Global Wind is a way of ensuring that all boats are sailing in the same wind, without the need for wind setters, or for skippers to manually set wind parameters.
- Windmaster is the name of the server that provides Global Wind, as well as wind shadow effects and other services.
This is a client/server system, where each boat is a client of the Windmaster server. The clients use scripts written in LSL (using the Mono compilation option), while the server is written in PHP and is external to Second Life. The clients communicate with the server using the HTTP services available in LSL. The data used by the server is stored in a MySQL database. All data is transferred in custom HTTP headers, or is formatted as plain text strings in the request and response bodies.
Each boat sends a small data packet to the server, and the server tells it the direction and speed of its wind at that point in time. The real work is all done in the background by the server, which takes care of several things…
- Acquiring real world wind data and generating a wind profile from it.
- Calculating inter-boat wind shadow effects.
- Calculating land shadow effects.
- Housekeeping of each boat’s data.
- Interacting with additional non-boat objects.
It is important to note that the server does not actively model, or ‘run’, a grid-wide global wind system in real time. Rather, it provides calculated results from its model in real time, on demand. In essence, a boat says, “I am here. What is my wind?”, the server calculates the requesting boat’s wind for that location, at that time, and says to the boat, “Your wind is this.” In other words, the real time weather model is only active when something is asking it for information. When there are no requests, it is dormant.
Real-world Wind and the Wind Profile
The real world wind data is picked up from the US weather service as an XML file. This is parsed to extract the latest observation’s wind direction, wind speed, and gust speed. The weather service data is updated hourly, which means that on-going gust data is not available – the supplied gust strength is that recorded during the preceding hour. Modelling realistic wind entails having gusts and shifts that occur over much shorter time spans – a gust can build from the steady wind speed to maximum gust speed in a handful of seconds. This is why Windmaster uses the base parameters from the hourly update to build a wind profile.
The wind profile is built by taking the weather observation data and calculating a sequence of gusts and shifts lasting for one hour. These vary more or less randomly within certain constraints. There are minima and maxima for gust strength, time between gusts, how long a gust lasts, and how quickly it builds from the steady wind speed. The gust shaping is calculated mathematically - functions are used to make the curve for the rise of the gust, the shape of the duration of the gust, and the ‘tail’ as the gust dies away. The wind also changes direction during a gust (it veers – moves clockwise), and this is proportional to the strength of the gust.
If the weather service becomes unavailable, Windmaster will use the last-known real world wind data to build a new wind profile every hour. Due to the use of random elements in building the profile, it is extremely unlikely that the pattern of gusts will ever repeat, even if the steady wind remains at the same speed and coming from the same direction.
To make this data available to the boats, the hour-long pattern is time-sliced to a resolution of one second and each result is stored in the database. Thus, one hour of wind profile data is stored as 3,600 separate database records. When a boat requests wind data, the server uses its local time to work out where in the hour-long sequence of profile data to look, retrieves the calculated wind data for that second, applies any local modifiers such as wind shadow effects, and passes the result to the boat.
A factor to consider when using hourly updates from a real world weather buoy is the difference between readings taken an hour apart. Real wind changes through time, and this could result in sudden changes in the base wind parameters just before, and just after the hourly update. Windmaster smooths these out by interpolating the previous hour’s data with the latest data. When generating the wind profile, the nominal parameters gradually change (second by second) from previous to latest, and the gusts and shifts are applied to the interpolated values.
- This means that the wind supplied by Windmaster is one hour out of date, and, if there has been a significant change in the base wind parameters from one hour to the next, the speed or direction will change linearly over the coming hour, regardless of how the real wind changed during the preceding hour.
Each boat contacts the Windmaster server once every second, using llHTTPRequest. When any object uses this to talk to a server, several custom HTTP headers are sent automatically by the SL simulator, and these can be extracted by Windmaster for use in providing its services. The boat also sends a small packet containing data that the custom HTTP headers don’t include, such as speed in knots, heading in true degrees, heel angle, sail angle, sail size, etc.
When the server receives a ‘what is my wind?’ request from a boat, it extracts data from the custom HTTP headers and the boat’s data packet, and stores the information it requires in a database record specific to that boat. This record is overwritten with new data as subsequent requests come in.
The server then searches the database for any nearby boats and nearby land, and calculates their effects on the nominal wind that the boat would experience if it was the only boat in a large exapanse of open water. The modified wind parameters are sent to the requesting boat as an HTTP response to the original request. The boat then feeds these parameters into its sailing engine and modifies its speed, heel, etc, accordingly.
- Note that the boat does not calculate any shifts and gusts – it is essentially always sailing in steady wind, but steady wind that is subject to change every second. The server only sends back two values: wind speed and wind direction. No variation data.
Some custom HTTP headers that are used by Windmaster are the boat’s coordinates, and the owner’s avatar UUID. The coordinates are used for calculating wind shadow, and the owner’s UUID for determining which record to update with the new data sent by the boat. The system extracts region coordinates and the boat’s local coordinates to determine the boat’s current global coordinates, and it is these that are used for calculations.
- The use of global coordinates means that the system never has to deal with regions – all wind modifcations (like shadowing) happen at all times without any adverse effects due to region boundaries.
To uniquely identify the record pertaining to a given user’s boat, it is not practical to use the boat’s Object Name or UUID. If the boat’s UUID was used to find its last-updated record, the newly-rezzed boat would have a new UUID, and the record would not be found. Similarly, the owner might rez a replacement Nemo with a different name, which would again not be found, or could even clash with an existing Nemo being sailed by someone else. The avatar UUID does not change, which means that the record associated with their boat can always be found (provided the record has not aged out during server housekeeping).
The wind shadow modelled by Windmaster covers an area of variable size. The intensity of the shadow is calculated mathematically, being strongest when very close to a shadowing boat, and tailing away very smoothly at the outer extremities of the shadow area. A contour map of shadow intensity would reveal a teardrop shape, with the wide part of the teardrop at the shadowing boat. The coordinates supplied by the custom HTTP headers are floating point values, and these are used without rounding.
There is a constraint on how slow the wind can be – a shadowed boat will never experience wind that is less than 25% of the nominal wind speed. This is to maintain a reasonable level of gameplay – finding yourself downwind of a starting race fleet with only 5% of the wind can be disheartening.
The amount of shadow created by an upwind boat is not limited to its relative position. The angle of the sail with respect to the shadowed boat is critical. If the upwind boat had let its sail out, such that the sail was in line with the wind, there would be little to no shadow effect downwind. Similarly, if the boat were to pull the sail in tight, such that the sail was perpendicular to the wind, a passing downwind boat would experience more shadow. Sail size is also a factor – a boat using a small sail will create less shadow than one using a large sail. At present, the shadowing boat’s heel angle is not accounted for (the apparent size of the sail presented to the wind reduces as the boat heels – it makes a smaller hole in the air), although this may be added at a later date.
At the time of writing, land shadow is experimental. It works in a similar way to wind shadow, except that the server looks at a different database table to find out if there is any land nearby. Land shadow can extend up 100m. The land data is built by surveying manually in-world using a custom survey tool built for the purpose. The survey procedure is done on a region-by-region basis, but the tool sends data to the server in global coordinate format, meaning that, as with boat shadow, the server does not have to deal with region boundaries.
Terrain in SL can be mapped to very fine resolution. For example, mapping at one-metre resolution would produce 65,536 data points per region. This will clearly multiply as regions are surveyed and there is a risk of the data becoming unmanagable. Database file size could become excessive, and the time taken to scan the database for nearby land in response to requests from multiple boats (all wanting answers very quicky, every second) could impact system response time. To keep these aspects under control, while still providing an effective experience for the user, the land is surveyed with a resolution of 16 metres – each region is represented by only 256 data points. It actually scans each 16x16m block at 1m resolution, and then calculates the average height for that block.
The survey tool also provides a means to represent the heights of structures on the land. It does not scan prims or attempt in any way to understand what is on the land. (The only automated part of the survey procedure is to use the llLand function to scan the underlying terrain at the 16m resolution.) To represent structure heights, the surveyor scans the region terrain, and then flies around the region, stopping over significant structures that he wishes to represent, and tells the tool to modifiy its height value for that 16x16m section. It uses the avatar’s altitude (minus 1m) to determine the new height for that part of the terrain map. When the survey for a region is complete, the data is uploaded to the server, at which point it is available for use immediately.
If the terrain or structures in a region change, the surveyor can return and use the tool to download the data for that region, make modifications as required, and then store the updated information. In cases where changes are substantial, a resurvey may be preferable.
A clear disadvantage of this method is the fact that it is manual. In particular, surveying structures and trees can be time consuming (usually several minutes per region, compared to a few seconds for the basic terrain survey). Moreover, there could be ‘holes’ if one tries (and fails) to survey land that has ban lines. For now, however, this is the only method available, and the results have proven to be very effective.
- The survey tool also stores the heights of terrain below the water. While this is not used at present, it could be in the future. The current server only calculates land shadow, but it could also calculate wind deflection and funnelling effects. If these are added, it should be possible to apply the same calculation principle to underwater flow effects on water currents.
Other Client Objects
The survey tool described above is an example of a non-boat client object. There is also currently a wind sock which requests wind data every 8 seconds, and an experimental live race map which shows the position and heading of boats that have registered for a race as they sail around the race course. There is an associated tool which allows a race director to create a reference to a race, which is then used by sailors for registration (via an option in the boat’s menu system).
To ensure that there are no false positives due to additional, non-boat client objects, every client that communicates with the server includes an ‘object type’ identifier in its data packet. When the server is calculating the effects of wind shadow for a boat, it only looks at records in the database which have a valid ‘boat identifier’. (Rather, the object type is one of the criteria used by the SQL query which looks for nearby boats.)
The terrain survey feature demonstrates a key aspect of using a separate server – flexibility. The land shadaw data table, the associated calculation and data management, and the in-world survey tool itself were all added after the basic Windmaster system had been created. Incorporating the effects of the land shadow modelling into the wind information sent to the boats took no more than adding a few lines of code to the main calculation algorithm. Similarly, other client objects can be added as the need and inspiration arises.
The only data table in the current system that is dynamic (ie, can have an undefined, or relatively uncontrolled, number of records) is that used for storing information about boats and other client objects. All other tables either have a fixed number of records, or the number of records is managed in a controlled way.
The reason for this is that the client objects table is populated with records that are created in response to the actions of multiple users outwith the server – people sailing boats in Second Life. By contrast, the wind profile table has a fixed size of 3,600 records, a small table stores the real wind data, etc. The terrain height data can change in 256 record steps depending on survey activity, but changes are controlled by an in-world tool that is only used by the system administrator.
Sailors in boats is the unpredictable data source, and it is this that needs some housekeeping. If there was no housekeeping, the table would gradually become bigger and bigger as people sail their boats and then de-rez. It must be remembered that the Nemo is a free boat, and there is likely to be a high percentage of ‘try once’ users. The system carries out some basic housekeeping to keep the number of active records under control.
Every time a boat requests the latest wind information, its associated record is updated, and is also timestamped. During the system’s hourly routine of acquiring new real wind parameters and generating the wind profile, a check is made in the client objects table for any records that have not been updated for at least one hour. Any records older than one hour are deleted. This means that boats that have been de-rezzed, have crashed, been auto-returned, or otherwise lost, do not clog up the system.
(Last revised 2014-10-12)