public QTree(LasDataManager dMgr, LASFile lasfile) { TreeID = Guid.NewGuid(); las_header = lasfile.header; int num_Leafs = (int)las_header.NumberOfPointRecords / POINTS_PER_LEAF; double d = Math.Sqrt((double)las_header.NumberOfPointRecords / POINTS_PER_LEAF); NumberOfTreeLevels = (int)Math.Ceiling(Math.Log(d, 2)) + 1; double nodesOneSide = Math.Pow(2, NumberOfTreeLevels - 1); double currLeafs = nodesOneSide * nodesOneSide; double dWidth = las_header.MaxX - las_header.MinX; double dHeight = las_header.MaxY - las_header.MinY; QTreeNode.MAX_WIDTH = (float)(dWidth / nodesOneSide); QTreeNode.MAX_HEIGHT = (float)(dHeight / nodesOneSide); Console.WriteLine("Creating QTree"); Console.WriteLine("Map width={0} height={1}", dWidth, dHeight); Console.WriteLine("Calculated points per leaf: {0} , actual: {1}, leafs: {2}", POINTS_PER_LEAF, (double)las_header.NumberOfPointRecords / (double)currLeafs, currLeafs); Console.WriteLine("Node width={0} height={1}", QTreeNode.MAX_WIDTH, QTreeNode.MAX_HEIGHT); //init qleaf direct access array numberOfLeafs = (int)currLeafs; root = new QTreeNode(new BoundingBox(0, 0, (float)dWidth, (float)dHeight), this, null, 0); Console.WriteLine("Created nodes={0}", QTreeNode.NUM_NODES); }
public static LasDataManager GetInstance() { if (instance == null) { instance = new LasDataManager(); } return(instance); }
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(); } } }
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; }