Welcome to MSDN Blogs Sign in | Join | Help

Installing VE3D without the setup package

In some scenarios it may be desirable to install the VE3D engine without visiting the www.bing.com/maps site, and/or to avoid the individual downloads that the setup package performs (eg offline or enterprise installations).

The main installation msi files are available at:

http://go.microsoft.com/fwlink/?LinkID=117319 for x86

http://go.microsoft.com/fwlink/?LinkID=117320 for x64 systems

If installed this way, the pre-requisites must already be installed:  the .NET 2.0 Framework and Windows Imaging Components.  Vista and Windows 7 already have both of these by default, for XP the latest versions are available by searching for them on the Microsoft Download Center.

For convenience, here are some links to the prerequisites:

http://go.microsoft.com/fwlink/?LinkID=106132 .NET 2.0 x86

http://go.microsoft.com/fwlink/?LinkID=106134 .NET 2.0 x64

http://go.microsoft.com/fwlink/?LinkID=101060 WIC x86

http://go.microsoft.com/fwlink/?LinkID=101061 WIC x64 

 

Posted by NikolaiF | 0 Comments
Filed under: ,

Hosting VE3D in native code

Sorry for the glut of posts this week.  I hadn't been able to write much, but there were still interesting topics and questions coming up and I'm trying to address that backlog now.  So, without further ado:

It is possible to host VE3D in a variety of contexts, and so far we've seen WinForms, WPF, and the browser.  It is also possible to host in straight native code.  In this sample, I address the COM interactions needed to host VE3D, and use OpenGL as an example hosting environment.

Download the code here.

VE3D on an OpenGL cube

This sample demonstrates four concepts:

Interaction with native code.
Back buffer retrieval.
Direct camera control.
OpenGL integration.

Native code:

Managed code provides easy and convenient methods for exposing your code to COM, and hence to native callers.
From the managed side, check "Register for COM interop" in your project's Build tab.  Decorate an interface
with ComVisible(true) and provide a guid, and the backing class with the interface type as shown.  Your types
are now visible and callable.

On the native side, you can now instantiate your managed code using typical COM calls, as shown.  It can then
be called similarly to any other object.

To add a new function to the interface, simply add it to the interface file and the backing .cs file, then
recompile.  By designing your interface in appropriately, you can then decide whether to do most of your logic
in native or managed code, depending on where you feel more comfortable.

Backbuffer retrieval:

The Render function provides the most efficient way of pulling VE3D's back buffer into main memory.  In general
it is better to not do this, rather let the hardware render to the screen directly, but some situations demand
using the scene in some other fashion.  Here, we get the memory as a direct pointer.  Note that this approach
assumes that you are handling any format and stride issues yourself.

It is also possible to get a graphics object from systemMemorySurface, an HDC from that, and then use functions
like BitBlt to copy out data and handle some of these issues for you.

Direct camera control:

Most samples thus far have demonstrated use of bindings and actions, or deriving camera controller.  The
CameraController class here shows how to write a controller that can react directly to user input, modifying
camera values directly.  The "best practices" method is to wrap your input device in a EventSource, and use
bindings and actions to communicate the information to your controller.  These structures provide simple
remapping of inputs, if necessary, and handle any threading or marshalling issues. 

However, it is also possible and sometimes appropriate to take the simpler approach used here.

OpenGL integration:

It is possible to integrate VE3D into an existing OpenGL application.  Using the Render method described above,
the pointer produced is suitable for direct consumption by OpenGL.  There are differences in how textures are
handled by the two APIs, but these are fairly simple to overcome, and are described in DrawOpenGLWindow().

Note that there is nothing that limits this sample to OpenGL, anything that can consume the buffer as provided
can host VE3D in the exact same manner.

Note on debugging:

The Visual Studio debugger requires some direction on how to deal with mixed native and managed code.
In the VE3DOpenGL properties page, expand Configuration Properties, click Debugging, then choose Debugger
Type.  You can elect to only attach to native, only to managed, or to both ("mixed").  "Auto" in this case
will be native-only.  If you find your breakpoints are not hitting, it is likely this setting.

Note on glut.h:

For some reason, in the release version only, I managed to get it thinking that it needed glut and I haven't
been able to figure out why.  If you encounter problems while compiling due to glut, just run in debug mode.
This is a problem that is specific to the sample app, not the methodology used.

