private static Mesh CreateDodecahedron(double r) { var vertices = new MyMatrix <double>(new double[, ] { { 0.469, 0.469, 0.469, 1 }, { 0.290, 0.000, 0.759, 1 }, { -0.759, -0.290, 0.000, 1 }, { 0.759, 0.290, 0.000, 1 }, { -0.469, 0.469, -0.469, 1 }, { 0.000, -0.759, -0.290, 1 }, { -0.759, 0.290, 0.000, 1 }, { 0.469, -0.469, 0.469, 1 }, { -0.469, 0.469, 0.469, 1 }, { -0.469, -0.469, 0.469, 1 }, { 0.469, -0.469, -0.469, 1 }, { 0.290, 0.000, -0.759, 1 }, { -0.469, -0.469, -0.469, 1 }, { 0.000, -0.759, 0.290, 1 }, { 0.000, 0.759, -0.290, 1 }, { -0.290, 0.000, 0.759, 1 }, { 0.759, -0.290, 0.000, 1 }, { -0.290, 0.000, -0.759, 1 }, { 0.469, 0.469, -0.469, 1 }, { 0.000, 0.759, 0.290, 1 } }); var incident = MyMatrix <double> .Incident(4, r); vertices = vertices * incident; for (var i = 0; i < vertices.Height; ++i) { vertices[i, 3] = 1; } var faces = new MyMatrix <int>(new int[, ] { { 9, 13, 7, 1, 15 }, { 6, 4, 14, 19, 8 }, { 12, 5, 13, 9, 2 }, { 6, 2, 12, 17, 4 }, { 16, 10, 11, 18, 3 }, { 19, 8, 15, 1, 0 }, { 16, 7, 1, 0, 3 }, { 5, 12, 17, 11, 10 }, { 18, 14, 4, 17, 11 }, { 16, 10, 5, 13, 7 }, { 2, 6, 8, 15, 9 }, { 19, 0, 3, 18, 14 } }); return(new Mesh(faces, vertices)); }
private MyMatrix <int> CalculateScreenCoordinates(MyMatrix <double> projectedVertices) { var result = new MyMatrix <int>(projectedVertices.Height, 2); int halfWidth = m_screenWidth / 2; int halfHeight = m_screenHeight / 2; for (var i = 0; i < result.Height; ++i) { result[i, 0] = (int)(halfWidth * projectedVertices[i, 0] + halfWidth); result[i, 1] = (int)(-halfHeight * projectedVertices[i, 1] + halfHeight); } return(result); }
private static Mesh CreateGrarlic(double r) { var horizontalSegments = 20; var verticalSegments = 16; var vertices = new MyMatrix <double>(horizontalSegments * (verticalSegments + 1), 4); for (var i = 0; i <= verticalSegments; ++i) { var theta = -Math.PI / 2 + Math.PI / verticalSegments * i; var y = r * Math.Sin(theta); if (theta > 0) { var t = theta / (Math.PI / 2.0); t = Math.Pow(t, 5); t = r * t; } var projection = r * Math.Cos(theta); for (var j = 0; j < horizontalSegments; ++j) { var fi = 2 * Math.PI / horizontalSegments * j; var multiplier = 1.0 + 0.5 * Math.Abs(Math.Sin(2 * fi)); var x = projection * Math.Cos(fi) * multiplier; var z = projection * Math.Sin(fi) * multiplier; vertices[i * horizontalSegments + j, 0] = x; vertices[i * horizontalSegments + j, 1] = y + (theta > 0 ? r * Math.Pow(theta / (Math.PI / 2.0), 5) : 0.0); vertices[i * horizontalSegments + j, 2] = z; vertices[i * horizontalSegments + j, 3] = 1; } } var faces = new MyMatrix <int>(2 * horizontalSegments * verticalSegments, 3); for (var i = 0; i < verticalSegments; ++i) { for (var j = 0; j < horizontalSegments; ++j) { var index = i * horizontalSegments + j; faces[2 * index, 0] = index; faces[2 * index, 1] = (index + 1) % horizontalSegments == 0 ? index - horizontalSegments + 1 : index + 1; faces[2 * index, 2] = (index + 1) % horizontalSegments == 0 ? index + 1 : index + horizontalSegments + 1; faces[2 * index + 1, 0] = index; faces[2 * index + 1, 1] = (index + 1) % horizontalSegments == 0 ? index + 1 : index + horizontalSegments + 1; faces[2 * index + 1, 2] = index + horizontalSegments; } } return(new Mesh(faces, vertices)); }
public static MyMatrix <double> Inverse(MyMatrix <double> matrix) { var array1d = matrix.GetInternalStorage().Cast <double>().ToArray(); var mathnetMatrix = new DenseMatrix(matrix.Height, matrix.Width, array1d); var inversedMathnetMatrix = mathnetMatrix.Inverse(); var result = new MyMatrix <double>(inversedMathnetMatrix.RowCount, inversedMathnetMatrix.ColumnCount); for (int i = 0; i < inversedMathnetMatrix.RowCount; ++i) { for (int j = 0; j < inversedMathnetMatrix.ColumnCount; ++j) { result[i, j] = inversedMathnetMatrix[i, j]; } } return(result); }
private static void CreateVerticesForFace( double xStart , double yStart , double zStart , double newLineXStep , double newLineYStep , double newLineZStep , double xStep , double yStep , double zStep , double radius , int subdivisions , int startIndex , MyMatrix <double> vertices) { vertices[startIndex, 0] = xStart; vertices[startIndex, 1] = yStart; vertices[startIndex, 2] = zStart; var numberOfLines = (int)Math.Pow(2, subdivisions) + 1; for (int lineNumber = 1, index = startIndex + 1; lineNumber < numberOfLines; ++lineNumber) { var firstVertexX = xStart + newLineXStep * lineNumber; var firstVertexY = yStart + newLineYStep * lineNumber; var firstVertexZ = zStart + newLineZStep * lineNumber; var numberOfVerticesInLine = lineNumber + 1; for (int vertexNumberInLine = 0; vertexNumberInLine < numberOfVerticesInLine; ++vertexNumberInLine) { var x = firstVertexX + xStep * vertexNumberInLine; var y = firstVertexY + yStep * vertexNumberInLine; var z = firstVertexZ + zStep * vertexNumberInLine; var length = Utilities.Length(x, y, z, 0, 0, 0); x *= radius / length; y *= radius / length; z *= radius / length; vertices[index, 0] = x; vertices[index, 1] = y; vertices[index, 2] = z; ++index; } } }
public MainWindow() { InitializeComponent(); m_bitmap = new WriteableBitmap((int)image.Width, (int)image.Height, 96, 96, PixelFormats.Bgr32, null); image.Source = m_bitmap; image.Stretch = Stretch.None; image.HorizontalAlignment = HorizontalAlignment.Left; image.VerticalAlignment = VerticalAlignment.Top; var vertices = new double[, ] { { 0, 0, 0, 1 }, { 1, 0, 0, 1 }, { 0.5, -0.2, 1, 1 }, { 0.5, 1, 0.5, 1 } }; var faces = new int[, ] { { 1, 0, 3 }, { 2, 1, 3 }, { 0, 2, 3 }, { 2, 0, 1 } }; var defaultObject = new MyObject("default", new Vector3D(0, 0, 0), new Vector3D(0, 0, 0), Default.SCALE, Shape.Tetrahedron); AddObject(defaultObject); objectsListBox.SelectedIndex = 0; var r = -1.0 / 15.0; var perspective = new double[, ] { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, r }, { 0, 0, 0, 1 } }; var projection = new MyMatrix <double>(perspective); m_currentObject = GetCurrentObject(); m_drawer = new Drawer(projection, (int)m_bitmap.Width, (int)m_bitmap.Height); projectionComboBox.SelectedIndex = 0; Redraw(); }
private static Mesh CreateSphere(double r) { var horizontalSegments = 14; var verticalSegments = 14; var vertices = new MyMatrix <double>(horizontalSegments * (verticalSegments + 1), 4); for (var i = 0; i <= verticalSegments; ++i) { var theta = -Math.PI / 2 + Math.PI / verticalSegments * i; var y = r * Math.Sin(theta); var projection = r * Math.Cos(theta); for (var j = 0; j < horizontalSegments; ++j) { var fi = 2 * Math.PI / horizontalSegments * j; var x = projection * Math.Cos(fi); var z = projection * Math.Sin(fi); vertices[i * horizontalSegments + j, 0] = x; vertices[i * horizontalSegments + j, 1] = y; vertices[i * horizontalSegments + j, 2] = z; vertices[i * horizontalSegments + j, 3] = 1; } } var faces = new MyMatrix <int>(2 * horizontalSegments * verticalSegments, 3); for (var i = 0; i < verticalSegments; ++i) { for (var j = 0; j < horizontalSegments; ++j) { var index = i * horizontalSegments + j; faces[2 * index, 0] = index; faces[2 * index, 1] = (index + 1) % horizontalSegments == 0 ? index - horizontalSegments + 1 : index + 1; faces[2 * index, 2] = (index + 1) % horizontalSegments == 0 ? index + 1 : index + horizontalSegments + 1; faces[2 * index + 1, 0] = index; faces[2 * index + 1, 1] = (index + 1) % horizontalSegments == 0 ? index + 1 : index + horizontalSegments + 1; faces[2 * index + 1, 2] = index + horizontalSegments; } } return(new Mesh(faces, vertices)); }
private static void CreateSpherePart( MyMatrix <double> tethraederVertices , int fristVertexIndex , int secondVertexIndex , int thirdVertexIndex , int subdivisions , int startIndex , double radius , MyMatrix <double> vertices , List <Face> faces) { var numberOfSegments = (int)Math.Pow(2, subdivisions); var newLineXStep = (tethraederVertices[secondVertexIndex, 0] - tethraederVertices[fristVertexIndex, 0]) / numberOfSegments; var newLineYStep = (tethraederVertices[secondVertexIndex, 1] - tethraederVertices[fristVertexIndex, 1]) / numberOfSegments; var newLineZStep = (tethraederVertices[secondVertexIndex, 2] - tethraederVertices[fristVertexIndex, 2]) / numberOfSegments; var xStep = (tethraederVertices[thirdVertexIndex, 0] - tethraederVertices[secondVertexIndex, 0]) / numberOfSegments; var yStep = (tethraederVertices[thirdVertexIndex, 1] - tethraederVertices[secondVertexIndex, 1]) / numberOfSegments; var zStep = (tethraederVertices[thirdVertexIndex, 2] - tethraederVertices[secondVertexIndex, 2]) / numberOfSegments; CreateVerticesForFace( tethraederVertices[fristVertexIndex, 0] , tethraederVertices[fristVertexIndex, 1] , tethraederVertices[fristVertexIndex, 2] , newLineXStep , newLineYStep , newLineZStep , xStep , yStep , zStep , radius , subdivisions , startIndex , vertices); CreateFacesForFace( startIndex , subdivisions , vertices , faces); }
private static Mesh CreateModifiedTorus(double r, double torusRadius) { var verticalSegments = 8; var horizontalSegments = 36; var vertices = new MyMatrix <double>(2 * verticalSegments * (horizontalSegments + 1), 4); for (var i = 0; i <= horizontalSegments; ++i) { var fi = 4 * Math.PI / horizontalSegments * i; for (var j = 0; j < verticalSegments; ++j) { var theta = 2 * Math.PI / verticalSegments * j; var x = (r + torusRadius * Math.Cos(theta)) * Math.Cos(fi); var y = (r + torusRadius * Math.Cos(theta)) * Math.Sin(fi); var z = torusRadius * Math.Sin(theta) + torusRadius * fi; vertices[i * verticalSegments + j, 0] = x; vertices[i * verticalSegments + j, 1] = y; vertices[i * verticalSegments + j, 2] = z; vertices[i * verticalSegments + j, 3] = 1; } } var faces = new MyMatrix <int>(4 * verticalSegments * (horizontalSegments + 1), 3); for (var i = 0; i < horizontalSegments; ++i) { for (var j = 0; j < verticalSegments; ++j) { var index = i * verticalSegments + j; faces[2 * index, 0] = index; faces[2 * index, 1] = index + verticalSegments; faces[2 * index, 2] = (index + 1) % verticalSegments == 0 ? (i + 1) * verticalSegments : index + verticalSegments + 1; faces[2 * index + 1, 0] = index; faces[2 * index + 1, 1] = (index + 1) % verticalSegments == 0 ? (i + 1) * verticalSegments : index + verticalSegments + 1; faces[2 * index + 1, 2] = (index + 1) % verticalSegments == 0 ? i * verticalSegments : index + 1; } } return(new Mesh(faces, vertices)); }
public static MyMatrix <T> operator *(MyMatrix <T> first, MyMatrix <T> second) { if (first.Width != second.Height) { throw new ArgumentException("Matrix multiplication: first matrix width must be equal to second matrix height"); } var result = new MyMatrix <T>(first.m_matrix.GetLength(0), second.m_matrix.GetLength(1)); for (var i = 0; i < first.Height; ++i) { for (var j = 0; j < second.Width; ++j) { for (var k = 0; k < first.Width; ++k) { result[i, j] += (dynamic)first[i, k] * (dynamic)second[k, j]; // some cheats with dynamic } } } return(result); }
public Mesh(MyMatrix <int> faces, MyMatrix <double> vertices) { CheckNullFacesOrVertices(faces, vertices); if (faces.Height <= 0 || faces.Width < 3) { throw new ArgumentException( "Wrong faces matrix size, height = " + faces.Height + ", width = " + faces.Width ); } CheckVerticesShape(vertices); for (int i = 0; i < faces.Height; ++i) { var faceBuilder = new FaceBuilder(); for (var j = 0; j < faces.Width; ++j) { faceBuilder.Add(faces[i, j]); } m_faces.Add(faceBuilder.Build()); } m_vertices = vertices; }
private static Mesh CreateSphereWithoutPole(double r, int subdivisions) { var vertices = new MyMatrix <double>(4, 4); var a = 4 * r / Math.Sqrt(6); var c = (a / 2) / Math.Cos(Utilities.ToRadians(30)); for (var i = 0; i < 3; ++i) { vertices[i, 0] = c * (Math.Cos(Utilities.ToRadians(150 + i * 120))); vertices[i, 1] = -Math.Sqrt(r * r - c * c); vertices[i, 2] = c * (Math.Sin(Utilities.ToRadians(-30 + i * 120))); } vertices[3, 0] = 0; vertices[3, 1] = r; vertices[3, 2] = 0; for (var i = 0; i < vertices.Height; ++i) { vertices[i, 3] = 1; } var sphereVertices = new MyMatrix <double>(4 * ((int)Math.Pow(2, subdivisions) + 1) * ((int)Math.Pow(2, subdivisions) + 2), 4); var faces = new List <Face>(); var numberOfSegments = (int)Math.Pow(2, subdivisions); var numberOfVerticesInFace = ((int)Math.Pow(2, subdivisions) + 1) * ((int)Math.Pow(2, subdivisions) + 2) / 2; CreateSpherePart(vertices, 3, 0, 2, subdivisions, 0, r, sphereVertices, faces); CreateSpherePart(vertices, 3, 1, 0, subdivisions, numberOfVerticesInFace, r, sphereVertices, faces); CreateSpherePart(vertices, 3, 2, 1, subdivisions, 2 * numberOfVerticesInFace, r, sphereVertices, faces); CreateSpherePart(vertices, 2, 1, 0, subdivisions, 3 * numberOfVerticesInFace, r, sphereVertices, faces); for (int i = 0; i < sphereVertices.Height; ++i) { sphereVertices[i, 3] = 1; } return(new Mesh(faces, sphereVertices)); }
private static Mesh CreateOctahedron(double r) { var vertices = new MyMatrix <double>(6, 4); var a = 6 * r / Math.Sqrt(6); vertices[0, 0] = vertices[1, 0] = -a / 2; vertices[2, 0] = vertices[3, 0] = a / 2; vertices[4, 0] = vertices[5, 0] = 0; vertices[0, 1] = vertices[1, 1] = vertices[2, 1] = vertices[3, 1] = 0; vertices[4, 1] = r; vertices[5, 1] = -r; vertices[1, 2] = vertices[2, 2] = -a / 2; vertices[0, 2] = vertices[3, 2] = a / 2; vertices[4, 2] = vertices[5, 2] = 0; for (var i = 0; i < vertices.Height; ++i) { vertices[i, 3] = 1; } var faces = new MyMatrix <int>(new int[, ] { { 1, 0, 4 }, { 2, 1, 4 }, { 3, 2, 4 }, { 0, 3, 4 }, { 0, 1, 5 }, { 1, 2, 5 }, { 2, 3, 5 }, { 3, 0, 5 } }); return(new Mesh(faces, vertices)); }
public IList <Face> GetVisibleFaces(double x, double y, double z) { //var inversedMatrix = Utilities.Inverse(m_rotation); //var inversedMatrix = m_rotation; //var vertices = m_vertices; var vertices = GetWorldCoordinates(); double barycenterX = 0; double barycenterY = 0; double barycenterZ = 0; for (var i = 0; i < vertices.Height; ++i) { barycenterX += vertices[i, 0]; barycenterY += vertices[i, 1]; barycenterZ += vertices[i, 2]; } barycenterX /= vertices.Height; barycenterY /= vertices.Height; barycenterZ /= vertices.Height; IList <Face> result = new List <Face>(); var planes = new MyMatrix <double>(4, Faces.Count); for (var i = 0; i < Faces.Count; ++i) { var x1 = vertices[Faces[i].Indices[1], 0] - vertices[Faces[i].Indices[0], 0]; var y1 = vertices[Faces[i].Indices[1], 1] - vertices[Faces[i].Indices[0], 1]; var z1 = vertices[Faces[i].Indices[1], 2] - vertices[Faces[i].Indices[0], 2]; var x2 = vertices[Faces[i].Indices[2], 0] - vertices[Faces[i].Indices[1], 0]; var y2 = vertices[Faces[i].Indices[2], 1] - vertices[Faces[i].Indices[1], 1]; var z2 = vertices[Faces[i].Indices[2], 2] - vertices[Faces[i].Indices[1], 2]; var a = y1 * z2 - y2 * z1; var b = z1 * x2 - z2 * x1; var c = x1 * y2 - x2 * y1; var d = -(a * vertices[Faces[i].Indices[0], 0] + b * vertices[Faces[i].Indices[0], 1] + c * vertices[Faces[i].Indices[0], 2]); planes[0, i] = a; planes[1, i] = b; planes[2, i] = c; planes[3, i] = d; var sign = -Math.Sign(a * barycenterX + b * barycenterY + c * barycenterZ + d); if (sign == -1) { planes[0, i] *= -1; planes[1, i] *= -1; planes[2, i] *= -1; planes[3, i] *= -1; } } //planes = inversedMatrix * planes; for (var i = 0; i < planes.Width; ++i) { //if (planes[0, i] * (x - barycenterX) + planes[1, i] * (y - barycenterY) + planes[2, i] * (z - barycenterZ) + planes[3, i] > 0 ) if (planes[0, i] * x + planes[1, i] * y + planes[2, i] * z + planes[3, i] > 0) { result.Add(Faces[i]); } } return(result); }
public void ResetScale() { m_scale = MyMatrix <double> .Incident(4); }
public void AddScale(MyMatrix <double> scale) { m_scale = m_scale * scale; }
public void SetScale(MyMatrix <double> scale) { m_scale = scale; }
public void ResetRotation() { m_rotation = MyMatrix <double> .Incident(4); }
public void AddRotation(MyMatrix <double> rotation) { m_rotation = m_rotation * rotation; }
public void SetRotation(MyMatrix <double> rotation) { m_rotation = rotation; }
public void ResetTranslation() { m_translation = MyMatrix <double> .Incident(4); }
public void AddTranslation(MyMatrix <double> translation) { m_translation = m_translation * translation; }
public void SetTranslation(MyMatrix <double> translation) { m_translation = translation; }
public Drawer(MyMatrix <double> projection, int width, int height) { m_projection = projection; m_screenWidth = width; m_screenHeight = height; }