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); } }
public static void DeleteFromGPU(VBOStorageInformation serverBufferIds) { //free memory on server if (serverBufferIds.NumberOfPoints == 0) { return; } int[] buffersToDelete = new int[3]; buffersToDelete[0] = serverBufferIds.VertexVBO; buffersToDelete[1] = serverBufferIds.NormalVBO; buffersToDelete[2] = serverBufferIds.ColorVBO; Gl.glDeleteBuffers(buffersToDelete.Length, buffersToDelete); LasMetrics.GetInstance().bytesCurrentlyOnGPURAM -= serverBufferIds.NumberOfPoints * 3 * 4; //3=every point has color, position and normal; 4=every value has 4 bytes LasMetrics.GetInstance().numberOfExistingVBOs--; LasMetrics.GetInstance().numberOfPointsLoadedIntoExistingVBOs -= serverBufferIds.NumberOfPoints; serverBufferIds.ColorVBO = serverBufferIds.NormalVBO = serverBufferIds.VertexVBO = 0; serverBufferIds.NumberOfPoints = 0; }
/// <summary> /// called from the child leaf or node. loads a subset of passed points into its VBOs and passes the rest upward /// /// </summary> public void AddVBO(Stack <VBOStorageInformation> vbos) { if (serverBufferIds == null) { serverBufferIds = new List <VBOStorageInformation>(); } //only insert if the node does not contain a leaf if (leaf == null) { VBOStorageInformation vbo = vbos.Pop(); serverBufferIds.Add(vbo); } //top most node finishes it if (ParentNodeID != null) { ParentNodeID.AddVBO(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; }
public static void RenderVBOsFastSecondPass() { if (LasMetrics.GetInstance().renderToggle == false || secondPassVBOs.Count == 0) { return; } int numVBOSIs = secondPassVBOs.Count; VBOStorageInformation vbo = null; int stride = 40; for (int i = 0; i < numVBOSIs; i++) { vbo = secondPassVBOs[i]; Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, vbo.InterleavedVBO); Gl.glInterleavedArrays(Gl.GL_C4F_N3F_V3F, stride, IntPtr.Zero); Gl.glDrawArrays(Gl.GL_POINTS, 0, vbo.NumberOfPoints); } }
public static void RenderVBO(VBOStorageInformation vbo) { if (LasMetrics.GetInstance().renderToggle == false) { return; } Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, vbo.InterleavedVBO); //array is interleaved like this: VVVNNNCCCC - this is 10*4 bytes. //try glInterleavedArrays instead of this three calls, should be faster Gl.glInterleavedArrays(Gl.GL_C4F_N3F_V3F, PointInformationSize, IntPtr.Zero); Gl.glDrawArrays(Gl.GL_POINTS, 0, vbo.NumberOfPoints); pointsDrawnInPass += vbo.NumberOfPoints; //add vbo for fast second pass rendering secondPassVBOs.Add(vbo); }
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; }