unity pcd 二进制版 简单显示文件对象(单色)

unity Point Cloud Viewer and Tool 那个插件不支持pcd二进制,而且网上到处都是AI

我恨这种AI滥用,提供不了一点价值

好了,言归正传

可以在Point Cloud Viewer and Tool这个插件报错地方转用这个代码,具体咋结合请自行研究。

部分参考:

Unity PointCloud开发:Mesh渲染点云_unity 点云特效-CSDN博客

步骤大致为

按行读取文件

发现是二进制文件

解码,计算出是三维坐标点的位置

然后直接实例化对象

为了保证性能,用了上面链接的方案,这样不用第三方库,也能兼容统信和多种平台

在一个空对象上直接挂载代码,作者设置如下

全代码+注释如下:

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class PCDReader :UnitySingleton<PCDReader> 
{
    public string filePath = "文件路径"; // PCD文件路径,需放置在Unity工程中

    public GameObject _obj;
    void Start()
    {
        LoadPCD(filePath);
    }

    public void LoadPCD(string path)//FileStream
    {
        /*if (!File.Exists(path))
        {
            Debug.LogError("文件不存在:" + path);
            return;
        }*/

        // 读取文件流
        using (FileStream stream=new FileStream(path, FileMode.Open))
        using (BinaryReader reader = new BinaryReader(stream))
        {
            // Step 1: 解析头部(ASCII格式)
            Dictionary<string, string> header = new Dictionary<string, string>();
            string line;
            while (true)
            {
                line = ReadLine(reader); // 自定义方法读取一行ASCII文本
                if (line == null || line.StartsWith("DATA binary"))
                    break;
                string[] parts = line.Split(' ');
                if (parts.Length >= 2)
                {
                    header[parts[0]] = parts[1];
                }
            }

            // 验证头部关键字段
            if (!header.ContainsKey("FIELDS") || !header.ContainsKey("POINTS") || !header.ContainsKey("SIZE"))
            {
                Debug.LogError("头部信息不完整");
             
            }

            // 提取元数据
            string[] fields = header["FIELDS"].Split(' ');
            int pointCount = int.Parse(header["POINTS"]);
            string[] sizes = header["SIZE"].Split(' ');
            List<Vector3> points = new List<Vector3>(); // 存储点坐标
            List<Color> colors = new List<Color>(); // 存储点颜色(如果存在rgb字段)

            // 计算每个点的大小(基于SIZE和COUNT)
            int pointSize = 0;
            foreach (string size in sizes)
            {
                pointSize += int.Parse(size); // SIZE每个值通常是4(字节)
            }

            // Step 2: 读取二进制数据部分
            for (int i = 0; i < pointCount; i++)
            {
                // 读取坐标(假设前三个字段是x,y,z)
                float x = reader.ReadSingle(); // 4字节浮点数
                float y = reader.ReadSingle();
                float z = reader.ReadSingle();

                points.Add(new Vector3(x, y, z));

                // 如果存在rgb字段,读取并转换为Unity颜色
                /*if (fields.Length >= 4 &amp;&amp; fields[3] == "rgb")
                {
                    uint rgb = reader.ReadUInt32(); // rgb通常以UInt32存储
                    float r = ((rgb >> 16) &amp; 0xFF) / 255.0f;
                    float g = ((rgb >> 8) &amp; 0xFF) / 255.0f;
                    float b = (rgb &amp; 0xFF) / 255.0f;
                    colors.Add(new Color(r, g, b));
                }*/
                // 跳过其他字段(如有)
                int remainingSize = pointSize;//- 12 - 4; // 减去xyz(12字节)和rgb(4字节)
                reader.ReadBytes(remainingSize);
            }

            // Step 3: 在Unity中创建点云对象
            CreatePointCloud(points, colors);
            
            //return points;
        }
    }

    // 辅助方法:从二进制流读取一行ASCII文本
    private string ReadLine(BinaryReader reader)
    {
        List<byte> bytes = new List<byte>();
        byte nextByte;
        while (reader.BaseStream.Position < reader.BaseStream.Length)
        {
            nextByte = reader.ReadByte();
            if (nextByte == '\n') // 换行符结束行
                break;
            bytes.Add(nextByte);
        }
        return System.Text.Encoding.ASCII.GetString(bytes.ToArray());
    }

    // 辅助方法:创建点云GameObject(使用Mesh)
    private void CreatePointCloud(List<Vector3> points, List<Color> colors)
    {
        GameObject pointCloud = _obj;/*new GameObject("PointCloud");
        Mesh mesh = new Mesh();
       // mesh.vertices = points.ToArray();

        // 设置颜色(如果存在)
        /*if (colors.Count == points.Count)
        {
            mesh.colors = colors.ToArray();
        }#1#

        // 创建MeshRenderer和MeshFilter
        MeshFilter meshFilter = pointCloud.AddComponent<MeshFilter>();
        MeshRenderer meshRenderer = pointCloud.AddComponent<MeshRenderer>();
        meshFilter.mesh = mesh;

        // 使用默认材质(可通过Unity材质自定义)
        meshRenderer.material = new Material(Shader.Find("Standard"));
        */
        CreateMesh(points.Count,points);
        /*for (int i = 0; i < points.Count; i++)
        {
            GameObject _obj=GameObject.Instantiate(pointCloud);
            _obj.transform.position = points[i];
        }*/
       
        
        Debug.Log("点云加载完成,点数: " + points.Count);
    }
  public  Mesh meshNeed;
    void CreateMesh(int num,List<Vector3> point)
    {
       
       int _PointNum = num;

        GameObject pointObj = new GameObject();
        pointObj.name = "PointCloud";

        // 绑定Mesh组件
        pointObj.AddComponent<MeshFilter>();
        pointObj.AddComponent<MeshRenderer>();
        // 为点云创建新的Mesh
        
        Material mat = new Material(Shader.Find("Custom/VertexColor"));
        pointObj.GetComponent<MeshFilter>().mesh = meshNeed;
        pointObj.GetComponent<MeshRenderer>().material = mat;

        Vector3[] points = new Vector3[num];
        Color[] colors = new Color[num];
        int[] indecies = new int[num];

        for (int i = 0; i < num; ++i)
        {
            points[i] = point[i];
            indecies[i] = i;
            colors[i] = Color.white;
        }

        meshNeed.vertices = points;
        meshNeed.colors = colors;
        meshNeed.SetIndices(indecies, MeshTopology.Points, 0);// 设置Mesh的渲染类型为Point
        meshNeed.SetIndexBufferParams(num, UnityEngine.Rendering.IndexFormat.UInt32);

    }
    

}

