Axiom.Components.Terrain.TerrainQuadTreeNode.UpdateVertexBuffer C# (CSharp) Method

UpdateVertexBuffer() protected method

protected UpdateVertexBuffer ( HardwareVertexBuffer posBuff, HardwareVertexBuffer deltaBuf, Rectangle rect ) : void
posBuff Axiom.Graphics.HardwareVertexBuffer
deltaBuf Axiom.Graphics.HardwareVertexBuffer
rect Axiom.Core.Rectangle
return void
        protected unsafe void UpdateVertexBuffer(HardwareVertexBuffer posBuff, HardwareVertexBuffer deltaBuf, Rectangle rect)
        {
            unsafe
            {
                Debug.Assert(rect.Left >= mOffsetX && rect.Right <= mBoundaryX &&
                    rect.Top >= mOffsetY && rect.Bottom <= mBoundaryY);
                // potentially reset our bounds depending on coverage of the update
                ResetBounds(rect);
                //main data
                ushort inc = (ushort)((mTerrain.Size - 1) / (mVertexDataRecord.Resolution - 1));
                long destOffsetX = rect.Left <= mOffsetX ? 0 : (rect.Left - mOffsetX) / inc;
                long destOffsetY = rect.Top <= mOffsetY ? 0 : (rect.Top - mOffsetY) / inc;
                // Fill the buffers

                BufferLocking lockmode;
                if (destOffsetX != 0 || destOffsetY != 0 || rect.Right - rect.Left < mSize
                     || rect.Bottom - rect.Top < mSize)
                {
                    lockmode = BufferLocking.Normal;
                }
                else
                {
                    lockmode = BufferLocking.Discard;
                }
                float uvScale = 1.0f / (mTerrain.Size - 1);
                float* pBaseHeight = (float*)mTerrain.GetHeightData(rect.Left, rect.Top);
                float* pBaseDelta = (float*)mTerrain.GetDeltaData(rect.Left, rect.Top);
                ushort rowskip = (ushort)(mTerrain.Size * inc);
                ushort destPosRowSkip = 0, destDeltaRowSkip = 0;
                byte* pRootPosBuf = (byte*)0;
                byte* pRootDeltaBuf = (byte*)0;
                byte* pRowPosBuf = (byte*)0;
                byte* pRowDeltaBuf = (byte*)0;
                if (posBuff != null)
                {
                    destPosRowSkip = (ushort)(mVertexDataRecord.Size * posBuff.VertexSize);
                    pRootPosBuf = (byte*)posBuff.Lock(lockmode);
                    pRowPosBuf = pRootPosBuf;
                    // skip dest buffer in by left/top
                    pRowPosBuf += destOffsetY * destPosRowSkip + destOffsetX * posBuff.VertexSize;
                }
                if (deltaBuf != null)
                {
                    destDeltaRowSkip = (ushort)(mVertexDataRecord.Size * deltaBuf.VertexSize);
                    pRootDeltaBuf = (byte*)deltaBuf.Lock(lockmode);
                    pRowDeltaBuf = pRootDeltaBuf;
                    // skip dest buffer in by left/top
                    pRowDeltaBuf += destOffsetY * destDeltaRowSkip + destOffsetX * deltaBuf.VertexSize;
                }
                Vector3 pos = Vector3.Zero;

                for (ushort y = (ushort)rect.Top; y < rect.Bottom; y += inc)
                {

                    float* pHeight = (float*)pBaseHeight;
                    float* pDelta = (float*)pBaseDelta;
                    float* pPosBuf = (float*)pRowPosBuf;
                    float* pDeltaBuf = (float*)pRowDeltaBuf;
                    for (ushort x = (ushort)rect.Left; x < rect.Right; x += inc)
                    {
                        if (pPosBuf != (float*)IntPtr.Zero)
                        {
                            if (*pHeight != 0)
                            {
                                float val = *pHeight;
                               // LogManager.Instance.Write("GetPoint(" + x.ToString() + " " + y.ToString() + " " + val.ToString());
                            }
                            mTerrain.GetPoint(x, y, *pHeight, ref pos);
                            // Update bounds *before* making relative
                            MergeIntoBounds(x, y, pos);
                            // relative to local centre
                            pos -= mLocalCentre;
                            pHeight += inc;

                            *pPosBuf++ = pos.x;
                            *pPosBuf++ = pos.y;
                            *pPosBuf++ = pos.z;

                            // UVs - base UVs vary from 0 to 1, all other values
                            // will be derived using scalings
                            *pPosBuf++ = x * uvScale;
                            *pPosBuf++ = 1.0f - (y * uvScale);
                        }

                        if (pDeltaBuf != (float*)IntPtr.Zero)
                        {
                            //delta
                            *pDeltaBuf++ = *pDelta;
                            pDelta += inc;
                            // delta LOD threshold
                            // we want delta to apply to LODs no higher than this value
                            // at runtime this will be combined with a per-renderable parameter
                            // to ensure we only apply morph to the correct LOD
                            *pDeltaBuf++ = (float)mTerrain.GetLODLevelWhenVertexEliminated(x, y) - 1.0f;
                        }
                    }//end for

                    pBaseHeight += rowskip;
                    pBaseDelta += rowskip;
                    if (pRowPosBuf != (byte*)IntPtr.Zero)
                        pRowPosBuf += destPosRowSkip;
                    if (pRowDeltaBuf != (byte*)IntPtr.Zero)
                        pRowDeltaBuf += destDeltaRowSkip;

                }//end for

                // Skirts now
                // skirt spacing based on top-level resolution (* inc to cope with resolution which is not the max)
                ushort skirtSpacing = (ushort)(mVertexDataRecord.SkirtRowColSkip * inc);
                Vector3 skirtOffset = Vector3.Zero;
                mTerrain.GetVector(0, 0, -mTerrain.SkirtSize, ref skirtOffset);
                // skirt rows
                // clamp rows to skirt spacing (round up)
                long skirtStartX = rect.Left;
                long skirtStartY = rect.Top;
                if (skirtStartY % skirtSpacing != 0)
                    skirtStartY += skirtSpacing - (skirtStartY % skirtSpacing);

                skirtStartY = System.Math.Max(skirtStartY, (long)mOffsetY);
                pBaseHeight = (float*)mTerrain.GetHeightData(skirtStartX, skirtStartY);
                if (posBuff != null)
                {
                    // position dest buffer just after the main vertex data
                    pRowPosBuf = pRootPosBuf + posBuff.VertexSize *
                        mVertexDataRecord.Size * mVertexDataRecord.Size;
                    // move it onwards to skip the skirts we don't need to update
                    pRowPosBuf += destPosRowSkip * (skirtStartY - mOffsetY) / skirtSpacing;
                    pRowPosBuf += posBuff.VertexSize * (skirtStartX - mOffsetX);
                }
                if (deltaBuf != null)
                {
                    // position dest buffer just after the main vertex data
                    pRowDeltaBuf = pRootDeltaBuf + deltaBuf.VertexSize
                        * mVertexDataRecord.Size * mVertexDataRecord.Size;
                    // move it onwards to skip the skirts we don't need to update
                    pRowDeltaBuf += destDeltaRowSkip * (skirtStartY - mOffsetY) / skirtSpacing;
                    pRowDeltaBuf += deltaBuf.VertexSize * (skirtStartX - mOffsetX);
                }

                for (ushort y = (ushort)skirtStartY; y < (ushort)rect.Bottom; y += skirtSpacing)
                {
                    float* pHeight = (float*)pBaseHeight;
                    float* pPosBuf = (float*)pRowPosBuf;
                    float* pDeltaBuf = (float*)pRowDeltaBuf;
                    for (ushort x = (ushort)skirtStartX; x < (ushort)rect.Right; x += inc)
                    {
                        if (pPosBuf != (float*)IntPtr.Zero)
                        {
                            mTerrain.GetPoint(x, y, *pHeight, ref pos);
                            // relative to local centre
                            pos -= mLocalCentre;
                            pHeight += inc;
                            pos += skirtOffset;
                            *pPosBuf++ = pos.x;
                            *pPosBuf++ = pos.y;
                            *pPosBuf++ = pos.z;

                            // UVs - same as base
                            *pPosBuf++ = x * uvScale;
                            *pPosBuf++ = 1.0f - (y * uvScale);
                        }
                        if (pDeltaBuf != (float*)IntPtr.Zero)
                        {
                            // delta (none)
                            *pDeltaBuf++ = 0;
                            // delta threshold (irrelevant)
                            *pDeltaBuf++ = 99;
                        }
                    }//end for
                    pBaseHeight += mTerrain.Size * skirtSpacing;
                    if (pRowPosBuf != (byte*)IntPtr.Zero)
                        pRowPosBuf += destPosRowSkip;
                    if (pRowDeltaBuf != (byte*)IntPtr.Zero)
                        pRowDeltaBuf += destDeltaRowSkip;
                }//end for

                // skirt cols
                // clamp cols to skirt spacing (round up)
                skirtStartX = rect.Left;
                if (skirtStartX % skirtSpacing != 0)
                    skirtStartX += skirtSpacing - (skirtStartX % skirtSpacing);
                skirtStartY = rect.Top;
                skirtStartX = System.Math.Max(skirtStartX, (long)mOffsetX);

                if (posBuff != null)
                {
                    // position dest buffer just after the main vertex data and skirt rows
                    pRowPosBuf = pRootPosBuf + posBuff.VertexSize
                        * mVertexDataRecord.Size * mVertexDataRecord.Size;
                    // skip the row skirts
                    pRowPosBuf += mVertexDataRecord.NumSkirtRowsCols * mVertexDataRecord.Size * posBuff.VertexSize;
                    // move it onwards to skip the skirts we don't need to update
                    pRowPosBuf += destPosRowSkip * (skirtStartX - mOffsetX) / skirtSpacing;
                    pRowPosBuf += posBuff.VertexSize * (skirtStartY - mOffsetY);
                }
                if (deltaBuf != null)
                {
                    // Deltaition dest buffer just after the main vertex data and skirt rows
                    pRowDeltaBuf = pRootDeltaBuf + deltaBuf.VertexSize
                        * mVertexDataRecord.Size * mVertexDataRecord.Size;

                    // skip the row skirts
                    pRowDeltaBuf += mVertexDataRecord.NumSkirtRowsCols * mVertexDataRecord.Size * deltaBuf.VertexSize;
                    // move it onwards to skip the skirts we don't need to update
                    pRowDeltaBuf += destDeltaRowSkip * (skirtStartX - mOffsetX) / skirtSpacing;
                    pRowDeltaBuf += deltaBuf.VertexSize * (skirtStartY - mOffsetY);
                }
                for (ushort x = (ushort)skirtStartX; x < (ushort)rect.Right; x += skirtSpacing)
                {
                    float* pPosBuf = (float*)pRowPosBuf;
                    float* pDeltaBuf = (float*)pRowDeltaBuf;
                    for (ushort y = (ushort)skirtStartY; y < (ushort)rect.Bottom; y += inc)
                    {
                        if (pPosBuf != (float*)IntPtr.Zero)
                        {
                            //float* hTmp = (float*)mTerrain.GetHeightData(x, y);
                            
                            mTerrain.GetPoint(x, y, mTerrain.GetHeightAtPoint(x, y), ref pos);
                            // relative to local centre
                            pos -= mLocalCentre;
                            pos += skirtOffset;

                            *pPosBuf++ = pos.x;
                            *pPosBuf++ = pos.y;
                            *pPosBuf++ = pos.z;

                            // UVs - same as base
                            *pPosBuf++ = x * uvScale;
                            *pPosBuf++ = 1.0f - (y * uvScale);

                            
                        }
                        if (pDeltaBuf != (float*)IntPtr.Zero)
                        {
                            // delta (none)
                            *pDeltaBuf++ = 0;
                            // delta threshold (irrelevant)
                            *pDeltaBuf++ = 99;
                        }
                        

                    }//end for
                    if (pRowPosBuf != (byte*)IntPtr.Zero)
                        pRowPosBuf += destPosRowSkip;
                    if (pRowDeltaBuf != (byte*)IntPtr.Zero)
                        pRowDeltaBuf += destDeltaRowSkip;
                    
                }//end for
                if (posBuff != null)
                    posBuff.Unlock();
                if (deltaBuf != null)
                    deltaBuf.Unlock();
            }
        }