Exemple #1
0
        /// <summary>
        /// Create a new heightField that is (equal or) lower LOD than the four sources,
        /// Height points are copied from the four sources.
        /// </summary>
        /// <param name="t"></param>
        /// <param name="srcNW"></param>
        /// <param name="srcNE"></param>
        /// <param name="srcSW"></param>
        /// <param name="srcSE"></param>
        public HeightField(Tile t, HeightField srcNW, HeightField srcNE, HeightField srcSW, HeightField srcSE) : base()
        {
            tile = t;

            Init(WorldManager.Instance.MetersPerSample(tile.Location));

            // copy from the source heightMap
            int halfSamples = numSamples / 2;

            CopyHeightFieldScaleDown(srcSW.heightMap, metersPerSample / srcSW.metersPerSample, srcSW.numSamples, 0, halfSamples);
            CopyHeightFieldScaleDown(srcSE.heightMap, metersPerSample / srcSE.metersPerSample, srcSE.numSamples, halfSamples, halfSamples);
            CopyHeightFieldScaleDown(srcNW.heightMap, metersPerSample / srcNW.metersPerSample, srcNW.numSamples, 0, 0);
            CopyHeightFieldScaleDown(srcNE.heightMap, metersPerSample / srcNE.metersPerSample, srcNE.numSamples, halfSamples, 0);

            // update minHeight and maxHeight by taking the most extreme from the 4 sources.
            // this could result in a bounding box slightly larger than necessary, but its
            // not enough of an issue to warrant scanning the entire heightField looking for
            // the true min and max.
            minHeight = srcSW.minHeight;
            if (srcSE.minHeight < minHeight)
            {
                minHeight = srcSE.minHeight;
            }
            if (srcNW.minHeight < minHeight)
            {
                minHeight = srcNW.minHeight;
            }
            if (srcNE.minHeight < minHeight)
            {
                minHeight = srcNE.minHeight;
            }

            maxHeight = srcSW.maxHeight;
            if (srcSE.maxHeight > maxHeight)
            {
                maxHeight = srcSE.maxHeight;
            }
            if (srcNW.maxHeight > maxHeight)
            {
                maxHeight = srcNW.maxHeight;
            }
            if (srcNE.maxHeight > maxHeight)
            {
                maxHeight = srcNE.maxHeight;
            }
            UpdateBounds();
        }
