예제 #1
0
        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);
                    }
                }
            }
        }
예제 #2
0
        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);
            }
        }