/// <summary> /// serializes qtree to file. /// </summary> /// <param name="rewriteIfExists"></param> private void SerializeQtreeToFile(QTreeWrapper qtree, bool rewriteIfExists) { Console.WriteLine("Serializing qtree to file"); string srlFilename = qtree.filename + "." + serializiationExtension; FileStream fileStreamObject = null; if (File.Exists(srlFilename) && !rewriteIfExists) { Console.WriteLine("File already exists and rewrite flag is set to false. Returning"); return; } try { fileStreamObject = new FileStream(srlFilename, FileMode.Create); BinaryFormatter binaryFormatter = new BinaryFormatter(); binaryFormatter.Serialize(fileStreamObject, qtree.qtree); } finally { if (fileStreamObject != null) { fileStreamObject.Close(); } } Console.WriteLine("Serialization finished"); }
/// <summary> /// initializes data manager with data from las file and fills QTree structure with preliminary data /// </summary> public void Initialize(QTreeWrapper qtree, bool forcePreprocessing) { if (forcePreprocessing) { Console.WriteLine("Preprocessing forced. Not using serialized even if available"); PreprocessDataFromFile(qtree); SerializeQtreeToFile(qtree, true); } else { QTree des = DeserializeQtreeFromFile(qtree.filename); if (des == null) { Console.WriteLine("Deserialization failed. Preprocessing."); PreprocessDataFromFile(qtree); SerializeQtreeToFile(qtree, true); } else { qtree.qtree = des; } } if (loadingEndedEvent != null) { loadingEndedEvent(true); } }
/// <summary> /// renders the QTree in current openGl context /// </summary> private void RenderingPass(QTreeWrapper qtree, float FOV, float near, float far, Vector3f eyeVector, Point2f position) { QTree lasTree = qtree.qtree; if (lasTree != null) { lasTree.RenderingPass(FOV, near, far, eyeVector, position - qtree.positionOffset); /* * Point3D tempPoint = new Point3D(); * int pointSize = Marshal.SizeOf(tempPoint); * * int allowedPointsInMemory = dedicatedPointMemory / pointSize; * * float percent = (float)lasTree.numberOfLoadedPoints / (float)allowedPointsInMemory; * * //allow discrepancy of 15% * if (Math.Abs(percent - LOD) > 0.1) * { * LOD = (float)allowedPointsInMemory / (float)qtree.lasFile.header.NumberOfPointRecords; * //lasTree.CascadeLOD(LOD); * } */ } }
/// <summary> /// loads and initializes the file /// </summary> /// <param name="filename"></param> public void Load(string filename, bool forcePreprocessing) { if (loadingStatusEvent != null) { loadingStatusEvent("Opening LAS file", 0.01f); } QTreeWrapper tree = AddQtreeFromFile(filename); Initialize(tree, forcePreprocessing); }
private void PreprocessDataFromFile(QTreeWrapper qtreeWrapper) { Stopwatch initTimer = new Stopwatch(); initTimer.Start(); qtreeWrapper.lasFile.PositionAtStartOfPointData(); uint index = 0; uint numAllPoints = qtreeWrapper.lasFile.header.NumberOfPointRecords; Point3D[] lineOfPoints = null; int step = 100000; determineInitialSelectionLOD(); TimeSpan accReadTime = new TimeSpan(); while (index < numAllPoints) { if (loadingStatusEvent != null) { loadingStatusEvent("Indexing points..." + index + "/" + numAllPoints, (float)index / (float)numAllPoints); } TimeSpan before = initTimer.Elapsed; lineOfPoints = GetPoints(qtreeWrapper, index, step); accReadTime += (initTimer.Elapsed - before); if (lineOfPoints != null) { qtreeWrapper.qtree.Initialize(index, lineOfPoints, SelectionLOD); } index += (uint)lineOfPoints.Length; lineOfPoints = null; } initTimer.Stop(); LasMetrics.GetInstance().indexing = initTimer.ElapsedMilliseconds; LasMetrics.GetInstance().indexingNoDisk = (initTimer.Elapsed - accReadTime).TotalMilliseconds; LasMetrics.GetInstance().avgPointsPerLeafActual = (double)numAllPoints / LasMetrics.GetInstance().numberOfNonEmptyLeafs; LasMetrics.GetInstance().numberOfPoints += numAllPoints; Console.WriteLine("lasDataManager.Initialize() took {0} ms for {1} points", initTimer.ElapsedMilliseconds, numAllPoints); Console.WriteLine("reading from disk took {0} ms, indexing without reading from disk took {1} ms", accReadTime.TotalMilliseconds, LasMetrics.GetInstance().indexingNoDisk); Console.WriteLine("nr. of all points: {0}, avg. points per leaf: {1}, without empty: {2}", numAllPoints, numAllPoints / LasMetrics.GetInstance().numberOfLeafs, LasMetrics.GetInstance().avgPointsPerLeafActual); Console.WriteLine("QTreeLeaf.findEnd() took {0} ms", QTreeLeaf.findStepStopWatch.ElapsedMilliseconds); Console.WriteLine("array copying() took {0} ms", QTreeLeaf.arrayCompyTimer.ElapsedMilliseconds); Console.WriteLine("mem alocated: {0}kb", GC.GetTotalMemory(false) / 1024); }
/// <summary> /// adds qtree to the collection and initializes it /// </summary> /// <param name="filename"></param> protected QTreeWrapper AddQtreeFromFile(string filename) { Console.WriteLine("Adding qtree from file: {0}", filename); QTreeWrapper qtreeWrapper = GetQtreeByFilename(filename); if (qtreeWrapper != null) { Console.WriteLine("Qtree already exists"); return(qtreeWrapper); } qtreeWrapper = new QTreeWrapper(); qtreeWrapper.filename = filename; qtreeWrapper.lasFile = new LASFile(filename); qtreeWrapper.lasFile = adjustParameters(qtreeWrapper.lasFile); if (QTrees.Count == 0) { Console.WriteLine("First loaded qtree. positioning at (0,0)"); } else { Console.WriteLine("Not first qtree to be loaded. Setting offset coordinates relative to the first qtree"); QTreeWrapper first = QTrees[0]; qtreeWrapper.positionOffset = new Point2f( (float)(qtreeWrapper.lasFile.header.MinX - first.lasFile.header.MinX), (float)(qtreeWrapper.lasFile.header.MinY - first.lasFile.header.MinY)); Console.WriteLine("Offset coordinates for tree {0} are {1}", QTrees.Count, qtreeWrapper.positionOffset); } if (loadingStatusEvent != null) { loadingStatusEvent("Creating quad tree", 0.02f); } qtreeWrapper.qtree = new QTree(this, qtreeWrapper.lasFile); QTrees.Add(qtreeWrapper); CalculateGlobalBoundingBox(); return(qtreeWrapper); }
public QTreeLeaf(BoundingBox bb, Guid parentTreeID, QTreeNode parentNode) { ParentTreeID = parentTreeID; this.ParentNode = parentNode; QTreeWrapper parent = LasDataManager.GetInstance().GetQtreeByGuid(parentTreeID); parentVBOs = new Stack <VBOStorageInformation>(); //stored on this level ListInfos = new List <ListInfo>(); LasMetrics.GetInstance().numberOfLeafs++; boundingBox = bb; if (randArray == null) { randArray = new float[3000]; for (int i = 0; i < randArray.Length; i++) { randArray[i] = (float)rand.NextDouble(); } } }
public Point3D[] GetPoints(QTreeWrapper qtree, uint index, int numberOfPoints) { //Console.WriteLine("getPoints entry. mem alocated: {0}", GC.GetTotalMemory(false)); Point3D[] pts = null; float minX = (float)((qtree.lasFile.header.MinX - qtree.lasFile.header.OffsetX)); float minY = (float)((qtree.lasFile.header.MinY - qtree.lasFile.header.OffsetY)); float minZ = (float)((qtree.lasFile.header.MinZ - qtree.lasFile.header.OffsetZ)); float scaleX = (float)qtree.lasFile.header.ScaleFactorX; float scaleY = (float)qtree.lasFile.header.ScaleFactorY; float scaleZ = (float)qtree.lasFile.header.ScaleFactorZ; //Console.WriteLine("loading point at index={0}, number to load={1}", index, numberOfPoints); if (qtree.lasFile.header.PointDataFormat == 0) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); LASPointFormat0[] pointArray = (LASPointFormat0[])qtree.lasFile.GetPoints(index, numberOfPoints); stopwatch.Stop(); //Console.WriteLine("loading took: {0} ms", stopwatch.ElapsedMilliseconds); long loading = stopwatch.ElapsedMilliseconds; stopwatch.Reset(); stopwatch.Start(); if (pointArray != null) { int count = pointArray.Length; index += (uint)count; pts = new Point3D[numberOfPoints]; for (int i = 0; i < count; i++) { pts[i].x = pointArray[i].X * scaleX * LasDataManager.GlobalPointsScaleFactor.x - minX; pts[i].y = (pointArray[i].Y) * scaleY * LasDataManager.GlobalPointsScaleFactor.y - minY; pts[i].z = (pointArray[i].Z) * scaleZ * LasDataManager.GlobalPointsScaleFactor.z - minZ; pts[i].colorIndex = pointArray[i].Classification; if (pts[i].z < GlobalBoundingCube.minZ) { GlobalBoundingCube.minZ = pts[i].z; } if (pts[i].y > GlobalBoundingCube.maxZ) { GlobalBoundingCube.maxZ = pts[i].z; } } } pointArray = null; stopwatch.Stop(); long transforming = stopwatch.ElapsedMilliseconds; //Console.WriteLine("transforming points: {0} ms", stopwatch.ElapsedMilliseconds); } else { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); LASPointFormat1[] pointArray = (LASPointFormat1[])qtree.lasFile.GetPoints(index, numberOfPoints); stopwatch.Stop(); //Console.WriteLine("loading poins: {0} ms", stopwatch.ElapsedMilliseconds); long loading = stopwatch.ElapsedMilliseconds; stopwatch.Reset(); stopwatch.Start(); if (pointArray != null) { int count = pointArray.Length; index += (uint)count; pts = new Point3D[numberOfPoints]; for (int i = 0; i < count; i++) { pts[i].x = pointArray[i].X * scaleX * LasDataManager.GlobalPointsScaleFactor.x - minX; pts[i].y = (pointArray[i].Y) * scaleY * LasDataManager.GlobalPointsScaleFactor.y - minY; pts[i].z = (pointArray[i].Z) * scaleZ * LasDataManager.GlobalPointsScaleFactor.z - minZ; pts[i].colorIndex = pointArray[i].Classification; if (pts[i].z < GlobalBoundingCube.minZ) { GlobalBoundingCube.minZ = pts[i].z; } if (pts[i].y > GlobalBoundingCube.maxZ) { GlobalBoundingCube.maxZ = pts[i].z; } } } pointArray = null; stopwatch.Stop(); long transforming = stopwatch.ElapsedMilliseconds; //Console.WriteLine("transforming poins: {0} ms", stopwatch.ElapsedMilliseconds); } //Console.WriteLine("getPoints exit. mem alocated: {0} ", GC.GetTotalMemory(false)); return(pts); }
protected unsafe void LoadIntoVBO() { if (serverBufferId != null) { throw new ApplicationException("should not occur"); } if (parentVBOs == null) { parentVBOs = new Stack <VBOStorageInformation>(); } QTreeWrapper parentTree = LasDataManager.GetInstance().GetQtreeByGuid(ParentTreeID); #region Create vertex arrays //form three arrays to copy to server memory ColorPalette pallette = LasDataManager.ColorPallette; //code that reduces given points //how many points to skip when loading int step = (int)Math.Ceiling((1.0 / ReductionToParentCoef)); //be conservative int allLevels = parentTree.qtree.NumberOfTreeLevels; int pointsOnLevel = NumberOfPoints / allLevels; int pointsOnLastLevel = pointsOnLevel + NumberOfPoints - pointsOnLevel * allLevels; if (pointsOnLevel < 5) { //no need to overburden the system with separate arrays for very small amounts of points allLevels = 1; pointsOnLastLevel = NumberOfPoints; } float[][] interleavedArrayAtLevel = new float[allLevels][]; int interleavedDataStride = VBOUtils.PointInformationSize; int byteStride = interleavedDataStride / 4; for (int i = 0; i < allLevels; i++) { if (i == (allLevels - 1)) { //last(leaf) level also contains all remaining points interleavedArrayAtLevel[i] = new float[pointsOnLastLevel * byteStride]; //10 is for 3*V,3*N and 4*C bytes } else if (pointsOnLevel > 0) { interleavedArrayAtLevel[i] = new float[pointsOnLevel * byteStride]; } } int currentLevel = 0; //we will iterate mod allLevels so the points are distributed fairly int pointIndex = 0; //point index inside an array for a level. increased only when we return to locating points to the frst level int numAllocatedPoints = 0; //counts total number of allcoated point int lastPointsThreshold = NumberOfPoints - pointsOnLastLevel + pointsOnLevel; //threshold which determines from where on points are only on the last level //generate points for all levels in one iteration over all the points for (int j = 0; j < ContainedPointLists.Count; j++) { Point3D[] pts = ContainedPointLists[j]; int len = pts.Length; for (int k = 0; k < len; k++) { Point3D p = pts[k]; //C4 GetColorFromPalette(interleavedArrayAtLevel[currentLevel], pallette, pointIndex, p); interleavedArrayAtLevel[currentLevel][pointIndex + 3] = 1; //N3 interleavedArrayAtLevel[currentLevel][pointIndex + 4] = p.nx; interleavedArrayAtLevel[currentLevel][pointIndex + 5] = p.nz; interleavedArrayAtLevel[currentLevel][pointIndex + 6] = p.ny; //V3 interleavedArrayAtLevel[currentLevel][pointIndex + 7] = p.x + parentTree.positionOffset.x; interleavedArrayAtLevel[currentLevel][pointIndex + 8] = p.z; interleavedArrayAtLevel[currentLevel][pointIndex + 9] = p.y + parentTree.positionOffset.y; numAllocatedPoints++; //increased for every point if (numAllocatedPoints < lastPointsThreshold) { currentLevel++; if (currentLevel == allLevels) { //increase point index only when going back to the first level pointIndex += byteStride; //3 values for vertices, 3 for colors and 3 for normals currentLevel = 0; } } else { currentLevel = allLevels - 1; pointIndex += byteStride; //point index is always updated, because we only insert points to the last layer now } } } #endregion //only if points wil bedistributed between nodes propagate them up the hierarchy if (allLevels > 1) { //load all arrays into VBOStorageInformation objects and pass them along to parents Stack <VBOStorageInformation> vbosForParents = new Stack <VBOStorageInformation>(allLevels - 1); //for parents parentVBOs.Clear(); for (int i = 0; i < allLevels - 1; i++) { VBOStorageInformation vbos = VBOUtils.GenerateVBOs(pointsOnLevel); VBOUtils.CopyPointsToVBOs(interleavedArrayAtLevel[i], vbos); //insert into stack so parents can take them out vbosForParents.Push(vbos); parentVBOs.Push(vbos); } ParentNode.AddVBO(vbosForParents); } //load also into this leafs VBO serverBufferId = VBOUtils.GenerateVBOs(pointsOnLastLevel); VBOUtils.CopyPointsToVBOs(interleavedArrayAtLevel[allLevels - 1], serverBufferId); ClearAllPoints(); State = LoadedState.BUFFERED_IN_GPU; }