REVISION:                 20/9/1997
AUTHOR:                   Giancarlo Castagno (gcastagno1@coord3.com)

Forewords
=========
This document contains the specs of the current points, lights, groups and
primitives memory format for TopModel, Gemini and related applications.


Points & lights:
================
The memory area in which they are stored will be identified from now on
with "points", which is the pointer to the start of the area.
Each point is stored in 32 bytes, apart lights and groups'control points.
The first 58 points in the area are reserved for TopModel use (points 0..57).
Thus valid user's points in a scene must be stored from the 58th on (starting
from an offset of 58*32 bytes from the start of the area).

Each element in this area is stored in 32 bytes, as said before. The word
"element" indicates a normal point (a vertex of a polygon, a control point of
a curve), a light, the central point of a group or data for the lights or the
groups. Each one has a control word, which indicates what it is.
The 32 bytes are basically 8 words, and the 4th is the control word (thus
placed at +12 bytes from the start of the element).
So, the control word of the point 0 in the list is placed at:

  (points + 58*32) + 0*32 + 12

The control word contains several informations:

 bit(s)   meaning
 -----------------------
 0      | if set, the point is selected
 1      | if set, the point belongs to a polygonal net of a bezier surface
 2      | if set, the point can be selected&edited (0: it belongs to a group)
 5-3    | type of the point: 0 ---> polygon vertex
                             1 ---> control point of a curve/surface
                             2 ---> reserved
                             3 ---> beam light
                             4 ---> point light
                             5 ---> sun light
                             6 ---> reserved
                             7 ---> center of a group
 15-6   | if it's a normal point (type 0 or 1): number of primitives using it
          if it's a light (type 3-4-5): number of light
 28-16  | number of the group this point belongs to (0=none)
 29     | used in TM to indicate it is selected for the current operation,
          mainly for defomations
 30,31  | reserved, set to 0

 All coordinates are stored as fixed point values (with 17 points of mantissa),
 so the value stored is n/2^17.

 Normal point: type 0 or 1
 -------------------------
 This is the 32 bytes structure:

 +0  X coordinate (*2^17)
 +4  Y coordinate (*2^17)
 +8  Z coordinate (*2^17)
 +12 control word (as above)
 +16 bits15-0  video X coordinate
     bits31-16 video Y coordinate
 +20 Z video coordinate
 +24 normal of the point (0-10 Z component of vector, 21-11 Y, 31-22 X)
 +28 bits  9-0 : reserved, set to 0
     bits 31-10: offset to the bezier surface that generated it/4, from the
                 start of the primitives memory area. Thus, if the bezier
                 surface that generates the point is at +4096, here you
                 found 1024. IF BIT 1 OF THE CONTROL WORD IS SET
     bits 31-10: radiosity colour of this vertex: 31-25 B, 24-18 G, 17-10 R

 Words +16 and +20 are filled by TM (gemini) when projecting the scene to match
 the current view. The normal of the point is used for shading, and usually is
 calculated by TM. It can be extracted:
 X =  (normal        ASR#22)ASL#7  (*2^15)
 Y = ((normal LSL#10)ASR#21)ASL#6  (*2^15)
 Z = ((normal LSL#21)ASR#21)ASL#6  (*2^15)

 Lights: type 3,4,5
 ------------------
 Light  type 4   is  stored on two   consecutive points
 Lights type 3,5 are stored on three consecutive points


 > Point#1 structure:

 exactly like the one of a normal point, apart from:
 +24 is not the normal, but the light direction (for type 3,5, calculated by TM)
 +28 lens-flare data: if the value of the word is 2^29, (i.e. only bit 29
                      is set) then no lens-flare, otherwise:
                      bits 31-24 radius of the effect
                           23    vertical flare type
                           22-18 vertical size
                           17    horizontal flare type
                           16-12 horizontal size
                           11-0  reserved, set to 0

 > Point#2 (only for types 3 and 5):
 +0     X coordinate of the point at which the light points at
 +4     Y coordinate
 +8     Z coordinate
 +12-28 set to 0

 > Point#3 (or Point#2 for type 4)
 +0     bits 31-10 solid angle (needed only for a beam light) or 0
        bits  9-0  colour of the light
 +4     light intensity  (*2^16)
 +8     dropoff distance (*2^17)
 +12-24 set to 0
 +28    reserved, set to 0

 Group central point
 -------------------
 It is stored on two consecutive points:

 > Point#1 : as for a normal point
 > Point#2 : bytes 0..11 are the groupname, NULL terminated (so up to 11 chars)


Primitives:
===========
The memory area in which they are stored will be identified from now on
with "primi", which is the pointer to the start of the area. No primitives
are used by TM by default, so you can start storing your primitives from
the start of this area. A primitive is not stored in a fixed number of bytes,
so you've to check it's type to move forward to the next.
The first word in the block is the control word of the primitive:

 bit(s)   meaning
 -----------------------
 0 - 7  | number of sides of the polygon
 8      | used in TM to indicate it is selected for the current operation,
          mainly for defomations
 9      | if clear, the primitive is visible, otherwise is hidden
 10     | if set, the primitive is selected
 15-11  | type of the primitive: 0 ---> polygon
                                 1 ---> polygon that belongs to a polygonal
                                        net of a bezier surface
                                 2 ---> reserved
                                 3 ---> bezier curve
                                 4 ---> Bezier surface
                                 5 ---> sphere
 16     | if set, the primitive is flat
 17     | if set, the primitive is luminous
 18     | if set, the primitive has a chrome mapping
 19     | if set, the primitive has a bump mapping
 20     | if set, the primitive is drawn wireframe
 21     | if set, the primitive is drawn shaded wireframe
 31-22  | reserved, set to 0

 The primitive's structure is as follows:

 +0  control word, as above
 +4  bits 31-22: colour number of the primitive
          21-12: material number
          11-0 : reserved, must be 0
 +8  normal of the primitive (0-10 Z component of vector, 21-11 Y, 31-22 X)
 +12 texture informations:
     bits 31-23: reserved, must be 0
          22-18: height of bump mapping
          17-9 : number of texture to be used for bump mapping
           8-0 : number of texture to be used for chrome or normal mapping
 +16 pointer to first point used by the primitive (in point memory area)
 +20 .....


 Primitive size
 --------------
 Each primitive needs 16 bytes of data, the one specified above: the words
 from +0 to +12. Then the number of points needed is as follow:

 a bezier curve   needs 4  points specified, so 16+ 4*4 = 32 bytes
 a bezier surface needs 16 points specified, so 16+16*4 = 80 bytes
 a sphere         needs 2  points specified, so 16+ 2*4 = 24 bytes

 A polygon, apart from a number of bytes proportional to the number of its
 sides, needs additional information for the textures. So, for each vertex,
 it needs a pointer to a point and a word containing the texture coordinate
 at that vertex (31-16 Y coordinate, 15-0 X coordinate).
 Thus, a triangle, is stored this way:

 +0  control word
 +4  data
 +8  normal
 +12 texture information
 +16 pointer to point#1
 +20 pointer to point#2
 +24 pointer to point#3
 +28 texture coordinates vertex#1
 +32 texture coordinates vertex#2
 +36 texture coordinates vertex#3

 So a polygon needs (16 + sides*8) bytes.
 Please note that altough TM (gemini) manages polygons up to 256 sides, it
 actually draws only triangles and squares!

=====================
PLEASE READ CAREFULLY
=====================
There's the possibility during the creation process in TM to delete a point
or a primitive. This leaves holes in the datas. TM has an algorithm of
garbage collection, to regain these spaces, but it isn't called during each
operation. So there is a mechanism to say that a point or a primitive is not
valid and shouldn't be considered (i.e. its space is free for the next
creation process). When the control word is 2^29 (i.e. only bit 29 is set),
this means that the object (a point or a primitive) must be skipped.
This means simply move by 32 bytes for a point, but for a primitive?
When a primitive is delete, all its words are set to 2^29, so what you've
to do when you encounter a control word of 2^29, is to move by 4 bytes and
try again, until you get a value different than 2^29. This is surely the
control word of the next valid primitive.
Furthermore, the list of points and primitives, MUST BE TERMINED, writing
the value 2^30 in the control word of the ghost object next to the last valid.



A little BASIC example
======================

this is a little example on how to create a triangle.

DIM point 58*32+4*32, primi 48

validPoint = point+58*32
validPoint!0 = x1*2^17 : validPoint!4 = y1*2^17 : validPoint!8 = z1*2^17
validPoint!12= 2^2  :REM type=vertex, editable, no primitive attached
validPoint!32= x2*2^17 : validPoint!36= y2*2^17 : validPoint!40= z2*2^17
validPoint!44= 2^2  :REM type=vertex, editable, no primitive attached
validPoint!64= x3*2^17 : validPoint!68= y3*2^17 : validPoint!72= z3*2^17
validPoint!80= 2^2  :REM type=vertex, editable, no primitive attached
validPoint!108= 2^30:REM terminator

primi!0  = 3        :REM polygon, 3 sides
primi!4  = 0        :REM colour 0 (black), material 0 (plastic)
primi!12 = 0        :REM no textures
REM now I set the pointers to the points used, updating, in the control
REM word of each point the number of primitives that use it
primi!16 = validPoint   :validPoint!(0*32+12)+=2^6
primi!20 = validPoint+32:validPoint!(1*32+12)+=2^6
primi!24 = validPoint+64:validPoint!(2*32+12)+=2^6
primi!40 = 2^30     :REM terminator


Now "point" and "primi" are two valid areas to pass to gemini to be
visualized.