public void DrawTriangle(MyPoint v1, MyPoint v2, MyPoint v3, Vector4 color) { if (v1.coords2d.Y > v2.coords2d.Y) { Swap <MyPoint>(ref v1, ref v2); } if (v2.coords2d.Y > v3.coords2d.Y) { Swap <MyPoint>(ref v2, ref v3); } if (v1.coords2d.Y > v2.coords2d.Y) { Swap <MyPoint>(ref v1, ref v2); } Vector4 p1 = v1.coords2d; Vector4 p2 = v2.coords2d; Vector4 p3 = v3.coords2d; Vector4 lightPos2 = new Vector4(0, 10, 10, 1); // Light position Vector4 lightPos = new Vector4(objects[1].pointList[5]._currentCoords.X - 0.1f, objects[1].pointList[5]._currentCoords.Y - 0.1f, objects[1].pointList[5]._currentCoords.Z - 0.1f, 1); List <Vector4> lights = new List <Vector4>(); lights.Add(lightPos); lights.Add(lightPos2); // computing the cos of the angle between the light vector and the normal vector // it will return a value between 0 and 1 that will be used as the intensity of the color float nl1 = 0.0f, nl2 = 0.0f, nl3 = 0.0f; if (radioButton4.Checked == true) { nl1 = CalculateLight(lights, v1); nl2 = CalculateLight(lights, v2); nl3 = CalculateLight(lights, v3); } var data = new ScanLineData { }; float dP1P2, dP1P3; dP1P2 = (p2.Y - p1.Y > 0) ? (p2.X - p1.X) / (p2.Y - p1.Y) : 0; dP1P3 = (p3.Y - p1.Y > 0) ? (p3.X - p1.X) / (p3.Y - p1.Y) : 0; // Light position // first triangle if (dP1P2 > dP1P3) { for (int y = (int)p1.Y; y <= (int)p3.Y; y++) { data.currentY = y; if (y < p2.Y) { data.ndotla = nl1; data.ndotlb = nl3; data.ndotlc = nl1; data.ndotld = nl2; data.normalA = v1.normal; data.normalB = v3.normal; data.normalC = v1.normal; data.normalD = v2.normal; ProcessScanLine(data, v1, v3, v1, v2, color); } else { data.ndotla = nl1; data.ndotlb = nl3; data.ndotlc = nl2; data.ndotld = nl3; data.normalA = v1.normal; data.normalB = v3.normal; data.normalC = v2.normal; data.normalD = v3.normal; ProcessScanLine(data, v1, v3, v2, v3, color); } } } // second triangle else { for (int y = (int)p1.Y; y <= (int)p3.Y; y++) { data.currentY = y; if (y < p2.Y) { data.ndotla = nl1; data.ndotlb = nl2; data.ndotlc = nl1; data.ndotld = nl3; data.normalA = v1.normal; data.normalB = v2.normal; data.normalC = v1.normal; data.normalD = v3.normal; ProcessScanLine(data, v1, v2, v1, v3, color); } else { data.ndotla = nl2; data.ndotlb = nl3; data.ndotlc = nl1; data.ndotld = nl3; data.normalA = v2.normal; data.normalB = v3.normal; data.normalC = v1.normal; data.normalD = v3.normal; ProcessScanLine(data, v2, v3, v1, v3, color); } } } }
void ProcessScanLine(ScanLineData data, MyPoint va, MyPoint vb, MyPoint vc, MyPoint vd, Vector4 color) { Vector4 pa = va.coords2d; Vector4 pb = vb.coords2d; Vector4 pc = vc.coords2d; Vector4 pd = vd.coords2d; // Thanks to current Y, we can compute the gradient to compute others values like // the starting X (sx) and ending X (ex) to draw between // if pa.Y == pb.Y or pc.Y == pd.Y, gradient is forced to 1 var gradient1 = pa.Y != pb.Y ? (data.currentY - pa.Y) / (pb.Y - pa.Y) : 1; var gradient2 = pc.Y != pd.Y ? (data.currentY - pc.Y) / (pd.Y - pc.Y) : 1; int sx = (int)Interpolate(pa.X, pb.X, gradient1); int ex = (int)Interpolate(pc.X, pd.X, gradient2); // starting Z & ending Z float z1 = Interpolate(pa.Z, pb.Z, gradient1); float z2 = Interpolate(pc.Z, pd.Z, gradient2); float real_z1 = Interpolate(va._currentCoords.Z, vb._currentCoords.Z, gradient1); float real_z2 = Interpolate(vc._currentCoords.Z, vd._currentCoords.Z, gradient1); Vector4 Vsnl = new Vector4(), Venl = new Vector4(); float snl = 0.0f, enl = 0.0f; if (radioButton4.Checked == true) { snl = Interpolate(data.ndotla, data.ndotlb, gradient1); enl = Interpolate(data.ndotlc, data.ndotld, gradient2); } else if (radioButton5.Checked == true) { Vsnl = Interpolate(data.normalA, data.normalB, gradient1); Venl = Interpolate(data.normalC, data.normalD, gradient2); } Vector4 lightPos2 = new Vector4(0, 10, 10, 1); // Light position Vector4 lightPos = new Vector4(objects[1].pointList[5]._currentCoords.X - 0.01f, objects[1].pointList[5]._currentCoords.Y - 0.01f, objects[1].pointList[5]._currentCoords.Z - 0.011f, 1); List <Vector4> lights = new List <Vector4>(); lights.Add(lightPos); lights.Add(lightPos2); // drawing a line from left (sx) to right (ex) for (var x = sx; x < ex; x++) { float gradient = (x - sx) / (float)(ex - sx); var z = Interpolate(z1, z2, gradient); var real_z = Interpolate(real_z1, real_z2, gradient); Vector4 Vndotl; float ndotl = 0.0f; if (radioButton4.Checked == true) { ndotl = Interpolate(snl, enl, gradient); } else if (radioButton5.Checked == true) { Vndotl = Interpolate(Vsnl, Venl, gradient); ndotl = CalculateLight(lights, new Vector4(x / pictureBox1.Width, data.currentY / pictureBox1.Height, real_z, 1), Vndotl); } float ndotl1 = Interpolate(snl, enl, gradient); // changing the color value using the cosine of the angle // between the light vector and the normal vector DrawPoint(new Vector4(x, data.currentY, z, 1), color * ndotl); } }