home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
graphics
/
a090_1
/
c
/
example
< prev
next >
Wrap
Text File
|
1992-04-21
|
17KB
|
606 lines
/**** example.c ****/
/* Program to show the euclid library in action */
/* By Paul Field
* See !ReadMe file for distribution/modification restrictions
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "cache.h"
#include "function.h"
#include "ewindow.h"
#include "euclid.h"
#include "alarm.h"
#include "baricon.h"
#include "dbox.h"
#include "event.h"
#include "flex.h"
#include "heap.h"
#include "kernel.h"
#include "menu.h"
#include "res.h"
#include "resspr.h"
#include "saveas.h"
#include "template.h"
#include "visdelay.h"
#include "werr.h"
#include "wimp.h"
#include "wimpt.h"
#include "win.h"
/**** Some test functions followed by 'graphdata' for them ****/
/**** Functions are actually 2D Versions of Kenneth De Jong's ****/
/**** Genetic Algorithm test functions ****/
static double fn1(double x, double y)
{ return((x*x+y*y)*0.25-6);
/* Scaled by 0.25 - otherwise it looks very tall and thin */
/* -6 to centre it */
}
static double fn3(double x, double y)
{ int total;
total = (int)x + (int)y;
return((double)total);
}
static double fn5(double x, double y)
{ static int a[2][25] =
{ {-2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0,0,0,0, 1, 1, 1, 1,1, 2, 2,2,2,2},
{-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1,0,1,2,-2,-1, 0, 1,2,-2,-1,0,1,2} };
int j;
double total = 0.002;
for (j = 0; j <= 24; j++)
{ double subtotal;
subtotal = pow(x-(double)(a[0][j])*10.0,6) + pow(y-(double)(a[1][j])*10.0,6);
total += 1.0/((double)j+1.0+subtotal);
}
return(total*150-50); /* Scaled by 150 - otherwise you can't see anything */
/* -50 to centre it */
}
#define GRAPHS 3 /* If you change this then change the menu definitions */
static graphdata graph[GRAPHS] =
{ { -5.12,5.12,
-5.12,5.12,
20, 700,
fn1, "Graph1", 0
},
{ -5.12,5.12,
-5.12,5.12,
30, 700,
fn3, "Graph2", 0
},
{ -65.536,65.536,
-65.536,65.536,
20, 700,
fn5, "Graph3", 0
}
};
/***** Now for the main wimp program *****/
#define VERSION "0.02"
#define info_version 4 /* 'Version' icon number in info box */
/********* Messages ********/
#define MESS_CRMENU "Unable to create menu."
#define MESS_ATMENU "Unable to attatch menu."
#define MESS_NOINFO "Cannot create the info box."
#define MESS_NOMEM "Not enough memory."
/********* Useful filetypes *********/
#define ftype_sprite 0xff9
#define ftype_euclid 0xde1
/********* menu definition text ***********/
/**** Main menu ****/
#define MM_ITEMS ">Info,Graph1,Graph2,Graph3,Quit"
typedef enum
{ mm_info=1, mm_graph1, mm_graph2, mm_graph3, mm_quit
}mm_item;
/**** Graph menu ****/
#define GM_ITEMS "Save,Style,Sprite,Rotate"
typedef enum
{ gm_save=1, gm_style, gm_sprite, gm_rotate
}gm_item;
/**** Save menu ****/
#define SM_ITEMS ">Euclid,>Sprite"
typedef enum
{ sm_euclid=1, sm_sprite
}sm_item;
/**** Style menu ****/
#define STM_ITEMS "Faces Only,Faces & Edges,Ray Trace|Lit"
typedef enum
{ stm_faces=1, stm_facesedges, stm_raytrace, stm_lit
}stm_item;
/**** Sprite options menu ****/
#define SOM_ITEMS "Multitask,Mode"
typedef enum
{ som_multitask = 1, som_mode
}som_item;
/**** Multitask menu ****/
#define MTM_ITEMS "None,Slow,Fast,VFast"
typedef enum
{ mtm_none=1, mtm_slow, mtm_fast, mtm_vfast
}mtm_item;
/**** Mode menu ****/
#define MDM_ITEMS "Current,Dynamic,num"
typedef enum
{ mdm_current=1, mdm_dynamic, mdm_num
}mdm_item;
/**** Global menu variables ****/
static menu mainmenu, graphmenu, savemenu, spritemenu, multimenu, modemenu, stylemenu;
static char modestring[4];
/********* Various global variables *********/
#define SIZE 30*1024 /* Amount of memory set aside for each graph */
#define ROTATEEVERY 10 /* Graph tries to rotate at 100/ROTATEEVERY frames per second */
typedef struct graphwinfo
{ int graphno;
euclid_header *structure;
ewindow ew;
BOOL closed; /* TRUE if window to graph is closed */
BOOL rotate; /* TRUE if graph is rotating in the window */
BOOL sprite; /* TRUE if window is using 'sprite' mode */
mtm_item multitask; /* Type of multitasking */
ewindow_spritemode mode;
euclid_mainstyle style; /* Drawing style of the picture */
BOOL lit;
}graphwinfo;
static graphwinfo gwi[GRAPHS];
static void *cache[GRAPHS]; /* Block of memory used by Euclid for drawing */
/********* Error handling macros ********/
#define ERR_NonFatal 0
#define ERR_Fatal 1
#define main_error(error) werr(ERR_NonFatal, error)
#define main_terminate(error) werr(ERR_Fatal, error)
/********** The program **********/
static void main_initcaches(void);
static void main_createmenus(void);
static void main_decodemainmenu(void *dummy, char *hit);
static menu main_makegraphmenu(void *handle);
static void main_decodegraphmenu(void *dummy, char *hit);
static void main_setgraphstyle(graphwinfo *gwientry);
static BOOL main_creategraph(int graphno);
static euclid_header *main_createstructure(graphdata *g, void *cache);
static void main_close(ewindow, void *closed);
static void main_programinfo(void);
static void main_barclick(wimp_i dummy);
static void main_rotategraph(int, void *handle);
static BOOL main_saveeuclid(char *name, void *handle);
static BOOL main_savesprite(char *name, void *handle);
int main(void)
{ int graphno;
wimpt_init("Euclid Library Example");
res_init("Example");
resspr_init();
template_init();
dbox_init();
alarm_init();
flex_init();
visdelay_init();
heap_init(TRUE);
main_initcaches();
for (graphno = 0; graphno < GRAPHS; graphno++)
{ gwi[graphno].structure = NULL;
gwi[graphno].graphno = graphno;
gwi[graphno].closed = TRUE;
gwi[graphno].rotate = FALSE;
}
main_createmenus();
baricon("!Example",(int) resspr_area(), main_barclick);
if (!event_attachmenu(win_ICONBAR, mainmenu, main_decodemainmenu, NULL))
{ main_terminate(MESS_ATMENU);
}
while(TRUE)
{ event_process();
}
return(0);
}
static void main_initcaches(void)
{ int cachesize;
BOOL seperate;
int cacheno;
char var[5];
/** Get and check the size of the drawing cache(s) **/
os_read_var_val("Example$Cachesize",var,5);
if (!*var)
{ main_terminate("Example$Cachesize not defined");
}
if ((cachesize = atoi(var)*1024) < 10*1024)
{ main_terminate("Example$Cachesize must be greater than or equal to 10");
}
/** Decide on a single or multiple caches **/
os_read_var_val("Example$Seperatecaches",var,5);
if (!*var)
{ main_terminate("Example$Seperatecaches not defined");
}
if (!strcmp(var, "yes"))
{ seperate = TRUE;
}
else
{ if ((seperate = strcmp(var, "no")) != 0)
{ main_terminate("Example$Seperatecaches must have a value of 'yes' or 'no' "
"(Note: lower case)");
}
}
/** Single cache - assign memory to cache[0] copy reference to cache[1] etc.. **/
/** Multiple caches - assign memory to each **/
cacheno = 0;
do
{ if ((cache[cacheno] = heap_alloc(cachesize)) == NULL)
{ main_terminate(MESS_NOMEM);
}
*(unsigned int *)cache[cacheno] = cachesize;
}
while(++cacheno < GRAPHS && seperate);
for (;cacheno < GRAPHS; cacheno++)
{ cache[cacheno] = cache[0];
}
}
/***** Creating and decoding menus *****/
static void main_createmenus(void)
{ if ((mainmenu = menu_new("Example", MM_ITEMS)) == NULL ||
(graphmenu = menu_new("Graph", GM_ITEMS)) == NULL ||
(savemenu = menu_new("Save", SM_ITEMS)) == NULL ||
(stylemenu = menu_new("Style", STM_ITEMS)) == NULL ||
(spritemenu= menu_new("Sprite", SOM_ITEMS)) == NULL ||
(multimenu = menu_new("Multitask",MTM_ITEMS)) == NULL ||
(modemenu = menu_new("Mode", MDM_ITEMS)) == NULL)
{ main_terminate(MESS_CRMENU);
}
menu_make_writeable(modemenu, mdm_num, modestring, 4, "A0-9");
menu_submenu(spritemenu, som_multitask, multimenu);
menu_submenu(spritemenu, som_mode, modemenu);
menu_submenu(graphmenu, gm_save, savemenu);
menu_submenu(graphmenu, gm_style, stylemenu);
menu_submenu(graphmenu, gm_sprite, spritemenu);
}
static void main_decodemainmenu(void *dummy, char *hit)
{ dummy=dummy;
switch(hit[0])
{ case mm_info : main_programinfo(); return;
case mm_quit : exit(0);
}
if (hit[0] != 0)
{ int graphno;
graphwinfo *gwientry;
graphno = hit[0]-mm_graph1;
gwientry = &gwi[graphno];
if (gwientry->structure == NULL)
{ main_creategraph(graphno);
}
if (gwientry->structure != NULL)
{ ewindow_open(gwientry->ew);
gwientry->closed = FALSE;
if (gwientry->rotate)
{ main_rotategraph(0, gwientry);
}
menu_setflags(mainmenu, hit[0], TRUE, FALSE);
}
}
}
static menu main_makegraphmenu(void *handle)
{ graphwinfo *gwientry = handle;
int option;
BOOL rayok; /* TRUE if raytracing can occur */
BOOL rayactive; /* TRUE if raytracing is occuring */
rayok = ewindow_hassprite(gwientry->ew) && gwientry->mode != ewindow_smdynamic &&
gwientry->multitask != mtm_none && !gwientry->rotate;
rayactive = gwientry->style == emainstyle_raytrace;
menu_setflags(graphmenu, gm_sprite, gwientry->sprite, FALSE);
menu_setflags(graphmenu, gm_rotate, gwientry->rotate, rayactive);
menu_setflags(multimenu, mtm_none, gwientry->multitask == mtm_none, rayactive);
for (option = mtm_none+1; option <= mtm_vfast; option++)
{ menu_setflags(multimenu, option, gwientry->multitask == option, FALSE);
}
if (gwientry->mode >= 0)
{ sprintf(modestring, "%d", gwientry->mode);
}
else
{ *modestring = NULL;
}
menu_setflags(modemenu, mdm_current, gwientry->mode == ewindow_smcurrent, FALSE);
menu_setflags(modemenu, mdm_dynamic, gwientry->mode == ewindow_smdynamic, rayactive);
menu_setflags(savemenu, sm_sprite, FALSE, !ewindow_updatecomplete(gwientry->ew) ||
!ewindow_hassprite(gwientry->ew));
for (option = stm_faces; option < stm_raytrace; option++)
{ menu_setflags(stylemenu, option, gwientry->style == option-1, FALSE);
}
menu_setflags(stylemenu, stm_raytrace, gwientry->style == stm_raytrace-1, !rayok);
menu_setflags(stylemenu, stm_lit, gwientry->lit, FALSE);
return(graphmenu);
}
static void main_decodegraphmenu(void *handle, char *hit)
{ graphwinfo *gwientry = handle;
switch(hit[0])
{ case gm_save:
switch(hit[1])
{ case sm_euclid:
saveas(ftype_euclid, "Euclid", SIZE, main_saveeuclid, 0,0, gwientry);
break;
case sm_sprite:
saveas(ftype_sprite, "Sprite", 0, main_savesprite, 0,0, gwientry);
break;
}
break;
case gm_style:
switch(hit[1])
{ case stm_raytrace :
case stm_faces :
case stm_facesedges :
gwientry->style = hit[1]-1;
break;
case stm_lit :
gwientry->lit = !gwientry->lit;
}
main_setgraphstyle(gwientry);
break;
case gm_sprite:
switch(hit[1])
{ case 0:
gwientry->sprite = !gwientry->sprite;
if (gwientry->style == emainstyle_raytrace)
{ main_error("Changing to faces only style.");
gwientry->style = emainstyle_facesonly;
main_setgraphstyle(gwientry);
}
break;
case som_multitask:
if (hit[2] != 0)
{ gwientry->multitask = hit[2];
}
switch(hit[2])
{ case mtm_none : ewindow_timing(gwientry->ew, 0, 0); break;
case mtm_slow : ewindow_timing(gwientry->ew, 1, 2); break;
case mtm_fast : ewindow_timing(gwientry->ew, 10, 2); break;
case mtm_vfast : ewindow_timing(gwientry->ew, 0xfe, 2); break;
}
break;
case som_mode:
switch(hit[2])
{ case mdm_current : gwientry->mode = ewindow_smcurrent; break;
case mdm_dynamic : gwientry->mode = ewindow_smdynamic; break;
case mdm_num : gwientry->mode = atoi(modestring); break;
}
break;
}
ewindow_usesprite(gwientry->ew, gwientry->sprite, gwientry->mode);
break;
case gm_rotate:
gwientry->rotate = !gwientry->rotate;
if (gwientry->rotate)
{ main_rotategraph(0, gwientry);
}
else
{ alarm_removeall(gwientry);
}
break;
}
}
/***** Creating and handling graphwindows *****/
static void main_setgraphstyle(graphwinfo *gwientry)
{ ewindow_setstyle(gwientry->ew, edrawstyle_mainstyle * gwientry->style +
gwientry->lit * (edrawstyle_lightson|edrawstyle_frontlighton));
}
#define GRAPHSTYLE ((edrawstyle_mainstyle * emainstyle_facesonly) |\
edrawstyle_lightson | edrawstyle_frontlighton)
static BOOL main_creategraph(int graphno)
{ char *error = NULL;
graphwinfo *gwientry;
euclid_header *structure;
wimp_wind *window;
gwientry = &gwi[graphno];
if ((window = template_syshandle("ewindow")) == NULL)
{ main_error("Template 'ewindow' not found");
return(FALSE);
}
window->box.y0 -= 40; /* Move each graph window down slightly */
window->box.y1 -= 40;
if ((structure = main_createstructure(&graph[graphno], cache[graphno])) != NULL &&
(gwientry->ew = ewindow_create(graph[graphno].name, GRAPHSTYLE, structure,
NULL, main_close, gwientry)) != NULL)
{ if (!event_attachmenumaker(ewindow_handle(gwientry->ew), main_makegraphmenu,
main_decodegraphmenu, gwientry))
{ error = MESS_ATMENU;
ewindow_destroy(gwientry->ew);
}
}
else
{ error = MESS_NOMEM;
}
if (error)
{ main_error(error);
if (structure != NULL)
{ heap_free(structure);
}
structure = NULL;
}
else
{ gwientry->structure = structure;
gwientry->multitask = mtm_none;
gwientry->mode = ewindow_smdynamic;
gwientry->style = emainstyle_facesonly;
gwientry->lit = TRUE;
main_setgraphstyle(gwientry);
}
return(error == NULL);
}
static euclid_header *main_createstructure(graphdata *g, void *cache)
{ euclid_header *data;
if ((data = heap_alloc(SIZE)) != NULL)
{ visdelay_begin();
wimpt_noerr(euclid_initialise(einitflags_blackonwhite, data, SIZE, NULL));
if (!wimpt_complain(function_makegraph(data, g, (euclid_mesh **)&data->root)))
{ data->observerrot.x = 0<<6;
data->observerrot.y = 80<<6;
data->observerrot.z = 90<<6;
data->cache = cache;
data->backgroundcol.c.abscolour = euclid_makecolour(0x80u,0,0xa0,0xff);
}
else
{ heap_free(data);
data = NULL;
}
visdelay_end();
}
return(data);
}
static void main_close(ewindow ew, void *vgwi)
{ graphwinfo *gwi = vgwi;
if (gwi->rotate)
{ alarm_removeall(gwi);
}
gwi->closed = TRUE;
menu_setflags(mainmenu, gwi->graphno + mm_graph1, FALSE, FALSE);
ewindow_closeoptions(ew, gwi->style != emainstyle_raytrace);
ewindow_close(ew);
}
/***** Miscellaneous functions *****/
static void main_programinfo(void)
{ dbox d;
char versionstring[80];
if ((d = dbox_new("progInfo")) == NULL)
{ main_error(MESS_NOINFO);
return;
}
sprintf(versionstring, "%s (%s)", VERSION, __DATE__);
dbox_setfield(d, info_version, versionstring);
dbox_show(d);
dbox_fillin(d);
dbox_dispose(&d);
}
static void main_barclick(wimp_i dummy)
{ dummy = dummy;
/* Need to register a function with 'baricon' otherwise clicking */
/* on the icon bar icon causes the program to crash. */
}
static void main_rotategraph(int time, void *handle)
{ graphwinfo *gwientry = handle;
int angle;
time=time;
if (ewindow_updatecomplete(gwientry->ew))
{ angle = gwientry->structure->observerrot.x>>6;
angle = (angle+10)%360;
gwientry->structure->observerrot.x = angle<<6;
ewindow_update(gwientry->ew);
}
alarm_set(alarm_timenow()+ROTATEEVERY, main_rotategraph, handle);
}
/***** Saving functions *****/
static BOOL main_saveeuclid(char *name, void *handle)
{ graphwinfo *gwientry = handle;
return(wimpt_complain(euclid_save(gwientry->structure, name)) == NULL);
}
static BOOL main_savesprite(char *name, void *handle)
{ graphwinfo *gwientry = handle;
sprite_area **area;
int offset;
BOOL ok;
if (ewindow_sprite(gwientry->ew, &area, &offset))
{ ok = (wimpt_complain(sprite_area_save(*area, name)) == NULL);
}
else
{ /* I don't think this can happen - but better safe than sorry */
main_error("The sprite memory has been freed - cannot save.");
ok = FALSE;
}
return(ok);
}