Insight3D provides interfaces for providing dynamic data to types which normally contain static data. From a client's perspective, once the types are initialized with the dynamic interface, they can still be utilized and consumed by all other interfaces within Insight3D as if the types contained just static data. When that data is requested by a user or internally within the library, the dynamic interface provides the data for that particular time.
For example, this pattern allows for projection data to translate and change attitude with time, or images within Insight3D to stream video. Since textures can be created from images, users can place video or other dynamic data on any object within Insight3D that supports textures, such as Marker and Surface Mesh primitives. Similarly, the AgGxGlobeInlayProjectedImage globe inlay, which projects an image onto a globe inlay, can be used with dynamic data to provide functionality such as displaying video while transforming a moving projection.
|
|
|
Subsequent animation steps of a Surface Mesh primitive using a texture from an image constructed with a dynamic interface. |
Dynamic interfaces within Insight3D contain an Update method which provides the current animation time and an interface for providing data at that particular time. Below, IAgGxDynamicImageData.Update is implemented to provide image data from the successive frames of an animated GIF, by copying the data from a bitmap to IAgGxImageData.ScanEntry. Since the data is updated, the method returns true:
public bool Update(IAgGxImageData ImageData, double Time) { Bitmap currentFrame = m_ImageProvider.GetNextFrame(); byte[] currentFrameData = ImagingUtil.DataFromBitmap(currentFrame); unsafe { IntPtr ptr = (IntPtr)ImageData.ScanEntry; Marshal.Copy(currentFrameData, 0, ptr, currentFrameData.Length); } return true; }
Similarly, IAgGxDynamicImageProjection.Update is implemented to set the projection data in AgGxImageProjectionData dynamically on each animation step:
public bool Update(IAgGxImageProjectionData ProjectionData, double Time) { ProjectionProviderData providerData = m_ProjectionProvider.Evaluate(Time); ProjectionData.SetCBFPosition( providerData.Position.X, providerData.Position.Y, providerData.Position.Z); ProjectionData.SetCBFAttitude( providerData.Rotation.M21, providerData.Rotation.M22, providerData.Rotation.M23, -providerData.Rotation.M11, -providerData.Rotation.M12, -providerData.Rotation.M13, providerData.Rotation.M31, providerData.Rotation.M32, providerData.Rotation.M33); ProjectionData.SetProjectionView(0.230908805, 0.174532925, 20.0, 10000.0, Time); return true; }
|
|
|
Subsequent animation steps of a IAgGxGlobeInlayProjectedImage globe inlay using image and projection data constructed with dynamic interfaces. |
Updating dynamic data is tied to animation and utilizes the Delta method of the dynamic data interface to allow a user to control the update rate of the data. The delta is specified in seconds, so a delta of .1 will update 10 times per second while animating. If the delta is set to 0, the dynamic data's Update method is called on every animation update. Below, the Delta method of the dynamic data interface is implemented to configure the update rate to 60 updates per second:
public void Delta(ref double delta) { delta = 0.0166; }
Any object which supports dynamic data can be initialized using the LoadFromDynamic method with an interface for providing the dynamic data to that object. Below, the AgGxImage and AgGxImageProjectionData types are initialized with types that implement the IAgGxDynamicImageData and IAgGxDynamicImageProjection interfaces:
IAgGxVideoData videoReader = new AgGxVideoData(); videoReader.Initialize(Program.localDataPath + "ProjectedImagery/fig8.avi"); videoReader.AnimationStartDate = 0; IAgGxImage projectedImage = new AgGxImage(); projectedImage.LoadFromDynamic(videoReader); IAgGxImageProjectionData projectionData = new AgGxImageProjectionData(); projectionData.LoadFromDynamic(new DynamicProjection());
Once a type is loaded with a dynamic data interface, it can be used with any other type as if it contained just static data. Below, a texture is created from an image that has been initialized with IAgGxDynamicImageData, which is then used to create a marker which inherits the dynamic properties of the image:
IAgGxImage dynamicImage = new AgGxImage(); dynamicImage.LoadFromDynamic(new DynamicSatellite()); IAgGxRendererTexture2D texture2D = sceneManager.Textures.LoadFromImage(dynamicImage); IAgGxCentralBody earth = sceneManager.CentralBodies("Earth"); IAgGxPrimitiveMarker marker = new AgGxPrimitiveMarker(); marker.InitializeCartographicFromTexture2D(earth, Trig.DegreesToRadians(30), Trig.DegreesToRadians(-80), 35786000, texture2D, 256);
|
|
|
Subsequent animation steps of a Marker primitive using a texture from an image constructed with a dynamic interface. |
See the HowTo for the complete set of the dynamic data examples shown in this overview.