/// <summary> /// Attempts to find the centroid or barycenter point of a mesh /// by using the average of the center of all triangles divided /// by their mass for an accurate representation. /// </summary> /// <param name="mesh">The mesh to find the barycenter point.</param> /// <returns>A <see cref="Vector3"/> containing the center.</returns> private static Vector3 FindBaryCenter(Shapes.IMesh mesh) { OpenTK.Vector3d totalSum = new OpenTK.Vector3d(); double totalArea = 0; foreach (Vector3 face in mesh.Faces) { Vector3[] vertices = mesh.GetVerticesFromFace(face); double area = mesh.GetTriArea(vertices); if (area == 0) { continue; } totalSum += OpenTK.Vector3d.Multiply( (OpenTK.Vector3d)CenterOfTriangle(vertices), area); totalArea += area; } return((Vector3)OpenTK.Vector3d.Divide(totalSum, totalArea)); }
private V3[] getExpDirections() { var v1 = new V3(1, 0, 0); if (radioButton1stY.Checked) { v1 = new V3(0, 1, 0); } else if (radioButton1stZ.Checked) { v1 = new V3(0, 0, 1); } var v2 = new V3(1, 0, 0); if (radioButton2ndY.Checked) { v2 = new V3(0, 1, 0); } else if (radioButton2ndZ.Checked) { v2 = new V3(0, 0, 1); } var v3 = new V3(1, 0, 0); if (radioButton3rdY.Checked) { v3 = new V3(0, 1, 0); } else if (radioButton3rdZ.Checked) { v3 = new V3(0, 0, 1); } return(new[] { v1, v2, v3 }); }
public TorusKnot(int pathsteps, int shapevertices, double radius, int p, int q, int TexCount) : base( ) { Trace.Assert(pathsteps >= MINPathSteps, "A Path must have at least " + MINPathSteps + " Steps to form a volume."); Trace.Assert(shapevertices >= MINShapeVertices, "A Shape must contain at least " + MINShapeVertices + " Vertices to be considered valid and create a volume."); Trace.Assert(TexCount > 1, "at least 1 Texture set is required."); PrimitiveMode = OpenTK.Graphics.OpenGL.BeginMode.TriangleStrip; Vector3d[] PathPositions = new Vector3d[pathsteps]; #region Find the center Points for each step on the path for (int i = 0; i < pathsteps; i++) { double Angle = (i / (double)pathsteps) * TwoPi; double AngleTimesP = Angle * p; double AngleTimesQ = Angle * q; double r = (0.5 * (2.0 + System.Math.Sin(AngleTimesQ))); PathPositions[i] = new Vector3d((r * System.Math.Cos(AngleTimesP)), (r * System.Math.Cos(AngleTimesQ)), (r * System.Math.Sin(AngleTimesP))); } #endregion Find the center Points for each step on the path #region Find the Torus length Vector3d result; double[] Lengths = new double[pathsteps]; Vector3d.Subtract(ref PathPositions[pathsteps - 1], ref PathPositions[0], out result); Lengths[0] = result.Length; double TotalLength = result.Length; for (int i = 1; i < pathsteps; i++) // skipping { Vector3d.Subtract(ref PathPositions[i - 1], ref PathPositions[i], out result); Lengths[i] = result.Length; TotalLength += result.Length; } Trace.WriteLine("the TorusKnot's length is: " + TotalLength + " "); #endregion Find the Torus length VertexArray = new VertexT2dN3dV3d[pathsteps * shapevertices]; #region Loft a circle Shape along the path double TwoPiThroughVert = TwoPi / shapevertices; // precalc for reuse for (uint i = 0; i < pathsteps; i++) { Vector3d last, next, normal, tangent; if (i == pathsteps - 1) { next = PathPositions[0]; } else { next = PathPositions[i + 1]; } if (i == 0) { last = PathPositions[pathsteps - 1]; } else { last = PathPositions[i - 1]; } Vector3d.Subtract(ref next, ref last, out tangent); // Guesstimate tangent tangent.Normalize(); Vector3d.Add(ref next, ref last, out normal); // Approximate N normal.Normalize(); Vector3d.Multiply(ref normal, radius, out normal); // scale the shape to desired radius for (uint j = 0; j < shapevertices; j++) { uint index = i * (uint)shapevertices + j; // Create a point on the plane and rotate it OpenTK.Matrix4d RotationMatrix = OpenTK.Matrix4d.Rotate(tangent, -(j * TwoPiThroughVert)); OpenTK.Vector3d point = OpenTK.Vector3d.TransformVector(normal, RotationMatrix); OpenTK.Vector3d.Add(ref PathPositions[i], ref point, out VertexArray[index].Position); // Since the used shape is a circle, the Vertex normal's heading is easy to find OpenTK.Vector3d.Subtract(ref VertexArray[index].Position, ref PathPositions[i], out VertexArray[index].Normal); VertexArray[index].Normal.Normalize(); // just generate some semi-useful UVs to fill blanks VertexArray[index].TexCoord = new OpenTK.Vector2d((double)(i / TotalLength / TexCount), j / (shapevertices - 1.0)); } } #endregion Loft a circle Shape along the path PathPositions = null; // not needed anymore uint currentindex = 0; #region Build a Triangle strip from the Vertices IndexArray = new uint[pathsteps * (shapevertices * 2 + 2)]; // 2 triangles per vertex, +2 due to added degenerate triangles for (uint i = 0; i < pathsteps; i++) { uint RowCurrent = i * (uint)shapevertices; uint RowBelow; if (i == pathsteps - 1) { RowBelow = 0; // for the last row, the first row is the following } else { RowBelow = (i + 1) * (uint)shapevertices; } // new ring begins here for (uint j = 0; j < shapevertices; j++) { IndexArray[currentindex++] = RowCurrent + j; IndexArray[currentindex++] = RowBelow + j; } // ring ends here, repeat first 2 vertices to insert 2 degenerate triangles to reach following ring IndexArray[currentindex++] = RowCurrent; IndexArray[currentindex++] = RowBelow; } #endregion Build a Triangle strip from the Vertices }
public VertexT2dN3dV3d(OpenTK.Vector2d texcoord, Vector3d normal, Vector3d position) { TexCoord = texcoord; Normal = normal; Position = position; }
/// <summary> /// ゴニオオブジェクトを生成 /// </summary> /// <param name="gl"></param> /// <param name="dir"></param> /// <param name="angle"></param> private void setGonio(GLControlAlpha gl, V3[] dir, double[] angle) { gl.DeleteAllObjects(); var r = 0.05; var obj = new List <GLObject>(); var rot = dir.Select((d, i) => Matrix3D.Rot(d, angle[i])).ToArray(); //1st var mat = new Material(new C4(0.8f, 0.8f, 0f, 1f)); obj.Add(new Cone(dir[0] * 2.1, dir[0] * -0.2, r * 2, mat, DrawingMode.Surfaces));//矢 obj.Add(new TextObject(gl.Name.Contains("ReciPro") ? "Φ" : "1st", 12, dir[0] * 2.1 + dir[0].Normalized() * 0.01, 0.05, true, mat)); if (!checkBoxEnable2nd.Checked) //2ndが存在しない時 { obj.Add(new Cylinder(dir[0] * -1.9, dir[0] * 3.8, r, mat, DrawingMode.Surfaces)); //軸 obj.Add(new Torus(new V3(0, 0, 0), rot[0] * V3.Cross(dir[0], new V3(dir[0].Z, dir[0].X, dir[0].Y)), 1.6, r * 1.5, mat, DrawingMode.Surfaces)); //トーラス } else //2ndが存在する時 { obj.Add(new Cylinder(dir[0] * -1.9, dir[0] * 0.3, r, mat, DrawingMode.Surfaces)); //軸 obj.Add(new Cylinder(dir[0] * 1.6, dir[0] * 0.3, r, mat, DrawingMode.Surfaces)); //軸 //1stトーラスの法線は、1st軸と2nd軸が直交する方向 obj.Add(new Torus(new V3(0, 0, 0), rot[0] * V3.Cross(dir[0], dir[1]), 1.6, r * 1.5, mat, DrawingMode.Surfaces)); //トーラス //以下2nd var rot01 = rot[0] * rot[1]; mat = new Material(new C4(0f, 0.8f, 0.8f, 1f)); var n = rot[0] * dir[1]; obj.Add(new Cone(n * 2.0, -n * 0.2, r * 2, mat, DrawingMode.Surfaces));//矢 obj.Add(new TextObject(gl.Name.Contains("ReciPro") ? "Θ" : "2nd", 12, n * 2.0 + n.Normalized() * 0.01, 0.05, true, mat)); if (!checkBoxEnable3rd.Checked) { obj.Add(new Cylinder(n * 1.9, -n * 3.8, r, mat, DrawingMode.Surfaces)); //軸 obj.Add(new Torus(new V3(0, 0, 0), rot01 * V3.Cross(dir[1], new V3(dir[1].Z, dir[1].X, dir[1].Y)), 1.1, r * 1.5, mat, DrawingMode.Surfaces)); //トーラス } else { obj.Add(new Cylinder(n * 1.9, -n * 0.8, r, mat, DrawingMode.Surfaces)); //軸 obj.Add(new Cylinder(-n * 1.9, n * 0.8, r, mat, DrawingMode.Surfaces)); //軸 //2ndトーラスの法線は、2nd軸と3rd軸が直交する方向 obj.Add(new Torus(new V3(0, 0, 0), rot01 * V3.Cross(dir[1], dir[2]), 1.1, r * 1.5, mat, DrawingMode.Surfaces)); //トーラス //以下、3rd mat = new Material(new C4(0.8f, 0f, 0.8f, 1f)); var rot012 = rot[0] * rot[1] * rot[2]; n = rot[0] * rot[1] * dir[2]; obj.Add(new Cylinder(n * 1.3, -n * 2.6, r, mat, DrawingMode.Surfaces)); //軸 obj.Add(new Cone(n * 1.45, -n * 0.2, r * 2, mat, DrawingMode.Surfaces)); //矢 obj.Add(new TextObject(gl.Name.Contains("ReciPro") ? "Ψ" : "3rd", 12, n * 1.45 + n.Normalized() * 0.01, 0.05, true, mat)); if (dir[2].Z == 0) { obj.Add(new Torus(new V3(0, 0, 0), rot012 * new V3(0, 0, 1), 0.6, r * 1.5, mat, DrawingMode.Surfaces));//トーラス } else { obj.Add(new Torus(new V3(0, 0, 0), rot012 * new V3(0, 1, 0), 0.6, r * 1.5, mat, DrawingMode.Surfaces));//トーラス } } } //中央の球 obj.AddRange(createObject(gl, dir, angle)); gl.AddObjects(obj); gl.Refresh(); }