v04i085: 3demo program - part 4 of 4

Leo de Wit leo at philmds.UUCP
Tue Sep 20 11:19:15 AEST 1988


Posting-number: Volume 4, Issue 85
Submitted-by: "Leo de Wit" <leo at philmds.UUCP>
Archive-name: 3demo/Part04

[Leo de Wit:  HELP!!!  Part 2 vanished into the cracks somewhere, and I didn't
catch it.  Please re-send ASAP.  ++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 matricks.doc'
sed 's/^X//' > matricks.doc << '+ END-OF-FILE matricks.doc'
X
X                  Documentation for the graphic functions.
X                  ----------------------------------------
X
X                     sources and doc by L.J.M. de Wit
X
X      OBJECTIVE
X
X   The purpose was to supply a number of useful graphic functions that
X   can be used in a modest scale for animation, 3D motion, demo's. Another
X   purpose was to poke up some discussion conceirning graphic functions,
X   representations, etc. I'm only in a minor way involved with graphics in
X   my job, so I'm open for any other ideas. The functions offered have not
X   the least pretention to be exhaustive, although it would be nice to
X   enlarge and enrich the capabilities in future releases. Whoever has ideas,
X   remarks, bugs found in the package, questions about the source or how to
X   use it, is invited to send them to me; any help is welcome but also gladly
X   offered.
X
X
X      COPYRIGHT AND THE LIKE
X
X   The source can be used freely for non-commercial purposes;
X   if you redistribute the source keep my copyright notice in; that's a small
X   fee for the effort I've put into it. If you plan to make changes to the
X   source and distribute I would like to know; this to prevent duplication of
X   effort, and existance of different branches; perhaps redistribution could
X   go via me (maybe I'm already too optimistic about others willing to work
X   on some part of the code 8-). Also anyone planning to use (part of) it in
X   a commercial product should contact me; this be said to keep everyone
X   interested! 8-).
X
X
X      TARGET MACHINES, LANGUAGE USED
X
X   In the present form the demo program runs on Atari STs (1 Meg required).
X   The amount of memory is merely required to run the demo that stores a
X   series of compressed images; this is the only part that really requires
X   memory. It should not be hard to port the code to various machines, notably
X   the Mac, the Amiga, the IBM PC with graphics card, a Sun, etc.
X   The language used is C; a small part of the code is in 68000 assembler.
X   Since this code also has a line drawing routine (for bit mapped display)
X   it can even be used on systems with a very limited or no graphics library.
X
X
X      BREAK UP OF SOURCES
X
X   Currently the following source modules exist:
X
X      matricks.h:    header file for extern declarations and the like.
X      3demo.c:       contains main and all demo functions
X      mat.c:         operations on matrices
X      object.c:      operations on objects: items and instances
X      gemfuncs.c:    O.S. dependant part of graphic functions: opening a work-
X                     station, swapping screen memory etc.
X      mxops.asm:     like mat.c but these are assembler functions.
X      drawlin.asm:   function to draw a line.
X
X   The last 3 named are the ones most likely to cause problems when porting.
X   If your system doesn't have GEM, gemfuncs.c will have to be rewritten,
X   but this is no big deal; if your system uses an other processor than a
X   68000 the assembler functions will have to be re-created; also if the
X   layout of your bitmap display is different from (any of the) Atari ST,
X   the drawlin.asm needs a thorough scan.
X
X
X      IDEAS ABOUT REPRESENTATIONS ETC.
X
X   In order to give you a better understanding of the source I'll explain
X   some of the ideas used in the code and why some choices were made.
X      1) Use of matrices for all motions (translation, rotation and any
X   combination of these). An object in space can be represented by a set
X   of coordinates for each point; if the object consists of a set of lines
X   it suffices to store the coordinates of the end points and the way the
X   points are connected (the polygons). The coordinates of an object are
X   stored per row for each point in a 2D array (the height equals the
X   number of points registrated, the width the number of coordinates: 4).
X   A motion of the object can now be computed by multiplying the (npoints x 4)
X   coordinate array with the (4 x 4) transformation array, resulting in a
X   new (npoints x 4) array, representing the new coordinates. Note that in
X   case a combination of transformations is applied to the object (e.g.
X   a translation followed by a rotation) it is cheaper (in terms of # of
X   multiplications) to first multiply the (4 x 4) transformation matrices
X   (resulting in a new 4 x 4 matrix) and then multiply the coordinate matrix
X   with this one than to multiply the coordinate matrix with each
X   transformation matrix separately. This is also one of the reasons that
X   using matrix calculus is much cleaner and clearer than using goniometric
X   formulas; you do not get lost in long formulas and you can concentrate
X   on things that really matter, and the speed gain is vast when you're
X   handling several points / several transformations at a time.
X      2) Use of 3D projective coordinates to represent a point in 3D space.
X   Those interested in but not familiar with these coordinates are advised
X   to read an (introductory) book about Projective Geometry; for those that
X   are only not familiar with it (and thus not interested 8-), it should
X   suffice to say that a point's
X   coordinates may all be multiplied with a constant, so for instance
X   (1, 2, 5, 7) is the same point as (3, 6, 15, 21) and that the (normal)
X   Carthesian coordinate system can be embedded in projective space as
X   follows: if (X,Y,Z) is a point in 3D Carthesian it corresponds with
X   (X,Y,Z,1) in 3D projective space (note: 4 coordinates). Of course
X   you could choose (2.3X,2.3Y,2.3Z,2.3) also or any constant you like.
X   The two main advantages of using projective (or homogeneous) coordinates
X   that I can see are: a) all motions of a rigid body in space can be
X   represented by a matrix (or series of) multiplication(s), or, put
X   differently, each transformation can be represented by a matrix.
X   b) since homogeneous coordinates are used, the elements of the matrix
X   may be scaled with a constant factor. This is an important issue in
X   terms of speed, since it allows the use of integers throughout the code
X   (many architectures deal faster with integer calculations than float
X   and double calculations); yes, by using correctly chosen scaling factors
X   (not too small to retain precision, no too big to prevent overflow)
X   even shorts are usable (16 bits shorts that is). The 68000 handles
X   word (16 bit) multiplications as one instruction, resulting in fast
X   performed matrix multiplications. The result matrix is of course a
X   matrix with 32-bit elements, but these are scaled afterwards to fit again
X   in a short. In fact, the scaling chosen is such that multiplying these
X   shorts in pairs and adding 4 such pairs does not overflow a signed long.
X
X
X      ABOUT OBJECTS
X
X   This being said and understood the notion of the objects used should be
X   easy now. Two types of objects are of special interest:
X   The item, in fact a pointer to a struct, defined by:
X
X   typedef struct itstruct {  /* item definition: ptr to this struct */
X      int count;              /* # of points in this item */
X      polygon next;           /* pointer to polygon list */
X      WORD r_data[1][4];      /* homogene coordinates of first point; */
X   } *item;                   /* the rest follows hereafter */
X
X   Note that only one row of the coordinate matrix is declared; this is to
X   allow for arbitrary sized arrays without having to resort to pointers
X   (of course the only reasonable usage must be by dynamic allocation of the
X   actual struct).
X   The 'polygon next' member is a pointer to a linked list of arrays of
X   indices, as follows:
X
X   typedef struct polystruct {/* polygon def: ptr to this struct */
X      int count;              /* # of points in this polygon */
X      struct polystruct *next;/* ptr to next polygon */
X      WORD coord[1];          /* index of first point */
X   } *polygon;                /* the rest follows hereafter */
X
X   Like with the item def. only one index is declared; in an actual case many
X   will follow in consecutive memory. Each polygon is a series of connected
X   lines, the indices being the numbers of the points in the coordinate array.
X   Thus an item can have several series of connected lines.
X
X   An item is in fact a very static object, it can be seen as an abstraction.
X   If we want to use it, we need an other type of object, i.e. the instance.
X   An instance is also a pointer to a struct, defined by:
X
X   typedef struct instruct {  /* instance def: ptr to this struct  */
X      item in_item;           /* item of which this is an instance */
X      WORD trans[4][4];       /* 4H that places it                 */
X      WORD i_data[1][2];      /* screen coordinates of first point */
X   } *instance;               /* the rest follows hereafter        */
X
X   The 'item' member is the pointer to the corresponding item structure
X   (containing a coordinate array and a list of polygons).
X   The 'trans' member is the transformation matrix that puts the item in 3D
X   space (so its contents varies because it is multiplied each time by
X   whatever transformations act on the object).
X   To be able to do the calculation of projected points and actual drawing
X   of the computed lines in different places, there is also a storage area
X   in the instance structure that contains for each point the actual screen
X   coordinates (pixel coordinates). So it's written by the projection functions
X   and read by the draw functions. Again there's room for one point only,
X   but dynamic allocation 'over the edge of the struct' allows for an
X   arbitrary number of points. Note that the definition of C says that
X   consecutive members of the struct occupy consecutive places in memory, so
X   that we may safely use 'the other end' of the struct.
X
X
X      TERMINOLOGY USED
X
X   To keep things small and simple the following abbreviations will be used:
X   4H: 4 x 4 homogeneous transformation (matrix). Unless stated otherwise,
X       this will be represented in the machine by a: short [4][4], where
X       short is a 16 bit wide integer.
X   I, O, IO: in, out, inout - for parameters.
X
X      LIST OF FUNCTIONS AND BRIEF DISCUSSION
X
X   Now follows a list of the functions offered and a tiny description of
X   them; consult the source if you want to go into detail, you will find
X   this text more or less also there. The functions from the 3demo.c module
X   are not listed here since they serve only a demonstration purpose and
X   are not suitable for general use.
X
X   From mat.c:
X
X   - note that, unless stated otherwise, memory for matrices etc. must
X     already exist, must be either dynamically or statically be allocated.
X
X   o  void matapply(mat,func,v,fac)
X      WORD *mat;          IO the 4H to be transformed (e.g. ins->trans).
X      WORD *(*func)();    I  the kind of transformation, i.e. a function ptr.
X                             func can currently only be mattlate, matrotate,
X                             or matreflect.
X      double *v;          I  a 3D vector to quantisize the transformation.
X      double fac;         I  a number with which v is multiplied.
X
X      Applies a transformation to a 4H. This can be a
X      translation, rotation or reflection. Matapply can typically be used
X      to create 4H's beforehand that represent a small motion (small
X      step in x-, y-, z - direction or turn around x-, y-, z - axis).
X      In that case mat is taken to be an 4H identity matrix, v one of the
X      unity vectors ((1,0,0), (0,1,0), (0,0,1)) and fac is a (small) number.
X
X   o  void matcompose(a,b)
X      WORD *a;            IO
X      WORD *b;            I
X
X      The result of the (homogeneous) multiplication of a and b is placed
X      into a. This function is implemented as a macro.
X      It can be used for instance to update an instance coordinate
X      transformation (take a to be ins->trans) when an other transformation
X      affects it (the b matrix).
X
X   o  WORD *matident(n,a)
X      int n;              I
X      WORD *a;            O
X
X      Create a nxn identity matrix and return the pointer to it.
X
X   o  WORD *matreflect(v,a)
X      double *v;          I  a quantisizing 3D vector: the normal vector
X      WORD *a;            O  the 4H.
X
X      Create a 4H reflection matrix. Used by matapply().
X
X   o  WORD *matrotate(v,a)
X      double *v;          I  a quantisizing 3D vector: the rotation axis
X      WORD *a;            O  the 4H.
X
X      Create a 4H rotation matrix.
X
X   o  WORD *mattlate(v,a)
X      double *v;          I  a quantisizing 3D vector: the translation step
X      WORD *a;            O  the 4H.
X
X      Create a 4H translation matrix.
X
X   o  uchar *matscr_to_str(b_and_w)
X      bool b_and_w;       I  Use-only-black-and-white flag
X
X      Compress screen into unsigned char array and return pointer to it.
X      If the flag is TRUE, the screen is handled as if only one colour was
X      present (even if it is multi-colour); this allows for some factors
X      extra compaction. The memory needed for the array is dynamically
X      allocated.
X      The screen information is stored in the following way:
X      Assume for simplicity's sake the screen consists of 200 lines, each
X      line being 160 bytes wide, so 160 (byte) columns wide (the peculiarities
X      of the different resolution and colours will be handled further on).
X      The first byte contains the number of nonempty columns that were found.
X      Then follows for each nonempty column:
X         the column number (0-159)
X         the number of line sets (0-80). A line set is a series of consecutive
X            nonzero bytes in one column.
X         Then follows for each line set:
X            the first line of the set (0-199).
X            the number of lines (0-199).
X            the actual values (each being 0-255)
X         until last line set in column
X      until last nonempty column on screen.
X      As for the different screen modes:
X         High res on the Atari has 400 lines, 80 byte columns. To be able
X         to deal with the lines from 256 up (the line no. must fit in a byte)
X         the lines from 200-399 are marked by using column numbers 160-239
X         (instead of 0-79) and line numbers 0-199 (instead of 200-399).
X         Medium and low res have both 200 lines. Medium has 80 columns,
X         2 colour bit planes, whereas low has 40 columns, 4 colour bit planes.
X         Because the colour info is stored as: word0 of plane0, word0 of
X         plane1, etc. the simple solution is to view an entire line as simply
X         160 bytes (of which there are overlapping pairs for medium and
X         overlapping quartets for low res.), so use columns 0-159.
X         The b_and_w flag simply says to ignore each odd word in medium res.
X         and each second, third and fourth word of four consecutive words in
X         low res. In this way, if the image was already black, a compaction
X         of 2 to 4 times above the existing compaction is reached.
X
X   o  void matstr_to_scr(s,b_and_w)
X      register uchar *s;  I  Array of compressed data
X      bool b_and_w;       I  Handle-as-black-and-white-only flag
X
X      Display compressed image. s should have been created by matscr_to_str().
X
X   o  void error(func)
X      char *func;         I  name of function in which error occured
X
X      Simple error handling function. Display a message and stop program.
X
X   o  double maxfactor(arr,cnt)
X      double *arr;        I  the array
X      int cnt;            I  # elements in array
X
X      Find maximal multiplication factor for an array of doubles so that each
X      array element after multiplication with this factor can be cast to
X      short without truncation.
X
X   o  double mycos(a)
X      double a;           I
X
X      Fast cosine function by table lookup. Each value that has been
X      calculated once can be retrieved by table lookup.
X
X   o  double mysin(a)
X      double a;           I
X
X      As mycos() for sine function.
X
X   From mxops.asm:
X
X   o  void mxhmul(a,b,c,p,q,r)                                                       *
X      short *a,           I  points to array of p x q shorts
X            *b,           I  points to array of q x r shorts
X            *c,           O  points to array of p x r shorts
X            p, q, r;
X
X      Matrix multiplication for homogeneous coordinate matrices
X      c points to the result of the multiplication of the matrices
X      pointed to by a and b. It is scaled to fit in shorts.
X      Since a temporary array is used to store intermediate 32 bit
X      results c may be one of a, b without a problem.
X
X   o  short *matcopy(a,b,n)
X      short *a;           I
X      short *b;           O
X      short n;            I
X
X      Copy over n shorts from the array pointed to by a to that pointed
X      to by b.
X
X   o  void mxproj(inarr,outarr,pcount,eye_z,scal_x,scal_y)
X      short *inarr,       I
X            *outarr;      O
X      short pcount;       I
X      short eye_z,        I  distance of observer to screen
X            scal_x,       I  scaling along x axis of screen
X            scal_y;       I  scaling along y axis of screen
X
X      Projection of inarr onto the instance's screen coordinates outarr.
X      inarr points to an pcount x 4 array of shorts representing the hom.
X      coordinates of the pcount points of the instance.
X      outarr points to a pcount x 2 array of shorts representing the screen
X      coordinates to be calculated for each point (this array is part of the
X      instance).
X      eye_z, scal_x and scal_y are parameters that determine the projection.
X
X   From gemfuncs.c:
X
X   o  void gem_init()
X
X      opens a virtual workstation and allocates extra screen memory for
X      smooth drawing.
X
X   o  void gem_exit()
X
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
X   o  void swapscreen()
X
X      switches the logical and physical screens. All drawing functions
X      (including displaying text) takes place on the logical screen, while
X      the physical screen is displayed. When the drawing is finished, the
X      pointers to the two screen areas are swapped. The VBL (vertical blank
X      interrupt routine) checks whether the physical screen pointer has
X      changed and if so, tells it the hardware. By altering the physical
X      screen location just before the screen is displayed (the beam is aimed
X      again at the start of the display it is ensured that movement is smooth
X      (no screen memory updating while is it being read).
X
X   From drawlin.asm:
X
X   o  void drawlin(x1,xy1,x2,y2)
X      WORD x1,y1,x2,y2;   I
X
X      Draw a line between points (x1,y1) and (x2,y2) in high, medium or low
X      resolution. No attempt has been made to handle colours, different line
X      styles/widths, clipping, although this should be simple - maybe
X      something for a next release.
X      The method used for calculating the pixel coordinates of the line is
X      Bresenham's algorithm, of which I will give an explanation. Also some
X      details of how it is speeded up further wil be given.
X      The algorithm consists of taking always a step in the direction of the
X      axis of greatest movement, and, depending on an accumulating error term
X      also in the direction of smallest movement. A derivation for the simple
X      case that the start point is (0,0) and the end point (a,b) with a >= b
X      and a and b both >= 0:
X      Equation of the line:
X
X                 a . y - b . x = 0                             (1)
X
X      Now take (x(n), y(n)) to be the nth point of the line. Because x(n) and
X      y(n) are integers, they will generally not satisfy (1). In fact an error
X      term d(n) exists, generally not 0:
X
X                 a . y(n)  - b . x(n)  = d(n)                  (2)
X
X      Since steps are to be taken in x direction, the x(n) is 'correct';
X      the y(n) may be off at most 0.5, so
X
X                 - 0.5a <= d(n) < 0.5a.                        (3)
X
X      It is easier to compare against 0, so instead of d(n) we use e(n) with
X
X                 e(n) = d(n) + 0.5a.                           (4)
X
X      and
X
X                 0 <= e(n) < a                                 (5)
X
X      By subtracting (2) from (2) with n+1 instead of n we get:
X
X                 a . (y(n+1) - y(n)) - b . (x(n+1) - x(n))  = d(n+1) - d(n)
X
X      Since x(n+1) - x(n) == 1, and d(n+1) - d(n) == e(n+1) - e(n):
X
X                 a . (y(n+1) - y(n)) - b = e(n+1) - e(n), or
X
X                 e(n+1) = e(n) - b + a . (y(n+1) - y(n))       (6)
X
X      Now it's easy, since the e(n+1) must be >= 0  (5), and y(n+1) - y(n)
X      is either 1 or 0:
X      subtract b from e(n); if result < 0 increment y and add a to error term.
X
X      In a C program:
X
X      short x,y,a,b,e;
X
X      e = a >> 1; /* d(0) == 0, so e(0) == 0.5a */
X      y = 0;
X
X      for (x = 0; x <= a; x++) {
X         plot(x,y);
X         if ((e -= b ) < 0) {
X            y++;
X            e += a;
X         }
X      }
X
X      The 'real' thing must also handle the other cases: b > a, a < 0 or
X      b < 0:
X      First end and starting point are swapped if x2 < x1, so that always
X      x2 >= x1; this implies a > 0. The increment of y is 1 if b >= 0,
X      -1 if b < 0 and furthermore b is then set to its absolute value.
X      The cases a >= b and b > a are dealt with separately.
X      Because the machine addresses bytes, not bits, and thus in order to
X      avoid excessive address calculations, the pixel (x,y) is represented
X      by a word address and a bit in that word. Stepping in x direction is
X      done by rotating the word by 1, incrementing/decrementing the address
X      if a carry is generated. Stepping in y direction is done by
X      adding/subtracting the number_of_bytes_per_line to the address
X      (effectively stepping a line).
X      The new point is OR-ed into the screen each time; in fact, this OR-ing
X      is done into a data register for speed; the actual storing into the
X      screen is done when the address is about to change. In the case that
X      b > a, the y-step is always taken, so the OR-ing into the data reg. is
X      NOT done there.
X      An even faster version of drawlin is being planned, but implementing
X      it would postpone the current distribution. Next release!
X
X   From object.c:
X
X   o  item matcrit(n,d,o)
X      int n;              I  the point count
X      double d[][3];      I  the n*3 coordinates of the points
X      short *o;           I  an array of indexes for the points; each -1 value
X                             ends a joined set of points, an extra -1 ends the
X                             array.
X
X      Create an item by giving its point count, point coordinates and order.
X      The function allocates memory for the item, in this it stores the point
X      count, the points homogeneous 4D coordinates and a polygon list pointer.
X      For each polygon also memory is allocated to contain a count and an
X      array of indices.
X
X   o  void matfrit(ip)
X      item ip;            I  item to be freed
X
X      Frees all memory belonging to the item that was allocated by matcrit.
X
X   o  instance matcrins(it,lia,tv)
X      item it;            I  the item it's refering to.
X      double lia[3][3];   I  the 3x3 transformation array.
X      double tv[3];       I  the translation vector.
X
X      Create an instance of the item by giving the item and a transformation
X      matrix to put it into space. Note that the transformation array is an
X      array of 3x3 doubles (non-homogeneous coordinates), and also the
X      translation vector is in non-homogeneous coordinates. The memory
X      allocated will contain a pointer to the item, a 4H to place the item
X      in space, and an array to hold the screen coordinates of each point of
X      the instance.
X
X   o  void matfrins(ins)
X      instance ins;       I  instance to be freed
X
X      Frees all memory belonging to the instance that was allocated by
X      matcrins.
X
X   o  WORD *matseteye(lia,tv,dist,sx,sy)
X      double lia[3][3];   I  the transformation to orientate the screen
X      double tv[3];       I  the vector to place the screen
X      double dist;        I  the distance of the eye from the proj. screen
X      double sx,sy;       I  scaling for X-, resp. Y-axis.
X
X      Fix the eye and projection screen positions and orientations and scaling.
X      This generally has to be done once, unless the eye or proj. screen are
X      moving.
X
X   o  void matproject(ins)
X      register instance ins; I  the instance to be projected.
X
X      Project an instance, i.e. calculate the screen coordinates it will need
X      to draw it. This will fill the array of screen coordinates within the
X      instance with values that depend on the current contents of the
X      instance's 4H transformation and the observer's position (set by
X      matseteye). The critical part is handled by mxproj for speed reasons.
X
X   o  void matdraw(ins,mode)
X      instance ins;       I  the instance to be drawn.
X      int mode;           I  the mode of drawing (OR,XOR,ERASE etc.)
X
X      Draw an instance, using VDI. Each polygon in the instance's item's
X      polygon list is drawn, using the coordinates in the instances screen
X      coordinates array.
X
X   o  void matfdraw(ins,mode)
X      instance ins;       I  the instance to be drawn.
X      int mode;           I  the mode of drawing (OR,XOR,ERASE etc.)
X
X      Draw an instance, using drawlin. The mode parameter is currently ignored.
X      See also matdraw. This method is faster; an even faster method for
X      drawing lines than drawlin is planned.
X
X   o  void insstore(ins,a,n)      stores
X      instance ins;       I  into
X      WORD *a;            O  as entry number
X      int n;              I  ; i.e. there are n WORDs in a preceding.
X
X      Store the calculated screenpoints of an instance.
X      The screen coordinates are stored in a as a[n], a[n+1] etc.
X      In this way line images can be stored with minimum overhead. The only
X      processing that needs to be done afterwards is calling insload and
X      matfdraw (or matdraw). Before insstore is called the coordinate array
X      has to be calculated, preferably with matproject.
X
X   o  void insload(ins,a,n)    loads
X      instance ins;       I  from
X      WORD *a;            I  as entry number
X      int n;              I  ; i.e. there are n WORDs in a preceding.
X
X      Recall the calculated screenpoints of an instance. See also insstore.
X
X   o  static WORD *matliatv(invers,lia,tv,rotra)
X      int invers;         I  Use inverse of lin. transf.
X      double lia[3][3],   I  Linear transform. to place it
X             tv[3];       I  Translation vector to place it
X      WORD *rotra;        O  4H result
X
X      Apply linear transformation and translation. Note that this function is
X      static and can thus not be used as external function. Use matapply for
X      a function with comparable capabilities; the difference is that
X      matliatv can specify all kinds of linear transformations, and that it
X      puts the result in rotra, while matapply is restricted to translation,
X      rotation and reflection and applies the thus created 4H upon the output
X      4H.
X
X   o  WORD *matseteye(lia,tv,dist,sx,sy)
X      double lia[3][3],   I  Linear transform. to place it
X             tv[3],       I  Translation vector to place it
X             dist,        I  Distance eye from screen
X             sx,sy;       I  Scaling x and y axis
X
X      Set eye coordinates. Besides setting distance and scaling the function
X      returns a pointer to the (static) 4H observer matrix.
+ END-OF-FILE matricks.doc
chmod 'u=rw,g=r,o=' 'matricks.doc'
echo 'SENT: -rw-r-----  1 leo         27488 Aug 21 15:09 matricks.doc'
echo -n 'RCVD: '
/bin/ls -l matricks.doc
echo 'Extracting readme.doc'
sed 's/^X//' > readme.doc << '+ END-OF-FILE readme.doc'
X
X
X         +--------------------------------------------------------------+
X         | MATRICKS: 3D graphics package; sources, docs, binaries, demo |
X         +--------------------------------------------------------------+
X
X   The distributions are as follows:
X
X      SOURCES:                         BINARIES:
X
X      3demo.c                          3demo.prg
X      drawlin.asm                      3dlib.bin
X      gemfuncs.c                       matricks.doc
X      makefile                         readme.doc
X      mat.c
X      matricks.doc
X      matricks.h
X      mxops.asm
X      object.c
X      readme.doc
X
X   SOURCES are planned to go to comp.sources.misc because there's a general
X   interest for the stuff.
X   BINARIES are planned to go to comp.binaries.atari.st; they are too specific
X   to run on other hardware than Atari ST's.
X
X   A few remarks conceirning the demo program and library:
X
X   1) Because clipping is not yet implemented, images can get distorted near
X   an edge. This is due to the projection function, that truncates all
X   coordinates that are too big to fit on the screen. Clipping will be
X   implemented in the next release; no truncation will be needed anymore.
X   2) For high resolution monitors the first demo only uses part of the screen.
X   Since I don't own one, a friend had to tell me (thanks, Frans!). Because
X   I don't consider it too important, it isn't fixed yet (next release?).
X   3) A remark about the library: all parameters of all functions are of size
X   4; this is due to the Lattice parameter passing mechanism. This can cause
X   problems when using them from other compilers (e.g. when passing shorts).
X   Suggestions: explicit casts to long, or using an interface library, or
X   creating your own library using the sources (see the makefile).
X
X   Enjoy!
X
X            Leo.
X
X   P.S.: For bug reports, problems, questions, suggestions, etc.:
X
X         L.J.M. de Wit
X         Nachtegaallaan 7
X         5731XP Mierlo
X         Holland
X
X         E-mail: ...!mcvax!philmds!leo
X
+ END-OF-FILE readme.doc
chmod 'u=rw,g=r,o=' 'readme.doc'
echo 'SENT: -rw-r-----  1 leo          2021 Aug 21 14:50 readme.doc'
echo -n 'RCVD: '
/bin/ls -l readme.doc
exit 0



More information about the Comp.sources.misc mailing list