MeshSimplifier(List <Vec3> verts, int?target) { Console.WriteLine("Converting to indexed form"); ConvertToIndexed(verts); var nmesh = new Mesh(Vertices.Select(x => new Vector3d(x.X, x.Y, x.Z)).ToArray(), Triangles.Select(x => x.Triangulate()).SelectMany(x => x).ToArray()); nmesh.RecalculateNormals(); nmesh.RecalculateTangents(); Console.WriteLine("Decimating mesh"); nmesh = target == null ? MeshDecimation.DecimateMeshLossless(nmesh) : MeshDecimation.DecimateMesh(nmesh, target.Value); Vertices = nmesh.Vertices.Select(x => new Vec3((float)x.x, (float)x.y, (float)x.z)).ToList(); var inds = nmesh.Indices; Triangles = new List <Triangle>(); for (var i = 0; i < inds.Length; i += 3) { Triangles.Add(new Triangle(inds[i], inds[i + 1], inds[i + 2])); } }
private void SetModelTask(ModelFileData modelData) { if (CurrentModelVisual != null) { this.Viewport.Children.Remove(CurrentModelVisual); CurrentModelVisual = null; GC.Collect(0, GCCollectionMode.Forced); } if (!this.Viewport.IsVisible) { this.ModelDataToLoadWhenVisible = modelData; return; } Model3DGroup modelGroup = new Model3DGroup(); ModelVisual3D modelVisual = new ModelVisual3D(); try { if (modelData != null) { ModelFileData newModelData = new ModelFileData(modelData.FileFullPath); this.ModelData = newModelData; Viewport.SubTitle = modelData.FileName; newModelData.LoadBasicFileData(); if (userSettings.GetSettingBool(UserSettingEnum.EnableMaxSizeMBToLoadMeshInView) && modelData.FileSizeMB > userSettings.GetSettingInt(UserSettingEnum.MaxSizeMBToLoadMeshInView)) { // TODO: Load generic model. Viewport.SubTitle = Loc.GetTextFormatted("FileSizeTooBigToLoadMB", modelData.FileSizeMB, userSettings.GetSettingInt(UserSettingEnum.MaxSizeMBToLoadMeshInView)); CurrentModelVisual = null; return; } if (!newModelData.HasBytes()) { newModelData.LoadFileBytes(newModelData.FileSizeMB < 50f); } if (newModelData.Mesh == null) { newModelData.ParseFile(); } newModelData.ReleaseData(true, false); if (newModelData.Mesh == null) { newModelData.ReleaseData(true, false); SetModel(null); return; } LoadModelInfoAvailableEvent?.Invoke(newModelData.FileName, newModelData.Mesh.TriangleCount, newModelData.Mesh.Vertices.Length, (int)newModelData.FileSizeKB); float modelScale = newModelData.Mesh.Scale / 4f; float modelScaleMultiply = (newModelData.Mesh.Scale < 0.001f ? 0.1f : (newModelData.Mesh.Scale > 0.1 ? 10f : 1)); var transformTranslate = new TranslateTransform3D(-newModelData.Mesh.OffsetX, -newModelData.Mesh.OffsetY, -newModelData.Mesh.OffsetZ); AxisAngleRotation3D axisRotation = new AxisAngleRotation3D(new Vector3D(0, 0, 1), 0); transformObjectRotation = new RotateTransform3D(axisRotation, new Point3D(newModelData.Mesh.OffsetX, newModelData.Mesh.OffsetY, 0)); ScaleTransform3D transformScale = new ScaleTransform3D(modelScaleMultiply, modelScaleMultiply, modelScaleMultiply); Transform3DGroup transforms = new Transform3DGroup(); transforms.Children.Add(transformObjectRotation); transforms.Children.Add(transformTranslate); transforms.Children.Add(transformScale); Mesh3D mesh; // Mesh decimation if enabled if (userSettings.GetSettingBool(UserSettingEnum.EnableMeshDecimation) && newModelData.Mesh.TriangleCount > userSettings.GetSettingInt(UserSettingEnum.MinTrianglesForMeshDecimation)) { MeshDecimator.Math.Vector3d[] vectors3D = newModelData.Mesh.Vertices.Select(v => new MeshDecimator.Math.Vector3d(v.x, v.y, v.z)).ToArray(); Mesh decimatorMesh = new Mesh(vectors3D, newModelData.Mesh.Triangles.ToArray()); Mesh decimatedMesh = MeshDecimation.DecimateMeshLossless(decimatorMesh); mesh = new Mesh3D(decimatedMesh.Vertices.Select(v => new Point3D(v.x, v.y, v.z)), decimatedMesh.Indices); // TODO: Possibly cache the decimated models to avoid re-processing. } else { mesh = new Mesh3D(Point3DFromLinearCoordinates(newModelData.Mesh.Vertices), newModelData.Mesh.Triangles); } GeometryModel3D geometryModel = new GeometryModel3D(mesh.ToMeshGeometry3D(), GetMaterial()); geometryModel.Freeze(); modelGroup.Children.Add(geometryModel); modelGroup.Freeze(); _modelHeightPosition = newModelData.Mesh.Height * modelScaleMultiply; newModelData.ReleaseData(true, true); // Animation if (ModelAutoRotationEnabled) { DoubleAnimation animation1 = new DoubleAnimation(-90, 395d, TimeSpan.FromMilliseconds(1000)); animation1.EasingFunction = new ExponentialEase(); DoubleAnimation animation2 = new DoubleAnimation(36d, 395d, TimeSpan.FromMilliseconds(7000)); animation2.RepeatBehavior = RepeatBehavior.Forever; animation1.Completed += (o, e) => axisRotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, animation2); axisRotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, animation1); } // Camera animation var nomalizedOriginalPosition = _originalCameraPosition.ToVector3D(); nomalizedOriginalPosition.Normalize(); _modelCameraPosition = new Point3D(nomalizedOriginalPosition.X / modelScale * modelScaleMultiply, nomalizedOriginalPosition.Y / modelScale * modelScaleMultiply, nomalizedOriginalPosition.Z / modelScale * modelScaleMultiply); Point3D targetCameraPosition = _modelCameraPosition; if (_CurrentCameraPosition == CameraPositionEnum.Default) { var normalizedPosition = Viewport.Camera.Position.ToVector3D(); normalizedPosition.Normalize(); targetCameraPosition = new Point3D(normalizedPosition.X / modelScale * modelScaleMultiply, normalizedPosition.Y / modelScale * modelScaleMultiply, normalizedPosition.Z / modelScale * modelScaleMultiply); Viewport.Camera.AnimateTo(targetCameraPosition, Viewport.Camera.LookDirection, Viewport.Camera.UpDirection, 500d); } else { ResetCamera(CameraPositionEnum.Current); } minZoom = targetCameraPosition.Multiply(0.5d).DistanceTo(new Point3D()); maxZoom = minZoom * 4d; this.CurrentAxisRotation = axisRotation; modelVisual.Transform = transforms; } modelVisual.Content = modelGroup; this.Viewport.Children.Add(modelVisual); this.CurrentModelVisual = modelVisual; } catch (Exception ex) { if (CurrentModelVisual != null) { this.Viewport.Children.Add(CurrentModelVisual); this.CurrentModelVisual = null; } } if (modelData == null) { _modelCameraPosition = _originalCameraPosition; ResetCamera(CameraPositionEnum.Default, true); LoadModelInfoAvailableEvent?.Invoke("", 0, 0, 0); _modelHeightPosition = (float)(_originalCameraPosition.Z / 2d); Viewport.SubTitle = string.Empty; } GC.Collect(); }