using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Threading.Tasks; namespace MMCG_lab_8_9 { class ZBuffer { private int sX, sY; private double[] zbuffer; private double[,] Zbuf; private Color[,] ZColor; private const double ph = 10 * Math.PI / 180; private const double ps = 50 * Math.PI / 180; private Point3D e1 = new Point3D(Math.Cos(ph), Math.Sin(ph), 0); private Point3D e2 = new Point3D(-1 * Math.Sin(ph) * Math.Sin(ps), Math.Cos(ph) * Math.Sin(ps), Math.Sin(ps)); public ZBuffer(int WIDTH, int HEIGHT) { sX = WIDTH; sY = HEIGHT; zbuffer = new double[sX * sY]; for (int i = 0; i < sX * sY; i++) zbuffer[i] = -32000; Zbuf = new double[sX, sY]; ZColor = new Color[sX, sY]; for (int i = 0; i < sX; i++) for (int j = 0; j < sY; j++) Zbuf[i, j] = 32000; } public void Show(List t, Graphics g) { for (int i = 0; i < t.Count; i++) ZBuffPart(t[i]); //DrawTriangle(t[i], g, t[i].color); for (int i = 0; i < sX; i++) for (int j = 0; j < sY; j++) g.DrawRectangle(new Pen(ZColor[i, j]), i, j, 1, 1); } private void ZBuffPart(Triangle t) { double u, v, du, dv; int x, y; Point3D R = new Point3D(0, 0, 0); du = 0.007; dv = 0.007; for (u = 0; u <= 1.0; u += du) for (v = 0; v <= 1.0 - u; v += dv) { R.X = t.A.X + u * (t.B.X - t.A.X) + v * (t.C.X - t.A.X); R.Y = t.A.Y + u * (t.B.Y - t.A.Y) + v * (t.C.Y - t.A.Y); R.Z = t.A.Z + u * (t.B.Z - t.A.Z) + v * (t.C.Z - t.A.Z); x = (int)Math.Round(R.scal(e1)); y = (int)Math.Round(R.scal(e2)); if (Zbuf[x, y] > R.Z) { Zbuf[x, y] = R.Z; ZColor[x, y] = t.color; } } } public void DrawTriangle(Triangle t, Graphics g, Color color) { if (t.A.Y == t.B.Y && t.A.Y == t.C.Y) return; if (t.A.Y > t.B.Y) { Point3D tmp; tmp = t.A; t.A = t.B; t.B = tmp; } if (t.A.Y > t.C.Y) { Point3D tmp; tmp = t.A; t.A = t.C; t.C = tmp; } if (t.B.Y > t.C.Y) { Point3D tmp; tmp = t.B; t.B = t.C; t.C = tmp; } int total_height = (int)Math.Round(t.C.Y - t.A.Y); for (int i = 0; i < total_height; i++) { bool second_half = i > t.B.Y - t.A.Y || t.B.Y == t.A.Y; int segment_height = second_half ? (int)Math.Round(t.C.Y - t.B.Y) : (int)Math.Round(t.B.Y - t.A.Y); float alpha = (float)i / total_height; //alpha = Math.Abs(alpha); float beta = (float)(i - (second_half ? t.B.Y - t.A.Y : 0)) / segment_height; //beta = Math.Abs(beta); Point3D A = new Point3D(t.A.X + (t.C.X - t.A.X) * alpha, t.A.Y + (t.C.Y - t.A.Y) * alpha, t.A.Z + (t.C.Z - t.A.Z) * alpha); Point3D B = second_half ? new Point3D(t.B.X + (t.C.X - t.B.X) * beta, t.B.Y + (t.C.Y - t.B.Y) * beta, t.B.Z + (t.C.Z - t.B.Z) * beta) : new Point3D(t.A.X + (t.B.X - t.A.X) * beta, t.A.Y + (t.B.Y - t.A.Y) * beta, t.A.Z + (t.B.Z - t.A.Z) * beta); if (A.X > B.X) { Point3D tmp; tmp = A; A = B; B = tmp; } for (int j = (int)(A.X); j <= (int)(B.X); j++) { float phi = B.X == A.X ? 1.0f : (float)(j - A.X) / (float)(B.X - A.X); //phi = Math.Abs(phi); Point3D P = new Point3D(A.X + (B.X - A.X) * phi, A.Y + (B.Y - A.Y) * phi, A.Z + (B.Z - A.Z) * phi); int idx = (int)(Math.Round(P.X * sX + P.Y)); if (zbuffer[idx] < P.Z) { zbuffer[idx] = P.Z; g.DrawRectangle(new Pen(color), (int)j, (int)Math.Round(t.A.Y + i), 1, 1); } } } } } }