Пример #1
0
        private void Vertical_Line(int x1, int y1, float z1, int x2, int y2, float z2, Color colour)
        {
            float z_increase_y = (z1 - z2) / (y1 - y2);

            if (y2 < y1)
            {
                NumericManipulation.Swap(ref y1, ref y2);
                NumericManipulation.Swap(ref z1, ref z2);
            }

            for (int y = y1; y <= y2; y++)
            {
                ZBufferCheck(colour, x1, y, z1);
                z1 += z_increase_y;
            }
        }
Пример #2
0
        private void Horizontal_Line(int x1, int y1, float z1, int x2, int y2, float z2, Color colour)
        {
            float z_increase_x = (z1 - z2) / (x1 - x2);

            if (x2 < x1)
            {
                NumericManipulation.Swap(ref x1, ref x2);
                NumericManipulation.Swap(ref z1, ref z2);
            }

            for (int x = x1; x <= x2; x++)
            {
                ZBufferCheck(colour, x, y1, z1);
                z1 += z_increase_x;
            }
        }
Пример #3
0
        private void CalculateDepth(
            Face face,
            int meshDimension,
            ref Matrix4x4 modelToView)
        {
            // Reset the vertices to model space values
            face.ResetVertices();

            // Move the face from model space to view space
            face.ApplyMatrix(modelToView);

            if (meshDimension == 3)
            {
                // Discard the face if it is not visible from the light's point of view
                if ((Vector3D)face.p1 * Vector3D.NormalFromPlane((Vector3D)face.p1, (Vector3D)face.p2, (Vector3D)face.p3) >= 0)
                {
                    return;
                }
            }

            // Clip the face in view space
            Queue <Face> faceClip = new();

            faceClip.Enqueue(face);
            if (!Clipping.ClipFaces(faceClip, ViewClippingPlanes))
            {
                return;
            }

            // Move the new triangles from view space to screen space, including a correction for perspective
            foreach (Face clippedFace in faceClip)
            {
                clippedFace.ApplyMatrix(ViewToScreen);

                if (this is PointLight or Spotlight)
                {
                    clippedFace.p1 /= clippedFace.p1.w;
                    clippedFace.p2 /= clippedFace.p2.w;
                    clippedFace.p3 /= clippedFace.p3.w;
                }
            }

            // Clip the face in screen space
            if (Settings.Screen_Space_Clip && !Clipping.ClipFaces(faceClip, ScreenClippingPlanes))
            {
                return;
            }

            foreach (Face clippedFace in faceClip)
            {
                // Don't draw anything if the face is flat
                if ((clippedFace.p1.x == clippedFace.p2.x && clippedFace.p2.x == clippedFace.p3.x) ||
                    (clippedFace.p1.y == clippedFace.p2.y && clippedFace.p2.y == clippedFace.p3.y))
                {
                    continue;
                }

                // Move the new triangles from screen space to window space
                clippedFace.ApplyMatrix(ScreenToWindow);

                // Round the vertices
                int   x1 = clippedFace.p1.x.RoundToInt();
                int   y1 = clippedFace.p1.y.RoundToInt();
                float z1 = clippedFace.p1.z;
                int   x2 = clippedFace.p2.x.RoundToInt();
                int   y2 = clippedFace.p2.y.RoundToInt();
                float z2 = clippedFace.p2.z;
                int   x3 = clippedFace.p3.x.RoundToInt();
                int   y3 = clippedFace.p3.y.RoundToInt();
                float z3 = clippedFace.p3.z;

                // Sort the vertices by their y-co-ordinate
                NumericManipulation.SortByY
                (
                    ref x1, ref y1, ref z1,
                    ref x2, ref y2, ref z2,
                    ref x3, ref y3, ref z3
                );

                // Interpolate each point in the triangle
                Interpolation.InterpolateTriangle
                (
                    MeshDepthFromLight,
                    null,
                    x1, y1, z1,
                    x2, y2, z2,
                    x3, y3, z3
                );
            }
        }
