diff --git a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.Import.cs b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.Import.cs index 7fa8b84..4237f6c 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.Import.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.Import.cs @@ -17,6 +17,8 @@ using Assimp; using HelixToolkit.Wpf; +using PcdSharp.IO; +using PcdSharp.Struct; using System; using System.IO; using System.Linq; @@ -54,6 +56,86 @@ public partial class HelixPanel modelVisual.Content = model; } } + if (importerType == ImporterType.Extended_PCD) + { + // Only support PCD files with PointXYZ format + // Not supported for Color or Intensity formats + var xyzCloud = PCDReader.Read(_path); + + // Create a single geometry for all points to improve performance + var pointCloudGeometry = new MeshGeometry3D(); + var positions = new Point3DCollection(); + var triangleIndices = new Int32Collection(); + + // Create material for points + var pointMaterial = new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(0x60, 0x80, 0xFF))); + + // Adaptive point size based on total number of points + var totalPoints = xyzCloud.Points.Count; + var pointSize = totalPoints > 10000 ? 0.05d : totalPoints > 1000 ? 0.1d : 0.2d; + + // Limit points for performance (show every Nth point if too many) + var step = Math.Max(1, totalPoints / 50000); // Limit to ~50k points max + + var vertexIndex = 0; + for (int i = 0; i < xyzCloud.Points.Count; i += step) + { + var point = xyzCloud.Points[i]; + + // Create a small cube for each point + var halfSize = pointSize / 2; + + // Add 8 vertices for the cube + var baseIndex = vertexIndex; + + // Front face vertices + positions.Add(new Point3D(point.X - halfSize, point.Y - halfSize, point.Z + halfSize)); + positions.Add(new Point3D(point.X + halfSize, point.Y - halfSize, point.Z + halfSize)); + positions.Add(new Point3D(point.X + halfSize, point.Y + halfSize, point.Z + halfSize)); + positions.Add(new Point3D(point.X - halfSize, point.Y + halfSize, point.Z + halfSize)); + + // Back face vertices + positions.Add(new Point3D(point.X - halfSize, point.Y - halfSize, point.Z - halfSize)); + positions.Add(new Point3D(point.X + halfSize, point.Y - halfSize, point.Z - halfSize)); + positions.Add(new Point3D(point.X + halfSize, point.Y + halfSize, point.Z - halfSize)); + positions.Add(new Point3D(point.X - halfSize, point.Y + halfSize, point.Z - halfSize)); + + // Add triangle indices for the cube (12 triangles, 36 indices) + // Front face + triangleIndices.Add(baseIndex + 0); triangleIndices.Add(baseIndex + 1); triangleIndices.Add(baseIndex + 2); + triangleIndices.Add(baseIndex + 0); triangleIndices.Add(baseIndex + 2); triangleIndices.Add(baseIndex + 3); + // Back face + triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 6); triangleIndices.Add(baseIndex + 5); + triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 7); triangleIndices.Add(baseIndex + 6); + // Left face + triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 0); triangleIndices.Add(baseIndex + 3); + triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 3); triangleIndices.Add(baseIndex + 7); + // Right face + triangleIndices.Add(baseIndex + 1); triangleIndices.Add(baseIndex + 5); triangleIndices.Add(baseIndex + 6); + triangleIndices.Add(baseIndex + 1); triangleIndices.Add(baseIndex + 6); triangleIndices.Add(baseIndex + 2); + // Top face + triangleIndices.Add(baseIndex + 3); triangleIndices.Add(baseIndex + 2); triangleIndices.Add(baseIndex + 6); + triangleIndices.Add(baseIndex + 3); triangleIndices.Add(baseIndex + 6); triangleIndices.Add(baseIndex + 7); + // Bottom face + triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 5); triangleIndices.Add(baseIndex + 1); + triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 1); triangleIndices.Add(baseIndex + 0); + + vertexIndex += 8; + } + + pointCloudGeometry.Positions = positions; + pointCloudGeometry.TriangleIndices = triangleIndices; + + // Create the model + var pointCloudModel = new GeometryModel3D + { + Geometry = pointCloudGeometry, + Material = pointMaterial, + BackMaterial = pointMaterial + }; + + modelVisual.Content = pointCloudModel; + } else { var modelImporter = new ModelImporter(); @@ -90,6 +172,7 @@ file static class Importer ".stl" or ".obj" or ".3ds" or ".lwo" or ".ply" => ImporterType.Default, ".fbx" or ".3mf" or ".glb" or ".gltf" or ".dae" or ".dxf" => ImporterType.Extended, ".pmx" => ImporterType.Extended_MMD, + ".pcd" => ImporterType.Extended_PCD, _ => ImporterType.Unknown, }; } @@ -97,8 +180,28 @@ file static class Importer file enum ImporterType { + /// + /// Reserved or unspecified import type + /// Unknown, + + /// + /// Default importer supported by HelixToolkit + /// Default, + + /// + /// Extended importer supported by Assimp + /// Extended, + + /// + /// Extended MMD (MikuMikuDance) importer + /// Extended_MMD, + + /// + /// Extended PCD (Point Cloud Data) importer for 3D spatial data + /// + Extended_PCD, } diff --git a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Plugin.cs index e51f752..eb3b6c2 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Plugin.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Plugin.cs @@ -31,17 +31,20 @@ public class Plugin : IViewer /// private static readonly HashSet WellKnownExtensions = new( [ - // Default + // Default supported by HelixToolkit ".stl", ".obj", ".3ds", ".lwo", ".ply", - // Extended + // Extended supported by Assimp ".fbx", ".3mf", ".blend", ".glb", ".gltf", ".dae", #if S_DXF ".dxf", #endif - // Extended_MMD + // TBD: MMD (MikuMikuDance) //".pmx", + + // PCD (Point Cloud Data) + ".pcd", ]); private HelixPanel _hp; diff --git a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/QuickLook.Plugin.HelixViewer.csproj b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/QuickLook.Plugin.HelixViewer.csproj index ba81ac7..a80bc43 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/QuickLook.Plugin.HelixViewer.csproj +++ b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/QuickLook.Plugin.HelixViewer.csproj @@ -55,6 +55,7 @@ +