[comp.sys.amiga.tech] Area Fills

33014-18@sjsumcs.sjsu.edu (Eduardo Horvath) (10/27/89)

   Does anybody out there have code for fast area fills using the blitter?
I have been putting together a program that has been rendering a large number
( >100 ) of multi-colored polygons in real time.  At first I sent each poly
to Area...() separately ( Called AreaEnd() between each 2 polys ) but that was
too slow.  Then I only called AreaEnd() at the end of each frame, but all I
got was a mono-chromatic blob, although the rendering speed more than doubled.
In the last version, I separated the colors and rendered them separately, but
the frame rate is not much better than the first method.

   I am on the point of junking GfxBase and poking around in the blitter
myself, so I would appreceate (sp?) any ideas on how to sort lines so when
they are filled, the colors go in the right places.


===============================================================================
         //x                                    =	MEN AT WORK
        /// \	Try:  33014-18@sjsumcs.SJSU.EDU =
       ///   \                                  =	This space
      ///     \		Eduardo Horvath		=	    is
\\\  ///=======\ 				=	   UNDER 
 \\\///         \				=	CONSTRUCTION
  \xxx           \miga. The computer for the corruptive mind.
===============================================================================

rap@peck.ardent.com (Rob Peck) (10/31/89)

In article <1989Oct27.162303.787@sjsumcs.sjsu.edu> 33014-18@sjsumcs.SJSU.EDU (Eduardo Horvath) writes:
>
> At first I sent each poly
>to Area...() separately ( Called AreaEnd() between each 2 polys ) but that was
>too slow.  Then I only called AreaEnd() at the end of each frame, but all I
>got was a mono-chromatic blob, although the rendering speed more than doubled.
>In the last version, I separated the colors and rendered them separately, but
>the frame rate is not much better than the first method.

In my BKDC2 contest entry, I created some 3D business graphics and tried
to get the maximum drawing speed out of the filled (and outlined) 3D bars
experimenting with the AreaMove, AreaDraw and placement of the AreaEnd
function relative to the others.  I found that the best speed was obtained
using the system functions when I rendered bunches of things at a time.
The key, however, to avoiding the blob is:

	"If you generate a single shape by using one AreaMove
	 command and an indefinite number of AreaDraw commands,
	 an AreaEnd will correctly generate a filled (and outlined)
	 area.
	 
	 If you generate multiple shapes by using several
	 groups of commands consisting each of:
	
	 	shape 1: One AreaMove + One or more AreaDraws
	 	shape 2: One AreaMove + One or more AreaDraws
		...
	 	shape n: One AreaMove + One or more AreaDraws

	 and then finally an AreaEnd, there can be NO overlapping
	 of polygonal shapes from the independent objects, though
	 the individual objects themselves may employ any number
	 of inter-object line crossings.

