/// <summary>
        /// Reads from the header of the point cloud file
        /// </summary>
        /// <param name="data"> The MeshInfos variable in which we store the data </param>
        /// <param name="reader"> The binary reader variable </param>
        /// <param name="maximumVertex"> The maximum number of vertices to render </param>
        private void readHeader(MeshInfos data, BinaryReader reader, int maximumVertex)
        {
            char v = reader.ReadChar();

            if (v == '\n')
            {
                if (readerInfos.lineText.Contains("end_header"))
                {
                    readerInfos.header = false;
                }
                else if (readerInfos.lineText.Contains("element vertex"))
                {
                    readMeshInfos(data, maximumVertex);
                }
                else if (readerInfos.lineText.Contains("property uchar alpha"))
                {
                    readerInfos.colorDataCount = 4;
                }
                else if (readerInfos.lineText.Contains("property float n"))
                {
                    readerInfos.normalDataCount += 1;
                }
                readerInfos.lineText = "";
            }
            else
            {
                readerInfos.lineText += v;
            }
            readerInfos.step    = sizeof(char);
            readerInfos.cursor += readerInfos.step;
        }
        /// <summary>
        /// Returns the mesh information of the point cloud by reading the .ply file
        /// </summary>
        /// <param name="filePath"> The file path of the point cloud file to load </param>
        /// <param name="maximumVertex"> The maximum number of vertices to render </param>
        public MeshInfos Load(string filePath, int maximumVertex = 65000)
        {
            MeshInfos data = new MeshInfos();

            if (File.Exists(filePath))
            {
                using (BinaryReader reader = new BinaryReader(File.Open(filePath, FileMode.Open))) {
                    int length = (int)reader.BaseStream.Length;
                    data.vertexCount = 0;
                    //ReaderInfos readerInfos = new ReaderInfos();
                    while (readerInfos.cursor + readerInfos.step < length)
                    {
                        if (readerInfos.header)
                        {
                            readHeader(data, reader, maximumVertex);
                        }
                        else
                        {
                            readBody(data, reader);
                        }
                    }
                }
            }
            return(data);
        }
        public void Export()
        {
            MeshInfos triangles = GetTriangles(points, size);

            materialBaked = new Material(shaderBaked);
            Generate(triangles, materialBaked, MeshTopology.Triangles);
            materialBaked.SetTexture("_MainTex", GetBakedColors(triangles));
        }
        public void Generate()
        {
            return;

            points   = LoadPointCloud();
            material = new Material(shader);
            Generate(points, material, MeshTopology.Points);
        }
        public MeshInfos GetTriangles(MeshInfos points, float radius)
        {
            MeshInfos triangles = new MeshInfos();

            triangles.vertexCount = points.vertexCount * 3;
            triangles.vertices    = new Vector3[triangles.vertexCount];
            triangles.normals     = new Vector3[triangles.vertexCount];
            triangles.colors      = new Color[triangles.vertexCount];
            int index           = 0;
            int meshVertexIndex = 0;
            int meshIndex       = 0;

            Vector3[] vertices = meshArray[meshIndex].vertices;
            for (int v = 0; v < triangles.vertexCount; v += 3)
            {
                Vector3 center  = vertices[meshVertexIndex];
                Vector3 normal  = points.normals[index];
                Vector3 tangent = Vector3.Normalize(Vector3.Cross(Vector3.up, normal));
                Vector3 up      = Vector3.Normalize(Vector3.Cross(tangent, normal));

                triangles.vertices[v]     = center + tangent * -radius / 1.5f;
                triangles.vertices[v + 1] = center + up * radius;
                triangles.vertices[v + 2] = center + tangent * radius / 1.5f;

                triangles.normals[v]     = normal;
                triangles.normals[v + 1] = normal;
                triangles.normals[v + 2] = normal;

                Color color = points.colors[index];
                triangles.colors[v]     = color;
                triangles.colors[v + 1] = color;
                triangles.colors[v + 2] = color;

                ++meshVertexIndex;

                if (meshVertexIndex >= meshArray[meshIndex].vertices.Length)
                {
                    meshVertexIndex = 0;
                    ++meshIndex;
                    if (meshIndex < meshArray.Length)
                    {
                        vertices = meshArray[meshIndex].vertices;
                    }
                }

                ++index;
            }
            return(triangles);
        }
 /// <summary>
 /// Reads the information about the mesh from the header of the point cloud file
 /// </summary>
 /// <param name="data"> The MeshInfos variable in which we store the data </param>
 /// <param name="maximumVertex"> The maximum number of vertices to render </param>
 private void readMeshInfos(MeshInfos data, int maximumVertex)
 {
     string[] array = readerInfos.lineText.Split(' ');
     if (array.Length > 0)
     {
         //int subtractor = array.Length - 2; Leave it we may need it
         data.vertexCount = Convert.ToInt32(array [2]);
         if (data.vertexCount > maximumVertex)
         {
             readerInfos.levelOfDetails = 1 + (int)Mathf.Floor(data.vertexCount / maximumVertex);
             data.vertexCount           = maximumVertex;
         }
         data.vertices = new Vector3[data.vertexCount];
         data.normals  = new Vector3[data.vertexCount];
         data.colors   = new Color[data.vertexCount];
     }
 }
        /// <summary>
        /// Reads the body of the point cloud file
        /// </summary>
        /// <param name="data"> The MeshInfos variable in which we store the data </param>
        /// <param name="reader"> The binary reader variable </param>
        private void readBody(MeshInfos data, BinaryReader reader)
        {
            if (readerInfos.index < data.vertexCount)
            {
                data.vertices[readerInfos.index] = new Vector3(-reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                if (readerInfos.normalDataCount == 3)
                {
                    data.normals[readerInfos.index] = new Vector3(-reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                }
                else
                {
                    data.normals[readerInfos.index] = new Vector3(1f, 1f, 1f);
                }
                data.colors[readerInfos.index] = new Color(reader.ReadByte() / 255f, reader.ReadByte() / 255f, reader.ReadByte() / 255f, 1f);

                readerInfos.step    = sizeof(float) * 6 * readerInfos.levelOfDetails + sizeof(byte) * readerInfos.colorDataCount * readerInfos.levelOfDetails;
                readerInfos.cursor += readerInfos.step;
                if (readerInfos.colorDataCount > 3)
                {
                    reader.ReadByte();
                }

                if (readerInfos.levelOfDetails > 1)
                {
                    for (int l = 1; l < readerInfos.levelOfDetails; ++l)
                    {
                        for (int f = 0; f < 3 + readerInfos.normalDataCount; ++f)
                        {
                            reader.ReadSingle();
                        }
                        for (int b = 0; b < readerInfos.colorDataCount; ++b)
                        {
                            reader.ReadByte();
                        }
                    }
                }
                ++readerInfos.index;
            }
        }
Example #8
0
        public MeshInfos Load(string filePath, int maximumVertex = 65000)
        {
            MeshInfos data           = new MeshInfos();
            int       levelOfDetails = 1;

            if (File.Exists(filePath))
            {
                using (BinaryReader reader = new BinaryReader(File.Open(filePath, FileMode.Open))) {
                    int    cursor         = 0;
                    int    length         = (int)reader.BaseStream.Length;
                    string lineText       = "";
                    bool   header         = true;
                    int    vertexCount    = 0;
                    int    colorDataCount = 3;
                    int    index          = 0;
                    int    step           = 0;
                    while (cursor + step < length)
                    {
                        if (header)
                        {
                            char v = reader.ReadChar();
                            if (v == '\n')
                            {
                                if (lineText.Contains("end_header"))
                                {
                                    header = false;
                                }
                                else if (lineText.Contains("element vertex"))
                                {
                                    string[] array = lineText.Split(' ');
                                    if (array.Length > 0)
                                    {
                                        int subtractor = array.Length - 2;
                                        vertexCount = Convert.ToInt32(array [array.Length - subtractor]);
                                        if (vertexCount > maximumVertex)
                                        {
                                            levelOfDetails = 1 + (int)Mathf.Floor(vertexCount / maximumVertex);
                                            vertexCount    = maximumVertex;
                                        }
                                        data.vertexCount = vertexCount;
                                        data.vertices    = new Vector3[vertexCount];
                                        data.normals     = new Vector3[vertexCount];
                                        data.colors      = new Color[vertexCount];
                                    }
                                }
                                else if (lineText.Contains("property uchar alpha"))
                                {
                                    colorDataCount = 4;
                                }
                                lineText = "";
                            }
                            else
                            {
                                lineText += v;
                            }
                            step    = sizeof(char);
                            cursor += step;
                        }
                        else
                        {
                            if (index < vertexCount)
                            {
                                data.vertices[index] = new Vector3(-reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                                data.normals[index]  = new Vector3(-reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                                data.colors[index]   = new Color(reader.ReadByte() / 255f, reader.ReadByte() / 255f, reader.ReadByte() / 255f, 1f);

                                step    = sizeof(float) * 6 * levelOfDetails + sizeof(byte) * colorDataCount * levelOfDetails;
                                cursor += step;
                                if (colorDataCount > 3)
                                {
                                    reader.ReadByte();
                                }

                                if (levelOfDetails > 1)
                                {
                                    for (int l = 1; l < levelOfDetails; ++l)
                                    {
                                        for (int f = 0; f < 6; ++f)
                                        {
                                            reader.ReadSingle();
                                        }
                                        for (int b = 0; b < colorDataCount; ++b)
                                        {
                                            reader.ReadByte();
                                        }
                                    }
                                }

                                ++index;
                            }
                        }
                    }
                }
            }
            return(data);
        }
        public void Generate(MeshInfos meshInfos, Material materialToApply, MeshTopology topology)
        {
            for (int c = transform.childCount - 1; c >= 0; --c)
            {
                Transform child = transform.GetChild(c);
                GameObject.DestroyImmediate(child.gameObject);
            }

            int vertexCount = meshInfos.vertexCount;
            int meshCount   = (int)Mathf.Ceil(vertexCount / (float)verticesMax);

            meshArray      = new Mesh[meshCount];
            transformArray = new Transform[meshCount];

            int index       = 0;
            int meshIndex   = 0;
            int vertexIndex = 0;

            int resolution = GetNearestPowerOfTwo(Mathf.Sqrt(vertexCount));

            while (meshIndex < meshCount)
            {
                int count = verticesMax;
                if (vertexCount <= verticesMax)
                {
                    count = vertexCount;
                }
                else if (vertexCount > verticesMax && meshCount == meshIndex + 1)
                {
                    count = vertexCount % verticesMax;
                }

                Vector3[] subVertices = meshInfos.vertices.Skip(meshIndex * verticesMax).Take(count).ToArray();
                Vector3[] subNormals  = meshInfos.normals.Skip(meshIndex * verticesMax).Take(count).ToArray();
                Color[]   subColors   = meshInfos.colors.Skip(meshIndex * verticesMax).Take(count).ToArray();
                int[]     subIndices  = new int[count];
                for (int i = 0; i < count; ++i)
                {
                    subIndices[i] = i;
                }

                Mesh mesh = new Mesh();
                mesh.bounds   = new Bounds(Vector3.zero, Vector3.one * 100f);
                mesh.vertices = subVertices;
                mesh.normals  = subNormals;
                mesh.colors   = subColors;
                mesh.SetIndices(subIndices, topology, 0);

                Vector2[] uvs2 = new Vector2[mesh.vertices.Length];
                for (int i = 0; i < uvs2.Length; ++i)
                {
                    float x = vertexIndex % resolution;
                    float y = Mathf.Floor(vertexIndex / (float)resolution);
                    uvs2[i] = new Vector2(x, y) / (float)resolution;
                    ++vertexIndex;
                }
                mesh.uv2 = uvs2;

                GameObject go = CreateGameObjectWithMesh(mesh, materialToApply, gameObject.name + "_" + meshIndex, transform);

                meshArray[meshIndex]      = mesh;
                transformArray[meshIndex] = go.transform;

                index += count;
                ++meshIndex;
            }
        }
        public Texture2D GetBakedColors(MeshInfos triangles)
        {
            List <Color> colorList = new List <Color>();

            int[] colorIndexMap = new int[triangles.vertexCount / 3];
            int   globalIndex   = 0;

            for (int meshIndex = 0; meshIndex < meshArray.Length; ++meshIndex)
            {
                Mesh    mesh   = meshArray[meshIndex];
                Color[] colors = mesh.colors;
                for (int i = 0; i < colors.Length; i += 3)
                {
                    Color color       = colors[i];
                    Color colorSimple = new Color(Mathf.Floor(color.r * details) / details, Mathf.Floor(color.g * details) / (float)details, Mathf.Floor(color.b * details) / (float)details);

                    int colorIndex = colorList.IndexOf(colorSimple);
                    if (colorIndex == -1)
                    {
                        colorIndex = colorList.Count;
                        colorList.Add(colorSimple);
                    }

                    colorIndexMap[globalIndex] = colorIndex;
                    ++globalIndex;
                }
            }

            int colorCount  = colorList.Count;
            int columnCount = GetNearestPowerOfTwo(Mathf.Sqrt(colorCount));
            int rowCount    = columnCount;         //1 + (int)Mathf.Floor(colorCount / (float)columnCount);
            int width       = circleRadius * columnCount;
            int height      = circleRadius * rowCount;

            colorMapTexture = new Texture2D(width, height, TextureFormat.RGBA32, false);
            Color[] colorMapArray = new Color[width * height];
            Vector2 pos;
            Vector2 target = new Vector2(0.5f, 0.3f);

            for (int i = 0; i < colorList.Count; ++i)
            {
                int x = i % columnCount;
                int y = (int)Mathf.Floor(i / columnCount);
                for (int c = 0; c < circleRadius * circleRadius; ++c)
                {
                    int ix = c % circleRadius;
                    int iy = (int)Mathf.Floor(c / circleRadius);
                    pos.x = ix / (float)circleRadius;
                    pos.y = iy / (float)circleRadius;
                    float dist       = Mathf.Clamp01(Vector2.Distance(target, pos));
                    int   colorIndex = x * circleRadius + y * width * circleRadius + ix + iy * width;
                    float circle     = 1f - Mathf.InverseLerp(0.2f, 0.35f, dist);
                    colorMapArray[colorIndex] = Color.Lerp(Color.clear, colorList[i], circle);
                }
            }
            colorMapTexture.SetPixels(colorMapArray);
            colorMapTexture.Apply(false);

            Vector2 halfSize = new Vector2(0.5f * circleRadius / (float)width, 0.5f * circleRadius / (float)height);
            Vector2 right    = Vector2.right * halfSize.x;
            Vector2 up       = Vector2.up * halfSize.y;

            globalIndex = 0;
            for (int meshIndex = 0; meshIndex < meshArray.Length; ++meshIndex)
            {
                Mesh      mesh = meshArray[meshIndex];
                Vector2[] uvs  = new Vector2[mesh.vertices.Length];
                for (int i = 0; i < uvs.Length; i += 3)
                {
                    int     colorIndex = colorIndexMap[globalIndex];
                    float   x          = ((colorIndex % columnCount) * circleRadius) / (float)width;
                    float   y          = (Mathf.Floor(colorIndex / columnCount) * circleRadius) / (float)height;
                    Vector2 center     = new Vector2(x + halfSize.x, y + halfSize.y);

                    uvs[i]     = center + right - up;
                    uvs[i + 1] = center + up;
                    uvs[i + 2] = center - right - up;

                    ++globalIndex;
                }
                mesh.uv = uvs;
            }

            return(colorMapTexture);
        }
        public MeshInfos Load(string filePath, int maximumVertex = 65000)
        {
            //System.Diagnostics.Process.Start("CMD.exe", "/C del / q / f *.txt");

            System.Diagnostics.Process          process   = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            startInfo.FileName    = "cmd.exe";
            startInfo.Arguments   = "/C del / q / f *.txt";
            process.StartInfo     = startInfo;
            process.Start();
            process.WaitForExit();

            {
                TextWriter sw = new StreamWriter("into Load.txt");
                sw.Close();
            }
            char[] filec  = filePath.ToCharArray();
            int    flen   = filePath.Length;
            IntPtr buffer = Marshal.AllocHGlobal(flen * sizeof(char));

            Marshal.Copy(filec, 0, buffer, flen);

            IntPtr ansp = new IntPtr(0);

            Debug.Log("readPCD");
            int anslen = readPCD(buffer, filePath.Length, ref ansp);

            Debug.Log("after readPCD.txt");
            char[] ans = new char[anslen];
            Marshal.Copy(ansp, ans, 0, anslen);


            string input = new string(ans);

            //object va = JsonConvert.DeserializeObject(input);
            JArray receivedObject = JArray.Parse(input);

            //dynamic receivedObject2 = JObject.Parse(input);

            //var list = receivedObject.Count
            Debug.Log("after Deserialize.txt");

            MeshInfos data = new MeshInfos();

            data.vertexCount = receivedObject.Count;
            data.vertices    = new Vector3[data.vertexCount];
            data.normals     = new Vector3[data.vertexCount];
            data.colors      = new Color[data.vertexCount];
            for (int i = 0; i < receivedObject.Count; ++i)
            {
                Dictionary <string, object> jp = receivedObject[i].ToObject <Dictionary <string, object> >();
                //decimal dx = jp["x"];
                float x = Convert.ToSingle(jp["x"]);
                float y = Convert.ToSingle(jp["y"]);
                float z = Convert.ToSingle(jp["z"]);
                data.vertices[i] = new Vector3(x, y, z);
                float r = Convert.ToSingle(jp["r"]) / 255;
                float g = Convert.ToSingle(jp["g"]) / 255;
                float b = Convert.ToSingle(jp["b"]) / 255;
                data.colors[i] = new Color(r, g, b);
            }
            Debug.Log("after MeshInfos.txt");
            return(data);
        }