french@caip.RUTGERS.EDU (12/12/85)
From: "french robert%d.mfenet"@LLL-MFE.ARPA
/*
MAND1.C - Graphics routines
Mandelbrot Self-Squared Dragon Generator
For the Commodore Amiga
Version 1.00
Accompanies MAND.C
Copyright (c) 1985, Robert S. French
Placed in the Public Domain
This program may be distributed free of charge as long as the above
notice is retained.
*/
/*-------------------*/
/* Lots of includes! */
#include <exec/types.h>
#include <exec/tasks.h>
#include <exec/libraries.h>
#include <exec/devices.h>
#include <devices/keymap.h>
#include <graphics/copper.h>
#include <graphics/display.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>
#include <graphics/view.h>
#include <graphics/gels.h>
#include <graphics/regions.h>
#include <hardware/blit.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <stdio.h>
/*-------------------*/
/* Misc. definitions */
#define EVER ;;
#define MAXX 640
#define MAXY 390
#define STARTY 10
#define TOPW2 w2->BorderTop
#define BOTTOMW2 (w2->Height - w2->BorderBottom)
#define LEFTW2 w2->BorderLeft
#define RIGHTW2 (w2->Width - w2->BorderRight)
/*---------------------------------*/
/* Fast-Floating-Point Definitions */
extern int SPFix();
extern int SPFlt();
extern int SPCmp();
extern int SPTst();
extern int SPAbs();
extern int SPNeg();
extern int SPAdd();
extern int SPSub();
extern int SPMul();
extern int SPDiv();
extern int SPAtan();
extern int SPSin();
extern int SPCos();
extern int SPTan();
extern int SPSincos();
extern int SPSinh();
extern int SPCosh();
extern int SPTanh();
extern int SPExp();
extern int SPLog();
extern int SPPow();
extern int SPSqrt();
extern int SPTieee();
extern int SPFieee();
extern int MathBase,MathTransBase;
/*----------------------*/
/* Graphics definitions */
extern struct GfxBase *GfxBase;
extern struct IntuitionBase *IntuitionBase;
struct RastPort *rp,*rp2;
struct ViewPort *vp;
struct TextAttr TextFont =
{
"topaz.font", /* Standard system font */
8, 0, 0
};
struct Window *w,*w2;
struct Screen *screen;
struct IntuiMessage *message;
struct NewScreen ns = {
0, 0, /* start position */
320, 200, 6, /* width, height, depth */
0, 1, /* detail pen, block pen */
HAM, /* Hold and Modify ViewMode */
CUSTOMSCREEN, /* screen type */
&TextFont, /* font to use */
"", /* default title for screen */
NULL /* pointer to additional gadgets */
};
struct NewWindow nw = {
0, 0, /* start position */
320, 200, /* width, height */
-1, -1, /* detail pen, block pen */
CLOSEWINDOW|MOUSEBUTTONS, /* IDCMP flags */
ACTIVATE|WINDOWCLOSE|BORDERLESS|BACKDROP,
/* window flags */
NULL, /* pointer to first user gadget */
NULL, /* pointer to user checkmark */
"Mandelbrot Dragons", /* window title */
NULL, /* pointer to screen (set below) */
NULL, /* pointer to superbitmap */
0, 0, 320, 200, /* ignored since not sizeable */
CUSTOMSCREEN /* type of screen desired */
};
struct NewWindow aw = {
0, 10,
100, 70,
-1, -1,
NULL,
WINDOWDRAG|WINDOWSIZING|SMART_REFRESH,
NULL,
NULL,
"Analysis",
NULL,
NULL,
0, 0, 320, 200,
CUSTOMSCREEN
};
long last_color;
/*----------------------------------*/
/* Miscellaneous Global Definitions */
extern union kludge {
float f;
int i;
} start_r,end_r,start_i,end_i; /* Block bounds for set */
extern int max_x,max_y; /* Graphics window size */
extern int max_count,color_inc,color_offset,color_set,color_mode,color_div;
extern int color_inset,func_num;
extern int v_starty,max_mem;
extern long v_offset;
extern UWORD *color_table,*v_mand_store;
extern int modified,want_read;
extern FILE *console,*v_fp,*redir_fp;
/*----------------*/
/* Color routines */
init_colors()
{
switch (color_set) {
case 0: init_cincr(); break;
case 1: init_c7rot(); break;
}
}
init_cincr()
{
UWORD i;
for (i=0;i<4096;i++)
*(color_table + i) = i;
}
init_c7rot()
{
UWORD i,j,*base;
base = color_table;
*(base++) = 0;
for (j=0;j<39;j++) {
for (i=1;i<16;i++)
*(base++) = i;
for (i=1;i<16;i++)
*(base++) = i << 4;
for (i=1;i<16;i++)
*(base++) = i << 8;
for (i=1;i<16;i++)
*(base++) = i | (i << 4);
for (i=1;i<16;i++)
*(base++) = i | (i << 8);
for (i=1;i<16;i++)
*(base++) = (i << 4) | (i << 8);
for (i=1;i<16;i++)
*(base++) = i | (i << 4) | (i << 8);
}
}
/*----------------*/
/* Other routines */
open_winds()
{
int i,color;
nw.Width = max_x;
nw.Height = max_y+STARTY;
if (color_mode & 1) {
ns.ViewModes = NULL;
ns.Depth = 5;
}
ns.ViewModes = HAM;
ns.Depth = 6;
}
if (color_mode & 2) {
ns.Height = 400;
}
else
ns.Height = 200;
if (color_mode & 4) {
ns.Width = 640;
ns.ViewModes |= HIRES;
ns.Depth = 4;
}
else
ns.Width = 320;
screen = (struct Screen *)OpenScreen(&ns);
if (screen == NULL) {
fputs("Can't open new screen!\n",console);
return (1);
}
ShowTitle(screen,FALSE);
nw.Screen = screen;
w = (struct Window *)OpenWindow(&nw);
if (w == NULL) {
CloseScreen(screen);
fputs("Can't open new window!\n",console);
return (1);
vp = &screen->ViewPort;
SetDrMd(rp,JAM1);
SetBPen(rp, 0);
if (color_mode & 1)
for (i=0;i<28;i++) {
color = *(color_table+i*color_inc);
SetRGB4(vp,i+4,(color >> 8) & 0xf,(color >> 4) & 0xf,color & 0xf);
}
return (0);
}
void wait_close()
{
ULONG class;
USHORT code;
if (redir_fp) {
Delay(600);
CloseWindow(w);
CloseScreen(screen);
return;
}
for (EVER) {
if (message = (struct IntuiMessage *)GetMsg(w->UserPort)) {
class = message->Class;
code = message->Code;
ReplyMsg(message);
if (class == CLOSEWINDOW) {
CloseWindow(w);
CloseScreen(screen);
return;
}
}
}
}
gen_mand()
{
void write_out();
int x_coord,y_coord,count;
union kludge x_gap,y_gap,z_r,z_i,u_r,u_i,temp,temp2,temp3,const0;
union kludge const1,const2,const12;
ULONG class;
USHORT code;
if (v_fp) {
fclose(v_fp);
v_fp = NULL;
}
v_fp = fopen("Mandelbrot.temp.file","w+");
if (v_fp == NULL) {
abort("Can't open temporary file!");
}
v_starty = 1;
v_offset = 0L;
modified = FALSE;
want_read = FALSE;
if (open_winds())
return (1);
x_gap.i = SPDiv(SPFlt(max_x),SPSub(start_r.i,end_r.i));
y_gap.i = SPDiv(SPFlt(max_y),SPSub(start_i.i,end_i.i));
const0.i = SPFlt(0);
const1.i = SPFlt(1);
const2.i = SPFlt(2);
const12.i = SPDiv(SPFlt(2),SPFlt(1));
for (y_coord=0;y_coord<max_y;y_coord++) {
last_color = 0xfff;
v_pos_line(y_coord);
modified = TRUE;
for (x_coord=0;x_coord<max_x;x_coord++) {
while (message = (struct IntuiMessage *)GetMsg(w->UserPort)) {
class = message->Class;
code = message->Code;
ReplyMsg(message);
/* This routine crashes for some reason, thus it is left out
if (class == CLOSEWINDOW) {
CloseWindow(w);
CloseScreen(screen);
fclose(v_fp);
v_fp = NULL;
return (0);
} */
}
if (func_num == 0)
z_r.i = const0.i;
else
z_r.i = const12.i;
z_i.i = const0.i;
u_r.i = SPAdd(start_r.i,SPMul(SPFlt(x_coord),x_gap.i));
u_i.i = SPAdd(start_i.i,SPMul(SPFlt(max_y-y_coord-1),y_gap.i));
count = 0;
for (count=0;SPFix(SPAdd(SPMul(z_r.i,z_r.i),SPMul(z_i.i,z_i.i)))<4&&(count<max_count);count++) {
if (func_num == 0) { /* z = z^2-u */
temp.i = SPSub(u_r.i,SPSub(SPMul(z_i.i,z_i.i),SPMul(z_r.i,z_r.i)));
z_i.i = SPSub(u_i.i,SPMul(SPMul(const2.i,z_r.i),z_i.i));
z_r = temp;
}
else if (func_num == 1) { /* z = uz(1-z) */
temp2.i = SPSub(z_r.i,const1.i);
temp3.i = SPNeg(z_i.i);
temp.i = SPSub(SPMul(temp3.i,z_i.i),SPMul(temp2.i,z_r.i));
z_i.i = SPAdd(SPMul(temp2.i,z_i.i),SPMul(temp3.i,z_r.i));
z_r = temp;
temp.i = SPSub(SPMul(z_i.i,u_i.i),SPMul(z_r.i,u_r.i));
z_i.i = SPAdd(SPMul(z_r.i,u_i.i),SPMul(z_i.i,u_r.i));
z_r = temp;
}
}
if (count >= max_count)
count = 0;
*(v_mand_store+(y_coord-v_starty)*max_x+x_coord) = count;
write_out(count,x_coord,y_coord);
}
}
return (0);
}
disp_mand()
{
void write_out();
int x_coord,y_coord,count;
if (open_winds())
return (1);
want_read = TRUE;
for (y_coord=0;y_coord<max_y;y_coord++) {
last_color = 0xfff;
v_pos_line(y_coord);
for (x_coord=0;x_coord<max_x;x_coord++) {
count = *(v_mand_store+(y_coord-v_starty)*max_x+x_coord);
write_out(count,x_coord,y_coord);
}
}
return (0);
}
anal_mand()
{
union kludge x_gap,y_gap,z_r,z_i,u_r,u_i,const0,const1,const2,const4;
union kludge const12,temp,temp2,temp3;
int count,x,y,width,height,last_x,last_y,select,lines;
ULONG class;
USHORT code;
if (disp_mand())
return (1);
x_gap.i = SPDiv(SPFlt(max_x),SPSub(start_r.i,end_r.i));
y_gap.i = SPDiv(SPFlt(max_y),SPSub(start_i.i,end_i.i));
const0.i = SPFlt(0);
const1.i = SPFlt(1);
const2.i = SPFlt(2);
const4.i = SPFlt(4);
const12.i = SPDiv(SPFlt(2),SPFlt(1));
last_x = -1;
last_y = -1;
select = 0;
lines = 0;
aw.Screen = screen;
w2 = (struct Window *)OpenWindow(&aw);
if (w2 == NULL)
{
CloseWindow(w);
CloseScreen(screen);
fputs("Can't open analyzing window\n",console);
return (1);
}
rp2 = w2->RPort;
SetDrMd(rp2,JAM1);
SetBPen(rp2, 0);
SetAPen(rp2, 1);
RectFill(rp2,LEFTW2+1,TOPW2+1,RIGHTW2-1,BOTTOMW2-1);
for (EVER) {
if (message = (struct IntuiMessage *)GetMsg(w->UserPort)) {
class = message->Class;
code = message->Code;
ReplyMsg(message);
if (class == CLOSEWINDOW) {
CloseWindow(w2);
CloseWindow(w);
CloseScreen(screen);
return (0);
}
if (class == MOUSEBUTTONS)
if (code == SELECTDOWN) {
if (w->MouseY < STARTY)
lines = !lines;
else
select = TRUE;
}
else if (code == SELECTUP)
select = FALSE;
}
if ((last_x != w->MouseX || last_y != w->MouseY) && select &&
w->MouseX < max_x && w->MouseY >= STARTY && w->MouseY < max_y+STARTY) {
last_x = w-> MouseX;
last_y = w-> MouseY;
SetAPen(rp2,1);
RectFill(rp2,LEFTW2+1,TOPW2+1,RIGHTW2-1,BOTTOMW2-1);
width = RIGHTW2 - LEFTW2 - 6;
height = BOTTOMW2 - TOPW2 - 4;
SetAPen(rp2,3);
Move(rp2,LEFTW2+2,TOPW2+height/2+2);
Draw(rp2,RIGHTW2-2,TOPW2+height/2+2);
Move(rp2,LEFTW2+width/2+3,TOPW2+2);
Draw(rp2,LEFTW2+width/2+3,BOTTOMW2-2);
SetAPen(rp2,2);
if (func_num == 0)
z_r.i = const0.i;
else
z_r.i = const12.i;
z_i.i = const0.i;
u_r.i = SPAdd(start_r.i,SPMul(SPFlt(last_x),x_gap.i));
u_i.i = SPAdd(start_i.i,SPMul(SPFlt(max_y-(last_y-STARTY)-1),y_gap.i));
count = 0;
for (count=0;SPFix(SPAdd(SPMul(z_r.i,z_r.i),SPMul(z_i.i,z_i.i)))<4&&(count<max_count);count++) {
temp.i = SPDiv(const4.i,SPMul(z_r.i,SPFlt(width)));
x = SPFix(temp.i);
temp.i = SPDiv(const4.i,SPMul(z_i.i,SPFlt(height)));
y = SPFix(temp.i);
if (!lines)
if (x != 0 || y != 0)
WritePixel(rp2,x+width/2+LEFTW2+3,height/2-y+TOPW2+2);
else ;
else
if (count == 0)
Move(rp2,x+width/2+LEFTW2+3,height/2-y+TOPW2+2);
else
Draw(rp2,x+width/2+LEFTW2+3,height/2-y+TOPW2+2);
if (func_num == 0) { /* z = z^2-u */
temp.i = SPSub(u_r.i,SPSub(SPMul(z_i.i,z_i.i),SPMul(z_r.i,z_r.i)));
z_i.i = SPSub(u_i.i,SPMul(SPMul(const2.i,z_r.i),z_i.i));
z_r = temp;
}
else if (func_num == 1) { /* z = uz(1-z) */
temp2.i = SPSub(z_r.i,const1.i);
temp3.i = SPNeg(z_i.i);
temp.i = SPSub(SPMul(temp3.i,z_i.i),SPMul(temp2.i,z_r.i));
z_i.i = SPAdd(SPMul(temp2.i,z_i.i),SPMul(temp3.i,z_r.i));
z_r = temp;
temp.i = SPSub(SPMul(z_i.i,u_i.i),SPMul(z_r.i,u_r.i));
z_i.i = SPAdd(SPMul(z_r.i,u_i.i),SPMul(z_i.i,u_r.i));
z_r = temp;
}
}
}
}
}
void write_out(color,x,y)
int color,x,y;
{
void ham_write();
y += STARTY;
if (!(color_mode & 1)) {
if (color == 0)
color = color_inset;
else
color = color*color_inc+color_offset;
ham_write(*(color_table+color),x,y);
}
else if ((color_mode & 1) && !(color_mode & 4)) {
if (color == 0)
color = color_inset % 28;
else
color = (((color-1)/color_div+color_offset) % 28);
SetAPen(rp,color+4);
WritePixel(rp,x,y);
}
else if (color_mode & 4) {
if (color == 0)
color = color_inset % 12;
else
color = (((color-1)/color_div+color_offset) % 12);
SetAPen(rp,color+4);
WritePixel(rp,x,y);
}
}
void ham_write(color, x, y)
int color;
int x, y;
{
if ((color & 0xf00) != (last_color & 0xf00)) {
SetAPen(rp,((color & 0xf00) >> 8) + 0x20);
WritePixel(rp,x,y);
last_color = (last_color & 0xff) | (color & 0xf00);
return;
}
if ((color & 0xf0) != (last_color & 0xf0)) {
SetAPen(rp,((color & 0xf0) >> 4) + 0x30);
WritePixel(rp,x,y);
last_color = (last_color & 0xf0f) | (color & 0xf0);
return;
}
SetAPen(rp,(color & 0xf) + 0x10);
WritePixel(rp,x,y);
last_color = (last_color & 0xff0) | (color & 0xf);
return;
}