@@ 301,6 301,7 @@ Renderer *NewRenderer(Pixel *pixels, int width, int height)
r->vertex_pool = NewVertexPool();
r->polygon_pool = NewPolygonPool();
+ r->alt_polygon_pool = NewPolygonPool();
/* planes in W-space */
r->clip_planes.x_neg = Pl(V4D(0, 0, 0, 0), V4D(-1, 0, 0, -1));
@@ 429,7 430,7 @@ void Render(Renderable renderable, Transform position, Renderer *renderer)
for (i = 0, polygon = renderable.mesh->faces;
i < renderable.mesh->numFaces;
i++, polygon += (*polygon) + 1) {
- ClipPolygon(polygon, renderable.mesh, renderer);
+ ClipPolygon(polygon, &renderMesh, renderer);
renderMesh.numFaces++;
}
@@ 459,38 460,53 @@ void ProjectVertex(Vertex *vertex, Renderer *renderer)
void ClipPolygon(int *polygon, Mesh *mesh, Renderer *renderer)
{
- ClipPolygonPlane(polygon, mesh, renderer->clip_planes.x_neg, renderer->vertex_pool);
- ClipPolygonPlane(polygon, mesh, renderer->clip_planes.x_pos, renderer->vertex_pool);
- ClipPolygonPlane(polygon, mesh, renderer->clip_planes.y_neg, renderer->vertex_pool);
- ClipPolygonPlane(polygon, mesh, renderer->clip_planes.y_pos, renderer->vertex_pool);
- ClipPolygonPlane(polygon, mesh, renderer->clip_planes.z_neg, renderer->vertex_pool);
- ClipPolygonPlane(polygon, mesh, renderer->clip_planes.z_pos, renderer->vertex_pool);
+ int *polygonA = NewPolygon(renderer->polygon_pool);
+ int *polygonB = NewPolygon(renderer->alt_polygon_pool);
+
+ ClipPolygonPlane(polygon, polygonB, mesh, renderer->clip_planes.x_neg, renderer->vertex_pool, renderer->polygon_pool);
+ ClipPolygonPlane(polygonB, polygonA, mesh, renderer->clip_planes.x_pos, renderer->vertex_pool, renderer->polygon_pool);
+ ClearPolygon(polygonB, renderer->alt_polygon_pool);
+ ClipPolygonPlane(polygonA, polygonB, mesh, renderer->clip_planes.y_neg, renderer->vertex_pool, renderer->polygon_pool);
+ ClearPolygon(polygonA, renderer->polygon_pool);
+ ClipPolygonPlane(polygonB, polygonA, mesh, renderer->clip_planes.y_pos, renderer->vertex_pool, renderer->polygon_pool);
+ ClearPolygon(polygonB, renderer->alt_polygon_pool);
+ ClipPolygonPlane(polygonA, polygonB, mesh, renderer->clip_planes.z_neg, renderer->vertex_pool, renderer->polygon_pool);
+ ClearPolygon(polygonA, renderer->polygon_pool);
+ ClipPolygonPlane(polygonB, polygonA, mesh, renderer->clip_planes.z_pos, renderer->vertex_pool, renderer->polygon_pool);
+ // clipped polygon is in polygonA
}
-void ClipPolygonPlane(int *polygon, Mesh *mesh, Plane clipBoundary, Vertex *vertex_pool)
+int *NewPolygon(int *pool)
{
- Vertex *newCurrent, *intersection, *current, *previous;
+ assert(PoolTotal(pool) < MAX_RENDER_POLYGONS);
+ int *polygon = PoolNext(pool);
+ *polygon = 0;
+ return polygon;
+}
- if (NumPolygonVertices(polygon) == 0) return;
+void ClipPolygonPlane(int *srcPolygon, int *dstPolygon, Mesh *mesh, Plane clipBoundary, Vertex *vertex_pool, int *polygon_pool)
+{
+ Vertex *intersection, *current, *previous;
- previous = LastPolygonVertex(polygon, mesh->vertices);
- for (int i = 0; i < NumPolygonVertices(polygon); i++) {
- current = PolygonVertex(polygon, mesh->vertices, i);
+ if (NumPolygonVertices(srcPolygon) == 0) return;
+
+ previous = LastPolygonVertex(srcPolygon, mesh->vertices);
+ for (int i = 0; i < NumPolygonVertices(srcPolygon); i++) {
+ current = PolygonVertex(srcPolygon, mesh->vertices, i);
if (VertexInside(current, clipBoundary)) {
if (VertexInside(previous, clipBoundary)) {
- newCurrent = NewVertex(vertex_pool);
- *newCurrent = *current;
- mesh->numVertices++;
+ AddPolygonValue(dstPolygon, polygon_pool, PolygonValue(srcPolygon, i));
} else {
intersection = NewVertex(vertex_pool);
*intersection = ClipIntersect(previous, current, clipBoundary);
- newCurrent = NewVertex(vertex_pool);
- *newCurrent = *current;
+ AddPolygonValue(dstPolygon, polygon_pool, mesh->numVertices++);
+ AddPolygonValue(dstPolygon, polygon_pool, PolygonValue(srcPolygon, i));
}
} else {
if (VertexInside(previous, clipBoundary)) {
intersection = NewVertex(vertex_pool);
*intersection = ClipIntersect(previous, current, clipBoundary);
+ AddPolygonValue(dstPolygon, polygon_pool, mesh->numVertices++);
}
}
previous = current;
@@ 524,13 540,99 @@ void WireframePolygon(int *polygon, Vertex *vertices, Renderer *renderer)
previous = LastPolygonVertex(polygon, vertices);
for (int i = 0; i < NumPolygonVertices(polygon); i++) {
current = PolygonVertex(polygon, vertices, i);
- RasterLine(previous, current, WHITE, renderer);
+ RasterLine(*previous, *current, WHITE, renderer);
}
}
-void RasterLine(Vertex *a, Vertex *b, Color color, Renderer *renderer)
+void RasterLine(Vertex a, Vertex b, Color color, Renderer *renderer)
{
- // TODO
+ double dx = b.x - a.x;
+ double dy = b.y - a.y;
+ if (fabs(dy) < fabs(dx)) {
+ if (a.x > b.x) {
+ RasterLineShallow(b, a, color, renderer);
+ } else {
+ RasterLineShallow(a, b, color, renderer);
+ }
+ } else {
+ if (a.y > b.y) {
+ RasterLineSteep(b, a, color, renderer);
+ } else {
+ RasterLineSteep(a, b, color, renderer);
+ }
+ }
+}
+
+void RasterLineShallow(Vertex a, Vertex b, Color color, Renderer *renderer)
+{
+ double dx = b.x - a.x;
+ double dy = b.y - a.y;
+ double yi = 1;
+ if (dy < 0) {
+ yi = -1;
+ dy = -dy;
+ }
+
+ double d = 2*dy - dx;
+ double x;
+ double y = a.y;
+
+ for (x = a.x; x <= b.x; x++) {
+ double z = MapRange(x, a.x, b.x, a.z, b.z);
+ if (UpdateDepthBuffer(x, y, z, renderer)) {
+ WritePixel(x, y, color, renderer);
+ }
+ if (d > 0) {
+ y += yi;
+ d -= 2*dx;
+ }
+ d += 2*dy;
+ }
+}
+
+void RasterLineSteep(Vertex a, Vertex b, Color color, Renderer *renderer)
+{
+ double dx = b.x - a.x;
+ double dy = b.y - a.y;
+ double xi = 1;
+ if (dx < 0) {
+ xi = -1;
+ dx = -dx;
+ }
+
+ double d = 2*dx - dy;
+ double x = a.x;
+ double y;
+
+ for (y = a.y; y <= b.y; y++) {
+ double z = MapRange(y, a.y, b.y, a.z, b.z);
+ if (UpdateDepthBuffer(x, y, z, renderer)) {
+ WritePixel(x, y, color, renderer);
+ }
+ if (d > 0) {
+ x += xi;
+ d -= 2*dy;
+ }
+ d += 2*dx;
+ }
+}
+
+void WritePixel(int x, int y, Color color, Renderer *renderer)
+{
+ Pixel p = ColorPixel(color);
+ if (x >= 0 && x < renderer->width && y >= 0 && y < renderer->height) {
+ renderer->pixels[(renderer->height - 1 - y)*renderer->width+x] = p;
+ }
+}
+
+bool UpdateDepthBuffer(int x, int y, double z, Renderer *renderer)
+{
+ if (z > renderer->depthBuffer[y*renderer->width+x]) {
+ renderer->depthBuffer[y*renderer->width+x] = z;
+ return true;
+ } else {
+ return false;
+ }
}
void RenderParticle(Particle particle, Renderer *renderer)