Enjoy, and as usual please let me know about any questions or problems you may have.

Posted by NikolaiF | 0 Comments

GraphicsProxy RenderState

I've gotten a few questions lately about how to do some alpha effects using models, specifically MeshGraphicsObject.  After you create the GraphicsObject, it has a RenderState object available on it.  The fields on this object will be familiar to those experienced with DirectX, but here's a rundown of a few especially useful ones:

Allow your model to cast shadows on the ground.

            newMesh.RenderState.Lighting.CastShadows = true;

Allow your model to have directional shading (you can adjust the direction of the light using Host.WorldEngine.Environment.SunPosition).

            newMesh.RenderState.Lighting.DirectionalLightEnabled = true;

Allow your model to use transparency, whether from vertex colors, textures, or TextureFactor (see below).

            newMesh.RenderState.Alpha.Enabled = true;
            newMesh.RenderState.Alpha.SourceBlend = Blend.SourceAlpha;
            newMesh.RenderState.Alpha.DestinationBlend = Blend.InvSourceAlpha;

Allow use of TextureFactor to control the overall color of the model.  For example, you can create a model that has a texture with a white patch, and then create two models, one red and one blue, both using the same texture but differing on the value of TextureFactor.

            newMesh.RenderState.Stages[0].Blending.ColorArgument1 = TextureArgument.TextureColor;
            newMesh.RenderState.Stages[0].Blending.ColorArgument2 = TextureArgument.TFactor;
            newMesh.RenderState.Stages[0].Blending.ColorOperation = TextureOperation.Modulate;

Allow use of TextureFactor to control the overall opacity of the model.  This is great for fading effects, as changing the TextureFactor per-frame is cheap.

            newMesh.RenderState.Stages[0].Blending.AlphaArgument1 = TextureArgument.TextureColor;
            newMesh.RenderState.Stages[0].Blending.AlphaArgument2 = TextureArgument.TFactor;
            newMesh.RenderState.Stages[0].Blending.AlphaOperation = TextureOperation.Modulate;

Change the filtering used for textures.  For example, in the XFile sample, if you zoom in close to the model the texture gets blocky.  Dropping this code in improves the situation.

            newMesh.RenderState.Stages[0].Sampler.MagnificationFilter = TextureFilter.Linear;
            newMesh.RenderState.Stages[0].Sampler.MinificationFilter = TextureFilter.Linear;

The TextureFactor value mentioned above.  This value would make the model ghostly transparent and red-tinged.  This (and other values in RenderState) can be cheaply changed every frame.

            newMesh.RenderState.TextureFactor.Value = Color.FromArgb(128, Color.Red);

One additional note:  to use alpha, you must also call AddAlphaRenderable in your actor's Render function instead of just AddRenderable.  The distance is a sorting function that lets the renderer know what order to draw the alpha in (affects blending).  A constant value works in some situations, but if you find things look wrong, especially when one of your models occludes another, try using a value based on the distance between the model and the camera.

Here's a few shots to demonstrate the effects of these switches:

XFile Model

Everyone's favorite XFile sample model.

XFile Model, lit

The same model, with shadows and directional lighting (the sun is above and a bit behind, if you move it the shading and shadows move appropriately).

XFile Model, alternate texture

The same again, with an alternate texture that contains transparency and the various alpha switches on.  Note one detail:  the shadow casting code does not account for transparency.

XFile model, all switches

Same again, with all switches described above turned on.  The texture filtering is improved (look for blockiness in the center of the body in the previous shot), the color is shifted red, and the whole model is somewhat transparent, even parts where the texture is opaque.

Posted by NikolaiF | 2 Comments
Filed under: , ,

X File bulk display

I was asked the other day about how to load multiple x file -based models into VE3D without having to place each one manually.  I've written up a sample here.  The idea is more or less a fusion of the existing ActorDataSource and XFile samples, using the actor from the XFile sample rather than the bunnies.  I've also mocked up a very simple data file that contains placement information, rather than generating data on the fly as for the bunnies.

The way I've done this, the parsing code for the x files is done in the actor.  In this way, swapping out file formats should be straightforward so long as you have parsing code for it (sorry, only x files are directly implemented in the engine, but the results of any parse should still be easily convertible into VE3D graphics objects).

