/// <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; } }
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); }