Quote:
Originally Posted by deimos
Edit: Oh, post-process the result...
Edit 2: I could just draw the line again to do that, I know where it starts and ends. I'll investigate this further. Adding the line is a kludge, I don't have a problem adding a second kludge to unkludge it.
|
I've now implemented that, and it works sweet, and I think is probably pretty efficient.
But my code is a complexity of nested if statements for all the different cases of how the horizon line might cross each edge of the screen, and I can't see an obvious way of simplifying it. If anyone can point out what I think I must be missing, that would be great:
Code:
void GroundAndSky_Draw(const Camera * camera) {
WORD displayHeight = display.displayMode == SPLIT_SCREEN_DISPLAY_MODE ? SPLIT_SCREEN_MAIN_DISPLAY_HEIGHT :
DISPLAY_HEIGHT;
LONG a = ((Entity *) camera)->transformation.rotation.value[0][1];
LONG b = ((Entity *) camera)->transformation.rotation.value[1][1];
LONG cz = ((Entity *) camera)->transformation.rotation.value[2][1] << 8; // 2^8 = 256 = viewing distance
LONG topY = displayHeight / 2 - 1;
LONG rightX = DISPLAY_WIDTH / 2 - 1;
LONG bottomY = -displayHeight / 2;
LONG leftX = -DISPLAY_WIDTH / 2;
BOOL topLeft = a * leftX + b * topY + cz < 0;
BOOL topRight = a * rightX + b * topY + cz < 0;
BOOL bottomRight = a * rightX + b * bottomY + cz < 0;
BOOL bottomLeft = a * leftX + b * bottomY + cz < 0;
BOOL intersectsTop = topLeft != topRight;
BOOL intersectsRight = topRight != bottomRight;
BOOL intersectsBottom = bottomLeft != bottomRight;
BOOL intersectsLeft = topLeft != bottomLeft;
if (intersectsTop) {
Point2D p0 = {{ rightX - (cz + b * topY) / a, 0 }};
if (intersectsRight) { // top edge to right edge
WORD y = topY + (cz + a * rightX) / b;
Point2D p1 = {{ DISPLAY_WIDTH - 1, y }};
Point2D line [2] = { p0, p1 };
WORD kludge [2] = { y + 1, displayHeight - 1 };
BOOL fci = topRight;
FancyBlitterFillWithKludge(line, kludge, fci);
} else if (intersectsBottom) { // top edge to bottom edge
Point2D p1 = {{ rightX - (cz - b * topY) / a, displayHeight - 1 }};
Point2D line [2] = { p0, p1 };
BOOL fci = topRight;
FancyBlitterFill(line, fci);
} else if (intersectsLeft) { // top edge to left edge
WORD y = topY + (cz - a * rightX) / b;
Point2D p1 = {{ 0, y }};
Point2D line [2] = { p0, p1 };
BOOL fci = !topLeft;
FancyBlitterFill(line, fci);
}
} else if (intersectsRight) {
if (intersectsBottom) { // right edge to bottom edge
WORD y = topY + (cz + a * rightX) / b;
Point2D p2 = {{ DISPLAY_WIDTH - 1, y }};
Point2D p3 = {{ rightX - (cz - b * topY) / a, displayHeight - 1 }};
Point2D line [2] = { p2, p3 };
WORD kludge [2] = { 0, y - 1 };
BOOL fci = !topLeft;
FancyBlitterFillWithKludge(line, kludge, fci);
} else if (intersectsLeft) { // left edge to right edge
WORD yLeft = topY + (cz - a * rightX) / b;
WORD yRight = topY + (cz + a * rightX) / b;
Point2D p0 = {{ 0, yLeft }};
Point2D p1 = {{ DISPLAY_WIDTH - 1, yRight }};
Point2D line [2] = { p0, p1 };
if (topLeft) {
if (yRight > yLeft) {
WORD kludge [2] = { yRight + 1, displayHeight - 1 };
FancyBlitterFillWithKludge(line, kludge, TRUE);
} else {
WORD kludge [2] = { 0, yRight - 1 };
FancyBlitterFillWithKludge(line, kludge, FALSE);
}
} else {
if (yRight < yLeft) {
WORD kludge [2] = { 0, yRight - 1 };
FancyBlitterFillWithKludge(line, kludge, TRUE);
} else {
WORD kludge [2] = { yRight + 1, displayHeight - 1 };
FancyBlitterFillWithKludge(line, kludge, FALSE);
}
}
}
} else if (intersectsBottom) { // bottom edge to left edge
Point2D p0 = {{ 0, topY + (cz - a * rightX) / b }};
Point2D p1 = {{ rightX - (cz - b * topY) / a, displayHeight - 1 }};
Point2D line [2] = { p0, p1 };
BOOL fci = topRight;
FancyBlitterFill(line, fci);
} else { // no intersections
BlitterFill(topLeft);
}
}