Exemplo n.º 1
0
        public static CpuDemGeometry CreateGeometry(RasterDatabase.RasterDatabase rDatabase, Device gDevice,
                                                    out float maxValue)
        {
            // TODO: Still some atifact problems?

            // just use default LOD for now
            RectangleGroupQuadTree rTree = rDatabase.ProduceLayerMipMap(0, maxRes);

            maxValue = rTree.MaxDataValue;

            // use bottom level only for now
            RectangleGroupQuadTree.GroupNode[] nodes;
            rTree.GetNodes(rTree.Depth, out nodes);

            // create sub-geometry for each node/area
            CpuDEMSubGeometry[] subGeometry = new CpuDEMSubGeometry[nodes.Length];
            for (int i = 0; i < nodes.Length; i++)
            {
                subGeometry[i] = CpuDEMSubGeometry.CreatePointList(nodes[i], gDevice, maxRes / numSamples,
                                                                   rDatabase.Layers[0].Area.Size,
                                                                   rTree.MinDataValue, rTree.MaxDataValue);
            }

            // TODO: Produce diffuse-maps (etc.) for the tree

            IndexBuffer[] iBuffers = CpuDEMSubGeometry.CreateSampleTriStripsIndices(numSamples, numSamples, gDevice);

            CpuDemGeometry geom = new CpuDemGeometry(new Vector3(), new Vector3(), new Vector3(),
                                                     0, 0, PrimitiveType.PointList, gDevice);

            geom.subGeometry = subGeometry;
            geom.iBuffers    = iBuffers;
            geom.tex         = new Texture[nodes.Length];
            geom.rTree       = rTree;
            geom.nodes       = nodes;

            geom.iBuffersLong2 = CpuDEMSubGeometry.CreateSampleTriStripsIndices(numSamples + 1, numSamples + 1, gDevice);
            return(geom);
        }
Exemplo n.º 2
0
        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);
        }