private void SubdivideKoch( double height, ref TetrahedronFace[] input, out TetrahedronFace[] output )
        {
            output = new TetrahedronFace[input.Length * 6];

            int counter = 0;
            for ( int i = 0; i < input.Length; i++ )
            {
                input[i].SubdivideKoch(height, out output[counter + 0], out output[counter + 1], out output[counter + 2], out output[counter + 3], out output[counter + 4], out output[counter + 5] );
                counter += 6; // every source triangle emits 6 new triangles
            }
        }
        /// <summary>Expects CCW triangle order as input, emits 4 new CCW triangles.</summary>
        /// <param name="first">1st output Triangle</param>
        /// <param name="second">2nd output Triangle</param>
        /// <param name="third">3rd output Triangle</param>
        /// <param name="fourth">4th output Triangle</param>
        public void SubdivideSierpinski( out TetrahedronFace first, out TetrahedronFace second, out TetrahedronFace third, out TetrahedronFace fourth )
        {
            Vector3d temp;

            // find the 3 points AB, BC, CA
            Vector3d CenterAB;
            Vector3d.Add( ref this.APosition, ref this.BPosition, out temp );
            Vector3d.Multiply( ref temp, 0.5f, out CenterAB );

            Vector3d CenterBC;
            Vector3d.Add( ref this.BPosition, ref this.CPosition, out temp );
            Vector3d.Multiply( ref temp, 0.5f, out CenterBC );

            Vector3d CenterCA;
            Vector3d.Add( ref this.CPosition, ref this.APosition, out temp );
            Vector3d.Multiply( ref temp, 0.5f, out CenterCA );

            // find the 3 points AD, BD, CD
            Vector3d CenterAD;
            Vector3d.Lerp( ref this.APosition, ref this.DPosition, 0.5, out CenterAD );

            Vector3d CenterBD;
            Vector3d.Lerp( ref this.BPosition, ref this.DPosition, 0.5, out CenterBD );

            Vector3d CenterCD;
            Vector3d.Lerp( ref this.CPosition, ref this.DPosition, 0.5, out CenterCD );

            // emit 4 new CCW triangles
            first = new TetrahedronFace( ref this.APosition, ref this.ATexCoord,
                              ref CenterAB, ref this.BTexCoord,
                              ref CenterCA, ref this.CTexCoord,
                              ref CenterAD,
                              ref this.Normal );

            second = new TetrahedronFace( ref CenterAB, ref this.ATexCoord,
                               ref this.BPosition, ref this.BTexCoord,
                               ref CenterBC, ref this.CTexCoord,
                               ref CenterBD,
                               ref this.Normal );

            third = new TetrahedronFace( ref CenterCA, ref this.ATexCoord,
                              ref CenterBC, ref this.BTexCoord,
                              ref this.CPosition, ref this.CTexCoord,
                              ref CenterCD,
                              ref this.Normal );

            fourth = new TetrahedronFace( ref CenterAD, ref this.ATexCoord,
                               ref CenterBD, ref this.BTexCoord,
                               ref CenterCD, ref this.CTexCoord,
                               ref this.DPosition,
                               ref this.Normal );
        }
        /// <summary>Generates the lowest subdivision mesh, which consists of 4 Triangles.</summary>
        internal static void CreateDefaultTetrahedron( double scale, out TetrahedronFace[] array )
        {
            Vector3d[] Points = new Vector3d[4];
            Points[0] = new Vector3d( 0.0 * scale, 0.0 * scale, 1.0 * scale );
            Points[1] = new Vector3d( -0.816 * scale, 0.471 * scale, -0.333 * scale );
            Points[2] = new Vector3d( 0.816 * scale, 0.471 * scale, -0.333 * scale );
            Points[3] = new Vector3d( 0.0 * scale, -0.943 * scale, -0.333 * scale );

            Vector2d[] TexCoords = new Vector2d[4];
            TexCoords[0] = new Vector2d( 0.0, 0.0 );
            TexCoords[1] = new Vector2d( 1.0, 0.0 );
            TexCoords[2] = new Vector2d( 0.0, 1.0 );
            TexCoords[3] = new Vector2d( 1.0, 1.0 );

            Vector3d Normal;
            array = new TetrahedronFace[4];

            FindNormal( ref Points[0], ref Points[2], ref Points[1], ref Points[3], out Normal );
            array[0] = new TetrahedronFace( ref Points[0], ref TexCoords[2],
                                                   ref Points[2], ref TexCoords[0],
                                                   ref Points[1], ref TexCoords[1],
                                                   ref Points[3],
                                                   ref Normal );

            FindNormal( ref Points[0], ref Points[3], ref Points[2], ref Points[1], out Normal );
            array[1] = new TetrahedronFace( ref Points[0], ref TexCoords[0],
                                                   ref Points[3], ref TexCoords[1],
                                                   ref Points[2], ref TexCoords[2],
                                                   ref Points[1],
                                                   ref Normal );

            FindNormal( ref Points[0], ref Points[1], ref Points[3], ref Points[2], out Normal );
            array[2] = new TetrahedronFace( ref Points[0], ref TexCoords[2],
                                                   ref Points[1], ref TexCoords[1],
                                                   ref Points[3], ref TexCoords[3],
                                                   ref Points[2],
                                                   ref Normal );

            FindNormal( ref Points[1], ref Points[2], ref Points[3], ref Points[0], out Normal );
            array[3] = new TetrahedronFace( ref Points[1], ref TexCoords[3],
                                                   ref Points[2], ref TexCoords[2],
                                                   ref Points[3], ref TexCoords[1],
                                                   ref Points[0],
                                                   ref Normal );
        }
        internal void SubdivideKoch( double height, out TetrahedronFace first, out TetrahedronFace second, out TetrahedronFace third, out TetrahedronFace fourth, out TetrahedronFace fifth, out TetrahedronFace sixth )
        {
            Vector3d CenterAB, CenterBC, CenterCA, CenterD;
            Vector2d TexCoordAB, TexCoordBC, TexCoordCA, TexCoordD;

            Vector3d.Lerp( ref this.APosition, ref this.BPosition, 0.5, out CenterAB );
            Vector3d.Lerp( ref this.BPosition, ref this.CPosition, 0.5, out CenterBC );
            Vector3d.Lerp( ref this.CPosition, ref this.APosition, 0.5, out CenterCA );
            CenterD = CenterAB;
            Vector3d.Add(ref CenterD, ref CenterBC, out CenterD);
            Vector3d.Add(ref CenterD, ref CenterCA, out CenterD);
            CenterD /= 3.0;
            Vector3d E = CenterD + ( this.Normal * 0.5 );
            Vector3d temp = this.Normal;
            temp *= height;
            Vector3d.Add(ref CenterD, ref temp, out CenterD);

            Vector2d.Lerp( ref this.ATexCoord, ref this.BTexCoord, 0.5, out TexCoordAB );
            Vector2d.Lerp( ref this.BTexCoord, ref this.CTexCoord, 0.5, out TexCoordBC );
            Vector2d.Lerp( ref this.CTexCoord, ref this.ATexCoord, 0.5, out TexCoordCA );
            TexCoordD = TexCoordAB;
            Vector2d.Add(ref TexCoordD, ref TexCoordBC, out TexCoordD);
            Vector2d.Add(ref TexCoordD, ref TexCoordCA, out TexCoordD);
            TexCoordD /= 3.0;
            #region 1
            first.APosition = this.APosition;
            first.ATexCoord = this.ATexCoord;

            first.BPosition = CenterAB;
            first.BTexCoord = TexCoordAB;

            first.CPosition = CenterCA;
            first.CTexCoord = TexCoordCA;

            first.Normal = this.Normal;
            temp = ( this.APosition + CenterAB + CenterCA );
            temp /= 3.0;
            temp += this.Normal * -1.0;
            first.DPosition = temp;
            #endregion 1
            #region 2
            second.APosition = CenterAB;
            second.ATexCoord = TexCoordAB;

            second.BPosition = this.BPosition;
            second.BTexCoord = this.BTexCoord;

            second.CPosition = CenterBC;
            second.CTexCoord = TexCoordBC;

            second.Normal = this.Normal;

            temp = CenterAB + this.BPosition + CenterBC;
            temp /=  3.0;
            temp += this.Normal * -1.0;
            second.DPosition = temp;

            #endregion 2
            #region 3
            third.APosition = CenterBC;
            third.ATexCoord = TexCoordBC;

            third.BPosition = this.CPosition;
            third.BTexCoord = this.CTexCoord;

            third.CPosition = CenterCA;
            third.CTexCoord = TexCoordCA;

            third.Normal = this.Normal;
            temp = CenterBC + this.CPosition + CenterCA;
            temp /= 3.0;
            temp += this.Normal * -1.0;
            third.DPosition = temp;
            #endregion 3
            #region 4
            fourth.APosition = CenterAB;
            fourth.ATexCoord = TexCoordAB;

            fourth.BPosition = CenterD;
            fourth.BTexCoord = TexCoordD;

            fourth.CPosition = CenterCA;
            fourth.CTexCoord = TexCoordCA;

            SierpinskiTetrahedron.FindNormal( ref CenterAB, ref CenterD, ref CenterCA, out fourth.Normal );
            fourth.DPosition = E;
            #endregion 4
            #region 5
            fifth.APosition = CenterAB;
            fifth.ATexCoord = TexCoordAB;

            fifth.BPosition = CenterBC;
            fifth.BTexCoord = TexCoordBC;

            fifth.CPosition = CenterD;
            fifth.CTexCoord = TexCoordD;

            SierpinskiTetrahedron.FindNormal( ref CenterAB, ref CenterBC, ref CenterD, out fifth.Normal );
            fifth.DPosition = E;

            #endregion 5
            #region 6
            sixth.APosition = CenterBC;
            sixth.ATexCoord = TexCoordBC;

            sixth.BPosition = CenterCA;
            sixth.BTexCoord = TexCoordCA;

            sixth.CPosition = CenterD;
            sixth.CTexCoord = TexCoordD;

            SierpinskiTetrahedron.FindNormal( ref CenterBC, ref CenterCA, ref CenterD, out sixth.Normal );
            sixth.DPosition = E;
            #endregion 6
        }
        /// <summary>Subdivides each triangle into 4 new ones.</summary>
        private void SubdivideTetrahedron( ref TetrahedronFace[] source, out TetrahedronFace[] output )
        {
            output = new TetrahedronFace[source.Length * 4];

            int counter = 0;
            for ( int i = 0; i < source.Length; i++ )
            {
                source[i].SubdivideSierpinski( out output[counter + 0], out output[counter + 1], out output[counter + 2], out output[counter + 3] );
                counter += 4; // every source triangle emits 4 new triangles
            }
        }
 internal static void GetVertexArray( ref TetrahedronFace[] input, out VertexT2dN3dV3d[] output )
 {
     output = new VertexT2dN3dV3d[input.Length * 3];
     int counter = 0;
     for ( int i = 0; i < input.Length; i++ )
     {
         input[i].GetVertices( out output[counter + 0], out output[counter + 1], out output[counter + 2] );
         counter += 3;
     }
 }