leo@philmds.UUCP (Leo de Wit) (09/20/88)
Posting-number: Volume 4, Issue 83 Submitted-by: "Leo de Wit" <leo@philmds.UUCP> Archive-name: 3demo/Part01 [PLEASE don't ask me what this is -- I have no more idea than you do! ++bsa] : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. echo 'Extracting 3demo.c' sed 's/^X//' > 3demo.c << '+ END-OF-FILE 3demo.c' X/* X ****************************************************************************** X * * X * 3demo.c version 1.1 of 17 July 1988 (C) L.J.M. de Wit 1988 * X * * X * This software may be used and distributed freely if not used commercially * X * and the originator (me) is mentioned. * X * * X ****************************************************************************** X * X * 3demo.c: the main part of the 3demo.prg program. X * It initializes the workstation, memory and contains the diverse demo X * functions - each demo function representing a complete demo. X */ X X#include <stdio.h> X#include <osbind.h> X#include <portab.h> X#include <math.h> X#include "matricks.h" X X#define HELP_KEY 0x620000 /* Help key code */ X#define NSTEPS 120 /* # of steps for a complete turn */ X#ifndef Wvbl() /* some osbind.h's don't contain */ X#define Wvbl() xbios(37) /* this entry, so add it */ X#endif Wvbl X X#define DT_REAL 0 /* demotype 'real time' */ X#define DT_COORDRES 1 /* demotype use saved coords */ X#define DT_IMGSAV 2 /* demotype save images */ X#define DT_IMGRES 3 /* demotype use saved images */ X#define DT_MAX 4 /* upper limit demotype range */ X Xstatic double dist = 5, /* distance eye from screen */ X scale_x, /* scale factor in x direction */ X scale_y; /* scale factor in y direction */ X X /* For each direction and axis: */ Xstatic WORD rotobject[2][3][4][4]; /* rotation matrices for object */ Xstatic WORD rotobserv[2][3][4][4]; /* rotation matrices for observer */ Xstatic WORD traobserv[2][3][4][4]; /* translation matrices for observer */ X Xstatic double idmat[][3] = { /* identity matrix */ X 1,0,0, X 0,1,0, X 0,0,1 X}; Xstatic double tl0[3] = { /* translation vector */ X 0,0,0 X}; Xstatic double tl1[] = { /* another one */ X 0.5,0.5,0.5 X}; Xstatic double tl2[] = { /* and yet another one */ X 0,0,0 X}; X Xstatic void st_demo(), /* demo using ST as logo */ X house_demo(), /* demo with street of houses */ X globe_demo(), /* demo with globe skeleton */ X move_it(); /* move item using user input */ X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X int i, j; X double lambda = 0.1, alpha = 0.05; X X /* Initialize matrices for small */ X /* movements. */ X for (i = 0; i < 2; i++) { /* 0: forward, 1: backward */ X for (j = 0; j < 3; j++) { /* 0, 1, 2: x, y, z direction */ X matident(4,traobserv[i][j]); X matapply(traobserv[i][j],mattlate,idmat[j], /* translation observer*/ X (i == 0) ? lambda : -lambda); X X matident(4,rotobserv[i][j]); X matapply(rotobserv[i][j],matrotate,idmat[j], /* rotation observer */ X (i == 0) ? alpha : -alpha); X X matident(4,rotobject[i][j]); X matapply(rotobject[i][j],mattlate,tl1,-1.0); X matapply(rotobject[i][j],matrotate,idmat[j], X (i == 0) ? alpha : -alpha); X matapply(rotobject[i][j],mattlate,tl1,1.0); /* rotation object */ X } X } X X gem_init(); /* initializations */ X scale_x = 13600/pixwidth; /* scale factors depend on pixel sizes */ X scale_y = 13600/pixheight; /* which are determined upon v_openvwk */ X st_demo(); /* Demo 1 */ X house_demo(); /* Demo 2 */ X globe_demo(); /* Demo 3 */ X gem_exit(0); X} X Xstatic void st_demo() X{ X static short lists[][2] = { /* coordinates for letter 'S' */ X -4,0,-2,0,-1,1,-1,2, X -2,3,-3,3,-3,4,-1,4, X -1,5,-3,5,-4,4,-4,3, X -3,2,-2,2,-2,1,-4,1, X -4,0 X }; X static short listt[][2] = { /* coordinates for letter 'T' */ X 2,0,3,0,3,4,4,4, X 4,5,1,5,1,4,2,4, X 2,0 X }; X int npoints, /* # of points in logo */ X i, j, n, mode0 = 1, demotype; X double (*st_coords)[3], /* ptr to array of coordinates of */ X /* vertices of original image */ X (*stp)[3]; /* to point into this array */ X short (*shp)[2]; /* ptr into lists or listt */ X short *order, /* ptr to array of indices */ X *op; /* to point into this array */ X item it; /* the item */ X instance ins; /* the (1) instance of the item */ X static WORD neweye[][4] = { /* transformation matrix that puts */ X 3978, 0, 0, 0, /* observer in its place the first time*/ X 0, 3978, 0, 0, X 0, 0, 3978, 0, X 29769, 10022, -25047, 3978 X }; X static WORD newtrans[][4] = { /* Transformation that puts the logo */ X 17405, 0, 0, 0, /* in its place the first time */ X 0, -18175, -51, 0, X 0, 49, -18245, 0, X -56, 17745, 17889, 17405 X }; X WORD *eye, /* ptr to eye coordin. tranformation */ X *savarr; /* ptr to all coordinates of the */ X /* vertices of the logo for 120 images*/ X bool done = FALSE; X char c; X static uchar *sinfo[NSTEPS]; /* array of ptrs to compressed screen */ X /* strings */ X X /* shorthands for # of points */ X#define S_POINTS (sizeof(lists)/sizeof(short[2])) X#define T_POINTS (sizeof(listt)/sizeof(short[2])) X X npoints = 2 * (S_POINTS + T_POINTS); X savarr = (WORD *)malloc(NSTEPS*2*npoints*sizeof(WORD)); X st_coords = (double (*)[3])malloc(npoints * sizeof(double[3])); X order = (short *)malloc( X (S_POINTS + T_POINTS + 1) * 5 * sizeof(short)); X X stp = st_coords; op = order; /* init S coordinates and ordering */ X for (shp = lists, i = 0; shp < lists + S_POINTS; shp++) { X (*stp)[0] = (*shp)[0]; X (*stp)[1] = (*shp)[1] - 2.5; X (*stp)[2] = 0; X stp++; X (*stp)[0] = (*shp)[0]; X (*stp)[1] = (*shp)[1] - 2.5; X (*stp)[2] = 1; X stp++; X *op++ = i++; X *op++ = i++; X *op++ = SV; X } X X for (shp = lists, i = 0; shp < lists + S_POINTS; shp++) { X *op++ = i++; X i++; X } X *op++ = SV; X for (shp = lists, i = 0; shp < lists + S_POINTS; shp++) { X i++; X *op++ = i++; X } X *op++ = SV; X n = i; X X /* init T coordinates and ordering */ X for (shp = listt, i = n; shp < listt + T_POINTS; shp++) { X (*stp)[0] = (*shp)[0]; X (*stp)[1] = (*shp)[1] - 2.5; X (*stp)[2] = 0; X stp++; X (*stp)[0] = (*shp)[0]; X (*stp)[1] = (*shp)[1] - 2.5; X (*stp)[2] = 1; X stp++; X *op++ = i++; X *op++ = i++; X *op++ = SV; X } X X for (shp = listt, i = n; shp < listt + T_POINTS; shp++) { X *op++ = i++; X i++; X } X *op++ = SV; X for (shp = listt, i = n; shp < listt + T_POINTS; shp++) { X i++; X *op++ = i++; X } X *op++ = SV; X *op++ = SV; X X it = matcrit(npoints,st_coords,order); /* create item */ X ins = matcrins(it,idmat,tl0); /* Create instance of this item */ X eye = matseteye(idmat,tl2, /* To make eye point to the */ X dist,scale_x,scale_y); /* correct static array */ X for (i = 0; i < 4; i++) { /* Use these (empiric) values instead */ X for (j = 0; j < 4; j++) { X eye[4*i + j] = neweye[i][j]; X ins->trans[i][j] = newtrans[i][j]; X } X } X X printf("%s\n\n\t%s\n\n\t\t- Press any key to start -\n\n", X CLS,"Demo 1: ST (press q to quit)"); X swapscreen(); /* Show text & */ X Crawcin(); /* wait for key press */ X X for ( ; !done; ) { /* while 'q' not pressed */ X for (i = 0; !done && i < 3; i++) { /* for each axis */ X for (demotype = 0; !done && demotype < DT_MAX; demotype++) { /* 4 x */ X static char *text[] = { X "real time calculation", X "using saved coordinates", X "saving images", X "using saved images" X }; X X printf("%s\n\n\tDemo 1: %s\n\n",CLS,text[demotype]); X swapscreen(); /* Show this text */ X for (j = 0; j < 100; j++) {/* wait some time */ X Wvbl(); X } X for (j = 0; !done && j < NSTEPS; j++) { X v_clrwk(handle); X switch (demotype) { X case DT_REAL: X matproject(ins); X insstore(ins,savarr,j); X matfdraw(ins,mode0); X break; X case DT_COORDRES: X insload(ins,savarr,j); X matfdraw(ins,mode0); X break; X case DT_IMGSAV: X insload(ins,savarr,j); X matfdraw(ins,mode0); X sinfo[j] = matscr_to_str((bool)TRUE); X break; X case DT_IMGRES: X matstr_to_scr(sinfo[j],(bool)TRUE); X break; X } X swapscreen(); X c = Crawio(0xff) & 0xff; X done = c == 'q'; X if (demotype == 0) { X matcompose(ins->trans,rotobject[0][i]); X } X } X if (demotype == DT_IMGRES) { X for (j = NSTEPS; --j >= 0; ) { X free(sinfo[j]); X } X } X } X } X } X /* Now free any occupied storages: */ X matfrit(it); /* the item */ X matfrins(ins); /* the instance */ X X free(savarr); /* the coordinates work space */ X free(st_coords); /* the real (initial) coordinates */ X free(order); /* the index array for the ordering seq*/ X} X Xstatic void house_demo() X{ X int nhouses = 4; /* street of 4 houses */ X static double a[][3] = { /* real coordinates of one house */ X 0,0,0, /* 0 */ X 1,0,0, /* 1 */ X 1,1,0, /* 2 */ X 0,1,0, /* 3 */ X 0,0,1, /* 4 */ X 1,0,1, /* 5 */ X 1,1,1, /* 6 */ X 0,1,1, /* 7 */ X 0.5,0.5,1.5 /* 8 */ X }; X X static short order[] = { /* ordering of indices: 3 polygons */ X 0,1,2,3,0,4,5,1,SV, X 2,6,5,8,4,7,3,SV, X 8,6,7,8,SV, X SV X }; X item it; /* The item */ X instance *insp; /* ptr to the (nhouses) instances */ X int i; X /* allocate space for instances */ X insp = (instance *)malloc(nhouses * sizeof(instance)); X X it = matcrit(sizeof(a)/sizeof(a[0]),a,order); /* create the item */ X for (i = 0; i < nhouses; i++) { /* Create (nhouses) instances */ X tl0[0] = i * 2; X insp[i] = matcrins(it,idmat,tl0); X } X move_it("Demo 2: houses (press Help for keys)",insp,nhouses); X matfrit(it); /* free item storage */ X for (i = 0; i < nhouses; i++) { X matfrins(insp[i]); /* free each instance storage */ X } X free(insp); /* and the storage for the pointers */ X} X Xstatic void globe_demo() /* Demo 3: globe */ X{ X static double rad = 1; /* radius of globe */ X int maxt = 12, /* # of 'tropics' */ X maxf = 16; /* # of meridians */ X int f, t; X double (*sphere)[3], (*sp)[3]; /* ptrs to array of initial coordinates*/ X double st, ct; X short *plist, *pl; /* list of indexes */ X item it; /* the item */ X instance ins; /* the instance */ X X/* Create space for coordinates and index list */ X sphere = (double (*)[3])malloc((maxt + 1) * (maxf + 1) * sizeof(double[3])); X plist = (short *)malloc(sizeof(short) * ((2 * maxt + 1) * (maxf + 1) - 2)); X if (sphere == (double (*)[3])0 || plist == (short *)0) { X fprintf(stderr,"Memory allocation failed\n"); X return; X } X X for (t = 0; t <= maxt; t++) { /* Calculate coordinates */ X st = rad * mysin(t * PI / maxt); X ct = rad * mycos(t * PI / maxt); X for (f = 0; f <= maxf; f++) { X sp = sphere + (maxf + 1) * t + f; X (*sp)[0] = st * mycos(f * 2 * PI / maxf); X (*sp)[1] = st * mysin(f * 2 * PI / maxf); X (*sp)[2] = ct; X } X } X X pl = plist; X for (t = 1; t <= maxt - 1; t++) { /* Calculate index list: 'tropics' */ X for (f = 0; f <= maxf; f++) { X *pl++ = (maxf + 1) * t + f; X } X *pl++ = SV; X } X for (f = 0; f <= maxf - 1; f++) { /* Calculate index list; meridians */ X for (t = 0; t <= maxt; t++) { X *pl++ = (maxf + 1) * t + f; X } X *pl++ = SV; X } X *pl++ = SV; X X it = matcrit((maxf + 1) * (maxt + 1),sphere,plist); /* create the item */ X tl0[0] = 0; X ins = matcrins(it,idmat,tl0); /* create instance */ X move_it("Demo 3: globe (press Help for keys)",&ins,1); /* move on input */ X matfrit(it); matfrins(ins); /* free item and instance */ X} X Xstatic void move_it(title,insp,inscnt) /* move inscnt instances */ Xchar *title; /* Title to be displayed */ Xinstance *insp; /* ptr to array of instances */ Xint inscnt; /* # of instances */ X{ X bool drawfast = TRUE; /* toggle to switch between drawing */ X /* algorithms */ X char c; X int i, X times, /* # of steps to take */ X mode0 = 1, /* OR drawing mode; ignored by fastdraw*/ X axis; /* axis: 0, 1, 2 = x, y, z */ X bool forward; /* direction: forward versus backward */ X long inkey; /* key pressed code */ X WORD *eye; /* observer transformation array ptr */ X X printf("%s\n\n\t%s\n\n\t\t- Press any key to start -\n\n",CLS,title); X swapscreen(); /* Show title */ X Crawcin(); /* Wait for keypress */ X X eye = matseteye(idmat,tl2,dist,scale_x,scale_y); /* Set observer tranform. */ X X times = 1; X for (c = '\0'; c != 'q'; ) { X v_clrwk(handle); /* clear logical screen */ X for (i = 0; i < inscnt; i++) { X matproject(insp[i]); /* project each instance */ X if (drawfast) { /* and draw it */ X matfdraw(insp[i],mode0); /* either fast */ X } else { X matdraw(insp[i],mode0); /* or standard */ X } X } X swapscreen(); /* Show (make logical screen physical) */ X inkey = Crawcin(); /* Wait for a key */ X if (inkey == HELP_KEY) { /* After Help key show help info */ X help(); X continue; X } X c = inkey; X if (c > '0' && c <= '9') { /* If numeric key */ X times = c - '0'; /* Number of steps at a time (def. 1) */ X continue; X } X X switch (c) { X case 's': /* Switch draw algorithm */ X drawfast = !drawfast; X break; X case 'x': /* Translations */ X case 'X': X case 'y': X case 'Y': X case 'z': X case 'Z': X forward = c < 'x'; X if (forward) { X axis = c - 'X'; X } else { X axis = c - 'x'; X } X while (times--) { /* Apply them to the observer transf. */ X matcompose(eye,traobserv[forward][axis]); X } X break; X case 'a': /* Rotations observer */ X case 'A': X case 'b': X case 'B': X case 'c': X case 'C': X forward = c < 'a'; X if (forward) { X axis = c - 'A'; X } else { X axis = c - 'a'; X } X while (times--) { /* Apply them to the observer transf. */ X matcompose(eye,rotobserv[forward][axis]); X } X break; X case 'k': /* Rotations object */ X case 'K': X case 'l': X case 'L': X case 'm': X case 'M': X forward = c < 'k'; X if (forward) { X axis = c - 'K'; X } else { X axis = c - 'k'; X } X while (times--) { /* Apply them to each object transf. */ X for (i = 0; i < inscnt; i++) { X matcompose(insp[i]->trans,rotobject[forward][axis]); X } X } X break; X } X times = 1; /* # steps back to default value */ X } X} + END-OF-FILE 3demo.c chmod 'u=rw,g=r,o=' '3demo.c' echo 'SENT: -rw-r----- 1 leo 17621 Aug 21 14:33 3demo.c' echo -n 'RCVD: ' /bin/ls -l 3demo.c echo 'Extracting gemfuncs.c' sed 's/^X//' > gemfuncs.c << '+ END-OF-FILE gemfuncs.c' X/* X ****************************************************************************** X * * X * gemfuncs.c version 1.0 of 17 July 1988 (C) L.J.M. de Wit 1988 * X * * X * This software may be used and distributed freely if not used commercially * X * and the originator (me) is mentioned. * X * * X ****************************************************************************** X * X * gemfuncs.c: graphics part of 3demo.prg. For O.S's without GEM an X * alternative module should be made. It includes the following functions: X * X * gem_init() : X * opens a virtual workstation and allocates extra screen memory for X * smooth drawing. X * gem_exit() : X * closes a virtual workstation, restores screen location and exits. X * The allocated memory for a screen is automatically returned to the X * system. X * swapscreen() : X * switches the logical and physical screens. Drawing takes place on the X * logical screen, while the physical screen is displayed. This ensures X * that movement is smooth. X * help() : X * Display help info about key use. X */ X X#include <osbind.h> X#include <portab.h> X#include <gemlib.h> X#include "matricks.h" X XWORD handle, /* Handle of virt. workstation */ X maxx, /* Max. x coordinate */ X maxy, /* Max. y coordinate */ X ncolor, /* # of colours: 2, 4, 16 */ X pixwidth, /* Pixel width in microns */ X pixheight; /* Pixel height in microns */ XLONG _mneed = 400000; /* Memory needed by this program */ X Xstatic WORD dummy; Xstatic LONG physbase, /* Physical screen base address */ X logbase; /* Logical screen base address */ X Xvoid gem_init() /* Init the vwk and screen mem */ X{ X int i; X short work_in[11], work_out[57]; X X physbase = Physbase(); /* Get physical base address */ X logbase = (Malloc(32256) + 255) & ~255; /* Allocate 32000 bytes */ X /* at 256 bytes boundary */ X printf(CLS); /* Clear both screens */ X swapscreen(); X printf(CLS); X swapscreen(); X X appl_init(); /* Administrate application */ X handle = graf_handle(&dummy,&dummy,&dummy,&dummy); X X for (i = 0; i < 10; i++) { X work_in[i] = 1; X } X work_in[10] = 2; X X v_opnvwk(work_in,&handle,work_out); /* Open virt. workstation */ X maxx = work_out[0]; /* Get some return parameters*/ X maxy = work_out[1]; X pixwidth = work_out[3]; X pixheight = work_out[4]; X ncolor = work_out[13]; X printf("\33f"); /* Cursor off */ X} X Xvoid gem_exit(code) /* Exit, returning this code */ Xint code; X{ X logbase = physbase; /* Next call to swapscreen */ X /* restores things to normal */ X v_clsvwk(handle); /* Close the vwk */ X appl_exit(); /* Exit application */ X swapscreen(); /* Standard screen addresses */ X exit(code); /* Finally exit with the code*/ X} X Xvoid swapscreen() /* Swap the two screens */ X{ X static int which = 0; /* Toggle to select screens */ X X if (!which) { X Setscreen(logbase,physbase,-1); X } else { X Setscreen(physbase,logbase,-1); X } X which = !which; /* Toggle it */ X} X Xvoid help() /* Show help info */ X{ X printf(CLS); X printf("\n ======== Keys to manipulate object ========\n\n"); X printf("a/A\tTurn around observer x-axis back-/forwards\n"); X printf("b/B\tTurn around observer y-axis back-/forwards\n"); X printf("c/C\tTurn around observer z-axis back-/forwards\n\n"); X printf("k/K\tTurn around object x-axis back-/forwards\n"); X printf("l/L\tTurn around object y-axis back-/forwards\n"); X printf("m/M\tTurn around object z-axis back-/forwards\n\n"); X printf("x/X\tMove along observer x-axis back-/forwards\n"); X printf("y/Y\tMove along observer y-axis back-/forwards\n"); X printf("z/Z\tMove along observer z-axis back-/forwards\n\n"); X printf("q\tQuit this demo\n\n"); X printf("Hit any key to continue...\n"); X swapscreen(); /* Now show it */ X Crawcin(); /* Wait for key press */ X swapscreen(); /* Get old screen back */ X} + END-OF-FILE gemfuncs.c chmod 'u=rw,g=r,o=' 'gemfuncs.c' echo 'SENT: -rw-r----- 1 leo 5015 Aug 21 14:36 gemfuncs.c' echo -n 'RCVD: ' /bin/ls -l gemfuncs.c exit 0