예제 #1
0
        /// <summary>
        /// checks & and draws line if it isn't out of bounds
        /// calculates new point if the line is half out of bounds
        /// </summary>
        /// <param name="vertex0">start point</param>
        /// <param name="vertex1">end point</param>
        /// <param name="allPrimitves">save primitives</param>
        /// <returns>returns new point that isn't out of bounds</returns>
        private SLVertex CheckAndDrawLine(SLVertex vertex0, SLVertex vertex1, ref List <SLVertex> allPrimitves)
        {
            // create new vertecies so that the original vertecies point dont get changed
            SLVertex v0 = new SLVertex();

            v0.Set(vertex0);
            SLVertex v1 = new SLVertex();

            v1.Set(vertex1);
            SLVertex border = null;

            #region checkBoundries
            bool f = false;
            while (!f)
            {
                int codeA = set4Bit(v0.position.x, v0.position.y);
                int codeB = set4Bit(v1.position.x, v1.position.y);

                if ((codeA | codeB) == 0)
                {
                    f = true;
                }
                if ((codeA & codeB) != 0)
                {
                    return(null);
                }
                if (codeA > 0 || codeB > 0)
                {
                    border = (codeA > 0) ? calcPoints(ref v0, ref v1, codeA) : calcPoints(ref v1, ref v0, codeB);
                }
            }
            #endregion

            if (!phong && !showZ)
            {
                v0.color = v0.colorToLight(light); v1.color = v1.colorToLight(light);
            }

            DrawLine(v0, v1, ref allPrimitves);

            return(border);
        }