更新一下:

代码上加了个清理,为了重复调用,优化性能

meshNeed.Clear();

还得记得在外面加个try,catch。

大致如下

相关推荐
在路上看风景1 小时前
2.Square Grid
unity
程序猿阿伟1 小时前
《突破Unity热更新瓶颈:底层函数调用限制与生态适配秘籍》
unity·游戏引擎
龙智DevSecOps解决方案4 小时前
Perforce《2025游戏技术现状报告》Part 3:不同行业挑战以及Unreal、Godot、自研游戏引擎的应用趋势
游戏引擎·godot·游戏开发·perforce
在路上看风景4 小时前
13. UGUI合批
unity
jtymyxmz16 小时前
《Unity Shader》12.2调整屏幕的亮度、饱和度和对比度
unity·游戏引擎
AllBlue1 天前
unity嵌入安卓界面,如何显示状态
android·unity·游戏引擎
tealcwu1 天前
【Unity技巧】实现在Play时自动保存当前场景
java·unity·游戏引擎
tealcwu1 天前
【Unity基础】实现Scroll View跟随动态内容滚动
java·unity·游戏引擎
野奔在山外的猫1 天前
【文档】VSCode 配置 Unity 环境流程
unity
技术小甜甜1 天前
[Godot排错] 上传 Google Play Console 封闭测试时签名证书不匹配错误的解决方案
游戏引擎·godot·游戏开发