/// <summary> /// renders the leaf from VBO /// </summary> public void Render(bool renderOverride) { visible = true; if (State == LoadedState.BUFFERED_IN_RAM) { LoadIntoVBO(); LoadedNewData = true; } if (State == LoadedState.BUFFERED_IN_GPU) { //render //enable vertex array if (renderOverride) { VBOUtils.RenderVBO(serverBufferId); } } else if (State == LoadedState.UNLOADED) { if (LeafLoadRequestEvent != null) { LeafLoadRequestEvent(this); } } }
private void Render() { if (serverBufferIds == null) { return; } for (int i = 0; i < serverBufferIds.Count; i++) { VBOUtils.RenderVBO(serverBufferIds[i]); } }
public void RemoveVBO(Stack <VBOStorageInformation> vbos) { //only delete if its not the node farthes in the hierarchy if (leaf == null) { //if leaf not null remove the VBO that is at this level and delete it from GPU memory VBOStorageInformation thisLevelVBO = vbos.Pop(); bool removed = serverBufferIds.Remove(thisLevelVBO); if (removed) { VBOUtils.DeleteFromGPU(thisLevelVBO); } } if (ParentNodeID != null) { ParentNodeID.RemoveVBO(vbos); } }
/// <summary> /// copies points into the VBOs. returns number of points that were copied /// </summary> /// <param name="nbrPts"></param> /// <param name="vertices"></param> /// <param name="normals"></param> /// <param name="colors"></param> /// <param name="serverBufferIds"></param> /// <returns></returns> unsafe public static void CopyPointsToVBOs(float[] interleavedData, VBOStorageInformation serverBufferIds) { //create and initialize vertexbuffer Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, serverBufferIds.InterleavedVBO); VBOUtils.CheckGlError("Tried first binding of interleaved VBO during glBegin() and glEnd()"); long bytesCopied = 0; int size = 0; fixed(float *vptr = interleavedData) { size = (sizeof(float) * interleavedData.Length); bytesCopied += size; Gl.glBufferData(Gl.GL_ARRAY_BUFFER, (IntPtr)size, (IntPtr)vptr, Gl.GL_STATIC_DRAW); } VBOUtils.CheckGlError("Error copying interleaved data to VBO"); LasMetrics.GetInstance().bytesTransferedToGPU += bytesCopied; LasMetrics.GetInstance().numberOfPointsLoadedIntoExistingVBOs += serverBufferIds.NumberOfPoints; }
unsafe public static VBOStorageInformation GenerateVBOs(int numberOfPoints) { //generate free buffer names for 3 different buffers int bufferId = 0; Gl.glGenBuffers(1, out bufferId); VBOUtils.CheckGlError("Tried first binding of VBO during glBegin() and glEnd()"); if (bufferId == 0) { throw new ApplicationException("ID of VBO should be set but was not!!!"); } VBOStorageInformation vboSI = new VBOStorageInformation(); vboSI.InterleavedVBO = bufferId; vboSI.NumberOfPoints = numberOfPoints; LasMetrics.GetInstance().numberOfExistingVBOs++; return(vboSI); }
internal void SetInvisibleAndUnbuffered() { visible = false; if (ClearAllPoints()) { numberOfLoadedPoints = 0; if (serverBufferId != null) { VBOUtils.DeleteFromGPU(serverBufferId); serverBufferId = null; if (parentVBOs.Count > 0) { ParentNode.RemoveVBO(parentVBOs); } } State = LoadedState.UNLOADED; } }
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; }