public void RequestLeafLoad(QTreeLeaf leaf) { if (leaf.State == LoadedState.UNLOADED && leaf.ListInfos.Count > 0 && leafLoadRequestQueue.Count < 1000) { leaf.State = LoadedState.REQUEST_LOAD; if (leaf.ListInfos.Count > 0) { leafLoadRequestQueue.Enqueue(leaf); } } }
private List <VBOStorageInformation> serverBufferIds = new List <VBOStorageInformation>(); //VBOS from all children public QTreeNode(BoundingBox boundingBox, QTree parentTree, QTreeNode parentNode, int hierarchyLevel) { NUM_NODES++; this.ParentNodeID = parentNode; this.boundingBox = boundingBox; nodeHierarchyLevel = (float)hierarchyLevel / parentTree.NumberOfTreeLevels; //if bounding box is bigger than allowed split it nodes if (boundingBox.width > MAX_WIDTH || boundingBox.height > MAX_HEIGHT) { nodes = new QTreeNode[4]; BoundingBox bb = new BoundingBox(); bb.width = boundingBox.width / 2.0f; bb.height = boundingBox.height / 2.0f; bb.x = boundingBox.x + bb.width; bb.y = boundingBox.y; nodes[NE] = new QTreeNode(bb, parentTree, this, hierarchyLevel + 1); bb.x = boundingBox.x; nodes[NW] = new QTreeNode(bb, parentTree, this, hierarchyLevel + 1); bb.y += bb.height; nodes[SW] = new QTreeNode(bb, parentTree, this, hierarchyLevel + 1); bb.x += bb.width; nodes[SE] = new QTreeNode(bb, parentTree, this, hierarchyLevel + 1); } else { //node is final - contains only data which is present in QTreeLeaf leaf = new QTreeLeaf(boundingBox, parentTree.TreeID, this); } }
/// <summary> /// leads leafs in a separate thread /// </summary> private void LeafLoader() { TimeSpan accLoadTime = new TimeSpan(); long loadCount = 0; TimeSpan accReadTime = new TimeSpan(); TimeSpan readTemp = new TimeSpan(); Stopwatch stopwatch = new Stopwatch(); long accPointsPerLeaf = 0; QTreeLeaf leaf = null; while (runLeafLoader) { if (LasMetrics.GetInstance().leafLoadToggle&& leafLoadRequestQueue.Count > 0) { leaf = leafLoadRequestQueue.Dequeue(); if (leaf == null) { continue; } if (leaf.State == LoadedState.REQUEST_LOAD) //if leaf still wants to be loaded { stopwatch.Start(); long readTicks = 0; for (int i = 0; i < leaf.ListInfos.Count; i++) { readTemp = stopwatch.Elapsed; Point3D[] pts = GetPoints(GetQtreeByGuid(leaf.ParentTreeID), leaf.ListInfos[i].startingPointIndex, leaf.ListInfos[i].numberOfPoints); readTicks = stopwatch.ElapsedTicks; accReadTime += (stopwatch.Elapsed - readTemp); leaf.InsertPoints(i, pts); } if (CALCULATE_NORMALS == true) { leaf.CalculateNormals(); } long loadTicks = stopwatch.ElapsedTicks; accLoadTime += stopwatch.Elapsed; stopwatch.Stop(); loadCount++; stopwatch.Reset(); leaf.State = LoadedState.BUFFERED_IN_RAM; if (loadCount > 0) { double avgLoadTime = accLoadTime.TotalMilliseconds / loadCount; double avgLoadTimeNoRead = (accLoadTime - accReadTime).TotalMilliseconds / loadCount; //Console.WriteLine("Avg. time from disk to GPU: {0} ms, without disk reads: {1} ms", avgLoadTime, avgLoadTimeNoRead); LasMetrics.GetInstance().avgLoad = avgLoadTime; LasMetrics.GetInstance().avgLoadNoDisk = avgLoadTimeNoRead; accPointsPerLeaf += leaf.NumberOfPoints; LasMetrics.GetInstance().avgPointsPerLeaf = (double)accPointsPerLeaf / loadCount; } } leaf = null; } else { Thread.Sleep(leafLoaderMSsleepInterval); } } }
/// <summary> /// calculates normals for point list at specified index /// </summary> /// <param name="pointListIdx"></param> private void CalculateNormals(int pointListIdx) { //2 consecutive points from the pointListIdx array will be taken and closest from the previous //or next point list Point3D[] pointList = ContainedPointLists[pointListIdx]; int len = pointList.Length; int closestPointIdxPrevList = -1; int closestPointIdxNextList = -1; int closestListIdx = -1; int closestPointIdxOnClosestList = -1; //iterate over array and calculate normals for one point back. last point will have same normal as one before for (int i = 1; i < pointList.Length - 1; i++) { Point3D p1 = pointList[i]; Point3D p2 = pointList[i - 1]; Point3D p3; closestPointIdxPrevList = findClosestPoint(pointListIdx - 1, p2, p1, i); closestPointIdxNextList = findClosestPoint(pointListIdx + 1, p2, p1, i); if (closestPointIdxPrevList < 0 && closestPointIdxNextList < 0) { //problem - only one list in BB?! pointList[i].nx = 0; pointList[i].ny = 1; pointList[i].nz = 0; continue; } else { //calculate and compare distances from closest points on other lists between each other and pick //the point that is closer float len1 = float.MaxValue; float len2 = float.MaxValue; if (closestPointIdxPrevList >= 0) { Point3D p3a = ContainedPointLists[pointListIdx - 1][closestPointIdxPrevList]; len1 = (p3a - p1).Length + (p3a - p2).Length; } if (closestPointIdxNextList >= 0) { Point3D p3b = ContainedPointLists[pointListIdx + 1][closestPointIdxNextList]; len2 = (p3b - p1).Length + (p3b - p2).Length; } if (len1 < len2) { p3 = ContainedPointLists[pointListIdx - 1][closestPointIdxPrevList]; closestListIdx = pointListIdx - 1; closestPointIdxOnClosestList = closestPointIdxPrevList; } else { p3 = ContainedPointLists[pointListIdx + 1][closestPointIdxNextList]; closestListIdx = pointListIdx + 1; closestPointIdxOnClosestList = closestPointIdxNextList; } } //handle long And narrow triangles by expanding p1 and p2 farther away from each other if (QTreeLeaf.isLongAndNarrow(p1, p2, p3)) { bool solutionFound = false; int leftIndex = i - 2; int rightIndex = i + 1; Point3D left = p1, right = p2; int iterationsNeeded = 0; while (leftIndex >= 0 && rightIndex < pointList.Length && iterationsNeeded < MAX_ITERATIONS_NORMAL) { iterationsNeeded++; p1 = pointList[leftIndex]; p2 = pointList[rightIndex]; if (!isLongAndNarrow(p1, p2, p3)) { solutionFound = true; break; } leftIndex--; rightIndex++; } if (!solutionFound) { p1 = pointList[i]; iterationsNeeded = 0; //go through closest list and all the point there to find a more suitable p2 for (int cli = closestPointIdxOnClosestList + 1; cli < ContainedPointLists[closestListIdx].Length && iterationsNeeded < MAX_ITERATIONS_SECOND ; cli++) { p2 = ContainedPointLists[closestListIdx][cli]; iterationsNeeded++; if (!isLongAndNarrow(p1, p2, p3)) { solutionFound = true; break; } } if (!solutionFound) { iterationsNeeded = 0; //try the other way too for (int cli = closestPointIdxOnClosestList - 1; cli >= 0 && iterationsNeeded < MAX_ITERATIONS_SECOND; cli--) { p2 = ContainedPointLists[closestListIdx][cli]; iterationsNeeded++; if (!isLongAndNarrow(p1, p2, p3)) { solutionFound = true; break; } } } if (!solutionFound) { //TODO: find yet another way or revert to the first three points p2 = pointList[i - 1]; //seach for p3 on this same list, in case it goes back and forth like it sometimes does iterationsNeeded = 0; //up to point i for (int s = 0; s < pointList.Length && iterationsNeeded < MAX_ITERATIONS_SAME; s++) { if (s < i - 5 || s > i + 5) { Point3D ppp = pointList[s]; iterationsNeeded++; if (!isLongAndNarrow(p1, p2, ppp)) { solutionFound = true; break; } } } } } } //Vector3f normal = Vector3f.CrossProduct(pointList[i - 1] - pointList[i+1], pointList[i+1] - closestPointList[closestPointIdx]); //Vector3f normal = Vector3f.CrossProduct(pointList[i - 1] - pointList[i + 1], closestPointList[closestPointIdx] - pointList[i + 1]); Vector3f normal = Vector3f.CrossProduct(p2 - p1, p3 - p1); normal.Normalize(); pointList[i].nx = normal.x; pointList[i].ny = normal.y; pointList[i].nz = normal.z; if (normal.z < 0) //z and y coordinates are inverted!! - Z is height here { pointList[i].nx = -normal.x; pointList[i].ny = -normal.y; pointList[i].nz = -normal.z; } } //last point has same normal as the one before her. first one is same as second one if (len > 1) { pointList[0].nx = pointList[1].nx; pointList[0].ny = pointList[1].ny; pointList[0].nz = pointList[1].nz; pointList[len - 1].nx = pointList[len - 2].nx; pointList[len - 1].ny = pointList[len - 2].ny; pointList[len - 1].nz = pointList[len - 2].nz; } }