For the sake of simplicitly I did do one thing wrong.  The flow of the code is like this:  multiple background threads all execute QueryPrimitivesInternal at the same time, and when they are finished, they move through a lock into ActorBuilder.  They are still on background threads, but they now execute serially.  So, really the data retrieval (in this case, loading from resources, but probably a network request) and the parsing, as appropriate, should happen in QueryPrimitivesInternal, and the action in ActorBuilder should be kept to a minimum.  I violated this rule in the sample code for the sake of illustration, but you should be aware of it.

Finally, an important consideration is level of detail.  Dense and numerous models can slow down loading and rendering.  DataSources take advantage of the ActorBounds and scale concepts, such that it is possible to use simplified models at certain LODs, and switch to more detailed as the user zooms in.  If your needs are less extreme, then you can simply use scale to cause models to stop rendering when not in view, and at a certain distance, which is what I have done in the sample.

Have fun!

Posted by NikolaiF | 0 Comments

Constraining camera movement

Just got a good question:  what if I want to prevent the camera from moving outside certain bounds, for example to restrict altitude?

Technically it may be best to implement your own CameraController, so that you can make sure the restrictions are done smoothly for all cases.  But for many cases a simple mechanism will do.  Here it is:

this.Host.CameraControllers.CameraChanged += new CameraControllerManager.CameraChangedEventHandler(CameraControllers_CameraChanged);

 

void CameraControllers_CameraChanged(Microsoft.MapPoint.Rendering3D.Cameras.PredictiveCamera camera)

{

   if (camera.Viewpoint.Position.Altitude > 10000)

   {

      camera.Viewpoint.Position.Altitude = 10000;

   }

}

Posted by NikolaiF | 0 Comments
Filed under:

Actor data source questions

I just fielded a few good questions via email about actor data sources, and thought it would make a good post.

Actor data sources are a way of getting little bits of your code (actors) into the world, handing spatial indexing and cache management for you.  When each actor is in view, they are given the opportunity to execute code in the Render and Update functions.  When the cache is full and an actor is evicted, they again may execute code in the OnRemove function.

You create them by implementing a DataSource with usage Actor, and an ActorBuilder which translates the Primitives returned into Actor objects, along with information like what areas of the Earth the actors should be used in, as an ActorBounds object.  All of this can be seen in the ActorDataSource sample.

In the sample, however, only one Primitive is returned per request, and only one Actor.  What if you want more?  The important thing to know is that there has to be a 1-1 correspondence between Primitives and Actors *.  You must create one Actor for every Primitive used.  If you create more than one Actor for a single Primitive, only one will appear.

The reason for this is the Actor update story.  It is possible to update an Actor already in the system by two methods.  When an Actor is updated, the PrimitiveId from the passed-in primitive is used to find and update the actor in question.  If you add multiple actors per primitive, an ambiguity arises as to what you actually want to do.

It is possible to resolve this ambiguity by creating "nested" actors.  This is simple.  Just create the actors you want, and then a "container"

*:  actually you can create a single Actor with multiple Primitives, but I don't want to confuse the issue for now.

Updating an Actor:

Expiration.  On the Entity attached to your primitive, add a property "ExpiresInSeconds":

e.EntityTypes["bunny"].Properties.Create("ExpiresInSeconds", typeof(double));

...

entitySpec.Properties.SetValue("ExpiresInSeconds", 10.0);

Your QueryPrimitivesInternal function will be called again for every area the affected Actors live, and OnRemove will be called for the expiring Actors.

Manual.  You can specify a specific PrimitiveId to update using OnDataChanged in your source DataSource.

PrimitiveIdWriteableCollection wc = new PrimitiveIdWriteableCollection();
wc.Add(new BunnyPrimitiveId(this, tile));
OnDataChanged(new SpatialExtent(null, null, wc.GetReadOnlyCopy()));

You must also implement the QueryPrimitivesByIdsInternal function.  A collection of ids is provided, and you must return an array of Primitives that matches the input (so, the first item in the id collection should result in a Primitive at array index 0, etc).  If an element of the array is left null, that means to delete the Actor corresponding to that PrimitiveId.  Your ActorBuilder is then called to allow you to create the new replacement Actors.