This is a largely experimental result, however thinking back to about 1986
and a conversation I had with Dale (that never quite got into the RKM's)
the areafill functions (AreaMove, AreaDraw) do not actually draw anything,
but simply create lists of things that will be drawn when AreaEnd is called.
The system needs the one-plane-deep TmpRas area as a workspace because it
actually uses that area into which the shapes are to be rendered.  The
area is used many times, once for each bitplane of the final shape.
The shapes are created in this background drawing area and then combined
with the area patterns, and line patterns, and then the writemask of the
RastPort is examined, and the drawing mode, combining the now fully formed
shape-plane with the target plane.  I don't remember whether a new shape
plane (in the TmpRas) is formed for each bitplane, but I don't think so.

Individual shapes are calculated so that a single blit to do the hardware
area fill from left to right will work correctly --- that is, look in the
hardware manual for the hardware area fill rules... filling of areas
begins and ends when a 1-bit is encountered on a line by line basis,
fill-on, fill-off, fill-on etc.  Thus each individual shape is carefully
calculated such that a hardware fill will correctly create the shape.
AreaMove, AreaDraw, AreaEnd, as a sequence, for any single shape, or
AreaMove, AreaDraw... AreaDraw... AreaDraw, AreaEnd is also acceptable
because the software is careful to position the line crossings and the
one or two dots on a line so that filling a shape goes as expected.

However if the user overlaps ANY of the shapes, all bets are off.  It
is no longer possible to say exactly what the rules for what to fill 
at the overlap points might possibly be.  Thus a monochrome blob is
perhaps the most likely result.

Rob Peck

33014-18@sjsumcs.sjsu.edu (Eduardo Horvath) (11/01/89)

In article <8888@ardent.UUCP> rap@peck.ardent.com (Rob Peck) writes:
>In article <1989Oct27.162303.787@sjsumcs.sjsu.edu> 33014-18@sjsumcs.SJSU.EDU (Eduardo Horvath) writes:
>>
>> At first I sent each poly
>>to Area...() separately ( Called AreaEnd() between each 2 polys ) but that was
>>too slow.  Then I only called AreaEnd() at the end of each frame, but all I
>>got was a mono-chromatic blob, although the rendering speed more than doubled.
>>In the last version, I separated the colors and rendered them separately, but
>>the frame rate is not much better than the first method.
>
>In my BKDC2 contest entry, I created some 3D business graphics and tried
>to get the maximum drawing speed out of the filled (and outlined) 3D bars
>experimenting with the AreaMove, AreaDraw and placement of the AreaEnd
>function relative to the others.  I found that the best speed was obtained
>using the system functions when I rendered bunches of things at a time.
>The key, however, to avoiding the blob is:
>
>	"If you generate a single shape by using one AreaMove
>	 command and an indefinite number of AreaDraw commands,
>	 an AreaEnd will correctly generate a filled (and outlined)
>	 area.

I started by doing this for each face, but speed for 30+ faces was abysmal.

>	 
>	 If you generate multiple shapes by using several
>	 groups of commands consisting each of:
>	
>	 	shape 1: One AreaMove + One or more AreaDraws
>	 	shape 2: One AreaMove + One or more AreaDraws
>		...
>	 	shape n: One AreaMove + One or more AreaDraws
>
>	 and then finally an AreaEnd, there can be NO overlapping
>	 of polygonal shapes from the independent objects, though
>	 the individual objects themselves may employ any number
>	 of inter-object line crossings.
>

I tried this next.  What I had were faces of differing colors coming in at
random due to depth sorting, etc.  What I ended up with was a blob *only
rendered in one color.*  Some of the lines and surfaces around the exterior
were also confused.  What I want to do is:

	SetAPen(Color1);
	AreaMove(Poly1); .... AreaDraw(Poly1);
	SetAPen(Color2);
	Area Move(Poly2); ..... AreaEnd(Poly2);
	
(This is, of course, greatly simplified to save space.)
Then when it finishes, I want the color of Poly1 to be different from the
color of Poly2.

>This is a largely experimental result, however thinking back to about 1986
>and a conversation I had with Dale (that never quite got into the RKM's)

[ details deleted ]

I had been able to infer that this must be how the functions worked from
the data structures involved.  But do they support more than one color per
AreaEnd() ?

>
>However if the user overlaps ANY of the shapes, all bets are off.  It
>is no longer possible to say exactly what the rules for what to fill 
>at the overlap points might possibly be.  Thus a monochrome blob is
>perhaps the most likely result.
>
>Rob Peck

Since I was trying to display a 3D object, the lines bordering the different
plygons should be the same.  Does that mean that there's an overlap?  There 
also seems to be a great deal of overhesd in the AreaEnd() function.  There are at least two blits (excluding line draws): one to fill the area in the TmpRas
and another to copy the area onto each bitplane that is being filled.  

Is there a good way to do the sorting and fixing of the lines so that:

	1)  Lines are clipped to the window boundaries.

	2)  Lines are separated by colors so I can execute a single blit-fill
		on each bit-plane at the end of each frame.

	3)  Polygons then appear in the color that was active when they were
		"rendered", not at the end of the operation.

	4)  Polygons are rendered correctly, regardless of overlapping.

	5)  Overhead is minimized.  I would like a minimum of two frames per
		second when rendering 100+ faces.

It is becoming apparent to me that I may need to write my own graphics kernel.
What I want to do is make the best use of the functions provided in the OS.


