using System; using OpenTK; namespace Examples.Shapes { /// winding always assumed CCW (Counter-ClockWise) internal struct TetrahedronFace { private Vector3d APosition, BPosition, CPosition; private Vector3d DPosition, Normal; private Vector2d ATexCoord, BTexCoord, CTexCoord; public TetrahedronFace( ref Vector3d apos, ref Vector2d atc, ref Vector3d bpos, ref Vector2d btc, ref Vector3d cpos, ref Vector2d ctc, ref Vector3d dpos, ref Vector3d normal ) { APosition = apos; ATexCoord = atc; BPosition = bpos; BTexCoord = btc; CPosition = cpos; CTexCoord = ctc; DPosition = dpos; Normal = normal; } /// Expects CCW triangle order as input, emits 4 new CCW triangles. /// 1st output Triangle /// 2nd output Triangle /// 3rd output Triangle /// 4th output Triangle 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 ); } 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 } /// Returns 3 Vertices which form a CCW triangle. public void GetVertices( out VertexT2dN3dV3d first, out VertexT2dN3dV3d second, out VertexT2dN3dV3d third ) { first.TexCoord = this.ATexCoord; first.Normal = this.Normal; first.Position = this.APosition; second.TexCoord = this.BTexCoord; second.Normal = this.Normal; second.Position = this.BPosition; third.TexCoord = this.CTexCoord; third.Normal = this.Normal; third.Position = this.CPosition; } /// Debugging Aid, no real purpose public override string ToString() { return "A= " + this.APosition.ToString() + " TexCoord: " + this.ATexCoord.ToString() + "\n" + "B= " + this.BPosition.ToString() + " TexCoord: " + this.ATexCoord.ToString() + "\n" + "C= " + this.CPosition.ToString() + " TexCoord: " + this.ATexCoord.ToString() + "\n" + "Normal= " + this.Normal.ToString(); } } }