Helix Viewport + SharpDX - Loaded models not visible in viewport

For some reason I can't see any of the models I'm importing into this Helix viewport I've set up. I've tried a thousand code combinations, drawing from the examples in the HelixToolkit git as well. Nothing. No errors, no exceptions, no crashes, nothing at all. The models simply aren't visible, even though I know for a fact the program is parsing them because it used to throw exceptions at me. Maybe it's just, you know, something really dumb I'm overlooking, but right now I'm drawing a blank.

(Slightly modified) code from model importer demo with some really simple console outputs for debugging purposes:

// MainViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using HelixToolkit.Wpf.SharpDX;
using HelixToolkit.Wpf.SharpDX.Animations;
using HelixToolkit.Wpf.SharpDX.Assimp;
using HelixToolkit.Wpf.SharpDX.Controls;
using HelixToolkit.Wpf.SharpDX.Model;
using HelixToolkit.Wpf.SharpDX.Model.Scene;
using Microsoft.Win32;
using MvvmHelpers;
using Point3D = System.Windows.Media.Media3D.Point3D;
using Vector3D = System.Windows.Media.Media3D.Vector3D;
using Color = System.Windows.Media.Color;
using Colors = System.Windows.Media.Colors;
using SharpDX;
using JulMar.Windows.Mvvm;
using System.Linq;

namespace FileLoadDemo
{
    public class MainViewModel : BaseViewModel
    {
        private string OpenFileFilter = $"{HelixToolkit.Wpf.SharpDX.Assimp.Importer.SupportedFormatsString}";
        private string ExportFileFilter = $"{HelixToolkit.Wpf.SharpDX.Assimp.Exporter.SupportedFormatsString}";
        private bool showWireframe = false;
        public bool ShowWireframe
        {
            set
            {
                if (SetProperty(ref showWireframe, value))
                {
                    ShowWireframeFunct(value);
                }
            }
            get
            {
                return showWireframe;
            }
        }

        private bool renderFlat = false;
        public bool RenderFlat
        {
            set
            {
                if (SetProperty(ref renderFlat, value))
                {
                    RenderFlatFunct(value);
                }
            }
            get
            {
                return renderFlat;
            }
        }

        private bool renderEnvironmentMap = true;
        public bool RenderEnvironmentMap
        {
            set
            {
                if (SetProperty(ref renderEnvironmentMap, value) && scene != null && scene.Root != null)
                {
                    foreach (var node in scene.Root.Traverse())
                    {
                        if (node is MaterialGeometryNode m && m.Material is PBRMaterialCore material)
                        {
                            material.RenderEnvironmentMap = value;
                        }
                    }
                }
            }
            get => renderEnvironmentMap;
        }

        public ICommand OpenFileCommand { get; set; }
        public DefaultEffectsManager EffectsManager { get; }
        public OrthographicCamera Camera { get; }
        public ICommand ResetCameraCommand { get; set; }
        public ICommand ExportCommand { private set; get; }
        public ICommand CopyAsBitmapCommand { private set; get; }
        public ICommand CopyAsHiresBitmapCommand { private set; get; }

        private bool isLoading = false;
        public bool IsLoading
        {
            private set => SetProperty(ref isLoading, value);
            get => isLoading;
        }

        private bool isPlaying = false;
        public bool IsPlaying
        {
            private set => SetProperty(ref isPlaying, value);
            get => isPlaying;
        }

        private float startTime;
        public float StartTime
        {
            private set => SetProperty(ref startTime, value);
            get => startTime;
        }

        private float endTime;
        public float EndTime
        {
            private set => SetProperty(ref endTime, value);
            get => endTime;
        }

        private float currAnimationTime = 0;
        public float CurrAnimationTime
        {
            set
            {
                if (EndTime == 0)
                { return; }
                if (SetProperty(ref currAnimationTime, value % EndTime + StartTime))
                {
                    animationUpdater?.Update(value, 1);
                }
            }
            get => currAnimationTime;
        }

        public ObservableCollection<IAnimationUpdater> Animations { get; } = new ObservableCollection<IAnimationUpdater>();

