home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format 19
/
af019.adf
/
MOSAIC_TEXT
< prev
next >
Wrap
Text File
|
1978-04-04
|
6KB
|
239 lines
Submission Ref: A374/1-1 Author: PAUL OVERAA
Title: Mosaic Transfer
Copy Date: 4th November 1990
------------------------------------------------
Paul Overaa describes a trick that's useful for
creating random mosaic fades and copy effects...
------------------------------------------------
I've got to admit at the outset that my heart is not really into
graphics programming. The underlying theoretical stuff is interesting but,
in practice, it all seems to get a bit too 'dirty' and machine dependent
for my liking. With high-speed processors you can do things cleanly, but
on most 16 bit computers you're forever having to cut corners to keep
the speed up.
Occasionally however I get attracted by the odd graphics problem and
such is the case with this month's little excursion...
You've no doubt seen those TV effects where the picture breaks into
hundreds of small squares which are then randomly disintegrated, faded
or otherwise modified. These 'mosaic' rearrangements aren't too difficult
to do and, since I've been playing around with a few ideas in this area,
I thought it might be a useful topic to look at.
Let's suppose then that we consider a rectangular 'source' area of the
screen as being broken into an unspecified number of smaller rectangular
blocks. It seems reasonable to identify these blocks by some co-ordinate
scheme and I've opted for using the top left co-ordinates in all cases.
If we do this it becomes possible to create a nice simple model whereby
identified screen blocks such as...
*------*------*-----.... etc
| | |
*------*------*--
| | |
*------*---
| |
*---
.
.
.
etc.
are represented just by their virtual top-left co-ordinates...
* * * .... etc. (0,0) (1,0) (2,0)... etc.
* * * (0,1) (1,1) (2,1)
<--- top left points
* * are stored as (0,2) (1,2)
. the array --->
* . (0,3)... etc.
. .
etc.
In other words we can describe the locations of all of the blocks in a
mosaic pattern by an array containing the (x,y) block number co-ordinates.
Rather than use a two dimensional array I will, in the following discussion,
be using separate x and y vectors. There's no real difference as far as
coding complexity goes, but the vector approach does make the explanations
a little easier to understand.
Essentially the problems we're solving are these:
Firstly we want to find a way of generating a random, or apparently random,
set of block (x,y) co-ordinates without eating into too much memory (ie
without building lists of every possible co-ordinate pair).
Secondly we want a way of accessing these co-ordinates using a mechanism
which ensures that, after the 'random' operations have been completed,
every co-ordinate pair will have been used.
One obvious way to ensure that every mosaic block would be used is to
use a twin loop like this...
for (x=0; x<XMAX; x++)
{
for (y=0; y<YMAX; y++)
{
do something with block (x,y)
eg copy block (x,y) to location (x+offset_X, y+offset_Y)
}
}
This moves all of the blocks but it does so in a uniform way. What we
want is some way of randomizing the x and y co-ordinates. To start with
let's assume that we have a mosaic block 'vertical_block_count' blocks
high and 'horizontal_block_count' blocks wide. We can create a random, but
complete, list of vertical co-ordinates by initializing and rearranging
the values like this...
for (n=0; n<vertical_block_count; n++) { yvector[n]=n; }
for (n=0; n<vertical_block_count; n++)
{
r=rand() % vertical_block_count;
d=yvector[n];
yvector[n]=yvector[r];
yvector[r]=d;
}
Now we carry out a similar operation (based incidentally on a mathematically
sound mod co-ordinate offset relationship) on the horizontal co-ordinate
set...
for (n=0; n<horizontal_block_count; n++)
{
xvector[n] = rand() % horizontal_block_count;
n_rand[n] = n;
}
for (n=0; n<horizontal_block_count; n++)
{
r=rand() % horizontal_block_count;
d=n_rand[n];
n_rand[n]=n_rand[r];
n_rand[r]=d;
}
With that done the only thing needed now is to use a standard twin loop
arrangement to read the jumbled up block co-ordinates.
Here's some example code for handling the calculations and data transfer.
Firstly the block co-ordinates are calculated, secondly they are converted
to real screen locations, finally the base addresses of the source and
target areas are added to provide the co-ordinates which are going to be
used. I've used a couple of system calls BltBitMap() and RectFill()
to move the data but obviously how you use the final co-ordinates depends
on what you're wishing to do.
Normally a lot of the operations shown in the following piece of code
would be coded together but, for clarity, I've written them so that the
individual stages are distinguishable...
for (m=0; m<vertical_block_count; m++)
{
for (n=0; n<horizontal_block_count; n++)
{
/* calculate the block co-ordinates... */
target_x=source_x = n_rand[n];
target_y=source_y = ((yvector[m] + xvector[n]) % vertical_block_count);
/* now translate to real screen co-ordinates... */
target_x=source_x*=pixel_block_width;
target_y=source_y*=pixel_block_height;
/* add the base addresses and move the data... */
source_x+=x_source_base;
source_y+=y_source_base;
target_x+=x_target_base;
target_y+=y_target_base;
BltBitMap(global_rastport_p->BitMap, source_x, source_y,
global_rastport_p->BitMap, target_x, target_y,
pixel_block_width, pixel_block_height, 0x30, 0xFF);
RectFill(global_rastport_p,source_x,source_y,
source_x+pixel_block_width-1,source_y+pixel_block_height-1);
}
}
You will find a WorkBench/CLI runable example, together with the source
code, in the 'mosaic' folder of the cover disk.