You can also specify a region of the Earth to update in the SpatialExtent, but update by entity is not supported.  Updating very large areas can be expensive, so use spatial regions with care.  Update by PrimitiveId is the most efficient.

Posted by NikolaiF | 0 Comments

Bing Maps 3D

As you may be aware, the website changed names to Bing Maps:  http://www.bing.com/maps/.  The 3D view on the site is now called "Bing Maps 3D".

As a developer it doesn't change much for you, and in terms of the engine/SDK it's still valid to refer to it as "Virtual Earth 3D".  The only technical issue I can think of is to repeat that it's a good idea to use fwlinks for the urls for our base layer data, as explained at the end of the post here.

Thanks!

Posted by NikolaiF | 0 Comments

Data Format update and reminder

You may recall that I posted about a data format change for the new version.  The final switch-over is going to happen July 9th.  If you are still using an old version, models will stop displaying.  So upgrade now, the new version is better anyway.

For those already on the new version (assembly version 4), you do not need to change anything at all.

The plus side is that all of you developers have, for reasons of compatibility, been getting the old data for some time now, even if you have upgraded (right now, only Bing Maps gets the new data, everyone else gets the old).  On that date you will automatically start getting the new data, and yes you will notice.

Posted by NikolaiF | 0 Comments
Filed under:

WMS Data

I was having a discussion with Kurt Guenther from Infusion yesterday on the topic of WMS servers and VE3D.  There is a large amount of very interesting spatial data out there served by Web Map Services, or WMS servers.  VE3D is able to process this data using ConnectionParameter-based DataSources.  Setting it up is pretty easy:

ConnectionParameters cp = new ConnectionParameters(http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Portland/Portland_ESRI_Neighborhoods_AGO/MapServer/export?bbox={16},{17},{18},{19}&bboxSR=4326&layers=&layersDefs=&size=256,256&imageSR=102113&format=png&transparent=true&dpi=&f=image);

            string connectionParameters = cp.ToString(); 

            DataSourceLayerData layerData = new DataSourceLayerData(LayerName, Name, connectionParameters, DataSourceUsage.TextureMap);

            Host.DataSources.Add(layerData);

Drop this in to your Activate (plug-in) or Initialized handler (winforms etc) app and fly to Portland, OR to see the data (thanks to ArcGIS for the sample data and Kurt for the pointer).

