/// <summary>
        /// Creates a new entity from a surface
        /// </summary>
        /// <param name="entityName">The entity Name</param>
        /// <param name="surface">The hololens surface information</param>
        /// <returns>The new entity</returns>
        protected override Entity CreateNewSurfaceEntity(string entityName, SpatialMappingSurface surface)
        {
            var surfaceEntity = new Entity(entityName)
            {
                IsSerializable = false,
                IsStatic = true
            }
            .AddComponent(new Transform3D());

            if (!string.IsNullOrEmpty(this.MaterialPath))
            {
                surfaceEntity.AddComponent(new MaterialsMap()
                {
                    DefaultMaterialPath = this.MaterialPath,
                    UseMaterialCopy = this.UseMaterialCopy,
                });
            }

            this.RefreshModel(surface, surfaceEntity);
            this.UpdateSurfaceEntity(surface, surfaceEntity);
            this.RefreshCollider(surfaceEntity);

            return surfaceEntity;
        }
 /// <summary>
 /// Updates a surface entity
 /// </summary>        
 /// <param name="surface">The hololens surface information</param>
 /// <param name="surfaceEntity">The entity to update</param>
 protected override void UpdateSurfaceEntity(SpatialMappingSurface surface, Entity surfaceEntity)
 {
     Transform3D transform = surfaceEntity.FindComponent<Transform3D>();
     transform.LocalPosition = surface.Position;
     transform.LocalScale = surface.Scale;
     transform.LocalOrientation = surface.Orientation;
 }
        /// <summary>
        /// Refresh the surface mesh
        /// </summary>
        /// <param name="surface">The hololens surface information</param>
        /// <param name="surfaceEntity">The entity to update</param>
        protected override void RefreshModel(SpatialMappingSurface surface, Entity surfaceEntity)
        {
            if (!surfaceEntity.IsDisposed)
            {
                surfaceEntity.RemoveComponent<Model>()
                    .RemoveComponent<ModelRenderer>()
                    .AddComponent(Model.CreateFromMesh(surface.Mesh));

                if (this.IsVisible && !string.IsNullOrEmpty(this.MaterialPath))
                {
                    surfaceEntity.AddComponent(new ModelRenderer());
                }
            }
        }
 /// <summary>
 /// Updates a surface entity
 /// </summary>        
 /// <param name="surface">The hololens surface information</param>
 /// <param name="surfaceEntity">The entity to update</param>
 protected abstract void UpdateSurfaceEntity(SpatialMappingSurface surface, Entity surfaceEntity);
 /// <summary>
 /// Refresh the surface mesh
 /// </summary>
 /// <param name="surface">The hololens surface information</param>
 /// <param name="surfaceEntity">The entity to update</param>
 protected abstract void RefreshModel(SpatialMappingSurface surface, Entity surfaceEntity);
        /// <summary>
        /// Handles the SurfaceObserver's OnSurfaceChanged event. 
        /// </summary>
        /// <param name="id">The identifier assigned to the surface which has changed.</param>
        /// <param name="surface">The surface</param>
        /// <param name="changeType">The type of change that occurred on the surface.</param>
        /// <param name="updateTime">The date and time at which the change occurred.</param>
        protected virtual void OnSurfaceChanged(Guid id, SpatialMappingSurface surface, SurfaceChange changeType, DateTimeOffset updateTime)
        {
            WaveServices.Dispatcher.RunOnWaveThread(() =>
            {
                if (surface.Mesh == null)
                {
                    return;
                }

                Debug.WriteLine("OnSurfaceChanged [" + changeType + "] " + id);

                string entityId = this.GetEntityNameFromSurfaceId(id);

                switch (changeType)
                {
                    case SurfaceChange.Added:
                    case SurfaceChange.Updated:

                        var surfaceEntity = this.Owner.FindChild(entityId);
                        if (surfaceEntity == null)
                        {
                            surfaceEntity = this.CreateNewSurfaceEntity(entityId, surface);
                            surfaceEntity.Tag = SurfaceEntityTag;

                            if (surfaceEntity != null)
                            {
                                this.Owner.AddChild(surfaceEntity);
                            }
                        }
                        else
                        {
                            this.RefreshModel(surface, surfaceEntity);
                            this.UpdateSurfaceEntity(surface, surfaceEntity);
                        }

                        break;

                    case SurfaceChange.Removed:

                        // Remove the child entity
                        this.Owner.RemoveChild(entityId);

                        break;

                    default:
                        break;
                }
            });
        }
 /// <summary>
 /// Creates a new entity from a surface
 /// </summary>
 /// <param name="entityName">The entity Name</param>
 /// <param name="surface">The hololens surface information</param>
 /// <returns>The new entity</returns>
 protected abstract Entity CreateNewSurfaceEntity(string entityName, SpatialMappingSurface surface);