        public SceneNodeGroupModel3D GroupModel { get; } = new SceneNodeGroupModel3D();

        private IAnimationUpdater selectedAnimation = null;
        public IAnimationUpdater SelectedAnimation
        {
            set
            {
                if (SetProperty(ref selectedAnimation, value))
                {
                    StopAnimation();
                    CurrAnimationTime = 0;
                    if (value != null)
                    {
                        animationUpdater = value;
                        animationUpdater.Reset();
                        animationUpdater.RepeatMode = AnimationRepeatMode.Loop;
                        StartTime = value.StartTime;
                        EndTime = value.EndTime;
                    }
                    else
                    {
                        animationUpdater = null;
                        StartTime = EndTime = 0;
                    }
                }
            }
            get
            {
                return selectedAnimation;
            }
        }

        private float speed = 1.0f;
        public float Speed
        {
            set
            {
                SetProperty(ref speed, value);
            }
            get => speed;
        }

        private Point3D modelCentroid = default;
        public Point3D ModelCentroid
        {
            private set => SetProperty(ref modelCentroid, value);
            get => modelCentroid;
        }
        private BoundingBox modelBound = new BoundingBox();
        public BoundingBox ModelBound
        {
            private set => SetProperty(ref modelBound, value);
            get => modelBound;
        }
        public TextureModel EnvironmentMap { get; }

        public ICommand PlayCommand { get; }

        private SynchronizationContext context = SynchronizationContext.Current;
        private HelixToolkitScene scene;
        private IAnimationUpdater animationUpdater;
        private List<BoneSkinMeshNode> boneSkinNodes = new List<BoneSkinMeshNode>();
        private List<BoneSkinMeshNode> skeletonNodes = new List<BoneSkinMeshNode>();
        private CompositionTargetEx compositeHelper = new CompositionTargetEx();
        private long initTimeStamp = 0;

        public MainViewModel(DefaultEffectsManager effectsManager)
        {
            EffectsManager = effectsManager;
            this.OpenFileCommand = new DelegateCommand(this.OpenFile);
            Camera = new OrthographicCamera()
            {
                LookDirection = new System.Windows.Media.Media3D.Vector3D(0, -10, -10),
                Position = new System.Windows.Media.Media3D.Point3D(0, 10, 10),
                UpDirection = new System.Windows.Media.Media3D.Vector3D(0, 1, 0),
                FarPlaneDistance = 5000,
                NearPlaneDistance = 0.1f
            };
            ResetCameraCommand = new DelegateCommand(() =>
            {
                (Camera as OrthographicCamera).Reset();
                (Camera as OrthographicCamera).FarPlaneDistance = 5000;
                (Camera as OrthographicCamera).NearPlaneDistance = 0.1f;
            });
            ExportCommand = new DelegateCommand(() => { ExportFile(); });

            CopyAsBitmapCommand = new DelegateCommand(() => { CopyAsBitmapToClipBoard(); });
            CopyAsHiresBitmapCommand = new DelegateCommand(() => { CopyAsHiResBitmapToClipBoard(); });

            EnvironmentMap = TextureModel.Create("Cubemap_Grandcanyon.dds");

            PlayCommand = new DelegateCommand(() =>
            {
                if (!IsPlaying && SelectedAnimation != null)
                {
                    StartAnimation();
                }
                else
                {
                    StopAnimation();
                }
            });
        }

        private void CopyAsBitmapToClipBoard()
        {
            var bitmap = ViewportExtensions.RenderBitmap((Viewport3DX)Application.Current.MainWindow.FindName("view"));
            try
            {
                Clipboard.Clear();
                Clipboard.SetImage(bitmap);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
            }
        }

        private void CopyAsHiResBitmapToClipBoard()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();

            var bitmap = ViewportExtensions.RenderBitmap((Viewport3DX)Application.Current.MainWindow.FindName("view"), 1920, 1080);
            try
            {
                Clipboard.Clear();
                Clipboard.SetImage(bitmap);
                stopwatch.Stop();
                Debug.WriteLine($"creating bitmap needs {stopwatch.ElapsedMilliseconds} ms");
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
            }
        }