Exemple #2
0
        unsafe private void fillVerts(HeightField src, float *buffer, int bufferOff, int numVerts,
                                      int xIndex, int zIndex,
                                      int xIndexIncr, int zIndexIncr,
                                      float xSampOffset, float zSampOffset, Vector3 pageLocation)
        {
            // convert from vert offset to float offset in the buffer
            bufferOff *= floatsPerVert;

            float unitsPerSample = src.metersPerSample * WorldManager.oneMeter;
            float xWorldOffset   = xSampOffset * WorldManager.oneMeter;
            float zWorldOffset   = zSampOffset * WorldManager.oneMeter;

            for (int n = 0; n < numVerts; n++)
            {
                float x      = (xIndex * unitsPerSample) + xWorldOffset;
                float z      = (zIndex * unitsPerSample) + zWorldOffset;
                float height = src.heightMap[zIndex * src.numSamples + xIndex];

                // Position
                buffer[bufferOff++] = x;
                buffer[bufferOff++] = height;
                buffer[bufferOff++] = z;

                // normals
                // XXX - need to calculate normal here.  Use straight up for now

                Vector3 norm = WorldManager.Instance.GetNormalAt(new Vector3(x + tile.Location.x, height, z + tile.Location.z));

                buffer[bufferOff++] = norm.x;
                buffer[bufferOff++] = norm.y;
                buffer[bufferOff++] = norm.z;

                // Texture
                // XXX - assumes one unit of texture space is one page.
                //   how does the vertex shader deal with texture coords?
                buffer[bufferOff++] = (x + location.x - pageLocation.x) /
                                      (WorldManager.Instance.PageSize * WorldManager.oneMeter);
                buffer[bufferOff++] = (z + location.z - pageLocation.z) /
                                      (WorldManager.Instance.PageSize * WorldManager.oneMeter);

                xIndex += xIndexIncr;
                zIndex += zIndexIncr;
            }
        }
        private unsafe void fillVerts(HeightField src, float* buffer, int bufferOff, int numVerts,
			int xIndex, int zIndex, 
			int xIndexIncr, int zIndexIncr,
			float xSampOffset, float zSampOffset, Vector3 pageLocation)
        {
            // convert from vert offset to float offset in the buffer
            bufferOff *= floatsPerVert;

            float unitsPerSample = src.metersPerSample * WorldManager.oneMeter;
            float xWorldOffset = xSampOffset * WorldManager.oneMeter;
            float zWorldOffset = zSampOffset * WorldManager.oneMeter;

            for (int n = 0; n < numVerts; n++ )
            {
                float x = ( xIndex * unitsPerSample ) + xWorldOffset;
                float z = ( zIndex * unitsPerSample ) + zWorldOffset;
                float height = src.heightMap[zIndex * src.numSamples + xIndex];

                // Position
                buffer[bufferOff++] = x;
                buffer[bufferOff++] = height;
                buffer[bufferOff++] = z;

                // normals
                // XXX - need to calculate normal here.  Use straight up for now

                Vector3 norm = WorldManager.Instance.GetNormalAt(new Vector3(x + tile.Location.x, height, z + tile.Location.z));

                buffer[bufferOff++] = norm.x;
                buffer[bufferOff++] = norm.y;
                buffer[bufferOff++] = norm.z;

                // Texture
                // XXX - assumes one unit of texture space is one page.
                //   how does the vertex shader deal with texture coords?
                buffer[bufferOff++] = ( x + location.x - pageLocation.x ) /
                    ( WorldManager.Instance.PageSize * WorldManager.oneMeter );
                buffer[bufferOff++] = ( z + location.z - pageLocation.z ) /
                    ( WorldManager.Instance.PageSize * WorldManager.oneMeter );

                xIndex += xIndexIncr;
                zIndex += zIndexIncr;
            }
        }
        public void Stitch(HeightField south1, HeightField south2, HeightField east1, 
			HeightField east2, HeightField southEast, bool stitchMiddleSouth, bool stitchMiddleEast)
        {
            Debug.Assert( ( south2 == null || south2.metersPerSample == south1.metersPerSample ), "south neighbors have different LOD");
            Debug.Assert( ( east2 == null || east2.metersPerSample == east1.metersPerSample ), "east neighbors have different LOD");

            //
            // Determine the stitch types for south and east direction
            //
            StitchType southStitchType;
            StitchType eastStitchType;

            int southMetersPerSample = 0;

            if ( south1 == null )
            {
                southStitchType = StitchType.None;
            }
            else
            {
                southMetersPerSample = south1.metersPerSample;

                if ( south1.metersPerSample == metersPerSample )
                {
                    southStitchType = StitchType.ToSame;
                }
                else if ( south1.metersPerSample > metersPerSample )
                {
                    Debug.Assert(south1.metersPerSample == ( 2 * metersPerSample ), "stitching:south LOD not half");
                    southStitchType = StitchType.ToLower;
                }
                else
                {
                    Debug.Assert( ( south1.metersPerSample * 2 ) == metersPerSample, "stitching: south LOD not double");
                    southStitchType = StitchType.ToHigher;
                }
            }

            int eastMetersPerSample = 0;

            if ( east1 == null )
            {
                eastStitchType = StitchType.None;
            }
            else
            {
                eastMetersPerSample = east1.metersPerSample;

                if ( east1.metersPerSample == metersPerSample )
                {
                    eastStitchType = StitchType.ToSame;
                }
                else if ( east1.metersPerSample > metersPerSample )
                {
                    Debug.Assert(east1.metersPerSample == ( 2 * metersPerSample ), "stitching:east LOD not half");
                    eastStitchType = StitchType.ToLower;
                }
                else
                {
                    Debug.Assert( ( east1.metersPerSample * 2 ) == metersPerSample, "stitching:east LOD not double");
                    eastStitchType = StitchType.ToHigher;
                }
            }

            if ( stitchRenderable != null )
            {
                if ( stitchRenderable.IsValid(numSamples, southMetersPerSample, eastMetersPerSample) )
                { // existing stitchRenderable is still ok, so just use it
                    return;
                }
                else
                {
                    stitchRenderable.Dispose();
                    stitchRenderable = null;
                }
            }

            //
            // The following combinations are acceptable:
            //  1) both same
            //  2) one same and one lower
            //  3) one same and one higher
            //  4) both lower
            //
            Debug.Assert( ( ( southStitchType == StitchType.ToSame ) || ( eastStitchType == StitchType.ToSame ) ) ||
                ( ( southStitchType == StitchType.ToLower ) && ( eastStitchType == StitchType.ToLower ) ) ||
                ( ( southStitchType == StitchType.None ) && ( eastStitchType == StitchType.None ) ),
                "stitching:invalid stitchType combination");

            bool bothSame = false;
            bool bothLower = false;
            int vertexCount;

            if ( southStitchType == eastStitchType )
            {
                if ( southStitchType == StitchType.ToSame )
                {
                    bothSame = true;
                    vertexCount = numSamples * 4;
                }
                else if ( southStitchType == StitchType.ToLower )
                {
                    bothLower = true;
                    vertexCount = numSamples * 3;
                }
                else
                {
                    // both are StitchType.None, which means we are at the NE corner, so we dont need stitching
                    return;
                }
            }
            else
            {
                if ( ( southStitchType == StitchType.ToLower ) || ( eastStitchType == StitchType.ToLower ) )
                {
                    // one same and one lower
                    vertexCount = numSamples * 3 + ( numSamples / 2 );
                }
                else if ( ( southStitchType == StitchType.ToHigher ) || ( eastStitchType == StitchType.ToHigher ) )
                {
                    // one same and one higher
                    vertexCount = numSamples * 5;
                }
                else
                {
                    // one same and one none
                    vertexCount = numSamples * 2;
                }
            }

            VertexData vertexData = new VertexData();

            vertexData.vertexCount = vertexCount;
            vertexData.vertexStart = 0;

            // set up the vertex declaration
            int vDecOffset = 0;
            vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float3, VertexElementSemantic.Position);
            vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float3);

            vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float3, VertexElementSemantic.Normal);
            vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float3);

            vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords);
            vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float2);

            // create the hardware vertex buffer and set up the buffer binding
            HardwareVertexBuffer hvBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                vertexData.vertexDeclaration.GetVertexSize(0), vertexData.vertexCount,
                BufferUsage.StaticWriteOnly, false);

            vertexData.vertexBufferBinding.SetBinding(0, hvBuffer);

            // lock the vertex buffer
            IntPtr ipBuf = hvBuffer.Lock(BufferLocking.Discard);

            int bufferOff = 0;

            int southSamples = 0;
            int eastSamples = 0;
            int vertOff = 0;

            unsafe
            {
                float* buffer = (float *) ipBuf.ToPointer();

                if ( southStitchType != StitchType.None )
                {
                    //
                    // First the south edge of this tile
                    //
                    fillVerts(this, buffer, vertOff, numSamples, 0, numSamples - 1, 1, 0, 0, 0, tile.Page.Location);
                    vertOff += numSamples;
                }

                if ( eastStitchType != StitchType.None )
                {
                    int adjust = 0;
                    if ( southStitchType == StitchType.None )
                    {
                        // include the inner corner because it wasnt done with the south edge
                        adjust = 1;
                    }
                    //
                    // Now the east edge of the tile
                    //
                    fillVerts(this, buffer, vertOff, numSamples - 1 + adjust, numSamples - 1, numSamples - 2 + adjust, 0, -1, 0, 0, tile.Page.Location);
                    vertOff += ( numSamples - 1 + adjust );
                }

                if ( southStitchType != StitchType.None )
                {
                    //
                    // fill the verts from the south neighbor
                    //
                    southSamples = neighborSamples(southStitchType);

                    if ( south2 == null )
                    { // only one southern neighbor

                        int xStart = 0;
                        int xSampOff = 0;
                        if ( stitchMiddleSouth )
                        {
                            // go from bottom to middle of east tile, rather than middle to top
                            xStart = southSamples;
                            xSampOff = -tile.Size;
                        }

                        fillVerts(south1, buffer, vertOff, southSamples, xStart, 0, 1, 0, xSampOff, tile.Size, tile.Page.Location);
                        vertOff += southSamples;
                    }
                    else
                    { // two southern neighbors
                        int halfSamples = southSamples / 2;
                        fillVerts(south1, buffer, vertOff, halfSamples, 0, 0, 1, 0, 0, tile.Size, tile.Page.Location);
                        vertOff += halfSamples;

                        fillVerts(south2, buffer, vertOff, halfSamples, 0, 0, 1, 0, south1.tile.Size, tile.Size, tile.Page.Location);
                        vertOff += halfSamples;
                    }
                }

                if ( ( southStitchType != StitchType.None ) && ( eastStitchType != StitchType.None ) )
                {
                    //
                    // fill the single sample from the SE neighbor
                    //
                    if ( southEast == east1 )
                    {
                        fillVerts(southEast, buffer, vertOff, 1, 0, neighborSamples(eastStitchType), 0, 0, tile.Size, 0, tile.Page.Location);
                    }
                    else if ( southEast == south1 )
                    {
                        fillVerts(southEast, buffer, vertOff, 1, neighborSamples(southStitchType), 0, 0, 0, 0, tile.Size, tile.Page.Location);
                    }
                    else
                    {
                        fillVerts(southEast, buffer, vertOff, 1, 0, 0, 0, 0, tile.Size, tile.Size, tile.Page.Location);
                    }
                    vertOff++;
                }

                if ( eastStitchType != StitchType.None )
                {
                    //
                    // fill the verts from the east neighbor
                    //
                    eastSamples = neighborSamples(eastStitchType);

                    if ( east2 == null )
                    { // only one eastern neighbor

                        int zStart = eastSamples - 1;
                        int zSampOff = 0;
                        if ( stitchMiddleEast )
                        {
                            // go from bottom to middle of east tile, rather than middle to top
                            zStart = ( eastSamples * 2 ) - 1;
                            zSampOff = -tile.Size;
                        }

                        fillVerts(east1, buffer, vertOff, eastSamples, 0, zStart, 0, -1, tile.Size, zSampOff, tile.Page.Location);
                        vertOff += eastSamples;
                    }
                    else
                    { // two eastern neighbors
                        int halfSamples = eastSamples / 2;

                        fillVerts(east2, buffer, vertOff, halfSamples, 0, halfSamples - 1, 0, -1, tile.Size, east1.tile.Size, tile.Page.Location);
                        vertOff += halfSamples;

                        fillVerts(east1, buffer, vertOff, halfSamples, 0, halfSamples - 1, 0, -1, tile.Size, 0, tile.Page.Location);
                        vertOff += halfSamples;
                    }
                }

                Debug.Assert(vertexCount == vertOff, "stitching: generated incorrect number of vertices");

            }
            hvBuffer.Unlock();

            IndexData indexData = IndexBufferManager.Instance.GetStitchIndexBuffer(numSamples, southSamples, eastSamples);

            stitchRenderable = new StitchRenderable(this, vertexData, indexData, numSamples, southMetersPerSample, eastMetersPerSample);
        }
        /// <summary>
        /// Create a new heightField that is (equal or) lower LOD than the four sources,
        /// Height points are copied from the four sources.
        /// </summary>
        /// <param name="t"></param>
        /// <param name="srcNW"></param>
        /// <param name="srcNE"></param>
        /// <param name="srcSW"></param>
        /// <param name="srcSE"></param>
        public HeightField(Tile t, HeightField srcNW, HeightField srcNE, HeightField srcSW, HeightField srcSE )
            : base()
        {
            tile = t;

            Init(WorldManager.Instance.MetersPerSample(tile.Location));

            // copy from the source heightMap
            int halfSamples = numSamples/2;
            CopyHeightFieldScaleDown(srcSW.heightMap, metersPerSample / srcSW.metersPerSample, srcSW.numSamples, 0, halfSamples);
            CopyHeightFieldScaleDown(srcSE.heightMap, metersPerSample / srcSE.metersPerSample, srcSE.numSamples, halfSamples, halfSamples);
            CopyHeightFieldScaleDown(srcNW.heightMap, metersPerSample / srcNW.metersPerSample, srcNW.numSamples, 0, 0);
            CopyHeightFieldScaleDown(srcNE.heightMap, metersPerSample / srcNE.metersPerSample, srcNE.numSamples, halfSamples, 0);

            // update minHeight and maxHeight by taking the most extreme from the 4 sources.
            // this could result in a bounding box slightly larger than necessary, but its
            // not enough of an issue to warrant scanning the entire heightField looking for
            // the true min and max.
            minHeight = srcSW.minHeight;
            if ( srcSE.minHeight < minHeight )
            {
                minHeight = srcSE.minHeight;
            }
            if ( srcNW.minHeight < minHeight )
            {
                minHeight = srcNW.minHeight;
            }
            if ( srcNE.minHeight < minHeight )
            {
                minHeight = srcNE.minHeight;
            }

            maxHeight = srcSW.maxHeight;
            if ( srcSE.maxHeight > maxHeight )
            {
                maxHeight = srcSE.maxHeight;
            }
            if ( srcNW.maxHeight > maxHeight )
            {
                maxHeight = srcNW.maxHeight;
            }
            if ( srcNE.maxHeight > maxHeight )
            {
                maxHeight = srcNE.maxHeight;
            }
            UpdateBounds();
        }
        /// <summary>
        /// create a new heightField that has the same LOD as the source,
        /// and 1/4 the area of the source.  Height points are copied from one
        /// quadrant of the source.
        /// If the heightField needs to be higher LOD, it will be adjusted
        /// later and the required points will be generated.
        /// </summary>
        /// <param name="t"></param>
        /// <param name="src"></param>
        /// <param name="quad"></param>
        public HeightField(Tile t, HeightField src, Quadrant quad)
            : base()
        {
            tile = t;

            // in this case we will make the new heightField have the same LOD as
            // the source.  The LOD will be adjusted upward later if necessary.
            Init(src.metersPerSample);

            Debug.Assert((numSamples * metersPerSample * 2) == ( src.metersPerSample * src.numSamples), "creating heightfield from source that is not next lower LOD");

            int xoff = 0;
            int zoff = 0;

            switch ( quad )
            {
                case Quadrant.Northeast:
                    xoff = src.numSamples / 2;
                    zoff = 0;
                    break;
                case Quadrant.Northwest:
                    xoff = 0;
                    zoff = 0;
                    break;
                case Quadrant.Southeast:
                    xoff = src.numSamples / 2;
                    zoff = src.numSamples / 2;
                    break;
                case Quadrant.Southwest:
                    xoff = 0;
                    zoff = src.numSamples / 2;
                    break;
            }

            // copy from the source heightMap
            this.CopyHeightFieldScaleUp(src.heightMap, 1, xoff, zoff, src.numSamples);

            // compute the min and max extents of this heightField, since nobody else is
            // going to do it.
            // XXX - do we need to do this?
            minHeight = float.MaxValue;
            maxHeight = float.MinValue;
            foreach ( float h in heightMap )
            {
                if ( h < minHeight )
                {
                    minHeight = h;
                }
                if ( h > maxHeight )
                {
                    maxHeight = h;
                }
            }

            // generate the height points that were not filled in above
            //WorldManager.Instance.TerrainGenerator.GenerateHeightField(location, Size, metersPerSample,
            //	heightMap, out minHeight, out maxHeight, src.metersPerSample);

            UpdateBounds();
        }
