I am using the open source AR library GART for a small Augmented Reality app on Windows Phone. I've followed the documentation and a tutorial how to use it and it works very well overall, with only one issue: it doesn't take the items' altitude into account and visualizes all items on the same horizontal level (i.e. the horizon), no matter what altitude I set.
I have the feeling I am just forgetting something and there is a quick fix… In the GART Tutorial (BingAR and SimpleAR) I saw they set the Altitude of the ARItem, and do it like that, but it seems to have no effect. Changing the Altitude value to double.Nan, 0 or any other value doesn’t change the position in the worldview:
// create and add ARItem
var altitudeDiff = (m.GPSInformation.Elevation - _currentCoordinate.Altitude);
m.GeoLocation = new GeoCoordinate
{
Latitude = m.GPSInformation.Coordinate.Latitude,
Longitude = m.GPSInformation.Coordinate.Longitude,
Altitude = altitudeDiff // or just height, or double.NaN or 0, or 10000 -> no effect
};
_arDisplay.ARItems.Add(m);
At some point I thought, it doesn’t consider the GeoLocation-property, but when I remove it altogether, it is missing the Lat & Long-values. When looking at the library at the Method DistanceTo3D(this Location a, Location b) (in ARHelper.cs in the WP8-project), I saw that they also calculate the altitude difference, but only if the device is WP7. In the other cases, they just add 0m as the altitude to the Vector3. Does this maybe have something to do with my issue?
static public Vector3 DistanceTo3D(this Location a, Location b)
{
// Use GeoCoordinate provided methods to calculate distance. Use
// same longitude on both points to calculate latitude distance and
// use same latitude on both points to calculate longitude distance.
float latitudeMeters = (float)a.DistanceTo(new Location() { Latitude = b.Latitude, Longitude = a.Longitude });
float longitudeMeters = (float)a.DistanceTo(new Location() { Latitude = a.Latitude, Longitude = b.Longitude });
// Invert the distance sign if necessary to account for direction
if (a.Latitude < b.Latitude)
{
latitudeMeters *= -1;
}
if (a.Longitude > b.Longitude)
{
longitudeMeters *= -1;
}
float altitudeMeters = 0f;
#if WP7
// Now calculate the altitude difference, but only if both sides of the equation have altitudes
if ((!double.IsNaN(a.Altitude)) && (!double.IsNaN(b.Altitude)))
{
// Calculate
altitudeMeters = (float)(b.Altitude - a.Altitude);
// Deal with really small double values getting converted to floats
if (float.IsInfinity(altitudeMeters)) { altitudeMeters = 0; }
}
#endif
// Return the new point
return new Vector3(longitudeMeters, altitudeMeters, latitudeMeters);
}
As I thought this was the issue (i.e. there is no altitude returned with the Vector3), I changed the library to use the altitude, but as soon as I add one (e.g. 20m or 1000m, etc.), the items are not displayed anymore in the WorldView.
Or does it have something to do with how I set the properties of the ARDisplay (note that the FarClippingPlane is relatively big, as items can be up to 100km away)?:
<ARControls:ARDisplay x:Name="ARDisplay" AttitudeRefreshRate="500" MovementThreshold="500" ServiceErrors="ARDisplay_ServiceErrors">
<ARControls:VideoPreview x:Name="VideoPreview" Canvas.ZIndex="1" />
<ARControls:WorldView x:Name="WorldView" ItemTemplate="{StaticResource ARMountainControl}" Canvas.ZIndex="3" MinItemScale="0.1" MaxItemScale="1.0" FarClippingPlane="100000.0" NearClippingPlane="50.0" />
</ARControls:ARDisplay>
Now I am pretty much out of ideas and appreciate all ideas and suggestions!