예제 #2
0
        /// <summary>
        /// Draws Line in the Bitmap and sets up the Primitives
        /// </summary>
        /// <param name="startVec">starting vector</param>
        /// <param name="endVec">ending vector</param>
        /// <param name="start_color">starting color of starting vector</param>
        /// <param name="end_color">ending color of ending vector</param>
        /// <param name="points">saves the coordinates of the line</param>
        /// <param name="colors">saves the colors of the line</param>
        private void DrawLine(SLVertex start, SLVertex end, ref List <SLVertex> primitves)
        {
            #region setup


            // color calculations
            double  distance = 0;
            SLVec3f newColor = new SLVec3f();

            SLVec3f startC = start.color, endC = end.color;
            SLVec3f startVec = start.position, endVec = end.position;


            RoundVector(ref startVec);
            RoundVector(ref endVec);



            // calculates slopes
            int dx = (int)(endVec.x - startVec.x);
            int dy = (int)(endVec.y - startVec.y);

            // steps size for calculation in ptr array
            int stepX = 3, stepY = stride;
            int stepDX = 1, stepDY = 1;

            // positions to know the coordinates of the active position
            int   posY = (int)startVec.y;
            int   posX = (int)startVec.x;
            float posZ;
            float startZ = startVec.z;
            float endZ   = endVec.z;

            // transformed starting coordinates for the ptr array
            int activeY = (int)startVec.y * stride;
            int activeX = (int)startVec.x * stepX;

            // transformed ending coordinates for the ptr array
            int lastX = (int)endVec.x * stepX;
            int lastY = (int)endVec.y * stepY;

            // if the slopes are negative
            if (dx < 0)
            {
                invertValues(ref dx, ref stepX, ref stepDX);
            }
            if (dy < 0)
            {
                invertValues(ref dy, ref stepY, ref stepDY);
            }

            //                                             ___________________________
            // distance between start and end vector      √ (x1 - x0)^2 + (y1 - y0)^2
            double lenght = Math.Sqrt(Math.Pow(endVec.x - startVec.x, 2) + Math.Pow(endVec.y - startVec.y, 2));


            #endregion
            #region Phong
            if (phong)
            {
                #region phongSetup
                SLVec3f newViewSpaceP = new SLVec3f();
                SLVec3f startVSP = start.posInView, endVSP = end.posInView;

                SLVec3f startNorm = start.normale, endNorm = end.normale;
                SLVec3f newNormale = new SLVec3f();
                #endregion
                unsafe
                {
                    byte *ptr = (byte *)data.Scan0;

                    if (dx > dy)
                    {
                        int dE  = (dy << 1);             // dy*2 anstatt dx  / 2
                        int dNE = (dy << 1) - (dx << 1); // dy*2 - dx*2
                        int D   = (dy << 1) - dx;        // dy*2 - dx

                        while (activeX != lastX)
                        {
                            #region calculationVertex
                            //                                             ___________________________
                            // distance between start and active pixel    √ (x1 - x0)^2 + (y1 - y0)^2
                            distance = Math.Sqrt((Math.Pow(posX - startVec.x, 2) + Math.Pow(posY - startVec.y, 2)));
                            // distance percent between the whole line
                            float ratio = (float)(distance / lenght);
                            if (ratio > 1)
                            {
                                ratio = 1;
                            }
                            // interpolate vertex
                            posZ          = startZ + ratio * (endZ - startZ);
                            newNormale    = startNorm + ratio * (endNorm - startNorm);
                            newColor      = startC + ratio * (endC - startC);
                            newViewSpaceP = startVSP + ratio * (endVSP - startVSP);
                            // save vertex
                            SLVertex nVertex = new SLVertex(posX, posY, posZ, newNormale, newColor, newViewSpaceP);
                            primitves.Add(nVertex);
                            #endregion

                            if (zB.checkZ(posX, posY, posZ))
                            {
                                newColor = nVertex.colorToLight(light);
                                // set active pixel the rgb (r=x, g=y, b=z)
                                ptr[activeX + activeY]     = (byte)(newColor.z);
                                ptr[activeX + activeY + 1] = (byte)(newColor.y);
                                ptr[activeX + activeY + 2] = (byte)(newColor.x);
                            }

                            if (D < 0)
                            {
                                D += dE;
                            }
                            else
                            {
                                D       += dNE;
                                activeY += stepY;
                                posY    += stepDY;
                            }

                            activeX += stepX;
                            posX    += stepDX;
                        }
                    }
                    else
                    {
                        int dE  = (dx << 1);      // = 2*dx
                        int dNE = (dx - dy) << 1; // = 2*(dx-dy)
                        int e   = (dx << 1) - dy; // = 2*dx - dy;

                        while (activeY != lastY)
                        {
                            #region calculationVertex
                            //                                             ___________________________
                            // distance between start and active pixel    √ (x1 - x0)^2 + (y1 - y0)^2
                            distance = Math.Sqrt((Math.Pow(posX - startVec.x, 2) + Math.Pow(posY - startVec.y, 2)));
                            float ratio = (float)(distance / lenght);
                            if (ratio > 1)
                            {
                                ratio = 1;
                            }
                            // interpolate Vertex
                            newColor      = startC + ratio * (endC - startC);
                            posZ          = startZ + ratio * (endZ - startZ);
                            newNormale    = startNorm + ratio * (endNorm - startNorm);
                            newViewSpaceP = startVSP + ratio * (endVSP - startVSP);
                            // save vertex
                            SLVertex nVertex = new SLVertex(posX, posY, posZ, newNormale, newColor, newViewSpaceP);
                            primitves.Add(nVertex);
                            #endregion

                            if (zB.checkZ(posX, posY, posZ))
                            {
                                newColor = nVertex.colorToLight(light);
                                // set active pixel the rgb (r=x, g=y, b=z)
                                ptr[activeX + activeY]     = (byte)(newColor.z);
                                ptr[activeX + activeY + 1] = (byte)(newColor.y);
                                ptr[activeX + activeY + 2] = (byte)(newColor.x);
                            }
                            activeY += stepY;
                            posY    += stepDY;
                            if (e < 0)
                            {
                                e += dE;
                            }
                            else
                            {
                                e       += dNE;
                                activeX += stepX;
                                posX    += stepDX;
                            }
                        }
                    }
                    // set last pixel
                    if (zB.checkZ(posX, posY, endVec.z))
                    {
                        endC = end.colorToLight(light);
                        ptr[lastX + lastY]     = (byte)(endC.z);
                        ptr[lastX + lastY + 1] = (byte)(endC.y);
                        ptr[lastX + lastY + 2] = (byte)(endC.x);
                    }
                    primitves.Add(new SLVertex(endVec, endNorm, endC, endVSP));
                }
            }
            #endregion
            #region zBufferVisulatation
            // zBufferVisulatation
            else if (showZ)
            {
                double lengthZ = zB.far - zB.near;
                double distanceZ;
                startC = new SLVec3f(255, 255, 255);
                endC   = new SLVec3f();
                unsafe
                {
                    byte *ptr = (byte *)data.Scan0;

                    if (dx > dy)
                    {
                        int dE  = (dy << 1);             // dy*2 anstatt dx  / 2
                        int dNE = (dy << 1) - (dx << 1); // dy*2 - dx*2
                        int D   = (dy << 1) - dx;        // dy*2 - dx

                        while (activeX != lastX)
                        {
                            #region calculationZColor
                            //                                             ___________________________
                            // distance between start and active pixel    √ (x1 - x0)^2 + (y1 - y0)^2
                            distance = Math.Sqrt((Math.Pow(posX - startVec.x, 2) + Math.Pow(posY - startVec.y, 2)));
                            // distance percent between the whole line
                            float ratio = (float)(distance / lenght);
                            if (ratio > 1)
                            {
                                ratio = 1;
                            }

                            // interpolate Z
                            posZ      = startZ + ratio * (endZ - startZ);
                            distanceZ = posZ - zB.near;
                            float ratioZ = (float)(distanceZ / lengthZ);

                            // gradient between near and far
                            newColor = startC + ratioZ * (endC - startC);
                            primitves.Add(new SLVertex(posX, posY, posZ, newColor));
                            #endregion

                            if (zB.checkZ(posX, posY, posZ))
                            {
                                // set active pixel the rgb (r=x, g=y, b=z)
                                ptr[activeX + activeY]     = (byte)(newColor.z);
                                ptr[activeX + activeY + 1] = (byte)(newColor.y);
                                ptr[activeX + activeY + 2] = (byte)(newColor.x);
                            }

                            if (D < 0)
                            {
                                D += dE;
                            }
                            else
                            {
                                D       += dNE;
                                activeY += stepY;
                                posY    += stepDY;
                            }
                            activeX += stepX;
                            posX    += stepDX;
                        }
                    }
                    else
                    {
                        int dE  = (dx << 1);      // = 2*dx
                        int dNE = (dx - dy) << 1; // = 2*(dx-dy)
                        int e   = (dx << 1) - dy; // = 2*dx - dy;

                        while (activeY != lastY)
                        {
                            #region calculationZColor
                            //                                             ___________________________
                            // distance between start and active pixel    √ (x1 - x0)^2 + (y1 - y0)^2
                            distance = Math.Sqrt((Math.Pow(posX - startVec.x, 2) + Math.Pow(posY - startVec.y, 2)));
                            float ratio = (float)(distance / lenght);
                            if (ratio > 1)
                            {
                                ratio = 1;
                            }

                            // interpolate Z
                            posZ      = startZ + ratio * (endZ - startZ);
                            distanceZ = posZ - zB.near;
                            float ratioZ = (float)(distanceZ / lengthZ);

                            // gradient between near and far
                            newColor = startC + ratioZ * (endC - startC);
                            primitves.Add(new SLVertex(posX, posY, posZ, newColor));
                            #endregion

                            if (zB.checkZ(posX, posY, posZ))
                            {
                                // set active pixel the rgb (r=x, g=y, b=z)
                                ptr[activeX + activeY]     = (byte)(newColor.z);
                                ptr[activeX + activeY + 1] = (byte)(newColor.y);
                                ptr[activeX + activeY + 2] = (byte)(newColor.x);
                            }
                            activeY += stepY;
                            posY    += stepDY;

                            if (e < 0)
                            {
                                e += dE;
                            }
                            else
                            {
                                e       += dNE;
                                activeX += stepX;
                                posX    += stepDX;
                            }
                        }
                    }
                    // set last pixel
                    if (zB.checkZ(posX, posY, endVec.z))
                    {
                        distanceZ = endVec.z - zB.near;
                        float ratioZ = (float)(distanceZ / lengthZ);
                        newColor               = startC + ratioZ * (endC - startC);
                        ptr[lastX + lastY]     = (byte)(newColor.z);
                        ptr[lastX + lastY + 1] = (byte)(newColor.y);
                        ptr[lastX + lastY + 2] = (byte)(newColor.x);
                    }

                    primitves.Add(new SLVertex(endVec, end.normale, newColor));
                }
            }
            #endregion
            // ohne phong & one z visualiesierung
            else
            {
                unsafe
                {
                    byte *ptr = (byte *)data.Scan0;

                    if (dx > dy)
                    {
                        int dE  = (dy << 1);             // dy*2 anstatt dx  / 2
                        int dNE = (dy << 1) - (dx << 1); // dy*2 - dx*2
                        int D   = (dy << 1) - dx;        // dy*2 - dx

                        while (activeX != lastX)
                        {
                            #region interpolateColor
                            //                                             ___________________________
                            // distance between start and active pixel    √ (x1 - x0)^2 + (y1 - y0)^2
                            distance = Math.Sqrt((Math.Pow(posX - startVec.x, 2) + Math.Pow(posY - startVec.y, 2)));
                            // distance percent between the whole line
                            float ratio = (float)(distance / lenght);
                            if (ratio > 1)
                            {
                                ratio = 1;
                            }
                            // interpolation of z axis
                            posZ = startZ + ratio * (endZ - startZ);
                            // gradient between start color and end color
                            newColor = startC + ratio * (endC - startC);
                            primitves.Add(new SLVertex(posX, posY, posZ, newColor));
                            #endregion

                            if (zB.checkZ(posX, posY, posZ))
                            {
                                // set active pixel the rgb (r=x, g=y, b=z)
                                ptr[activeX + activeY]     = (byte)(newColor.z);
                                ptr[activeX + activeY + 1] = (byte)(newColor.y);
                                ptr[activeX + activeY + 2] = (byte)(newColor.x);
                            }

                            if (D < 0)
                            {
                                D += dE;
                            }
                            else
                            {
                                D       += dNE;
                                activeY += stepY;
                                posY    += stepDY;
                            }

                            activeX += stepX;
                            posX    += stepDX;
                        }
                    }
                    else
                    {
                        int dE  = (dx << 1);      // = 2*dx
                        int dNE = (dx - dy) << 1; // = 2*(dx-dy)
                        int e   = (dx << 1) - dy; // = 2*dx - dy;

                        while (activeY != lastY)
                        {
                            #region interpolateColor
                            //                                             ___________________________
                            // distance between start and active pixel    √ (x1 - x0)^2 + (y1 - y0)^2
                            distance = Math.Sqrt((Math.Pow(posX - startVec.x, 2) + Math.Pow(posY - startVec.y, 2)));
                            float ratio = (float)(distance / lenght);
                            if (ratio > 1)
                            {
                                ratio = 1;
                            }
                            // interpolate color
                            newColor = startC + ratio * (endC - startC);
                            // interpolate z axis
                            posZ = startZ + ratio * (endZ - startZ);
                            primitves.Add(new SLVertex(posX, posY, posZ, newColor));
                            #endregion

                            if (zB.checkZ(posX, posY, posZ))
                            {
                                // set active pixel the rgb (r=x, g=y, b=z)
                                ptr[activeX + activeY]     = (byte)(newColor.z);
                                ptr[activeX + activeY + 1] = (byte)(newColor.y);
                                ptr[activeX + activeY + 2] = (byte)(newColor.x);
                            }
                            activeY += stepY;
                            posY    += stepDY;

                            if (e < 0)
                            {
                                e += dE;
                            }
                            else
                            {
                                e       += dNE;
                                activeX += stepX;
                                posX    += stepDX;
                            }
                        }
                    }
                    // set last pixel
                    if (zB.checkZ(posX, posY, endVec.z))
                    {
                        endC = end.colorToLight(light);
                        ptr[lastX + lastY]     = (byte)(endC.z);
                        ptr[lastX + lastY + 1] = (byte)(endC.y);
                        ptr[lastX + lastY + 2] = (byte)(endC.x);
                    }

                    primitves.Add(new SLVertex(endVec, end.normale, endC));
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Draws line only on one y axis
        /// </summary>
        /// <param name="x1"> left point</param>
        /// <param name="x2"> right point</param>
        /// <param name="y"> y axis on wich the line will be drawn</param>
        /// <param name="startColor"> color from x1 </param>
        /// <param name="endColor"> color from x2 </param>
        private void draw1DLine(SLVertex x1, SLVertex x2, int y)
        {
            #region drawLineSetUp
            int   stepX = 3, stepY = stride * y, increX = 1;
            int   activeX = (int)x1.position.x;
            int   startX  = activeX;
            float startZ  = x1.position.z;
            float activeZ = startZ;
            float endZ    = x2.position.z;

            SLVec3f newColor = new SLVec3f();
            double  distance;
            double  length = Math.Abs(activeX - x2.position.x);

            float   zDiffrence     = endZ - startZ;
            SLVec3f colorDiffrence = x2.color - x1.color;

            SLVec3f startColor = x1.color;
            SLVec3f endColor   = x2.color;

            SLVec3f  nNormale = new SLVec3f();
            SLVertex nVertex  = new SLVertex();

            int activePosition = (int)(startX * stepX) + stepY;
            int endPosition    = (int)x2.position.x * stepX + stepY;
            #endregion

            #region phong
            if (phong)
            {
                #region phongSetup
                SLVec3f startNormale = x1.normale, endNormale = x2.normale;
                SLVec3f normaleDiffrence = endNormale - startNormale;
                nNormale = startNormale;

                SLVec3f startVSP = x1.posInView, endVSP = x2.posInView;
                SLVec3f posVSDiffrence = endVSP - startVSP;
                SLVec3f nViewSpaceP    = startVSP;
                #endregion
                unsafe
                {
                    byte *ptr = (byte *)data.Scan0;

                    while (activePosition != endPosition)
                    {
                        distance = activeX - startX;
                        float ratio = (float)(distance / length);

                        // interpolate the z axis
                        activeZ = startZ + ratio * zDiffrence;

                        if (zB.checkZ(activeX, y, activeZ))
                        {
                            #region calc new vertex color
                            // interpolate vertecies color, normale and viewspace
                            newColor    = startColor + ratio * colorDiffrence;
                            nNormale    = startNormale + ratio * normaleDiffrence;
                            nViewSpaceP = startVSP + ratio * posVSDiffrence;
                            nVertex     = new SLVertex(activeX, y, activeZ, nNormale, newColor, nViewSpaceP);

                            newColor = nVertex.colorToLight(light);
                            #endregion

                            ptr[activePosition]     = (byte)newColor.z;
                            ptr[activePosition + 1] = (byte)newColor.y;
                            ptr[activePosition + 2] = (byte)newColor.x;
                        }


                        activePosition += stepX;
                        activeX        += increX;
                    }
                }
            }
            #endregion
            #region showZBuffer
            else if (showZ)
            {
                #region showZSetUp
                startColor = new SLVec3f(255, 255, 255);
                endColor   = new SLVec3f();
                double distanceZ;
                double lengthZ = zB.far - zB.near;
                #endregion
                unsafe
                {
                    byte *ptr = (byte *)data.Scan0;

                    while (activePosition != endPosition)
                    {
                        distance = activeX - startX;
                        float ratio = (float)(distance / length);

                        // interpolate z
                        activeZ = startZ + ratio * zDiffrence;

                        if (zB.checkZ(activeX, y, activeZ))
                        {
                            #region colorRelativeToZBuffer
                            newColor  = startColor + ratio * colorDiffrence;
                            distanceZ = activeZ - zB.near;
                            float ratioZ = (float)(distanceZ / lengthZ);
                            // interpolate between near and far
                            newColor = startColor + ratioZ * (endColor - startColor);
                            #endregion

                            ptr[activePosition]     = (byte)newColor.z;
                            ptr[activePosition + 1] = (byte)newColor.y;
                            ptr[activePosition + 2] = (byte)newColor.x;
                        }

                        activePosition += stepX;
                        activeX        += increX;
                    }
                }
            }
            #endregion
            else
            {
                unsafe
                {
                    byte *ptr = (byte *)data.Scan0;

                    while (activePosition != endPosition)
                    {
                        distance = activeX - startX;
                        float ratio = (float)(distance / length);
                        // interpolate z position
                        activeZ = startZ + ratio * zDiffrence;
                        if (zB.checkZ(activeX, y, activeZ))
                        {
                            // color interpolation
                            newColor = startColor + ratio * colorDiffrence;

                            ptr[activePosition]     = (byte)newColor.z;
                            ptr[activePosition + 1] = (byte)newColor.y;
                            ptr[activePosition + 2] = (byte)newColor.x;
                        }

                        activePosition += stepX;
                        activeX        += increX;
                    }
                }
            }
        }