Пример #4
0
        private void AddFaceToZBuffer(
            Face face,
            int meshDimension,
            ref Matrix4x4 modelToView,
            ref Matrix4x4 viewToScreen,
            ref Matrix4x4 screenToWindow)
        {
            // Reset the vertices to model space values
            face.ResetVertices();

            // Draw outline if needed ??
            if (face.DrawOutline)
            {
                DrawEdge(face.p1, face.p2, Color.Black, ref modelToView, ref viewToScreen);
                DrawEdge(face.p1, face.p3, Color.Black, ref modelToView, ref viewToScreen);
                DrawEdge(face.p2, face.p3, Color.Black, ref modelToView, ref viewToScreen);
            }

            // Move the face from model space to view space
            face.ApplyMatrix(modelToView);

            if (meshDimension == 3)
            {
                // Discard the face if it is not visible from the camera's point of view
                if ((Vector3D)face.p1 * Vector3D.NormalFromPlane((Vector3D)face.p1, (Vector3D)face.p2, (Vector3D)face.p3) >= 0)
                {
                    return;
                }
            }

            // Clip the face in view space
            Queue <Face> faceClip = new();

            faceClip.Enqueue(face);
            if (!Clipping.ClipFaces(faceClip, this.ViewClippingPlanes))
            {
                return;
            }

            // Move the new triangles from view space to screen space, including a correction for perspective
            foreach (Face clippedFace in faceClip)
            {
                clippedFace.ApplyMatrix(viewToScreen);

                if (this is PerspectiveCamera)
                {
                    clippedFace.p1 /= clippedFace.p1.w;
                    clippedFace.p2 /= clippedFace.p2.w;
                    clippedFace.p3 /= clippedFace.p3.w;

                    if (face.HasTexture)
                    {
                        clippedFace.t1 /= clippedFace.p1.w;
                        clippedFace.t2 /= clippedFace.p2.w;
                        clippedFace.t3 /= clippedFace.p3.w;
                    }
                }
            }

            // Clip the face in screen space
            if (Settings.Screen_Space_Clip && !Clipping.ClipFaces(faceClip, ScreenClippingPlanes))
            {
                return;
            }                                                                                                  // anything outside cube?

            foreach (Face clippedFace in faceClip)
            {
                // Skip the face if it is flat
                if ((clippedFace.p1.x == clippedFace.p2.x && clippedFace.p2.x == clippedFace.p3.x) ||
                    (clippedFace.p1.y == clippedFace.p2.y && clippedFace.p2.y == clippedFace.p3.y))
                {
                    continue;
                }

                // Move the new triangles from screen space to window space
                clippedFace.ApplyMatrix(screenToWindow);

                // Round the vertices
                int   x1 = clippedFace.p1.x.RoundToInt();
                int   y1 = clippedFace.p1.y.RoundToInt();
                float z1 = clippedFace.p1.z;
                int   x2 = clippedFace.p2.x.RoundToInt();
                int   y2 = clippedFace.p2.y.RoundToInt();
                float z2 = clippedFace.p2.z;
                int   x3 = clippedFace.p3.x.RoundToInt();
                int   y3 = clippedFace.p3.y.RoundToInt();
                float z3 = clippedFace.p3.z;

                // Check if the face has a texture
                if (face.HasTexture)
                {
                    // Scale the texture co-ordinates
                    int textureWidth  = face.Texture_Object.File.Width - 1;
                    int textureHeight = face.Texture_Object.File.Height - 1;

                    // afterwards?
                    float tx1 = face.T1.x * textureWidth;
                    float ty1 = face.T1.y * textureHeight;
                    float tz1 = face.T1.z;
                    float tx2 = face.T2.x * textureWidth;
                    float ty2 = face.T2.y * textureHeight;
                    float tz2 = face.T2.z;
                    float tx3 = face.T3.x * textureWidth;
                    float ty3 = face.T3.y * textureHeight;
                    float tz3 = face.T3.z;

                    // Sort the vertices by their y-co-ordinate
                    NumericManipulation.TexturedSortByY
                    (
                        ref x1, ref y1, ref tx1, ref ty1, ref tz1,
                        ref x2, ref y2, ref tx2, ref ty2, ref tz2,
                        ref x3, ref y3, ref tx3, ref ty3, ref tz3
                    );

                    // Generate z-buffer
                    Textured_Triangle
                    (
                        face.Texture_Object.File,
                        x1, y1, tx1, ty1, tz1,
                        x2, y2, tx2, ty2, tz2,
                        x3, y3, tx3, ty3, tz3
                    );
                }
                else
                {
                    // Sort the vertices by their y-co-ordinate
                    NumericManipulation.SortByY
                    (
                        ref x1, ref y1, ref z1,
                        ref x2, ref y2, ref z2,
                        ref x3, ref y3, ref z3
                    );

                    // Generate z-buffer
                    Interpolation.InterpolateTriangle
                    (
                        ZBufferCheck,
                        face.Colour,
                        x1, y1, z1,
                        x2, y2, z2,
                        x3, y3, z3
                    );
                }
            }
        }