I won't go into all the details of the WMS spec here, but I will call out a few important parts.  First, in order for this to work you must specify the bbox to be in Geographic coordinates (4326).  This is usually the default.  Second, you must pay attention to the returned projection.  In the above case, we have instructed the server to return 102113, which is Web Mercator, VE3D's native image projection.  This data can be consumed directly with very little overhead.  However, different servers support only certain formats and projections, and you must be careful for any particular server (it is possible to query this using WMS's GetCapabilities).  Nearly all support returning images in Geographic coordinates, 4326.  It is possible to instruct VE3D to reproject this to Web Mercator (this is the only reprojection VE3D will do for you, fortunately it will work for the majority of data).

Now, to look at ConnectionParameters and what it can do for you.  First, there's the big url.  Notice that the bbox has string.Format replacement variables in it:  {16}, {17}, etc.  Requests to the server are made on a per-tile basis (the T key is useful here).  For each request, these variables are replaced with data specific to the tile in question.  Here is a list of available parameters:

0 Reserved

1 Map Style

2 Round-robin integer

3 Reserved

4 Quadkey

5 Extension

6 Generation

7 Stripe (0-3)

8 Tile Host

9 App Host

10 Language code

11 Region code

12 Tile LOD

13 Tile X

14 Tile Y

15 Low order stripe (0-1)

16 MinLong

17 MinLat

18 MaxLong

19 MaxLat

20 RequestToken

21 Culture name

The most interesting ones are 4 (the main quad-key, very useful for already-tiled data), 12, 13, 14, and and 16-19.  To see some of this in action, check out the TerrainImages sample (also available in the sample code of course).  Programatically, you can investigate these values using the TileId class, using GetRequestCode, GetPosition, and GetLatLonBoundingBox.

As for other values on ConnectionParameters, you can control reprojection (if your data is in Geographic, specify CoordinateReferenceSystem = WGS84CoordinateReferenceSystem.Instance, as noted before this is the only reprojection natively supported, so otherwise leave this field uninitialized), the bounds of where the data is valid is terms of Lat/Long and LOD (useful to reducing unnecessary network requests), and caching behavior.

Caching behavior deserves special discussion, because WMS servers are often quite slow.  By default, data loaded using ConnectionParameters is not cached locally.  Once it moves out of memory, it must be re-queried.  If you set CacheRetention however, the data will be kept locally for the period of time specified (unless it is evicted due to space restrictions in the interim).  If you set CacheRetention = new TimeSpan(24, 0, 0), for example, for 24 hours from the time of query a given tile will not be re-queried.  Note that some servers are dynamic, such as weather data, so it's important to use an appropriate value here.

And just to give Kurt a poke in the ribs, please remember to only add DataSources after/during the Initialized event!

 Update:

John Fletcher from Latitude Geographics pointed out that the example I give above isn't actually WMS compliant in its query parameters.  He suggests an alternate sample, of the British Columbia, CA area:

ConnectionParameters p = new ConnectionParameters("http://openmaps.gov.bc.ca/mapserver/libcwms2?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=DBM_7H_MIL_BATHYMETRIC_POLY,BC_LABEL,DBM_7H_MIL_DRAINAGE_LINE,DBM_7H_MIL_DRAINAGE_POLY,DBM_7H_MIL_ROADS_LINE,DBM_7H_MIL_POLITICAL_POLY_PS,DBM_7H_MIL_POPULATION_POINT&STYLES=,,,,,,&SRS=EPSG:4326&BBOX={16},{17},{18},{19}&WIDTH=256&HEIGHT=256&FORMAT=image/png&TRANSPARENT=TRUE&EXCEPTIONS=application/vnd.ogc.se_inimage&");

p.CoordinateReferenceSystem = Microsoft.MapPoint.CoordinateSystems.Wgs84CoordinateReferenceSystem.Instance;

Host.DataSources.Add(new DataSourceLayerData("foo", "bar", p.ToString(), DataSourceUsage.TextureMap));

John also provided a link to the WMS spec repository (http://www.opengeospatial.org/standards/wms).  Note that the sample above is for WMS 1.1.1.  The most current version is 1.3.0, but many servers use the older, or support both.  No matter which you use (or even for something a little off spec like my original example) the interface with VE3D is the same.

Posted by NikolaiF | 0 Comments
Filed under: , , , ,

Modifying cache location

My, it has been a long time since I posted.  I promise I will try to be better.

Recently I was asked if it is possible to change the location of the cache file.  It is, with certain minor restrictions.  You can change the location by adding this to user.config:

      <setting name="PersistentCacheDirectory" serializeAs="String">
        <value>path here</value>
      </setting>

 

Or, when creating the GlobeControl directly, pass in a GlobeControlInitializationOptions object with PersistentCachePath set.

 

In either case, you can either specify a full path to anywhere, or a relative path from the current location (\AppData\LocalLow\Microsoft\Virtual Earth 3D\).

Putting the file outside LocalLow will cause problems when running in IE7/8 protected mode (Vista/Win7 with UAC on).  For a WinForms or WPF-based solution, it’s fine.  In such a case, the GlobeControlInitializationOptions setting is generally preferred as it will prevent problems when running Bing Maps on the same machine.  On the other hand, this will also cause two caches to be written, one in the default location and containing data from runs in Bing Maps, and one in the specified location.  The best approach depends on your exact usage.

 

Posted by NikolaiF | 0 Comments
Filed under: ,

Manual Rendering

Folks have really reacted to my mention of manual rendering, so I've made a sample for it.  Good thing, too, because to be frank there are a few warts.  On the upside, however, it is possible to work around all of them and the code required is not too scary.

Get the code!

In this sample, I host a GlobeControl on a form like normal, but instead of using the built-in render thread I render on the UI thread using the manual render API.  If you are content to let WinForms present to the screen for you, you're done at this point.

But it is common in these situations to want to get the rendered surface to make a movie, present in some other context like WPF, etc.  I include an example of the most basic way to do this, which is the only official way to currently do it (WorldEngine.CaptureScreenShot).  If this isn't good enough, and you're a bit more daring, it is possible to get our rendering surface and do more clever things with it.  That's what the good folks at Infostrat did for their WPF code, and for the time being I actually recommend using their wrapper if you want to use WPF.

I've labelled all the warts and their workarounds with the tag "WORKAROUND" in the code so you can look more closely if you like, but you should also just be able to copy and paste the sample and get your code to work as it should.  Also, this is not actually an an official part of the sample pack, but something similar to it will be.

Anisotropic Filtering

Anisotropic has been a bit of a frustration for us because while it is very easy to do (it's really just a flag to DirectX), the compatibility issue I mentioned before made it a pain to actually get it in to the control.  It's a shame we couldn't turn it on by default, but at least it's there.  The effect of it is really quite dramatic, as you can see below.  I took these images at this location, near the 405 and 90 interchange in Bellevue.

With anisotropic filtering enabled:

Anisotropic filtering

Without:

Trilinear Filtering

To turn it on in the website, click "options" in the upper right corner, then "3D settings", and finally check "Use anisotropic filtering".  To turn it on in code:

plugIn.Host.RenderEngine.Graphics.Settings.UseAnisotropicFiltering = true;

These settings are remembered in the user.config file for future runs of the control.  The perf penalty for this on cards that are even remotely modern is almost zero, so go turn it on now!

Posted by NikolaiF | 3 Comments
Filed under: ,

New Version Released!

Our new version has gone live.  Head on over to maps.live.com and click "3D" to upgrade.  This release is billed primarily as a perf and bug release because it doesn't add a lot of new features at the end-user level (though I think you will be pleased with the perf improvements), but we did have time to throw in some good stuff for the devs.

I've updated the Samples entry, and clicking on the link should get you the new sample set.  As usual, please pass along any problems in comments or blog feedback.  The samples are mostly the same, with a few new additions, but they have been cleaned up for best practices and new features.  I do recommend that you take a glance at them even if you're already familiar with the API.  The Camera sample is most changed, and hopefully should help explain the flow of camera control a little better.

Get the code!

Here's a sampling of new and expanded areas:

Initialized event
 A new event on RenderEngine that simplifies the startup scenario.  Check out SimpleForm to see it.  Remember that use of this event or FirstFrameRendered is now required!

Anisotropic Filtering
 Greatly improves the appearance of terrain when at an angle.  It's off by default, since there are some graphics cards that don't play nice with it (usually old and rare, but still).  You can turn this on through the website in the options box, or you can set it programmatically.  See SimpleForm.

Dem Data
 The ability to supply custom DEM data, and have it automatically stitched into existing data.  Previously DEM datasources did not work very well, mostly because we did not automatically stitch.  They are still a bit trickier than imagery, but there's a new sample DemData to help you out.

ILocationListener
 An interface that allows automatic and efficient query of a location to determine elevation as data changes.  ActorDataSource now uses it.  Essentially, you register this object and report its Lat/Lon position.  If the ground or other solid object moves or changes there, you will get a call to update.

Manual Rendering
 Manual render functions that allow use your own thread as the render thread, good for offline rendering or incorporation into another product.  RenderEngine.ManuallyInitializeRender and ManuallyRenderNextFrame.

Datasource ConnectionParameters
 Helper function for specifying data sources without a content manifest.  The string parameter was very hard to use, this is nicer.  There are also a few new options, like allowing caching of data specified this way.  See TerrainImages.

CelestialStyle
 Allow display of a stylized sky with constellations.  This is used on the website in Road Mode, but you can set it yourself.  See SimpleForm.

Versioning
 Support for running code built against previous control versions, if it meets certain requirements.  I've outlined this in http://blogs.msdn.com/virtualearth3d/archive/2009/04/01/upcoming-new-version.aspx.  To show it working, I've set up a page with samples built from the previous version and from the new version.  Both sets work just fine with the new release.

Pixel-width lines
 GeometryManager supports pixel-width 3D lines (previously only single-pixel or meter-width).  See the Camera sample.  We also now have nice looking text labels.  See the XFile sample.

Constant value datasources
 Helper functions for supplying flat color or elevation data.  The Mandelbrot sample uses one to display flat elevation.  Please note that a DEM and an Imagery datasource are actually required for proper display.  These constant value sources are useful for this case.

Terrain Scaling
 WorldEngine.Min/MaxElevationScaling.  It is actually possible to have varying scale based on your altitude, but there is some cost associated and I recommend that you set the two values equal to each other.  Our default value is 1.0, unscaled.

Override Loading Screen
 You can now render (or suppress) the loading screen (affectionately known as "The Circle Of Hope" since our first version, back when the startup flow was a bit less stable than it is now).  In the very simplest case, write this:

 class MyControl : GlobeControl
 {
    protected override void OnPaintLoading(...)
    {
    }
 }

This will get you a black screen.  You can also grab a reference to the control's Graphics object from the PaintEventArgs and draw anything you like.

Building culling value
 Allows control of how many buildings are displayed, based on distance and size of the buildings.  WorldEngine.BuildingCulling.  The effectiveness of this varies on hardware -- some hardware benefits a great deal, some very little.

Turn on/off street level navigation
 Can turn off some of the special navigation effects that occur when right next to the ground, such as sticking to the ground, and the screen drag regions on the sides of the screen when at low altitude.  WorldEngine.Enable*.


We have not yet updated the docs.  However, we did not make many fundamental changes to the code from an API perspective, and in fact existing code is as much as possible exactly the same.  So it is just lacking detail on the new features, and still a good reference.

Posted by NikolaiF | 13 Comments
Filed under: , ,

Data Format Revision

As part of our version update, we are also updating the file format of our 3D buildings.  The upside is that the new data format is significantly smaller, for faster download.  The downside is that old versions of the code cannot understand the new data.  However, in the short term this should not affect you.  There will be a period where old data will still be served to clients that are using the Javascript API and the Managed API.  This represents a bit of a compromise, because even clients that have updated to the new version will get the old data for this period, but we felt that this was better than releasing new code and breaking old (and existing) code on the same day.

To see the new data after the version update, simply navigate to maps.live.com and click 3D.  The new data will be live on the site.

Once this period is over, clients that have updated will automatically begin receiving the new data without any required changes or interruptions.  You will probably hardly notice, except that buildings of course will load faster.  Clients that have not updated will break!  You've been warned!  The only issue really will be that buildings will not appear, and only if your code is directly adding model data sources.

The exact length of this period is TBD, but probably about a month.  Our hope is that most everyone will update by then anyway, because the new version really is better.  I will blog a reminder when the date is decided and approaching.  As always, let me know if you will need any help during the transition.

In addition, in several samples I directly linked to the manifest files for some resources, like imagery, dem, and models.  These are the urls used when creating DataSourceLayerData objects.  I encourage you to instead use fwlinks, which are just redirects to the same resources.  This will help us update data while minimizing impact to clients.

Road:  http://go.microsoft.com/fwlink/?LinkID=98770
Aerial:  http://go.microsoft.com/fwlink/?LinkID=98771
Hybrid:  http://go.microsoft.com/fwlink/?LinkID=98772
DEM:  http://go.microsoft.com/fwlink/?LinkID=98774
Models:  http://go.microsoft.com/fwlink/?LinkID=98775

Edit:  took down the traffic link.  If you are interested in traffic data, please see here:  http://msdn.microsoft.com/en-us/library/bb877877.aspx

Posted by NikolaiF | 2 Comments

Logging

At times it can be useful to know when and if errors are occurring in VE3D.  When instructed, VE3D produces a log file that can be helpful for diagnosis.  This requires editing the user.config file and adding an entry:

      <setting name="Logging" serializeAs="String">
        <value>True</value>
      </setting>


The user.config file is located at:

(Vista) C:\Users\{username}\AppData\LocalLow\Microsoft\Virtual Earth 3D

(XP) C:\Documents and Settings\{username}\Application Data\Microsoft\Virtual Earth 3D

Log files are generated at:

(Vista) C:\Users\{username}\AppData\LocalLow\Microsoft\Virtual Earth 3D

(XP) C:\Documents and Settings\{username}\Local Settings\Application Data\Microsoft\Virtual Earth 3D

To increase the verbosity of logs, add another entry to user.config:

      <setting name="LoggingLevel" serializeAs="String">
        <value>2</value>
      </setting>

The values are like so:

0:  Critical errors only.  These errors may affect users.
1:  Warnings only.  These are errors that are handled internally and should not affect users.
2:  Informational.  These are not errors, but can be useful in some cases for debugging.

Posted by NikolaiF | 1 Comments
Filed under: ,
More Posts Next page »
 
Page view tracker