/// <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); }
/// <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)); } } }
/// <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; } } } }