public static GpuDemGeometry CreateGeometry(RasterDatabase.RasterDatabase rDatabase, Device gDevice, out float maxValue, GDALReader reader) { // create actual geometry - tesselated plane IndexBuffer geomPlaneIndices; PlaneHelper.CreateIndexBuffer(gDevice, 14, 14, out geomPlaneIndices); VertexBuffer geomPlaneVerts; PlaneHelper.CreateVertexBufferInside(gDevice, 16, 16, new Vector2(1, 1), out geomPlaneVerts); VertexBuffer geomPatchVerts; PlaneHelper.CreatePatchVertexBuffer(gDevice, 16, 16, new Vector2(1, 1), out geomPatchVerts); IndexBuffer geomPatchIndices; PlaneHelper.CreatePatchIndexBuffer(gDevice, 16, 16, out geomPatchIndices); // create cache of all depths RectangleGroupQuadTree rTree = rDatabase.ProduceLayerMipMap(0, 256); RectangleGroupQuadTree.GroupNode[][] dataNodes = new RectangleGroupQuadTree.GroupNode[rTree.Depth][]; for (int depth = 0; depth < rTree.Depth; depth++) { RectangleGroupQuadTree.GroupNode[] nodes; rTree.GetNodes(depth + 1, out nodes); dataNodes[depth] = nodes; } GpuDemGeometry geom = new GpuDemGeometry(new Vector3(), new Vector3(10, 0, 10), new Vector3(5, 0, 5), 16 * 16, 15 * 15 * 2, PrimitiveType.TriangleList, gDevice); geom.geomPlaneVerts = geomPlaneVerts; geom.geomPlaneIndices = geomPlaneIndices; geom.geomPatchIndices = geomPatchIndices; geom.geomPatchVerts = geomPatchVerts; geom.reader = reader; geom.dataNodes = dataNodes; geom.ViewUpdated(new Vector3()); maxValue = 1; return(geom); }
public static CpuDEMSubGeometry CreatePointList(RectangleGroupQuadTree.GroupNode node, Device gDevice, int sampleInterval, Size totalAreaSz, float minValue, float maxValue) { // BUG: Not working right for < native? int xSamples = node.NodeArea.Width / sampleInterval; int ySamples = node.NodeArea.Height / sampleInterval; bool blendStartX = (node.NodeArea.Left != 0); bool blendEndX = (node.NodeArea.Right != totalAreaSz.Width); bool blendStartY = (node.NodeArea.Top != 0); bool blendEndY = (node.NodeArea.Bottom != totalAreaSz.Height); Size iBufSize = new Size(xSamples, ySamples); int xAdditional = 0; int yAdditional = 0; if (!blendStartX) { xAdditional++; } if (!blendEndX) { xAdditional++; } if (!blendStartY) { yAdditional++; } if (!blendEndY) { yAdditional++; } // create buffers VertexBuffer vBuffer = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), (xSamples + xAdditional) * (ySamples + yAdditional), gDevice, Usage.WriteOnly, CustomVertex.PositionNormalTextured.Format, Pool.Managed); CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[])vBuffer.Lock(0, LockFlags.None); // fill x+z and texCoord components independant of y heights float yActual = /*-2.5f +*/ ((float)node.NodeArea.Top / totalAreaSz.Height * 5f); float xActInc = ((float)node.NodeArea.Width / totalAreaSz.Width * 5) / (xSamples - 1); float yActInc = ((float)node.NodeArea.Height / totalAreaSz.Height * 5) / (ySamples - 1); int vPos = 0; float ty = 0; float tyInc = 1f / (ySamples - 1); for (int y = 0; y < ySamples; y++) { float xActual = /*-2.5f + */ ((float)node.NodeArea.Left / totalAreaSz.Width * 5f); float tx = 0; float txInc = 1f / (xSamples - 1); for (int x = 0; x < xSamples; x++) { verts[vPos++] = new CustomVertex.PositionNormalTextured(xActual, 0, yActual, 0, 0, 0, tx, ty); xActual += xActInc; tx += txInc; } yActual += yActInc; ty += tyInc; } // skirts IndexBuffer[] skirts = new IndexBuffer[xAdditional + yAdditional]; int skirtIdx = 0; if (!blendStartX) { yActual = /*-2.5f +*/ ((float)node.NodeArea.Top / totalAreaSz.Height * 5f); ty = 0; for (int y = 0; y < ySamples; y++) { float xActual = /*-2.5f +*/ ((float)node.NodeArea.Left / totalAreaSz.Width * 5f); verts[vPos++] = new CustomVertex.PositionNormalTextured(xActual, -0.5f, yActual, 0, 0, 0, -0.1f, ty); yActual += yActInc; ty += tyInc; } skirts[skirtIdx] = CreateTriStripSkirtIndices(xSamples, gDevice, 0, skirtIdx); skirtIdx++; } if (!blendEndX) { yActual = /*-2.5f +*/ ((float)node.NodeArea.Top / totalAreaSz.Height * 5f); ty = 0; for (int y = 0; y < ySamples; y++) { float xActual = /*-2.5f +*/ ((float)node.NodeArea.Right / totalAreaSz.Width * 5); verts[vPos++] = new CustomVertex.PositionNormalTextured(xActual, -0.5f, yActual, 0, 0, 0, 1.1f, ty); yActual += yActInc; ty += tyInc; } skirts[skirtIdx] = CreateTriStripSkirtIndices(xSamples, gDevice, 1, skirtIdx); skirtIdx++; } if (!blendStartY) { float xActual = /*-2.5f +*/ ((float)node.NodeArea.Left / totalAreaSz.Width * 5f); float tx = 0; for (int y = 0; y < ySamples; y++) { yActual = /*-2.5f +*/ ((float)node.NodeArea.Top / totalAreaSz.Height * 5f); verts[vPos++] = new CustomVertex.PositionNormalTextured(xActual, -0.5f, yActual, 0, 0, 0, tx, -0.1f); xActual += xActInc; tx += tyInc; } skirts[skirtIdx] = CreateTriStripSkirtIndices(xSamples, gDevice, 2, skirtIdx); skirtIdx++; } if (!blendEndY) { float xActual = /*-2.5f +*/ ((float)node.NodeArea.Left / totalAreaSz.Width * 5f); float tx = 0; for (int y = 0; y < ySamples; y++) { yActual = /*-2.5f +*/ ((float)node.NodeArea.Bottom / totalAreaSz.Height * 5f); verts[vPos++] = new CustomVertex.PositionNormalTextured(xActual, -0.5f, yActual, 0, 0, 0, tx, 1.1f); xActual += xActInc; tx += tyInc; } skirts[skirtIdx] = CreateTriStripSkirtIndices(xSamples, gDevice, 3, skirtIdx); skirtIdx++; } SizeF onePixel = new SizeF(1f / (node.NodeArea.Width - 1), 1f / (node.NodeArea.Height - 1)); // fill in from sample rectangles only float[] heights = new float[xSamples * ySamples]; foreach (DataArea area in node.Rectangles) { SimpleRasterSampler sampler = new MultiSampleRasterSampler(area, sampleInterval, xSamples); SimpleRasterSampler singleSampler = new SimpleRasterSampler(area, sampleInterval); // TODO: Sample only area not 0 -> (1-1px%) float xAdv = 1f / (xSamples - 1); float yAdv = 1f / (ySamples - 1); float yPos = 0; vPos = 0; int yStart = 0; int yEnd = ySamples; // y edge if (blendStartY) { float xPos = 0; int xStart = 0; int xEnd = xSamples; // xy edge float rawValue1, rawValue2, rawValue3, rawValue4; float sVal, value; if (blendStartX) { if (sampler.DataSource is ByteArea) { rawValue1 = singleSampler.GetByte(xPos, yPos); rawValue2 = singleSampler.GetByte(xPos - onePixel.Width, yPos); rawValue3 = singleSampler.GetByte(xPos, yPos - onePixel.Height); rawValue4 = singleSampler.GetByte(xPos - onePixel.Width, yPos - onePixel.Height); } else { rawValue1 = singleSampler[xPos, yPos]; rawValue2 = singleSampler[xPos - onePixel.Width, yPos]; rawValue3 = singleSampler[xPos, yPos - onePixel.Height]; rawValue4 = singleSampler[xPos - onePixel.Width, yPos - onePixel.Height]; } sVal = ((rawValue1 / maxValue) + (rawValue2 / maxValue) + (rawValue3 / maxValue) + (rawValue4 / maxValue)) / 4; value = -0.5f + sVal; heights[vPos++] = value; xPos += xAdv; xStart++; } if (blendEndX) { xEnd--; } // do normal range for (int x = xStart; x < xEnd; x++) { if (sampler.DataSource is ByteArea) { rawValue1 = singleSampler.GetByte(xPos, yPos); rawValue2 = singleSampler.GetByte(xPos, yPos - onePixel.Height); } else { rawValue1 = singleSampler[xPos, yPos]; rawValue2 = singleSampler[xPos, yPos - onePixel.Height]; } sVal = ((rawValue1 / maxValue) + (rawValue2 / maxValue)) / 2; value = -0.5f + sVal; heights[vPos++] = value; xPos += xAdv; } // xy edge if (blendEndX) { // take 2 samples if (sampler.DataSource is ByteArea) { rawValue1 = singleSampler.GetByte(xPos, yPos); rawValue2 = singleSampler.GetByte(xPos + onePixel.Width, yPos); rawValue3 = singleSampler.GetByte(xPos, yPos - onePixel.Height); rawValue4 = singleSampler.GetByte(xPos + onePixel.Width, yPos - onePixel.Height); } else { rawValue1 = singleSampler[xPos, yPos]; rawValue2 = singleSampler[xPos + onePixel.Width, yPos]; rawValue3 = singleSampler[xPos, yPos - onePixel.Height]; rawValue4 = singleSampler[xPos + onePixel.Width, yPos - onePixel.Height]; } sVal = ((rawValue1 / maxValue) + (rawValue2 / maxValue) + (rawValue3 / maxValue) + (rawValue4 / maxValue)) / 4; value = -0.5f + sVal; heights[vPos++] = value; } yPos += yAdv; yStart++; } if (blendEndY) { yEnd--; } // normal range + x exclusive edges for (int y = yStart; y < yEnd; y++) { float xPos = 0; int xStart = 0; int xEnd = xSamples; if (blendStartX) { // take 2 samples float rawValue1, rawValue2; if (sampler.DataSource is ByteArea) { rawValue1 = singleSampler.GetByte(xPos, yPos); rawValue2 = singleSampler.GetByte(xPos - onePixel.Width, yPos); } else { rawValue1 = singleSampler[xPos, yPos]; rawValue2 = singleSampler[xPos - onePixel.Width, yPos]; } float sVal = ((rawValue1 / maxValue) + (rawValue2 / maxValue)) / 2; float value = -0.5f + sVal; heights[vPos++] = value; xPos += xAdv; xStart++; } if (blendEndX) { xEnd--; } // do normal range for (int x = xStart; x < xEnd; x++) { float rawValue; if (sampler.DataSource is ByteArea) { rawValue = sampler.GetByte(xPos, yPos); } else { rawValue = sampler[xPos, yPos]; } float sVal = rawValue / maxValue; float value = -0.5f + sVal; heights[vPos++] = value; xPos += xAdv; } if (blendEndX) { // take 2 samples float rawValue1, rawValue2; if (sampler.DataSource is ByteArea) { rawValue1 = singleSampler.GetByte(xPos, yPos); rawValue2 = singleSampler.GetByte(xPos + onePixel.Width, yPos); } else { rawValue1 = singleSampler[xPos, yPos]; rawValue2 = singleSampler[xPos + onePixel.Width, yPos]; } float sVal = ((rawValue1 / maxValue) + (rawValue2 / maxValue)) / 2; float value = -0.5f + sVal; heights[vPos++] = value; } yPos += yAdv; } // y edge if (blendEndY) { float xPos = 0; int xStart = 0; int xEnd = xSamples; // xy egde float rawValue1, rawValue2, rawValue3, rawValue4; float sVal, value; if (blendStartX) { if (sampler.DataSource is ByteArea) { rawValue1 = singleSampler.GetByte(xPos, yPos); rawValue2 = singleSampler.GetByte(xPos - onePixel.Width, yPos); rawValue3 = singleSampler.GetByte(xPos, yPos + onePixel.Height); rawValue4 = singleSampler.GetByte(xPos - onePixel.Width, yPos + onePixel.Height); } else { rawValue1 = singleSampler[xPos, yPos]; rawValue2 = singleSampler[xPos - onePixel.Width, yPos]; rawValue3 = singleSampler[xPos, yPos + onePixel.Height]; rawValue4 = singleSampler[xPos - onePixel.Width, yPos + onePixel.Height]; } sVal = ((rawValue1 / maxValue) + (rawValue2 / maxValue) + (rawValue3 / maxValue) + (rawValue4 / maxValue)) / 4; value = -0.5f + sVal; heights[vPos++] = value; xPos += xAdv; xStart++; } if (blendEndX) { xEnd--; } // do normal range for (int x = xStart; x < xEnd; x++) { if (sampler.DataSource is ByteArea) { rawValue1 = singleSampler.GetByte(xPos, yPos); rawValue2 = singleSampler.GetByte(xPos, yPos + onePixel.Height); } else { rawValue1 = singleSampler[xPos, yPos]; rawValue2 = singleSampler[xPos, yPos + onePixel.Height]; } sVal = ((rawValue1 / maxValue) + (rawValue2 / maxValue)) / 2; value = -0.5f + sVal; heights[vPos++] = value; xPos += xAdv; } // xy edge if (blendEndX) { if (sampler.DataSource is ByteArea) { rawValue1 = singleSampler.GetByte(xPos, yPos); rawValue2 = singleSampler.GetByte(xPos + onePixel.Width, yPos); rawValue3 = singleSampler.GetByte(xPos, yPos + onePixel.Height); rawValue4 = singleSampler.GetByte(xPos + onePixel.Width, yPos + onePixel.Height); } else { rawValue1 = singleSampler[xPos, yPos]; rawValue2 = singleSampler[xPos + onePixel.Width, yPos]; rawValue3 = singleSampler[xPos, yPos + onePixel.Height]; rawValue4 = singleSampler[xPos + onePixel.Width, yPos + onePixel.Height]; } sVal = ((rawValue1 / maxValue) + (rawValue2 / maxValue) + (rawValue3 / maxValue) + (rawValue4 / maxValue)) / 4; value = -0.5f + sVal; heights[vPos++] = value; } } } // pick up additional heights for internal borders // generate triangle normals from heights Vector3[] vNormals = new Vector3[xSamples * ySamples]; vPos = 0; Vector3 v0 = new Vector3(0, 0, 0); Vector3 v1 = new Vector3(0, 0, 1); Vector3 v2 = new Vector3(1, 0, 0); Vector3 v3 = new Vector3(1, 0, 1); for (int y = 0; y < ySamples - 1; y++) { for (int x = 0; x < xSamples - 1; x++) { v0.Y = heights[vPos]; v1.Y = heights[vPos + xSamples]; v2.Y = heights[vPos + 1]; v3.Y = heights[vPos + xSamples + 1]; Vector3 e1 = v1 - v0; Vector3 e2 = v2 - v0; Vector3 normal = Vector3.Normalize(Vector3.Cross(e1, e2)); vNormals[vPos] += normal; vNormals[vPos + xSamples] += normal; vNormals[vPos + 1] += normal; e1 = v1 - v2; e2 = v3 - v2; normal = Vector3.Normalize(Vector3.Cross(e1, e2)); vNormals[vPos + xSamples] += normal; vNormals[vPos + 1] += normal; vNormals[vPos + xSamples + 1] += normal; vPos++; } } // calculate vertex normals and input heights into vBuffer vPos = 0; for (int x = 0; x < xSamples; x++) { Vector3 result = vNormals[vPos] * (1f / 4f); verts[vPos].Y = heights[vPos]; verts[vPos].Normal = result; vPos++; } for (int y = 1; y < ySamples - 1; y++) { Vector3 result = vNormals[vPos] * (1f / 3f); verts[vPos].Y = heights[vPos]; verts[vPos].Normal = result; vPos++; for (int x = 1; x < xSamples - 1; x++) { result = vNormals[vPos] * (1f / 6f); verts[vPos].Y = heights[vPos]; verts[vPos].Normal = result; vPos++; } result = vNormals[vPos] * (1f / 3f); verts[vPos].Y = heights[vPos]; verts[vPos].Normal = result; vPos++; } for (int x = 0; x < xSamples; x++) { Vector3 result = vNormals[vPos] * (1f / 4f); verts[vPos].Y = heights[vPos]; verts[vPos].Normal = result; vPos++; } vBuffer.Unlock(); CpuDEMSubGeometry geom = new CpuDEMSubGeometry(); geom.vBuffer = vBuffer; geom.iBufSize = iBufSize; geom.skirts = skirts; return(geom); }