public void Draw1(int w, int h, Matrix3D projection, Mesh mesh, Action <int, int, int> setFacePixel, Action <int, int, int> setEdgePixel ) { for (var fi = 0; fi < mesh.Indices.Count; ++fi) { var face = mesh.Indices[fi]; if (face.Count < 3) { continue; // nothing to draw } // check normal var v0 = projection * mesh.Points[face[0]]; var v1 = projection * mesh.Points[face[1]]; var v2 = projection * mesh.Points[face[2]]; if (Vector3D.Cross(v0 - v1, v2 - v1).Z < 0) { continue; } // projected points var ppts = new List <Vector3D>(); for (var i = 0; i < face.Count; ++i) { ppts.Add(projection * mesh.Points[face[i]]); } ppts.Add(ppts[0]); // double up on last one // draw filled polygon // get min, max y int minY = int.MaxValue, maxY = int.MinValue; foreach (var pt in ppts) { minY = Math.Min(minY, (int)pt.Y); maxY = Math.Max(maxY, (int)pt.Y); } // space for left, right ends var left = new int[maxY - minY + 1]; var right = new int[maxY - minY + 1]; // initialize them for (var i = 0; i < left.Length; ++i) { left[i] = int.MaxValue; right[i] = int.MinValue; } // now walk all edges, setting left and right at each y value for (var i = 0; i < ppts.Count - 1; ++i) { var p1 = ppts[i]; var p2 = ppts[i + 1]; int x1 = (int)p1.X, y1 = (int)p1.Y; int x2 = (int)p2.X, y2 = (int)p2.Y; DDA.Compute(x1, y1, x2, y2, (x, y) => { left[y - minY] = Math.Min(left[y - minY], x); right[y - minY] = Math.Max(right[y - minY], x); } ); } // now walk and fill var color = mesh.FaceColors[fi]; for (var j = 0; j < left.Length; ++j) { for (var i = left[j]; i <= right[j]; ++i) { setFacePixel(i, j + minY, fi); } } // draw wireframe for (var i = 0; i < ppts.Count - 1; ++i) { var p1 = ppts[i]; var p2 = ppts[i + 1]; int x1 = (int)p1.X, y1 = (int)p1.Y; int x2 = (int)p2.X, y2 = (int)p2.Y; Draw.Line(x1, y1, x2, y2, (i1, j1) => setEdgePixel(i1, j1, fi)); } } }
public static void Line(int x1, int y1, int x2, int y2, Action <int, int> setPixel) { DDA.Compute(x1, y1, x2, y2, (x, y) => setPixel(x, y)); }