        private void OpenFile()
        {
            if (isLoading)
            {
                Console.WriteLine("Loading");
                return;
            }
            string path = OpenFileDialog(OpenFileFilter);
            if (path == null)
            {
                Console.WriteLine("Null path");
                return;
            }
            StopAnimation();
            var syncContext = SynchronizationContext.Current;
            IsLoading = true;
            Task.Run(() =>
            {
                var loader = new Importer();
                var scene = loader.Load(path);
                scene.Root.Attach(EffectsManager); // Pre attach scene graph
                Console.WriteLine("Attached scene graph");
                scene.Root.UpdateAllTransformMatrix();
                Console.WriteLine("Transform matrix updated");
                if (scene.Root.TryGetBound(out var bound))
                {
                    /// Must use UI thread to set value back.
                    syncContext.Post((o) => { ModelBound = bound; }, null);
                }
                if (scene.Root.TryGetCentroid(out var centroid))
                {
                    /// Must use UI thread to set value back.
                    syncContext.Post((o) => { ModelCentroid = centroid.ToPoint3D(); }, null);
                }
                return scene;
            }).ContinueWith((result) =>
            {
                IsLoading = false;
                Console.WriteLine("Completed");
                if (result.IsCompleted)
                {
                    scene = result.Result;
                    Animations.Clear();
                    var oldNode = GroupModel.SceneNode.Items.ToArray();
                    GroupModel.Clear(false);
                    Task.Run(() =>
                    {
                        foreach (var node in oldNode)
                        { node.Dispose(); }
                    });
                    if (scene != null)
                    {
                        if (scene.Root != null)
                        {
                            foreach (var node in scene.Root.Traverse())
                            {
                                if (node is MaterialGeometryNode m)
                                {
                                    //m.Geometry.SetAsTransient();
                                    if (m.Material is PBRMaterialCore pbr)
                                    {
                                        pbr.RenderEnvironmentMap = RenderEnvironmentMap;
                                        Console.WriteLine("pbr");
                                    }
                                    else if (m.Material is PhongMaterialCore phong)
                                    {
                                        phong.RenderEnvironmentMap = RenderEnvironmentMap;
                                        Console.WriteLine("phong");
                                    }
                                }
                            }
                        }
                        GroupModel.AddNode(scene.Root);
                        if (scene.HasAnimation)
                        {
                            var dict = scene.Animations.CreateAnimationUpdaters();
                            foreach (var ani in dict.Values)
                            {
                                Animations.Add(ani);
                            }
                        }
                        FocusCameraToScene();
                    }
                }
                else if (result.IsFaulted && result.Exception != null)
                {
                    MessageBox.Show(result.Exception.Message);
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }

        public void StartAnimation()
        {
            initTimeStamp = Stopwatch.GetTimestamp();
            compositeHelper.Rendering += CompositeHelper_Rendering;
            IsPlaying = true;
        }

        public void StopAnimation()
        {
            IsPlaying = false;
            compositeHelper.Rendering -= CompositeHelper_Rendering;
        }

        private void CompositeHelper_Rendering(object sender, System.Windows.Media.RenderingEventArgs e)
        {
            if (animationUpdater != null)
            {
                var elapsed = (Stopwatch.GetTimestamp() - initTimeStamp) * speed;
                CurrAnimationTime = elapsed / Stopwatch.Frequency;
            }
        }

        private void FocusCameraToScene()
        {
            var maxWidth = Math.Max(Math.Max(modelBound.Width, modelBound.Height), modelBound.Depth);
            var pos = modelBound.Center + new Vector3(0, 0, maxWidth);
            Camera.Position = pos.ToPoint3D();
            Camera.LookDirection = (modelBound.Center - pos).ToVector3D();
            Camera.UpDirection = Vector3.UnitY.ToVector3D();
            if (Camera is OrthographicCamera orthCam)
            {
                orthCam.Width = maxWidth;
            }
        }

        private void ExportFile()
        {
            var index = SaveFileDialog(ExportFileFilter, out var path);
            if (!string.IsNullOrEmpty(path) && index >= 0)
            {
                var id = HelixToolkit.Wpf.SharpDX.Assimp.Exporter.SupportedFormats[index].FormatId;
                var exporter = new HelixToolkit.Wpf.SharpDX.Assimp.Exporter();
                exporter.ExportToFile(path, scene, id);
                return;
            }
        }

        private string OpenFileDialog(string filter)
        {
            var d = new OpenFileDialog();
            d.CustomPlaces.Clear();
            d.Filter = filter;

            if (!d.ShowDialog().Value)
            {
                return null;
            }
            return d.FileName;
        }

        private int SaveFileDialog(string filter, out string path)
        {
            var d = new SaveFileDialog();
            d.Filter = filter;
            if (d.ShowDialog() == true)
            {
                path = d.FileName;
                return d.FilterIndex - 1; // This is starting from 1. So must minus 1
            }
            else
            {
                path = "";
                return -1;
            }
        }

        private void ShowWireframeFunct(bool show)
        {
            foreach (var node in GroupModel.GroupNode.Items.PreorderDFT((node) => node.IsRenderable))
            {
                if (node is MeshNode m)
                {
                    m.RenderWireframe = show;
                }
            }
        }

        private void RenderFlatFunct(bool show)
        {
            foreach (var node in GroupModel.GroupNode.Items.PreorderDFT((node) => node.IsRenderable))
            {
                if (node is MeshNode m)
                {
                    if (m.Material is PhongMaterialCore phong)
                    {
                        phong.EnableFlatShading = show;
                    }
                    else if (m.Material is PBRMaterialCore pbr)
                    {
                        pbr.EnableFlatShading = show;
                    }
                }
            }
        }
    }
}

The code I'm attempting to call previous code from:

using System;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using HelixToolkit.Wpf.SharpDX.Controls;
using FileLoadDemo;
using HelixToolkit.Wpf.SharpDX;

namespace Intelligencecasinos_Animation_Maker
{
    public partial class Form3 : Form
    {
        private Viewport3DX viewport;
        private MainViewModel viewModel;
        private DefaultEffectsManager effectsManager;

        public Form3()
        {
            InitializeComponent();
            this.Load += Form3_Load;
        }

        private void Form3_Load(object sender, EventArgs e)
        {
            InitializeEffectsManager();
            InitializeHelixViewport();
            InitializeViewModel();
        }
        private void CreateGrid()
        {
            var grid = new AxisPlaneGridModel3D();
            viewport.Items.Add(grid);
        }
        private void InitializeEffectsManager()
        {
            effectsManager = new DefaultEffectsManager();
        }

        private void InitializeHelixViewport()
        {
            viewport = new Viewport3DX
            {
                Name = "view",
                EffectsManager = effectsManager,
                Camera = new PerspectiveCamera
                {
                    LookDirection = new System.Windows.Media.Media3D.Vector3D(0, -10, -10),
                    Position = new System.Windows.Media.Media3D.Point3D(0, 10, 10),
                    UpDirection = new System.Windows.Media.Media3D.Vector3D(0, 1, 0),
                    FarPlaneDistance = 5000,
                    NearPlaneDistance = 0.1f
                },
                BackgroundColor = System.Windows.Media.Color.FromRgb(30, 30, 30) // Dark background
            };

            // Create a WindowsFormsHost to host the WPF control
            var host = new ElementHost
            {
                Dock = DockStyle.Fill,
                Child = viewport
            };

            // Add the WindowsFormsHost to the existing viewportPanel
            CreateGrid();
            viewportPanel.Controls.Add(host);
        }

        private void InitializeViewModel()
        {
            viewModel = new MainViewModel(effectsManager);
            viewport.DataContext = viewModel;
            viewport.Items.Add(viewModel.GroupModel);
            Console.WriteLine("Viewmodel initialized");
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            viewModel.OpenFileCommand.Execute(null);
        }
    }
}

Upvotes: 0

Views: 171

Answers (0)

Related Questions