Blame |
Last modification |
View Log
| RSS feed
using System;
using System.Diagnostics;
using OpenTK;
namespace Examples
.Shapes
{
public sealed partial class SierpinskiTetrahedron
: DrawableShape
{
public enum eSubdivisions
{
/// <summary>Creates a Sierpinski Tetrahedron using 4 triangles.</summary>
Zero
= 0,
/// <summary>Creates a Sierpinski Tetrahedron using 16 triangles.</summary>
One
= 1,
/// <summary>Creates a Sierpinski Tetrahedron using 64 triangles.</summary>
Two
= 2,
/// <summary>Creates a Sierpinski Tetrahedron using 256 triangles.</summary>
Three
= 3,
/// <summary>Creates a Sierpinski Tetrahedron using 1024 triangles.</summary>
Four
= 4,
/// <summary>Creates a Sierpinski Tetrahedron using 4096 triangles.</summary>
Five
= 5,
/// <summary>Creates a Sierpinski Tetrahedron using 16384 triangles.</summary>
Six
= 6,
/// <summary>Creates a Sierpinski Tetrahedron using 65536 triangles.</summary>
Seven
= 7,
/// <summary>Creates a Sierpinski Tetrahedron using 262144 triangles.</summary>
Eight
= 8,
/// <summary>Creates a Sierpinski Tetrahedron using 1048576 triangles.</summary>
Nine
= 9,
}
/// <summary>Creates a Sierpinski Tetrahedron which is centered at (0,0,0) and fits into a sphere of radius 1f, or a diameter of 2f</summary>
/// <param name="scale">Default: 1f.</param>
/// <param name="subdivs">The number of subdivisions of the Tetrahedron.</param>
/// <param name="useDL"></param>
public SierpinskiTetrahedron
( double scale, eSubdivisions subdivs,
bool useDL
)
: base( useDL
)
{
TetrahedronFace
[] Triangles
;
switch ( subdivs
)
{
case eSubdivisions
.Zero:
CreateDefaultTetrahedron
( scale,
out Triangles
);
break;
case eSubdivisions
.One:
case eSubdivisions
.Two:
case eSubdivisions
.Three:
case eSubdivisions
.Four:
case eSubdivisions
.Five:
case eSubdivisions
.Six:
case eSubdivisions
.Seven:
case eSubdivisions
.Eight:
case eSubdivisions
.Nine:
CreateDefaultTetrahedron
( scale,
out Triangles
);
for ( int i
= 0; i
< (int)subdivs
; i
++ )
{
TetrahedronFace
[] temp
;
SubdivideTetrahedron
( ref Triangles,
out temp
);
Triangles
= temp
;
}
break;
default: throw new ArgumentOutOfRangeException
( "Subdivisions other than contained in the enum cause overflows and are not allowed." );
}
PrimitiveMode
= OpenTK
.Graphics.OpenGL.BeginMode.Triangles;
SierpinskiTetrahedron
.GetVertexArray( ref Triangles,
out VertexArray
);
IndexArray
= null;
}
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;
}
}
/// <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
);
}
/// <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
}
}
/// <summary>A, B and C are the triangle whos normal is to be determined. D is the 4th Point in the Tetraeder which does not belong to the triangle.</summary>
internal static void FindNormal
( ref Vector3d A,
ref Vector3d B,
ref Vector3d C,
ref Vector3d D,
out Vector3d result
)
{
Vector3d temp1, temp2, temp3
;
Vector3d
.Subtract( ref A,
ref D,
out temp1
);
Vector3d
.Subtract( ref B,
ref D,
out temp2
);
Vector3d
.Subtract( ref C,
ref D,
out temp3
);
Vector3d
.Add( ref temp1,
ref temp2,
out result
);
Vector3d
.Add(ref result,
ref temp3,
out result
);
result
.Normalize();
}
internal static void FindNormal
( ref Vector3d A,
ref Vector3d B,
ref Vector3d C,
out Vector3d result
)
{
Vector3d temp1, temp2
;
Vector3d
.Subtract( ref A,
ref B,
out temp1
);
temp1
.Normalize();
Vector3d
.Subtract(ref C,
ref B,
out temp2
);
temp2
.Normalize();
Vector3d
.Cross( ref temp1,
ref temp2,
out result
);
result
*= -1.0;
result
.Normalize();
}
}
}