Class RasterDepthGraphics
- java.lang.Object
-
- com.nerius.grafx.d3.RasterDepthGraphics
-
- All Implemented Interfaces:
DepthGraphics
public class RasterDepthGraphics extends java.lang.Object implements DepthGraphics
Implementation of a 3D graphics rendering library, with hooks to do custom pixel and z buffer manipulations. At the moment texture mapping and custom lighting calculations are not supported but will very likely be in the next release. Color interpolation between polygon vertices is supported, as is color interpolation between line segment endpoints.An extreme degree of attention is paid to pixel x,y locations and to the interpolated z values; a relatively expensive method of casting from 64 bit space to 32 bit space is employed to "chop off" accumulation errors. However, in the case of color interpolation, all such techniques are not employed for the sake of making this code somewhat performance-oriented. Implementing similar techniques for exact color correctness on every pixel would require a significant amount of coding effort, and it would effect the runtime performance negatively.
I consider this creation to be an interactive educational tool, which is coded in such a way that makes it easily studied and easily translatable to other programming languages that support IEEE 64 bit floating point numbers. This library exposes a modern line-drawing technique that is far superior to Bresenham's way of drawing lines, and which draws lines with an extreme degree of pixel-level accuracy, making the task of drawing two "nearly overlapping" line segments which have slightly shifted endpoints [in the direction of line] very favorable with respect to having their pixels overlap perfectly. At the very least I would encourage anyone studying the intricacies of this 3D rendering library to realize that the line-drawing strategy that it employs is both novel and correct. A very good demo exists with many tweakable parameters (including wireframe drawing), for purposes of better comprehending what this 3D rendering library does and how to use it properly. That demo code is embodied in the class
com.nerius.grafx.d3.demo.Donut
, which defines amain()
method and can be run from the command-line with no arguments passed to it.
-
-
Field Summary
Fields Modifier and Type Field Description static int
DEFAULT_ZBITS
This value is currently set toZBITS_16
.static int
ZBITS_0
Values ofzBits
which are less than eight may be useful for debugging, for demonstrational, and for educational purposes.static int
ZBITS_16
Allowable number of bits to use for z buffering, medium resolution.static int
ZBITS_24
Allowable number of bits to use for z buffering, high resolution.static int
ZBITS_8
Allowable number of bits to use for z buffering, low resolution.
-
Constructor Summary
Constructors Constructor Description RasterDepthGraphics(int[] pix, int width, int height, double zFront, double zBack)
Arraypix
will be used to store pixel information; the array's length must therefore be at leastwidth*height
.RasterDepthGraphics(int[] pix, int width, int height, int zBits, double zFront, double zBack)
RasterDepthGraphics(RasterDepthPixBuff pixBuff)
Allows for custom pixel and z buffer manipulation, including the proper handling of translucent or transparent pixels.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
clear(FloatColor color)
Paints the current clip area.void
drawLine(double x0, double y0, double z0, double x1, double y1, double z1, FloatColor color)
Draws a line of constant color.void
drawLine(double x0, double y0, double z0, FloatColor color0, double x1, double y1, double z1, FloatColor color1)
Draws a line of varying color.void
drawPoint(double x, double y, double z, FloatColor color, double[] normal)
Callers of this function may choose to implement "back face culling" by dropping calls wherenormal
has a negative z component, or where this z component is within an epsilon value of zero, which would otherwise cause inaccurate computations.void
fillPolygon(double[] xPts, double[] yPts, double[] zPts, int offset, int numPts, FloatColor color)
Fills a polygon of constant color.void
fillPolygon(double[] xPts, double[] yPts, double[] zPts, FloatColor[] colors, int offset, int numPts)
Fills a polygon of varying color.ClipRectangle
getClip()
Modifying the returned value will have no impact on the actual clip area.static void
getPointAlias(double x, double y, double[] resultXY)
Gives information regarding choice of aliased sample point when drawing withdrawPoint()
.void
setClip(ClipRectangle clip)
The clip determines how much of an object [to be rendered] is visible.
-
-
-
Field Detail
-
ZBITS_0
public static final int ZBITS_0
Values ofzBits
which are less than eight may be useful for debugging, for demonstrational, and for educational purposes.- See Also:
- Constant Field Values
-
ZBITS_8
public static final int ZBITS_8
Allowable number of bits to use for z buffering, low resolution. Divides the z dimension into 256 discrete buckets.- See Also:
- Constant Field Values
-
ZBITS_16
public static final int ZBITS_16
Allowable number of bits to use for z buffering, medium resolution. Recommended.- See Also:
- Constant Field Values
-
ZBITS_24
public static final int ZBITS_24
Allowable number of bits to use for z buffering, high resolution. The problem with this mode is that accumulation errors don't get chopped as effectively.- See Also:
- Constant Field Values
-
DEFAULT_ZBITS
public static final int DEFAULT_ZBITS
This value is currently set toZBITS_16
. Allowable quantities for z buffer bits are betweenZBITS_0
andZBITS_24
, inclusive.- See Also:
- Constant Field Values
-
-
Constructor Detail
-
RasterDepthGraphics
public RasterDepthGraphics(int[] pix, int width, int height, double zFront, double zBack)
Arraypix
will be used to store pixel information; the array's length must therefore be at leastwidth*height
.Orientation:
. The values stored inimagePixel(x,y) = pix[y*width + x]
pix
represent color in the ARGB format: in each 32 bit integer, bits 24-31 (the high bits) are alpha, bits 16-23 are red, bits 8-15 are green, and bits 0-7 (the low bits) are blue. For example, an integer0xff0000ff
represents the fully opaque color bright blue.Pixel data is written through; no alpha blending is done. For custom alpha blending logic, you must subclass
RasterDepthPixBuff
and use one of the other constructors.The boundary values
zFront
andzBack
are intended to be inclusive bounds for the z value of objects. In other words, if a polygon/line is rendered having vertices which all have a z coordinate ofzFront
, then the object would still be rendered. Likewise is the case for objects having vertices all of which have a z coordinate ofzBack
.- See Also:
RasterDepthGraphics(RasterDepthPixBuff)
-
RasterDepthGraphics
public RasterDepthGraphics(int[] pix, int width, int height, int zBits, double zFront, double zBack)
- Parameters:
zBits
- should be betweenZBITS_0
andZBITS_24
, inclusive.- See Also:
RasterDepthGraphics(int[],int,int,double,double)
-
RasterDepthGraphics
public RasterDepthGraphics(RasterDepthPixBuff pixBuff)
Allows for custom pixel and z buffer manipulation, including the proper handling of translucent or transparent pixels.
-
-
Method Detail
-
getPointAlias
public static void getPointAlias(double x, double y, double[] resultXY)
Gives information regarding choice of aliased sample point when drawing withdrawPoint()
. The x and y coordinates of computed sample point are both always exactly halfway between two consecutive integers (in other words the x and y coordinates are both an integer plus 0.5). The pixel that gets turned on (if within bounds and in front) has coodinates which are each the floor value of the quantities returned here. The purpose of this function call is to allow drawing of polygon vertices by outside callers; if multiple polygons meet at a vertex, this function call will answer the question, which of the polygons contains the sample point, for purposes of then passing the correct normal todrawPoint()
.No clipping is done here, and negative input values are still honored.
-
drawPoint
public void drawPoint(double x, double y, double z, FloatColor color, double[] normal)
Callers of this function may choose to implement "back face culling" by dropping calls wherenormal
has a negative z component, or where this z component is within an epsilon value of zero, which would otherwise cause inaccurate computations. Technicallynormal
does not need to necessarily be a normalized vector.The computations implemented do handle the situations where
normal[2]
is equal to zero or is infinitesimally close to zero, by doing proper handling ofDouble.NEGATIVE_INFINITY
,Double.POSITIVE_INFINITY
, andDouble.NaN
. In such cases no pixel is drawn, due to z buffer bounds which are finite.Because the computation for determining correct z value of pixel sample point becomes inaccurate as
normal[2]
becomes very small, it is suggested to cull calls where the angle of normal is within a small epsilon of zero, with respect to the x/y plane. Dividing a 90 degrees angle into 65536 equal angles, and taking such a small angle as a minimum angle for this normal (with respect to x/y plane) seems like a reasonable choice. For small value of theta (in radians), we have sin(theta) is approximately equal to theta. But this is exactlynormal[2]
. And pi/(2*65536) is equal to approximately 0.000024.- Specified by:
drawPoint
in interfaceDepthGraphics
-
drawLine
public void drawLine(double x0, double y0, double z0, double x1, double y1, double z1, FloatColor color)
Description copied from interface:DepthGraphics
Draws a line of constant color.- Specified by:
drawLine
in interfaceDepthGraphics
-
drawLine
public void drawLine(double x0, double y0, double z0, FloatColor color0, double x1, double y1, double z1, FloatColor color1)
Description copied from interface:DepthGraphics
Draws a line of varying color. The color of a point on the line will be determined by interpolating the colors of the line's endpoints in some reasonable manner.- Specified by:
drawLine
in interfaceDepthGraphics
-
fillPolygon
public void fillPolygon(double[] xPts, double[] yPts, double[] zPts, int offset, int numPts, FloatColor color)
Description copied from interface:DepthGraphics
Fills a polygon of constant color.- Specified by:
fillPolygon
in interfaceDepthGraphics
-
fillPolygon
public void fillPolygon(double[] xPts, double[] yPts, double[] zPts, FloatColor[] colors, int offset, int numPts)
Description copied from interface:DepthGraphics
Fills a polygon of varying color. The color of a point on the polygon will be determined by interpolating the colors of the polygon's vertices.If a polygon contains more than three vertices, then those vertices should lie on the same physical plane and on the same color plane. If this isn't the case then the definition of color and distance from camera may not be uniquely defined.
The interior of a polygon may be defined in different ways for self-intersecting polygons; for example, an even-odd rule or a non-zero-winding-number rule may be used to define the interior of a self-intersecting polygon.
- Specified by:
fillPolygon
in interfaceDepthGraphics
-
setClip
public void setClip(ClipRectangle clip)
Description copied from interface:DepthGraphics
The clip determines how much of an object [to be rendered] is visible. The clip does not necessarily force objects to be clipped against it before they are rendered; rather, you can think of objects being rendered onto an infinite [blank] canvas, and then the clip would be applied to the canvas to determine how much of the object is visible; the visible portion would then be actually painted. This principle is important for objects such as lines, for example, which are represented by an infinitely thin line but may, when rendered, have some thickness.- Specified by:
setClip
in interfaceDepthGraphics
-
getClip
public ClipRectangle getClip()
Modifying the returned value will have no impact on the actual clip area.- Specified by:
getClip
in interfaceDepthGraphics
-
clear
public void clear(FloatColor color)
Description copied from interface:DepthGraphics
Paints the current clip area. All z-information for objects previously rendered within this clip area will be reset.clear()
is required to clobber all visual information in the current clip; transparent or translucent colors should not be handled in a special way.- Specified by:
clear
in interfaceDepthGraphics
-
-