PointCloudData ImportLaz(AssetImportContext context) { var name = Path.GetFileName(context.assetPath); using (var laz = new Laszip(context.assetPath)) { long count = laz.Count; if (count > MaxPointCount) { Debug.LogWarning($"Too many points ({count:n0}), truncating to {MaxPointCount:n0}"); count = MaxPointCount; } var bounds = new PointCloudBounds() { MinX = laz.MinX, MinY = laz.MinY, MinZ = laz.MinZ, MaxX = laz.MaxX, MaxY = laz.MaxY, MaxZ = laz.MaxZ, }; double scaleX, scaleY, scaleZ; double centerX, centerY, centerZ; if (Normalize) { centerX = -0.5 * (bounds.MaxX + bounds.MinX); centerY = -0.5 * (bounds.MaxY + bounds.MinY); centerZ = -0.5 * (bounds.MaxZ + bounds.MinZ); scaleX = 2.0 / (bounds.MaxX - bounds.MinX); scaleY = 2.0 / (bounds.MaxY - bounds.MinY); scaleZ = 2.0 / (bounds.MaxZ - bounds.MinZ); } else if (Center) { centerX = -0.5 * (bounds.MaxX + bounds.MinX); centerY = -0.5 * (bounds.MaxY + bounds.MinY); centerZ = -0.5 * (bounds.MaxZ + bounds.MinZ); scaleX = scaleY = scaleZ = 1.0; } else { centerX = centerY = centerZ = 0.0; scaleX = scaleY = scaleZ = 1.0; } bool hasColor = laz.HasColor; var transform = GetTransform(); var points = new PointCloudPoint[(int)count]; try { for (long i = 0; i < count; i++) { if ((i % (128 * 1024)) == 0) { float progress = (float)((double)i / count); EditorUtility.DisplayProgressBar($"Importing {name}", $"{i:N0} points", progress); } var p = laz.GetNextPoint(); double x = (p.X + centerX) * scaleX; double y = (p.Y + centerY) * scaleY; double z = (p.Z + centerZ) * scaleZ; var pt = transform.MultiplyVector(new Vector3((float)x, (float)y, (float)z)); byte intensity; if (LasRGB8BitWorkaround) { intensity = (byte)(p.Intensity >> 0); } else { intensity = (byte)(p.Intensity >> 8); } uint color = (uint)(intensity << 24); if (hasColor) { if (LasRGB8BitWorkaround) { byte r = (byte)(p.Red >> 0); byte g = (byte)(p.Green >> 0); byte b = (byte)(p.Blue >> 0); color |= (uint)((b << 16) | (g << 8) | r); } else { byte r = (byte)(p.Red >> 8); byte g = (byte)(p.Green >> 8); byte b = (byte)(p.Blue >> 8); color |= (uint)((b << 16) | (g << 8) | r); } } else { color |= (uint)((intensity << 16) | (intensity << 8) | intensity); } points[i] = new PointCloudPoint() { Position = pt, Color = color, }; } } finally { EditorUtility.ClearProgressBar(); } var unityBounds = GetBounds(bounds); unityBounds.center = transform.MultiplyPoint3x4(unityBounds.center); unityBounds.extents = transform.MultiplyVector(unityBounds.extents); return(PointCloudData.Create(points, unityBounds, hasColor, transform.MultiplyPoint3x4(bounds.Center), transform.MultiplyVector(bounds.Extents))); } }
private PointCloudData <T> ParseLines(FileInfo f, int id) { _metadata = new PointCloudMetaData(); bool isInitialized = false; int index = 0; _startData = false; T[] points = new T[0]; string[] lines = new string[0]; try { lines = File.ReadAllLines(f.FullName); } catch (Exception e) { UnityEngine.Debug.Log(e.Message); } foreach (string line in lines) { // Parse metadata if (!_startData) { ParseMetadata(line, ref _metadata); } else { if (!isInitialized) { points = new T[_metadata.pointSize]; isInitialized = true; } // Parse vertices string[] values = line.Split(' '); if (values.Length != _metadata.numFields) { throw new System.Exception("Vertices was not same as fields"); } float x = 0, y = 0, z = 0; bool success = float.TryParse(values[0], out x); success = success && float.TryParse(values[1], out y); success = success && float.TryParse(values[2], out z); if (!success) { throw new System.Exception("Could not parse a vertex"); } if (_metadata.field == PointCloudDataType.XYZ) { Vector3 pos = new Vector3(x, y, z); PointXYZ point = new PointXYZ(pos); points[index++] = (T)point; } /* * else if (_metadata.field == PointCloudDataType.XYZRGB) * { * float rgba = float.Parse(values[3]); * byte r, g, b; * * // Unpack packed float - 3 channel * byte[] colorBytes = BitConverter.GetBytes(rgba); * r = colorBytes[0]; * g = colorBytes[1]; * b = colorBytes[2]; * * Vector3 point = new Vector3(x, y, z); * Color col = new Color(r, g, b); * points[index++] = new PointXYZRGBA(point, col); * } * else if (_metadata.field == PointCloudDataType.XYZRGBA) * { * int rgba = int.Parse(values[3]); * byte r, g, b, a; * * // Unpack float - 4 channel * byte[] colorBytes = BitConverter.GetBytes(rgba); * r = colorBytes[0]; * g = colorBytes[1]; * b = colorBytes[2]; * a = colorBytes[3]; * * Vector3 point = new Vector3(x, y, z); * Color32 col = new Color32(r, g, b, a); * points[index++] = new PointXYZRGBA(point, col); * } */ } } if (points.Length == 0 || points.Length != _metadata.pointSize) { throw new System.Exception("Vertices were empty or did not match declared points. Was:" + points.Length + ", but expected: " + _metadata.pointSize); } PointCloudData <T> pcd = new PointCloudData <T>(points, points.Length, _metadata, id); return(pcd); }
public void SetPointCloudDataFromInteropData(PointCloudData <PointXYZConfidence> pcd, PointCloudMetaData metadata) { throw new NotImplementedException(); }
/// <summary> /// Reads the specified file and returns PointCloudData, assigning the given frame id. /// </summary> /// <param name="f"></param> public virtual PointCloudData <PointXYZConfidence> ParseFile(FileInfo f, int id) { _metadata = new PointCloudMetaData(); bool isInitialized = false; int index = 0; _startData = false; PointXYZConfidence[] points = new PointXYZConfidence[0]; string[] lines = new string[0]; int numPoints = 0; try { lines = File.ReadAllLines(f.FullName); } catch (Exception e) { UnityEngine.Debug.Log(e.Message); } foreach (string line in lines) { // Parse metadata if (!_startData) { ParseMetadata(line, ref _metadata); } else { if (!isInitialized) { numPoints = _metadata.pointSize; if (_metadata.pointSize != lines.Length - 11) { numPoints = lines.Length - 11; UnityEngine.Debug.Log("Metadata point count didn't match. Overriding point count."); } points = new PointXYZConfidence[numPoints]; isInitialized = true; } // Parse vertices string[] values = line.Split(' '); if (values.Length != _metadata.numFields) { throw new System.Exception("Vertices was not same as fields"); } float x = 0, y = 0, z = 0, conf = 0; bool success = float.TryParse(values[0], out x); success = success && float.TryParse(values[1], out y); success = success && float.TryParse(values[2], out z); success = success && float.TryParse(values[3], out conf); //-3.402823E+38 -3.402823E+38 -3.402823E+38 0 // Watch for these values - causes Unity AABB error. Skip for now. To investigate. if (conf == 0) { points[index++] = new PointXYZConfidence(Vector3.zero, 0); continue; } if (!success) { throw new System.Exception("Could not parse a vertex"); } Vector3 pos = new Vector3(x, y, z); PointXYZConfidence point = new PointXYZConfidence(pos, conf); points[index++] = point; } } // Fixing metadata _metadata.maxSize = MaxPoints; if (points.Length == 0) { throw new System.Exception("Vertices were empty"); } PointCloudData <PointXYZConfidence> pcd = new PointCloudData <PointXYZConfidence>(points, numPoints, _metadata, id); return(pcd); }