public void printPolyZ(RPolygon pIn) { if (pIn.isEpsilonGeometry()) { return; } RPolygon polygon = pIn.reSort(); if (polygon.isOffScreen(this.pixelLeftTop, this.pixelRightBottom)) { return; } if (polygon.isFlatTop()) { printPolyFlatTopZ(polygon); } else { if (polygon.isFlatBottom()) { printPolyFlatBottomZ(polygon); } else { RPolygon p1 = polygon.getBottomFlat(); printPolyFlatBottomZ(p1); RPolygon p2 = polygon.getTopFlat(); printPolyFlatTopZ(p2); } } }
public void calculateProj(float nearPlane = 0.1f, float farPlane = 1000.0f) { polygons_proj = new List <RPolygon>(); foreach (RPolygon poly in polygons_view) { Vec3f nearPlaneNormal = new Vec3f(0.0f, 0.0f, 1.0f); Vec3f nearPlaneP0 = new Vec3f(0.0f, 0.0f, nearPlane); float sideOfPoint1 = nearPlaneNormal.dot(poly.vertex0.position - nearPlaneP0); float sideOfPoint2 = nearPlaneNormal.dot(poly.vertex1.position - nearPlaneP0); float sideOfPoint3 = nearPlaneNormal.dot(poly.vertex2.position - nearPlaneP0); if (sideOfPoint1 <= 0 || sideOfPoint2 <= 0 || sideOfPoint3 <= 0) { poly.visible = false; } if (poly.visible) { RVertex vertex1 = new RVertex(poly.vertex0); vertex1.position = new Vec3f(proj * poly.v0); RVertex vertex2 = new RVertex(poly.vertex1); vertex2.position = new Vec3f(proj * poly.v1); RVertex vertex3 = new RVertex(poly.vertex2); vertex3.position = new Vec3f(proj * poly.v2); RPolygon newPolygon = new RPolygon(vertex1, vertex2, vertex3, poly.rasterType, poly.texture); float cosTheta = newPolygon.normalCalc().dot(GlobalDirection.forward3f); newPolygon.visible = cosTheta >= 0.0f ? false : true; if (newPolygon.visible) { polygons_proj.Add(newPolygon); } } } }
public void calculateView(bool needToSort) { polygons_view = new List <RPolygon>(); foreach (RPolygon poly in polygons_world) { RVertex vertex1 = new RVertex(poly.vertex[0]); vertex1.position = new Vec3f(view * poly.v0); RVertex vertex2 = new RVertex(poly.vertex[1]); vertex2.position = new Vec3f(view * poly.v1); RVertex vertex3 = new RVertex(poly.vertex[2]); vertex3.position = new Vec3f(view * poly.v2); RPolygon newPolygon = new RPolygon(vertex1, vertex2, vertex3, poly.rasterType, poly.texture); polygons_view.Add(newPolygon); } if (needToSort) { polygons_view = polygons_view.OrderBy(p => p.center).ToList(); } }
public void calculateProj() { polygons_proj = new List <RPolygon>(); foreach (RPolygon poly in polygons_view) { RVertex vertex1 = new RVertex(poly.vertex[0]); vertex1.position = new Vec3f(proj * poly.v0); RVertex vertex2 = new RVertex(poly.vertex[1]); vertex2.position = new Vec3f(proj * poly.v1); RVertex vertex3 = new RVertex(poly.vertex[2]); vertex3.position = new Vec3f(proj * poly.v2); RPolygon newPolygon = new RPolygon(vertex1, vertex2, vertex3, poly.rasterType, poly.texture); float cosTheta = newPolygon.normalCalc().dot(GlobalDirection.forward3f); newPolygon.visible = cosTheta >= 0.0f ? false : true; if (newPolygon.visible) { polygons_proj.Add(newPolygon); } } }
public void calculateAll(float nearPlane, float farPlane, float width, float height, bool isNDC, bool backFaceCull = true) { polygons_raster = new List <RPolygon>(); object sync = new object(); Parallel.ForEach <RPolygon>( polygons, poly => { Mat4f mwv = model; mwv = mwv * world; mwv = mwv * view; RVertex vertex1 = new RVertex(poly.vertex0); vertex1.position = new Vec3f(mwv * poly.v0); RVertex vertex2 = new RVertex(poly.vertex1); vertex2.position = new Vec3f(mwv * poly.v1); RVertex vertex3 = new RVertex(poly.vertex2); vertex3.position = new Vec3f(mwv * poly.v2); Vec3f nearPlaneNormal = new Vec3f(0.0f, 0.0f, 1.0f); Vec3f nearPlaneP0 = new Vec3f(0.0f, 0.0f, nearPlane); Vec3f farPlaneNormal = new Vec3f(0.0f, 0.0f, -1.0f); Vec3f farPlaneP0 = new Vec3f(0.0f, 0.0f, farPlane); float sideOfPoint1near = nearPlaneNormal.dot(vertex1.position - nearPlaneP0); float sideOfPoint2near = nearPlaneNormal.dot(vertex2.position - nearPlaneP0); float sideOfPoint3near = nearPlaneNormal.dot(vertex3.position - nearPlaneP0); float sideOfPoint1far = farPlaneNormal.dot(vertex1.position - farPlaneP0); float sideOfPoint2far = farPlaneNormal.dot(vertex2.position - farPlaneP0); float sideOfPoint3far = farPlaneNormal.dot(vertex3.position - farPlaneP0); if ((sideOfPoint1near >= 0 && sideOfPoint2near >= 0 && sideOfPoint3near >= 0) && (sideOfPoint1far >= 0 && sideOfPoint2far >= 0 && sideOfPoint3far >= 0)) { vertex1.position = new Vec3f(proj * vertex1.position); vertex2.position = new Vec3f(proj * vertex2.position); vertex3.position = new Vec3f(proj * vertex3.position); vertex1.position.x = isNDC ? (vertex1.position.x + 1.0f) * 0.5f * width : vertex1.position.x * width; vertex1.position.y = isNDC ? (vertex1.position.y + 1.0f) * 0.5f * height : vertex1.position.y * height; vertex2.position.x = isNDC ? (vertex2.position.x + 1.0f) * 0.5f * width : vertex2.position.x * width; vertex2.position.y = isNDC ? (vertex2.position.y + 1.0f) * 0.5f * height : vertex2.position.y * height; vertex3.position.x = isNDC ? (vertex3.position.x + 1.0f) * 0.5f * width : vertex3.position.x * width; vertex3.position.y = isNDC ? (vertex3.position.y + 1.0f) * 0.5f * height : vertex3.position.y * height; RPolygon newPolygon = new RPolygon(vertex1, vertex2, vertex3, poly.rasterType, poly.texture); float cosTheta = newPolygon.normalCalc().dot(GlobalDirection.forward3f); newPolygon.visible = cosTheta >= 0.0f ? false : true; if (!backFaceCull || newPolygon.visible) { newPolygon.sort(); lock (sync) { polygons_raster.Add(newPolygon); } } } } ); }
public void printPolyFlatTopZ(RPolygon poly) { Vec3f v0 = new Vec3f(poly.v0); Vec3f v1 = new Vec3f(poly.v1); Vec3f v2 = new Vec3f(poly.v2); bool clockWise = v1.x > v0.x ? true : false; if (!clockWise) { Vec3f temp = v1; v1 = v0; v0 = temp; } float height = v2.y - v0.y; float dx_left = (v2.x - v0.x) / height; float dx_right = (v2.x - v1.x) / height; float xStart = v0.x; float xEnd = v1.x; int iy1; int iy3; int loop_y; if (v0.y < 0.0f) { xStart = xStart + dx_left * (-v0.y); xEnd = xEnd + dx_right * (-v0.y); v0.y = 0.0f; iy1 = 0; } else { iy1 = (int)Math.Ceiling(v0.y); xStart = xStart + dx_left * ((float)iy1 - v0.y); xEnd = xEnd + dx_right * ((float)iy1 - v0.y); } if (v2.y > pixelHeight) { v2.y = pixelHeight; iy3 = (int)v2.y - 1; } else { iy3 = (int)Math.Ceiling(v2.y) - 1; } float v0z = 1.0f / v0.z; float v1z = 1.0f / v1.z; float v2z = 1.0f / v2.z; float yTemp = v0.y; if (v0.x >= 0 && v0.x < pixelWidth && v1.x >= 0 && v1.x < pixelWidth && v2.x >= 0 && v2.x < pixelWidth) { for (loop_y = iy1; loop_y <= iy3; loop_y++) { int ixStart = (int)xStart; int ixEnd = (int)xEnd; float xTemp = xStart; for (int x = ixStart; x < ixEnd; x++) { Vec2f p = new Vec2f(xTemp, loop_y); Vec3f w = poly.nlambdas(p); float z = 1.0f / (w.x * v0z + w.y * v1z + w.z * v2z); Vec3f color = new Vec3f( (poly.c0.r * v0z * w.x + poly.c1.r * v1z * w.y + poly.c2.r * v2z * w.z) * z, (poly.c0.g * v0z * w.x + poly.c1.g * v1z * w.y + poly.c2.g * v2z * w.z) * z, (poly.c0.b * v0z * w.x + poly.c1.b * v1z * w.y + poly.c2.b * v2z * w.z) * z ); Vec2f UV = new Vec2f( (poly.t0.x * v0z * w.x + poly.t1.x * v1z * w.y + poly.t2.x * v2z * w.z) * z, (poly.t0.y * v0z * w.x + poly.t1.y * v1z * w.y + poly.t2.y * v2z * w.z) * z ); bool alphaColor = false; if (poly.rasterType == RPolygon.RasterType.Textured) { Vec4f texColor = poly.texture.sampleTextureA(UV); if (texColor.a == 1.0f) { color.x = texColor.r; color.y = texColor.g; color.z = texColor.b; } else { alphaColor = true; } } if (!alphaColor) { printPixelZ( x, loop_y, z, color ); } xTemp += 1.0f; } xStart += dx_left; xEnd += dx_right; yTemp += 1.0f; } } else { for (loop_y = iy1; loop_y <= iy3; loop_y++) { float left = xStart; float right = xEnd; xStart += dx_left; xEnd += dx_right; if (left < 0) { left = 0; if (right < 0) { continue; } } if (right > pixelWidth) { right = pixelWidth; if (left > pixelWidth) { continue; } } int ixStart = (int)left; int ixEnd = (int)right; float xTemp = left; for (int x = ixStart; x < ixEnd; x++) { Vec2f p = new Vec2f(xTemp, loop_y); Vec3f w = poly.nlambdas(p); float z = 1.0f / (w.x * v0z + w.y * v1z + w.z * v2z); Vec3f color = new Vec3f( (poly.c0.r * v0z * w.x + poly.c1.r * v1z * w.y + poly.c2.r * v2z * w.z) * z, (poly.c0.g * v0z * w.x + poly.c1.g * v1z * w.y + poly.c2.g * v2z * w.z) * z, (poly.c0.b * v0z * w.x + poly.c1.b * v1z * w.y + poly.c2.b * v2z * w.z) * z ); Vec2f UV = new Vec2f( (poly.t0.x * v0z * w.x + poly.t1.x * v1z * w.y + poly.t2.x * v2z * w.z) * z, (poly.t0.y * v0z * w.x + poly.t1.y * v1z * w.y + poly.t2.y * v2z * w.z) * z ); bool alphaColor = false; if (poly.rasterType == RPolygon.RasterType.Textured) { Vec4f texColor = poly.texture.sampleTextureA(UV); if (texColor.a == 1.0f) { color.x = texColor.r; color.y = texColor.g; color.z = texColor.b; } else { alphaColor = true; } } if (!alphaColor) { printPixelZ( x, loop_y, z, color ); } xTemp += 1.0f; } yTemp += 1.0f; } } }
public void printTriangleWireframe(RPolygon polygon, Vec3f color) { printLine(new Linef(polygon.v0, polygon.v1), color); printLine(new Linef(polygon.v1, polygon.v2), color); printLine(new Linef(polygon.v2, polygon.v0), color); }
public void printPolyZ(RPolygon pIn) { RPolygon polygon = pIn.reSort(); float area = polygon.screenArea(); float oneOverArea = 1.0f / area; Vec3f v0 = polygon.v0; Vec3f v1 = polygon.v1; Vec3f v2 = polygon.v2; if (polygon.isEpsilonGeometry()) { return; } if (polygon.isOffScreen(this.pixelLeftTop, this.pixelRightBottom)) { return; } if (area < 1.0f && area > -1.0f) { return; } Vec2i leftTop = polygon.topLeft(); Vec2i bottomRight = polygon.bottomRight(); if (leftTop.x < 0) { leftTop.x = 0; } if (leftTop.y < 0) { leftTop.y = 0; } if (bottomRight.x >= pixelWidth) { bottomRight.x = pixelWidth - 1; } if (bottomRight.y >= pixelHeight) { bottomRight.y = pixelHeight - 1; } for (int x = leftTop.x; x < bottomRight.x; x++) { for (int y = leftTop.y; y < bottomRight.y; y++) { Vec2f p = new Vec2f(x, y); Vec3f w = polygon.lambdas(p); if ((w.x >= 0.0f && w.y >= 0.0f && w.z >= 0.0f) || (w.x <= 0.0f && w.y <= 0.0f && w.z <= 0.0f)) { w *= oneOverArea; float z = 1.0f / (v0.z * w.x + v1.z * w.y + v2.z * w.z); Vec2f UV = new Vec2f( (polygon.vertex0.textureCoordinates.x * w.x + polygon.vertex1.textureCoordinates.x * w.y + polygon.vertex2.textureCoordinates.x * w.z) * z, (polygon.vertex0.textureCoordinates.y * w.x + polygon.vertex1.textureCoordinates.y * w.y + polygon.vertex2.textureCoordinates.y * w.z) * z ); Vec4f texColor = polygon.texture.sampleTextureA(UV); printPixelZ(x, y, z, new Vec3f(texColor)); } } } }