===============================================================================
         //x                                    =	MEN AT WORK
        /// \	Try:  33014-18@sjsumcs.SJSU.EDU =
       ///   \                                  =	This space
      ///     \		Eduardo Horvath		=	    is
\\\  ///=======\ 				=	   UNDER 
 \\\///         \				=	CONSTRUCTION
  \xxx           \miga. The computer for the corruptive mind.
===============================================================================

rap@peck.ardent.com (Rob Peck) (11/02/89)

In article <1989Oct31.191532.19902@sjsumcs.sjsu.edu> 33014-18@sjsumcs.SJSU.EDU (Eduardo Horvath) writes:

(quoting me):

>>       If you generate multiple shapes by using several
>>       groups of commands consisting each of:
>>
>>              shape 1: One AreaMove + One or more AreaDraws
>>              shape 2: One AreaMove + One or more AreaDraws
>>              ...
>>              shape n: One AreaMove + One or more AreaDraws
>>
>>       and then finally an AreaEnd, there can be NO overlapping
>>       of polygonal shapes from the independent objects, though
>>       the individual objects themselves may employ any number
>>       of inter-object line crossings.

>Since I was trying to display a 3D object, the lines bordering the different
>polygons should be the same.  Does that mean that there's an overlap? 

Note that the term overlap also refers to edge-to-edge abutment.

>I tried this next.  What I had were faces of differing colors coming in at
>random due to depth sorting, etc.  What I ended up with was a blob *only
>rendered in one color.*  Some of the lines and surfaces around the exterior
>were also confused.  What I want to do is:
>
>       SetAPen(Color1);
>       AreaMove(Poly1); .... AreaDraw(Poly1);
>       SetAPen(Color2);
>       Area Move(Poly2); ..... AreaEnd(Poly2);
>
....
....
>I had been able to infer that this must be how the functions worked from
>the data structures involved.  But do they support more than one color per
>AreaEnd() ?
>
NO.  The AreaEnd uses whatever is the current contents of the RastPort
as its key.  It uses the foreground pen for the primary color, the
background pen as the secondary color (if there is an area pattern
and/or a line pattern present).  It uses the current color of the
area outline pen to outline the shapes.


This areafilling system was designed to be a fast 2-D system that takes
advantage of the custom hardware area fill, but also assures that layering
operations always work as expected.

Re the overhead in AreaEnd... it has to be there to make sure that
no matter whether there are obscured or unobscured layers, the drawing
still happens correctly.  The fastest speed, though, will be obtained
by drawing directly into the Screen's RastPort, with no windows
attached to the screen, minimizes consideration of layers.


One way to solve the overlap problem before rendering would be to
calculate a bounding rectangle for each shape before it was added
to a list of shapes to be rendered.  If there is no bounding rectangle
overlap with previously added shapes (all prior to generating an
AreaEnd) there'd be no blob.

Doing a shape-overlap calculation would take a lot more effort and
I would not care to try to tackle it.

There is another method that Amiga supports directly, supported by
the blitter.  There is a bit that indicates whether as a result of a blit
there were any one bits in the result.  (Check the Hardware Manual
for this), but it would entail creating two single-plane rastports,
rendering the polygon shapes one at a time into one of the planes.
Then doing a single blit operation with an AND function between the
two planes, throwing away the output (turning off the store-to-destination
bit) and only examining the flag that said whether or not there were
any one's in the result of the operation.  That'd say whether or not
there was an overlap of the new polygon with any of the existing ones.
Then, if not, do an OR operation between the two planes and store the
result in the destination plane against which a new polygon can be
compared.   AreaMove, AreaDraw and AreaEnd could be used to create
the polygons and since they'd be working with a single-plane
RastPort, and with no layers to slice and dice, they'd be pretty
fast.   You'd keep rolling this background check until the first
overlap occurred, then do issue an AreaEnd for the main drawing area
instead of adding the thing that causes the blob.   Continue until
all shapes are drawn.  BLITLAB, by Tom Rokiki (available on a FISH
disk) contains more details about blitter register operations and can
let you experiment to verify what happens in cases of overlap.

Frankly, the bounding rectangle idea is probably a lot faster.

Rob Peck