Пример #5
0
        // floats or ints for everything? Should it take an average of texels (or pixels in method above)?
        private void Textured_Triangle(Bitmap texture,
                                       int x1, int y1, float tx1, float ty1, float tz1,
                                       int x2, int y2, float tx2, float ty2, float tz2,
                                       int x3, int y3, float tx3, float ty3, float tz3)
        {
            // Create steps
            float dy_step_1 = y1 - y2;
            float dy_step_2 = y1 - y3;
            float dy_step_3 = y2 - y3;

            float x_step_1 = 0, tx_step_1 = 0, ty_step_1 = 0, tz_step_1 = 0;
            float x_step_3 = 0, tx_step_3 = 0, ty_step_3 = 0, tz_step_3 = 0;

            if (dy_step_1 != 0)
            {
                x_step_1  = (x1 - x2) / dy_step_1;     // dx from point 1 to point 2
                tx_step_1 = (tx1 - tx2) / dy_step_1;   // dtx from point 1 to point 2
                ty_step_1 = (ty1 - ty2) / dy_step_1;   // dty from point 1 to point 2
                tz_step_1 = (tz1 - tz2) / dy_step_1;   // dtz from point 1 to point 2
            }
            float x_step_2  = (x1 - x3) / dy_step_2;   // dx from point 1 to point 3
            float tx_step_2 = (tx1 - tx3) / dy_step_2; // dtx from point 1 to point 3
            float ty_step_2 = (ty1 - ty3) / dy_step_2; // dty from point 1 to point 3
            float tz_step_2 = (tz1 - tz3) / dy_step_2; // dtz from point 1 to point 3

            if (dy_step_3 != 0)
            {
                x_step_3  = (x2 - x3) / dy_step_3;   // dx from point 2 to point 3
                tx_step_3 = (tx2 - tx3) / dy_step_3; // dtx from point 2 to point 3
                ty_step_3 = (ty2 - ty3) / dy_step_3; // dty from point 2 to point 3
                tz_step_3 = (tz2 - tz3) / dy_step_3; // dtz from point 2 to point 3
            }

            // Draw a flat-bottom triangle
            if (dy_step_1 != 0)
            {
                for (int y = y2; y <= y1; y++)
                {
                    int sx = ((y - y2) * x_step_1 + x2).RoundToInt();
                    int ex = ((y - y3) * x_step_2 + x3).RoundToInt();

                    float stx = (y - y2) * tx_step_1 + tx2;
                    float sty = (y - y2) * ty_step_1 + ty2;
                    float stz = (y - y2) * tz_step_1 + tz2;

                    float etx = (y - y3) * tx_step_2 + tx3;
                    float ety = (y - y3) * ty_step_2 + ty3;
                    float etz = (y - y3) * tz_step_2 + tz3;

                    // ?
                    if (sx > ex)
                    {
                        NumericManipulation.Swap(ref sx, ref ex);
                        NumericManipulation.Swap(ref stx, ref etx);
                        NumericManipulation.Swap(ref sty, ref ety);
                        NumericManipulation.Swap(ref stz, ref etz);
                    }

                    float t = 0, t_step = 1f / (ex - sx);
                    for (int x = sx; x <= ex; x++)
                    {
                        int   tx = (stx + t * (etx - stx)).RoundToInt();
                        int   ty = (sty + t * (ety - sty)).RoundToInt();
                        float tz = stz + t * (etz - stz);

                        TexturedCheckAgainstZBuffer(texture, x, y, tz, tx, ty);

                        t += t_step;
                    }
                }
            }

            // Draw a flat-top triangle
            if (dy_step_3 != 0)
            {
                for (int y = y3; y <= y2; y++)
                {
                    int sx = ((y - y3) * x_step_3 + x3).RoundToInt();
                    int ex = ((y - y3) * x_step_2 + x3).RoundToInt();

                    float stx = (y - y3) * tx_step_3 + tx3;
                    float sty = (y - y3) * ty_step_3 + ty3;
                    float stz = (y - y3) * tz_step_3 + tz3;

                    float etx = (y - y3) * tx_step_2 + tx3;
                    float ety = (y - y3) * ty_step_2 + ty3;
                    float etz = (y - y3) * tz_step_2 + tz3;

                    if (sx > ex)
                    {
                        NumericManipulation.Swap(ref sx, ref ex);
                        NumericManipulation.Swap(ref stx, ref etx);
                        NumericManipulation.Swap(ref sty, ref ety);
                        NumericManipulation.Swap(ref stz, ref etz);
                    }

                    float t = 0, t_step = 1f / (ex - sx);
                    for (int x = sx; x <= ex; x++)
                    {
                        int   tx = (stx + t * (etx - stx)).RoundToInt();
                        int   ty = (sty + t * (ety - sty)).RoundToInt();
                        float tz = stz + t * (etz - stz);

                        TexturedCheckAgainstZBuffer(texture, x, y, tz, tx, ty);

                        t += t_step;
                    }
                }
            }
        }