public static void ZeroNormals(VertexPositionNormalColor[] vertices)
 {
     for (var i = 0; i < vertices.Length; i++)
     {
         vertices[i].Normal = Vector3.Zero;
     }
 }
        public SimpleSurface(VertexPositionNormalColor[] vertices, int xDimension, int yDimension)
        {
            _xDimension = xDimension;
            _yDimension = yDimension;
            _vertices = vertices;

            if (GraphicsDeviceManager.Current.RenderMode != RenderMode.Hardware) return;
            _vertexBuffer = new VertexBuffer(GraphicsDeviceManager.Current.GraphicsDevice,
                typeof (VertexPositionNormalColor), vertices.Length, BufferUsage.WriteOnly);
            _vertexBuffer.SetData(_vertices);
            DrawStyle = DrawStyle.Surface;
        }
        /// <summary>
        /// Calculate lighing normals for specified vertex array.
        /// </summary>
        /// <param name="vertices"></param>
        /// <param name="indices"></param>
        public static void CalculateTriangleNormals(VertexPositionNormalColor[] vertices, short[] indices)
        {
            ZeroNormals(vertices);
            for (var i = 0; i < indices.Length/3; i++)
            {
                var idx0 = indices[i*3];
                var idx1 = indices[i*3 + 1];
                var idx2 = indices[i*3 + 2];

                var side0 = vertices[idx0].Position - vertices[idx2].Position;
                var side1 = vertices[idx0].Position - vertices[idx1].Position;
                var normal = Vector3.Cross(side0, side1);

                vertices[idx0].Normal -= normal;
                vertices[idx1].Normal -= normal;
                vertices[idx2].Normal -= normal;
            }
        }
        private ISurface CreateSegment(int uIdx, int vIdx,
            MathFunction function)
        {
            var meshDensity = Properties.MeshDensity;
            var uSize = Math.Abs(UDimension.Max - UDimension.Min)
                        /(UDimension.KnotCount - 1);
            var vSize = Math.Abs(VDimension.Max - VDimension.Min)
                        /(VDimension.KnotCount - 1);

            var u0 = UDimension.Min + uSize*uIdx; //afv[uIdx][vIdx].X;
            var u1 = UDimension.Min + uSize*(uIdx + 1);
            var v0 = VDimension.Min + vSize*vIdx;
            var v1 = VDimension.Min + vSize*(vIdx + 1);

            var uKnotsDistance = Math.Abs(u1 - u0);
            var xCount = Math.Ceiling(uKnotsDistance/meshDensity);
            var yKnotDistance = Math.Abs(v1 - v0);
            var yCount = Math.Ceiling(yKnotDistance/meshDensity);
            var verticesCount = (int) ((++xCount)*(++yCount));
            var segmentMeshVertices =
                new VertexPositionNormalColor[verticesCount];
            var k = 0;
            var x = (float) u0;
            for (var i = 0; i < xCount; i++, x += meshDensity)
            {
                x = x < u1 ? x : (float) u1;
                var y = (float) v0;
                for (var j = 0; j < yCount; j++, y += meshDensity)
                {
                    y = y < v1 ? y : (float) v1;

                    var z = (float) function.SafeCall(x, y);
                    segmentMeshVertices[k++] =
                        new VertexPositionNormalColor(new Vector3(x, y, z),
                            DefaultNormal,
                            DefaultColor);
                }
            }
            return new SimpleSurface(segmentMeshVertices, (int) xCount,
                (int) yCount);
        }
using System;
using System.Collections.Generic;
using HermiteInterpolation.MathFunctions;
using HermiteInterpolation.Numerics;

using HermiteInterpolation.Primitives;
using HermiteInterpolation.SplineKnots;
using MathNet.Numerics.LinearAlgebra;
using Microsoft.Xna.Framework;

namespace HermiteInterpolation.Shapes.SplineInterpolation
{
    public class BicubicHermiteSurface :Spline
    {

        public BicubicHermiteSurface(SurfaceDimension uDimension, SurfaceDimension vDimension, MathExpression mathExpression, Derivation derivation = Derivation.Zero) : base(uDimension, vDimension, mathExpression, derivation)
        {
        }

        public BicubicHermiteSurface(SurfaceDimension uDimension, SurfaceDimension vDimension, InterpolativeMathFunction interpolativeMathFunction, Derivation derivation = Derivation.Zero) : base(uDimension, vDimension, interpolativeMathFunction, derivation)
        {
        }

        public BicubicHermiteSurface(SurfaceDimension uDimension, SurfaceDimension vDimension, KnotsGenerator knotsGenerator, Derivation derivation = Derivation.Zero) : base(uDimension, vDimension, knotsGenerator, derivation)
        {
        }

        protected delegate Vector<double> BasisVector(double t, double t0, double t1);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="uIdx"></param>
        /// <param name="vIdx"></param>
        /// <param name="knots"></param>
        /// <returns></returns>
        protected override ISurface CreateSegment(int uIdx, int vIdx, KnotMatrix knots)
        {
            
            var u0 = knots[uIdx,vIdx].X;
            var u1 = knots[uIdx+1,vIdx].X;
            var v0 = knots[uIdx,vIdx].Y;
            var v1 = knots[uIdx,vIdx+1].Y;
            var meshDensity = Constants.MeshDensity;
            var uKnotsDistance = Math.Abs(u1-u0);           
            var xCount = Math.Ceiling(uKnotsDistance/meshDensity);       
            var yKnotDistance =  Math.Abs(v1 - v0);
            var yCount = Math.Ceiling(yKnotDistance / meshDensity);          
            var verticesCount = (int)((++xCount) * (++yCount));

            var segmentMeshVertices = new VertexPositionNormalColor[verticesCount];
            var basisCalculator = new BicubicBasis(knots,Derivation);//BasisFactory.CreateBasis(Surface.Type);
            
            var phi = basisCalculator.Matrix(uIdx, vIdx);
            var k = 0;
            var x = (float) u0 ;
            for (var i = 0; i < xCount; i++,x += meshDensity)
            {
                x = x < u1 ? x : (float)u1;
                var lambda1 = basisCalculator.Vector(x, u0, u1);
                var basis = phi.LeftMultiply(lambda1);       
                var y = (float) v0;
                for (var j = 0; j < yCount; j++,y += meshDensity)
                {
                    y = y < v1 ? y : (float)v1;
                    var lambda2 = basisCalculator.Vector(y, v0, v1);
                    var zv = basis.PointwiseMultiply(lambda2);
                    var z = (float) zv.Sum();
                    z = MathHelper.Clamp(z, -Constants.MaxSceneZDifference, Constants.MaxSceneZDifference);   
                    segmentMeshVertices[k++] = new VertexPositionNormalColor(new Vector3(x, y, z), DefaultNormal,
                        DefaultColor);
                  
                }
               
            }
           
            return new SimpleSurface(segmentMeshVertices, (int)xCount, (int)yCount);
          
        }
    }
}