Exemple #7
0
        public void Stitch(HeightField south1, HeightField south2, HeightField east1,
                           HeightField east2, HeightField southEast, bool stitchMiddleSouth, bool stitchMiddleEast)
        {
            Debug.Assert((south2 == null || south2.metersPerSample == south1.metersPerSample), "south neighbors have different LOD");
            Debug.Assert((east2 == null || east2.metersPerSample == east1.metersPerSample), "east neighbors have different LOD");

            //
            // Determine the stitch types for south and east direction
            //
            StitchType southStitchType;
            StitchType eastStitchType;

            int southMetersPerSample = 0;

            if (south1 == null)
            {
                southStitchType = StitchType.None;
            }
            else
            {
                southMetersPerSample = south1.metersPerSample;

                if (south1.metersPerSample == metersPerSample)
                {
                    southStitchType = StitchType.ToSame;
                }
                else if (south1.metersPerSample > metersPerSample)
                {
                    Debug.Assert(south1.metersPerSample == (2 * metersPerSample), "stitching:south LOD not half");
                    southStitchType = StitchType.ToLower;
                }
                else
                {
                    Debug.Assert((south1.metersPerSample * 2) == metersPerSample, "stitching: south LOD not double");
                    southStitchType = StitchType.ToHigher;
                }
            }

            int eastMetersPerSample = 0;

            if (east1 == null)
            {
                eastStitchType = StitchType.None;
            }
            else
            {
                eastMetersPerSample = east1.metersPerSample;

                if (east1.metersPerSample == metersPerSample)
                {
                    eastStitchType = StitchType.ToSame;
                }
                else if (east1.metersPerSample > metersPerSample)
                {
                    Debug.Assert(east1.metersPerSample == (2 * metersPerSample), "stitching:east LOD not half");
                    eastStitchType = StitchType.ToLower;
                }
                else
                {
                    Debug.Assert((east1.metersPerSample * 2) == metersPerSample, "stitching:east LOD not double");
                    eastStitchType = StitchType.ToHigher;
                }
            }

            if (stitchRenderable != null)
            {
                if (stitchRenderable.IsValid(numSamples, southMetersPerSample, eastMetersPerSample))
                {                 // existing stitchRenderable is still ok, so just use it
                    return;
                }
                else
                {
                    stitchRenderable.Dispose();
                    stitchRenderable = null;
                }
            }

            //
            // The following combinations are acceptable:
            //  1) both same
            //  2) one same and one lower
            //  3) one same and one higher
            //  4) both lower
            //
            Debug.Assert(((southStitchType == StitchType.ToSame) || (eastStitchType == StitchType.ToSame)) ||
                         ((southStitchType == StitchType.ToLower) && (eastStitchType == StitchType.ToLower)) ||
                         ((southStitchType == StitchType.None) && (eastStitchType == StitchType.None)),
                         "stitching:invalid stitchType combination");

            bool bothSame  = false;
            bool bothLower = false;
            int  vertexCount;

            if (southStitchType == eastStitchType)
            {
                if (southStitchType == StitchType.ToSame)
                {
                    bothSame    = true;
                    vertexCount = numSamples * 4;
                }
                else if (southStitchType == StitchType.ToLower)
                {
                    bothLower   = true;
                    vertexCount = numSamples * 3;
                }
                else
                {
                    // both are StitchType.None, which means we are at the NE corner, so we dont need stitching
                    return;
                }
            }
            else
            {
                if ((southStitchType == StitchType.ToLower) || (eastStitchType == StitchType.ToLower))
                {
                    // one same and one lower
                    vertexCount = numSamples * 3 + (numSamples / 2);
                }
                else if ((southStitchType == StitchType.ToHigher) || (eastStitchType == StitchType.ToHigher))
                {
                    // one same and one higher
                    vertexCount = numSamples * 5;
                }
                else
                {
                    // one same and one none
                    vertexCount = numSamples * 2;
                }
            }

            VertexData vertexData = new VertexData();

            vertexData.vertexCount = vertexCount;
            vertexData.vertexStart = 0;

            // set up the vertex declaration
            int vDecOffset = 0;

            vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float3, VertexElementSemantic.Position);
            vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float3);

            vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float3, VertexElementSemantic.Normal);
            vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float3);

            vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords);
            vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float2);

            // create the hardware vertex buffer and set up the buffer binding
            HardwareVertexBuffer hvBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                vertexData.vertexDeclaration.GetVertexSize(0), vertexData.vertexCount,
                BufferUsage.StaticWriteOnly, false);

            vertexData.vertexBufferBinding.SetBinding(0, hvBuffer);

            // lock the vertex buffer
            IntPtr ipBuf = hvBuffer.Lock(BufferLocking.Discard);

            int bufferOff = 0;

            int southSamples = 0;
            int eastSamples  = 0;
            int vertOff      = 0;

            unsafe
            {
                float *buffer = (float *)ipBuf.ToPointer();

                if (southStitchType != StitchType.None)
                {
                    //
                    // First the south edge of this tile
                    //
                    fillVerts(this, buffer, vertOff, numSamples, 0, numSamples - 1, 1, 0, 0, 0, tile.Page.Location);
                    vertOff += numSamples;
                }

                if (eastStitchType != StitchType.None)
                {
                    int adjust = 0;
                    if (southStitchType == StitchType.None)
                    {
                        // include the inner corner because it wasnt done with the south edge
                        adjust = 1;
                    }
                    //
                    // Now the east edge of the tile
                    //
                    fillVerts(this, buffer, vertOff, numSamples - 1 + adjust, numSamples - 1, numSamples - 2 + adjust, 0, -1, 0, 0, tile.Page.Location);
                    vertOff += (numSamples - 1 + adjust);
                }

                if (southStitchType != StitchType.None)
                {
                    //
                    // fill the verts from the south neighbor
                    //
                    southSamples = neighborSamples(southStitchType);

                    if (south2 == null)
                    {                     // only one southern neighbor
                        int xStart   = 0;
                        int xSampOff = 0;
                        if (stitchMiddleSouth)
                        {
                            // go from bottom to middle of east tile, rather than middle to top
                            xStart   = southSamples;
                            xSampOff = -tile.Size;
                        }

                        fillVerts(south1, buffer, vertOff, southSamples, xStart, 0, 1, 0, xSampOff, tile.Size, tile.Page.Location);
                        vertOff += southSamples;
                    }
                    else
                    {                     // two southern neighbors
                        int halfSamples = southSamples / 2;
                        fillVerts(south1, buffer, vertOff, halfSamples, 0, 0, 1, 0, 0, tile.Size, tile.Page.Location);
                        vertOff += halfSamples;

                        fillVerts(south2, buffer, vertOff, halfSamples, 0, 0, 1, 0, south1.tile.Size, tile.Size, tile.Page.Location);
                        vertOff += halfSamples;
                    }
                }

                if ((southStitchType != StitchType.None) && (eastStitchType != StitchType.None))
                {
                    //
                    // fill the single sample from the SE neighbor
                    //
                    if (southEast == east1)
                    {
                        fillVerts(southEast, buffer, vertOff, 1, 0, neighborSamples(eastStitchType), 0, 0, tile.Size, 0, tile.Page.Location);
                    }
                    else if (southEast == south1)
                    {
                        fillVerts(southEast, buffer, vertOff, 1, neighborSamples(southStitchType), 0, 0, 0, 0, tile.Size, tile.Page.Location);
                    }
                    else
                    {
                        fillVerts(southEast, buffer, vertOff, 1, 0, 0, 0, 0, tile.Size, tile.Size, tile.Page.Location);
                    }
                    vertOff++;
                }

                if (eastStitchType != StitchType.None)
                {
                    //
                    // fill the verts from the east neighbor
                    //
                    eastSamples = neighborSamples(eastStitchType);

                    if (east2 == null)
                    {                     // only one eastern neighbor
                        int zStart   = eastSamples - 1;
                        int zSampOff = 0;
                        if (stitchMiddleEast)
                        {
                            // go from bottom to middle of east tile, rather than middle to top
                            zStart   = (eastSamples * 2) - 1;
                            zSampOff = -tile.Size;
                        }

                        fillVerts(east1, buffer, vertOff, eastSamples, 0, zStart, 0, -1, tile.Size, zSampOff, tile.Page.Location);
                        vertOff += eastSamples;
                    }
                    else
                    {                     // two eastern neighbors
                        int halfSamples = eastSamples / 2;

                        fillVerts(east2, buffer, vertOff, halfSamples, 0, halfSamples - 1, 0, -1, tile.Size, east1.tile.Size, tile.Page.Location);
                        vertOff += halfSamples;

                        fillVerts(east1, buffer, vertOff, halfSamples, 0, halfSamples - 1, 0, -1, tile.Size, 0, tile.Page.Location);
                        vertOff += halfSamples;
                    }
                }

                Debug.Assert(vertexCount == vertOff, "stitching: generated incorrect number of vertices");
            }
            hvBuffer.Unlock();

            IndexData indexData = IndexBufferManager.Instance.GetStitchIndexBuffer(numSamples, southSamples, eastSamples);

            stitchRenderable = new StitchRenderable(this, vertexData, indexData, numSamples, southMetersPerSample, eastMetersPerSample);
        }
