using System; using System.Collections.Generic; using OpenTK; namespace Examples.Shapes { public sealed partial class MengerSponge { private struct MengerCube { private Vector3d Center; private double SideLength; private eSides[] VisibleSides; private eSides[] VisibilityToInherit; public void GetArraySizes( out uint vertexcount, out uint indexcount ) { vertexcount = (uint)VisibleSides.Length * 8 + 6 * 12; indexcount = (uint)VisibleSides.Length * 8 * 3 + 6 * 8 * 3; } public MengerCube( Vector3d center, double sidelength, eSides[] visibleSides, eSides[] parentsVisibility ) { Center = center; SideLength = sidelength; /* List Sides = new List(); foreach ( eSides s in visibleSides ) { bool isVisible = false; foreach ( eSides p in parentsVisibility ) { if ( (int)p == (int)s ) { isVisible = true; break; } } if ( isVisible ) { Sides.Add( s ); } } VisibleSides = Sides.ToArray();*/ VisibleSides = visibleSides; VisibilityToInherit = visibleSides; } public void Subdivide( out MengerCube[] cubes ) { cubes = new MengerCube[20]; // 8 + 4 + 8 double NewLength = this.SideLength / 3.0; double six = this.SideLength * 2.0 / 3.0; // we got 3x3x3 cubes. All center cubes who touch the XYZ-Axis are removed. // front cubes[0] = new MengerCube( new Vector3d( Center.X - six, Center.Y + six, Center.Z + six ), NewLength, new eSides[] { eSides.Front, eSides.Left, eSides.Top }, this.VisibilityToInherit ); cubes[1] = new MengerCube( new Vector3d( Center.X + 0.0, Center.Y + six, Center.Z + six ), NewLength, new eSides[] { eSides.Front, eSides.Bottom, eSides.Back, eSides.Top }, this.VisibilityToInherit ); cubes[2] = new MengerCube( new Vector3d( Center.X + six, Center.Y + six, Center.Z + six ), NewLength, new eSides[] { eSides.Front, eSides.Right, eSides.Top }, this.VisibilityToInherit ); cubes[3] = new MengerCube( new Vector3d( Center.X - six, Center.Y + 0.0, Center.Z + six ), NewLength, new eSides[] { eSides.Front, eSides.Right, eSides.Back, eSides.Left }, this.VisibilityToInherit ); cubes[4] = new MengerCube( new Vector3d( Center.X + six, Center.Y + 0.0, Center.Z + six ), NewLength, new eSides[] { eSides.Front, eSides.Right, eSides.Back, eSides.Left }, this.VisibilityToInherit ); cubes[5] = new MengerCube( new Vector3d( Center.X - six, Center.Y - six, Center.Z + six ), NewLength, new eSides[] { eSides.Front, eSides.Left, eSides.Bottom } , this.VisibilityToInherit ); cubes[6] = new MengerCube( new Vector3d( Center.X + 0.0, Center.Y - six, Center.Z + six ), NewLength, new eSides[] { eSides.Front, eSides.Top, eSides.Back, eSides.Bottom }, this.VisibilityToInherit ); cubes[7] = new MengerCube( new Vector3d( Center.X + six, Center.Y - six, Center.Z + six ), NewLength, new eSides[] { eSides.Front, eSides.Right, eSides.Bottom }, this.VisibilityToInherit ); // center cubes[8] = new MengerCube( new Vector3d( Center.X - six, Center.Y + six, Center.Z + 0.0 ), NewLength, new eSides[] { eSides.Top, eSides.Right, eSides.Bottom, eSides.Left }, this.VisibilityToInherit ); cubes[9] = new MengerCube( new Vector3d( Center.X + six, Center.Y + six, Center.Z + 0.0 ), NewLength, new eSides[] { eSides.Top, eSides.Right, eSides.Bottom, eSides.Left }, this.VisibilityToInherit ); cubes[10] = new MengerCube( new Vector3d( Center.X - six, Center.Y - six, Center.Z + 0.0 ), NewLength, new eSides[] { eSides.Top, eSides.Right, eSides.Bottom, eSides.Left }, this.VisibilityToInherit ); cubes[11] = new MengerCube( new Vector3d( Center.X + six, Center.Y - six, Center.Z + 0.0 ), NewLength, new eSides[] { eSides.Top, eSides.Right, eSides.Bottom, eSides.Left }, this.VisibilityToInherit ); // back cubes[12] = new MengerCube( new Vector3d( Center.X - six, Center.Y + six, Center.Z - six ), NewLength, new eSides[] { eSides.Top, eSides.Back, eSides.Left }, this.VisibilityToInherit ); cubes[13] = new MengerCube( new Vector3d( Center.X + 0.0, Center.Y + six, Center.Z - six ), NewLength, new eSides[] { eSides.Top, eSides.Back, eSides.Bottom, eSides.Front }, this.VisibilityToInherit ); cubes[14] = new MengerCube( new Vector3d( Center.X + six, Center.Y + six, Center.Z - six ), NewLength, new eSides[] { eSides.Top, eSides.Back, eSides.Right }, this.VisibilityToInherit ); cubes[15] = new MengerCube( new Vector3d( Center.X - six, Center.Y + 0.0, Center.Z - six ), NewLength, new eSides[] { eSides.Front, eSides.Right, eSides.Back, eSides.Left } , this.VisibilityToInherit ); cubes[16] = new MengerCube( new Vector3d( Center.X + six, Center.Y + 0.0, Center.Z - six ), NewLength, new eSides[] { eSides.Front, eSides.Right, eSides.Back, eSides.Left } , this.VisibilityToInherit ); cubes[17] = new MengerCube( new Vector3d( Center.X - six, Center.Y - six, Center.Z - six ), NewLength, new eSides[] { eSides.Back, eSides.Bottom, eSides.Left } , this.VisibilityToInherit ); cubes[18] = new MengerCube( new Vector3d( Center.X + 0.0, Center.Y - six, Center.Z - six ), NewLength, new eSides[] { eSides.Top, eSides.Back, eSides.Bottom, eSides.Front }, this.VisibilityToInherit ); cubes[19] = new MengerCube( new Vector3d( Center.X + six, Center.Y - six, Center.Z - six ), NewLength, new eSides[] { eSides.Back, eSides.Bottom, eSides.Right }, this.VisibilityToInherit ); } public enum eSides: byte { Front, Back, Right, Left, Top, Bottom } internal static readonly eSides[] AllSides = new eSides[] { eSides.Front, eSides.Back, eSides.Right, eSides.Left, eSides.Top, eSides.Bottom }; public void GetVboAndIbo( ref List chunks ) { foreach ( eSides s in AllSides ) { DrawSide( s, ref chunks ); } } private void DrawSide( eSides side, ref List chunks ) { #region Setup constants for current direction double _Zero = 0.0; // 0/3 double _Three = 0.3333333333333; // 1/3 double _Six = 0.66666666666666; // 2/3 double _One = 1.0; // 3/3 double ThirdLength = SideLength / 3f; Vector3d C0 = Center + new Vector3d( -SideLength, -SideLength, +SideLength ); Vector3d C1 = Center + new Vector3d( +SideLength, -SideLength, +SideLength ); Vector3d C2 = Center + new Vector3d( +SideLength, +SideLength, +SideLength ); Vector3d C3 = Center + new Vector3d( -SideLength, +SideLength, +SideLength ); Vector3d C4 = Center + new Vector3d( -SideLength, -SideLength, -SideLength ); Vector3d C5 = Center + new Vector3d( +SideLength, -SideLength, -SideLength ); Vector3d C6 = Center + new Vector3d( +SideLength, +SideLength, -SideLength ); Vector3d C7 = Center + new Vector3d( -SideLength, +SideLength, -SideLength ); Vector3d P0, P1, P2, P3, P4, P5, P6, P7; switch ( side ) { case eSides.Front: P0 = C0; P1 = C1; P2 = C2; P3 = C3; P4 = C4; P5 = C5; P6 = C6; P7 = C7; break; case eSides.Back: P0 = C5; P1 = C4; P2 = C7; P3 = C6; P4 = C1; P5 = C0; P6 = C3; P7 = C2; break; case eSides.Right: P0 = C1; P1 = C5; P2 = C6; P3 = C2; P4 = C0; P5 = C4; P6 = C7; P7 = C3; break; case eSides.Left: P0 = C4; P1 = C0; P2 = C3; P3 = C7; P4 = C5; P5 = C1; P6 = C2; P7 = C6; break; case eSides.Top: P0 = C3; P1 = C2; P2 = C6; P3 = C7; P4 = C0; P5 = C1; P6 = C5; P7 = C4; break; case eSides.Bottom: P0 = C1; P1 = C0; P2 = C4; P3 = C5; P4 = C2; P5 = C3; P6 = C7; P7 = C6; break; default: throw new NotImplementedException( "Unknown enum value: " + side ); } #endregion Setup constants for current direction #region Set Normal Vector3d FaceNormal; switch ( side ) { case eSides.Front: FaceNormal = Vector3d.UnitZ; break; case eSides.Back: FaceNormal = -Vector3d.UnitZ; break; case eSides.Right: FaceNormal = Vector3d.UnitX; break; case eSides.Left: FaceNormal = -Vector3d.UnitX; break; case eSides.Top: FaceNormal = Vector3d.UnitY; break; case eSides.Bottom: FaceNormal = -Vector3d.UnitY; break; default: throw new NotImplementedException( "Unknown enum value: " + side ); } #endregion Set Normal bool FaceIsVisible = false; foreach ( eSides s in VisibleSides ) { if ( s == side ) { FaceIsVisible = true; break; } } if ( FaceIsVisible ) { #region Define Layer1 Vertices Chunk Layer1 = new Chunk( 8, 8 * 3 ); Layer1.Vertices[0].TexCoord = new Vector2d( _Zero, _Zero ); Layer1.Vertices[0].Normal = FaceNormal; Layer1.Vertices[0].Position = P0; Layer1.Vertices[1].TexCoord = new Vector2d( _One, _Zero ); Layer1.Vertices[1].Normal = FaceNormal; Layer1.Vertices[1].Position = P1; Layer1.Vertices[2].TexCoord = new Vector2d( _One, _One ); Layer1.Vertices[2].Normal = FaceNormal; Layer1.Vertices[2].Position = P2; Layer1.Vertices[3].TexCoord = new Vector2d( _Zero, _One ); Layer1.Vertices[3].Normal = FaceNormal; Layer1.Vertices[3].Position = P3; Layer1.Vertices[4].TexCoord = new Vector2d( _Three, _Three ); Layer1.Vertices[4].Normal = FaceNormal; Vector3d.Lerp( ref P0, ref P2, _Three, out Layer1.Vertices[4].Position ); Layer1.Vertices[5].TexCoord = new Vector2d( _Six, _Three ); Layer1.Vertices[5].Normal = FaceNormal; Vector3d.Lerp( ref P1, ref P3, _Three, out Layer1.Vertices[5].Position ); Layer1.Vertices[6].TexCoord = new Vector2d( _Six, _Six ); Layer1.Vertices[6].Normal = FaceNormal; Vector3d.Lerp( ref P0, ref P2, _Six, out Layer1.Vertices[6].Position ); Layer1.Vertices[7].TexCoord = new Vector2d( _Three, _Six ); Layer1.Vertices[7].Normal = FaceNormal; Vector3d.Lerp( ref P1, ref P3, _Six, out Layer1.Vertices[7].Position ); #endregion Define Layer1 Vertices #region Define Layer1 Indices Layer1.Indices[0] = 0; Layer1.Indices[1] = 5; Layer1.Indices[2] = 4; Layer1.Indices[3] = 0; Layer1.Indices[4] = 1; Layer1.Indices[5] = 5; Layer1.Indices[6] = 5; Layer1.Indices[7] = 1; Layer1.Indices[8] = 2; Layer1.Indices[9] = 6; Layer1.Indices[10] = 5; Layer1.Indices[11] = 2; Layer1.Indices[12] = 7; Layer1.Indices[13] = 6; Layer1.Indices[14] = 2; Layer1.Indices[15] = 3; Layer1.Indices[16] = 7; Layer1.Indices[17] = 2; Layer1.Indices[18] = 0; Layer1.Indices[19] = 7; Layer1.Indices[20] = 3; Layer1.Indices[21] = 0; Layer1.Indices[22] = 4; Layer1.Indices[23] = 7; chunks.Add( Layer1 ); #endregion Define Layer1 Indices } #region Define Layer2 Vertices Chunk Layer2 = new Chunk( 12, 8 * 3 ); Vector3d T0, T1, T2, T3; Vector3d.Lerp( ref P0, ref P4, _Six, out T0 ); Vector3d.Lerp( ref P1, ref P5, _Six, out T1 ); Vector3d.Lerp( ref P2, ref P6, _Six, out T2 ); Vector3d.Lerp( ref P3, ref P7, _Six, out T3 ); Layer2.Vertices[0].TexCoord = new Vector2d( _Three, _Zero ); Layer2.Vertices[0].Normal = FaceNormal; Vector3d.Lerp( ref T0, ref T1, _Three, out Layer2.Vertices[0].Position ); Layer2.Vertices[1].TexCoord = new Vector2d( _Six, _Zero ); Layer2.Vertices[1].Normal = FaceNormal; Vector3d.Lerp( ref T0, ref T1, _Six, out Layer2.Vertices[1].Position ); Layer2.Vertices[3].TexCoord = new Vector2d( _One, _Three ); Layer2.Vertices[3].Normal = FaceNormal; Vector3d.Lerp( ref T1, ref T2, _Three, out Layer2.Vertices[3].Position ); Layer2.Vertices[4].TexCoord = new Vector2d( _One, _Six ); Layer2.Vertices[4].Normal = FaceNormal; Vector3d.Lerp( ref T1, ref T2, _Six, out Layer2.Vertices[4].Position ); Layer2.Vertices[6].TexCoord = new Vector2d( _Six, _One ); Layer2.Vertices[6].Normal = FaceNormal; Vector3d.Lerp( ref T2, ref T3, _Three, out Layer2.Vertices[6].Position ); Layer2.Vertices[7].TexCoord = new Vector2d( _Three, _One ); Layer2.Vertices[7].Normal = FaceNormal; Vector3d.Lerp( ref T2, ref T3, _Six, out Layer2.Vertices[7].Position ); Layer2.Vertices[9].TexCoord = new Vector2d( _Zero, _Six ); Layer2.Vertices[9].Normal = FaceNormal; Vector3d.Lerp( ref T3, ref T0, _Three, out Layer2.Vertices[9].Position ); Layer2.Vertices[10].TexCoord = new Vector2d( _Zero, _Three ); Layer2.Vertices[10].Normal = FaceNormal; Vector3d.Lerp( ref T3, ref T0, _Six, out Layer2.Vertices[10].Position ); Layer2.Vertices[2].TexCoord = new Vector2d( _Six, _Three ); Layer2.Vertices[2].Normal = FaceNormal; Vector3d.Lerp( ref Layer2.Vertices[1].Position, ref Layer2.Vertices[6].Position, _Three, out Layer2.Vertices[2].Position ); Layer2.Vertices[5].TexCoord = new Vector2d( _Six, _Six ); Layer2.Vertices[5].Normal = FaceNormal; Vector3d.Lerp( ref Layer2.Vertices[1].Position, ref Layer2.Vertices[6].Position, _Six, out Layer2.Vertices[5].Position ); Layer2.Vertices[8].TexCoord = new Vector2d( _Three, _Six ); Layer2.Vertices[8].Normal = FaceNormal; Vector3d.Lerp( ref Layer2.Vertices[7].Position, ref Layer2.Vertices[0].Position, _Three, out Layer2.Vertices[8].Position ); Layer2.Vertices[11].TexCoord = new Vector2d( _Three, _Three ); Layer2.Vertices[11].Normal = FaceNormal; Vector3d.Lerp( ref Layer2.Vertices[7].Position, ref Layer2.Vertices[0].Position, _Six, out Layer2.Vertices[11].Position ); #endregion Define Layer2 Vertices #region Define Layer2 Indices Layer2.Indices[0] = 0; Layer2.Indices[1] = 2; Layer2.Indices[2] = 11; Layer2.Indices[3] = 0; Layer2.Indices[4] = 1; Layer2.Indices[5] = 2; Layer2.Indices[6] = 2; Layer2.Indices[7] = 3; Layer2.Indices[8] = 4; Layer2.Indices[9] = 2; Layer2.Indices[10] = 4; Layer2.Indices[11] = 5; Layer2.Indices[12] = 5; Layer2.Indices[13] = 6; Layer2.Indices[14] = 8; Layer2.Indices[15] = 8; Layer2.Indices[16] = 6; Layer2.Indices[17] = 7; Layer2.Indices[18] = 11; Layer2.Indices[19] = 8; Layer2.Indices[20] = 10; Layer2.Indices[21] = 10; Layer2.Indices[22] = 8; Layer2.Indices[23] = 9; chunks.Add( Layer2 ); #endregion Define Layer2 Indices } } } }