Class 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 a main() 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 to ZBITS_16.
      static int ZBITS_0
      Values of zBits 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)
      Array pix will be used to store pixel information; the array's length must therefore be at least width*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 where normal 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 with drawPoint().
      void setClip​(ClipRectangle clip)
      The clip determines how much of an object [to be rendered] is visible.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • ZBITS_0

        public static final int ZBITS_0
        Values of zBits 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 to ZBITS_16. Allowable quantities for z buffer bits are between ZBITS_0 and ZBITS_24, inclusive.
        See Also:
        Constant Field Values
    • Constructor Detail

      • RasterDepthGraphics

        public RasterDepthGraphics​(int[] pix,
                                   int width,
                                   int height,
                                   double zFront,
                                   double zBack)
        Array pix will be used to store pixel information; the array's length must therefore be at least width*height.

        Orientation: imagePixel(x,y) = pix[y*width + x]. The values stored in 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 integer 0xff0000ff 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 and zBack 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 of zFront, then the object would still be rendered. Likewise is the case for objects having vertices all of which have a z coordinate of zBack.

        See Also:
        RasterDepthGraphics(RasterDepthPixBuff)
      • RasterDepthGraphics

        public RasterDepthGraphics​(int[] pix,
                                   int width,
                                   int height,
                                   int zBits,
                                   double zFront,
                                   double zBack)
        Parameters:
        zBits - should be between ZBITS_0 and ZBITS_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 with drawPoint(). 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 to drawPoint().

        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 where normal has a negative z component, or where this z component is within an epsilon value of zero, which would otherwise cause inaccurate computations. Technically normal 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 of Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, and Double.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 exactly normal[2]. And pi/(2*65536) is equal to approximately 0.000024.

        Specified by:
        drawPoint in interface DepthGraphics
      • 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 interface DepthGraphics
      • 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 interface DepthGraphics
      • 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 interface DepthGraphics
      • 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 interface DepthGraphics
      • 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 interface DepthGraphics
      • getClip

        public ClipRectangle getClip()
        Modifying the returned value will have no impact on the actual clip area.
        Specified by:
        getClip in interface DepthGraphics
      • 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 interface DepthGraphics