Exemple #8
0
        /// <summary>
        /// create a new heightField that has the same LOD as the source,
        /// and 1/4 the area of the source.  Height points are copied from one
        /// quadrant of the source.
        /// If the heightField needs to be higher LOD, it will be adjusted
        /// later and the required points will be generated.
        /// </summary>
        /// <param name="t"></param>
        /// <param name="src"></param>
        /// <param name="quad"></param>
        public HeightField(Tile t, HeightField src, Quadrant quad) : base()
        {
            tile = t;

            // in this case we will make the new heightField have the same LOD as
            // the source.  The LOD will be adjusted upward later if necessary.
            Init(src.metersPerSample);

            Debug.Assert((numSamples * metersPerSample * 2) == (src.metersPerSample * src.numSamples), "creating heightfield from source that is not next lower LOD");

            int xoff = 0;
            int zoff = 0;

            switch (quad)
            {
            case Quadrant.Northeast:
                xoff = src.numSamples / 2;
                zoff = 0;
                break;

            case Quadrant.Northwest:
                xoff = 0;
                zoff = 0;
                break;

            case Quadrant.Southeast:
                xoff = src.numSamples / 2;
                zoff = src.numSamples / 2;
                break;

            case Quadrant.Southwest:
                xoff = 0;
                zoff = src.numSamples / 2;
                break;
            }

            // copy from the source heightMap
            this.CopyHeightFieldScaleUp(src.heightMap, 1, xoff, zoff, src.numSamples);

            // compute the min and max extents of this heightField, since nobody else is
            // going to do it.
            // XXX - do we need to do this?
            minHeight = float.MaxValue;
            maxHeight = float.MinValue;
            foreach (float h in heightMap)
            {
                if (h < minHeight)
                {
                    minHeight = h;
                }
                if (h > maxHeight)
                {
                    maxHeight = h;
                }
            }

            // generate the height points that were not filled in above
            //WorldManager.Instance.TerrainGenerator.GenerateHeightField(location, Size, metersPerSample,
            //	heightMap, out minHeight, out maxHeight, src.metersPerSample);

            UpdateBounds();
        }