Finally the crux of the problem, the Z-buffer. Again according to the
wiki article on perspective projection, determining the pixel X and Y coordinates was easy, since the projected X and Y (pX, pY, pZ) are guaranteed to be between -1 and 1, and it worked like a charm.
pixelX = (((pX/ pZ) * 0.5) + 0.5) * renderingWidth
pixelY = (((pY/ pZ) * 0.5) + 0.5) * renderingHeight[/CODE]
Z-buffering requires a distance (or depth) per pixel, however, and doing a matrix multiply for every pixel, every polygon seemed like quite a bit of overkill. Since I've already guaranteed that all of the points are co-planar, I figured that in my fillPolygon call I could easily determine the equation of the plane made up by the [B]projected[/B] points of the polygon, then use that to find the z values for each item. The first step was to convert the pixel values (pixelX, pixelY) back to world coordinates (pX, pY) or (projectedX, projectedY), as shown in the first 2 lines below. Calculating the z in world-coordinates was a simple matter of using the equation for the plane found earlier. Finally, taking the distance from there to the camera (cX, cY, cZ) is easy...
[CODE]
pX = ((pixelX / renderingWidth) - 0.5) * 2
pY = ((pixelY / renderingHeight) - 0.5) * 2
pZ = {Use equation for a plane from projected end points of polygon to determine pZ)
pD = sqrt((cX-pX)^2 + (cY-pY)^2 + (cZ-pZ)^2)[/CODE]
With that distance, I used a simple formula (from the [URL="
http://en.wikipedia.org/wiki/Z-buffering"]z-buffer wiki article[/URL]) to scale all viewable Z depths (from sdNear {scaledDistNear} to sdFar {scaledDistFar}) from -1 to 1.
[CODE]sD = ((sdFar + sdNear)/(sdFar - sdNear)) + (1 / pD) * ((-2 * sdFar * sdNear)/(sdFar - sdNear))[/CODE]
That formula also worked as expected, and yielded values between -1 and 1. From there, implementing the Z-buffer was trivial, but, as is usually the case with this much code, there were problems.
[/SPOILER]
[SIZE="4"]The questions / tl;dr[/SIZE]
For clarification, at this point the all of my math does work, and with the Z-buffer off, it shows the classic problems with simply setting a paint order (two objects intersecting through each other, etc). This means that my math for determining the pixelX, pixelY and the fillPolygon call itself are acting appropriately.
The Z-buffer does function, but it has difficulty with a certain subset of camera theta and phi angles (azimuth and elevation). I have deduced that this has to do with my assessment of the pZ coordinate on a per pixel basis. All of that in mind...
[LIST]
[*]What needs to be done to the a perspective projected Z coordinate when the projection is complete? At the moment, I just leave it as it is, alongside it's projected x and y coordinate (in world coordinates), in order to get an equation of a plane from several of the projected points
[*]Is it even mathematically correct to assume that if several (10 to 12) points are co-planar [B]before[/B] perspective projection, that they will [B]still[/B] be co-planar after?
[*]Should I be using some other point as a reference for the final distance calculation? At the moment, I'm using the camera position (cX, cY, cZ) in world coordinates.
[*]Anything else I should be looking out for?
[/LIST][CODE]pixelX = (((pX/ pZ) * 0.5) + 0.5) * renderingWidth
pixelY = (((pY/ pZ) * 0.5) + 0.5) * renderingHeight[/CODE]
Z-buffering requires a distance (or depth) per pixel, however, and doing a matrix multiply for every pixel, every polygon seemed like quite a bit of overkill. Since I've already guaranteed that all of the points are co-planar, I figured that in my fillPolygon call I could easily determine the equation of the plane made up by the
projected points of the polygon, then use that to find the z values for each item. The first step was to convert the pixel values (pixelX, pixelY) back to world coordinates (pX, pY) or (projectedX, projectedY), as shown in the first 2 lines below. Calculating the z in world-coordinates was a simple matter of using the equation for the plane found earlier. Finally, taking the distance from there to the camera (cX, cY, cZ) is easy...
pX = ((pixelX / renderingWidth) - 0.5) * 2
pY = ((pixelY / renderingHeight) - 0.5) * 2
pZ = {Use equation for a plane from projected end points of polygon to determine pZ)
pD = sqrt((cX-pX)^2 + (cY-pY)^2 + (cZ-pZ)^2)[/CODE]
With that distance, I used a simple formula (from the [URL="
http://en.wikipedia.org/wiki/Z-buffering"]z-buffer wiki article[/URL]) to scale all viewable Z depths (from sdNear {scaledDistNear} to sdFar {scaledDistFar}) from -1 to 1.
[CODE]sD = ((sdFar + sdNear)/(sdFar - sdNear)) + (1 / pD) * ((-2 * sdFar * sdNear)/(sdFar - sdNear))[/CODE]
That formula also worked as expected, and yielded values between -1 and 1. From there, implementing the Z-buffer was trivial, but, as is usually the case with this much code, there were problems.
[/SPOILER]
[SIZE="4"]The questions / tl;dr[/SIZE]
For clarification, at this point the all of my math does work, and with the Z-buffer off, it shows the classic problems with simply setting a paint order (two objects intersecting through each other, etc). This means that my math for determining the pixelX, pixelY and the fillPolygon call itself are acting appropriately.
The Z-buffer does function, but it has difficulty with a certain subset of camera theta and phi angles (azimuth and elevation). I have deduced that this has to do with my assessment of the pZ coordinate on a per pixel basis. All of that in mind...
[LIST]
[*]What needs to be done to the a perspective projected Z coordinate when the projection is complete? At the moment, I just leave it as it is, alongside it's projected x and y coordinate (in world coordinates), in order to get an equation of a plane from several of the projected points
[*]Is it even mathematically correct to assume that if several (10 to 12) points are co-planar [B]before[/B] perspective projection, that they will [B]still[/B] be co-planar after?
[*]Should I be using some other point as a reference for the final distance calculation? At the moment, I'm using the camera position (cX, cY, cZ) in world coordinates.
[*]Anything else I should be looking out for?
[/LIST][CODE]
pX = ((pixelX / renderingWidth) - 0.5) * 2
pY = ((pixelY / renderingHeight) - 0.5) * 2
pZ = {Use equation for a plane from projected end points of polygon to determine pZ)
pD = sqrt((cX-pX)^2 + (cY-pY)^2 + (cZ-pZ)^2)[/CODE]
With that distance, I used a simple formula (from the
z-buffer wiki article) to scale all viewable Z depths (from sdNear {scaledDistNear} to sdFar {scaledDistFar}) from -1 to 1.
sD = ((sdFar + sdNear)/(sdFar - sdNear)) + (1 / pD) * ((-2 * sdFar * sdNear)/(sdFar - sdNear))[/CODE]
That formula also worked as expected, and yielded values between -1 and 1. From there, implementing the Z-buffer was trivial, but, as is usually the case with this much code, there were problems.
[/SPOILER]
[SIZE="4"]The questions / tl;dr[/SIZE]
For clarification, at this point the all of my math does work, and with the Z-buffer off, it shows the classic problems with simply setting a paint order (two objects intersecting through each other, etc). This means that my math for determining the pixelX, pixelY and the fillPolygon call itself are acting appropriately.
The Z-buffer does function, but it has difficulty with a certain subset of camera theta and phi angles (azimuth and elevation). I have deduced that this has to do with my assessment of the pZ coordinate on a per pixel basis. All of that in mind...
[LIST]
[*]What needs to be done to the a perspective projected Z coordinate when the projection is complete? At the moment, I just leave it as it is, alongside it's projected x and y coordinate (in world coordinates), in order to get an equation of a plane from several of the projected points
[*]Is it even mathematically correct to assume that if several (10 to 12) points are co-planar [B]before[/B] perspective projection, that they will [B]still[/B] be co-planar after?
[*]Should I be using some other point as a reference for the final distance calculation? At the moment, I'm using the camera position (cX, cY, cZ) in world coordinates.
[*]Anything else I should be looking out for?
[/LIST][CODE]sD = ((sdFar + sdNear)/(sdFar - sdNear)) + (1 / pD) * ((-2 * sdFar * sdNear)/(sdFar - sdNear))[/CODE]
That formula also worked as expected, and yielded values between -1 and 1. From there, implementing the Z-buffer was trivial, but, as is usually the case with this much code, there were problems.
Posts
How is this different than a perspective transformation? The perspective handles the big/small issue... and that's about all I need. Albeit, my case is insanely simple relative to a real graphics engine (no shading, shadows, texture mapping, HLSL, etc)
edit: That wikipedia article is kinda weird. As a first attempt I'd ditch that chunk of math and make your "perspective transformation" just chopping off the Z coordinate.
One other benefit to using a proper camera transform is that finding the depth buffer values becomes trivial- it's just the z coordinates of your pixel locations in camera space.
Disclaimer: I haven't worked on graphics this low level for 7 or 8 years, so most of this is subject to a quick and dirty implementation and sanity check.
After checking all of the math on my previous implementation, you're absolutely right. Co-planarity before does not necessarily imply co-planarity after. So it's on to triangles!
Cause...yeah...yeah I did fucking need it.