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。

大致如下

相关推荐
SmalBox10 小时前
【光照】Unity[经验模型]和[物理模型]
unity·渲染
在路上看风景12 小时前
10. 游戏开发中的TCP与UDP
unity
陈言必行13 小时前
Unity 性能优化 之 静态资源优化 (音频 | 模型 | 纹理 | 动画)
unity·性能优化·游戏引擎
Thomas_YXQ1 天前
Unity3D RectTransform.rect属性详解
unity·编辑器·游戏引擎·材质
平行云1 天前
赋能数字孪生:Paraverse平行云实时云渲染平台LarkXR,提供强大的API与SDK用于二次开发和深度集成
3d·unity·ue5·webgl·实时云渲染·云xr
SmalBox1 天前
【光照】[光照模型]发展里程碑时间线
unity·渲染
0wioiw01 天前
Unity(①基础)
unity·游戏引擎
死也不注释1 天前
【Unity UGUI 交互组件——InputFild(TMP版本)(11)】
unity·游戏引擎·交互
王维志2 天前
Unity Embedded Browser文档翻译
unity·c#