home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 106 / EnigmaAmiga106CD.iso / www / afc / afc-dir / vectworld_source.lha / Source / vectWorld.e < prev   
Text File  |  1999-02-20  |  101KB  |  3,501 lines

  1. /*
  2. $VER: vectWorld V1.00 - by Andrea Galimberti - (C) Brighting Brain Brothers
  3.  
  4. Base Number: $8005
  5.  
  6. Description: this MODULE contains a SET OF instructions TO build 3D
  7.              Objects. These objects can be linked together in a World
  8.              OBJECT AND can be rendered in wireframe mode OR in filled
  9.              vectors mode.
  10.  
  11. Note: *pensare a come far diventare visibili le superfici che si scoprono
  12.         quando cancello quelle davanti.
  13. */
  14.  
  15. ->/// Main docs
  16. /*
  17. @node main "AFC Module: vectWorld / Main"
  18.  
  19.  
  20.               ** vectWorld V1.00 - Original By Andrea Galimberti **
  21.  
  22.                          Part of Amiga Foundation Classes
  23.  
  24.                            --- NO LONGER SUPPORTED ---
  25.  
  26.  
  27.     @{" Introduction   " LINK world_intro} Important: don't skip this as usual.
  28.     @{" Author(s) Info " LINK author}
  29.  
  30.  
  31.     Requires: @{" nodemaster " LINK "nodemaster.guide/Main"}
  32.  
  33.     Base: $8005
  34.  
  35.     Sections:    @{" vectWorld methods " LINK world_methods}
  36.                  @{" Object_obj methods   " LINK world_o_methods}
  37.                  @{" Procedures           " LINK world_procedures}
  38.  
  39.  
  40.                  @{" ERROR TABLE        " LINK Error_Table}
  41. @endnode
  42.  
  43. @node world_methods "AFC module: vectWorld methods"
  44.  
  45.     vectWorld methods:
  46.  
  47.     COMMANDS                          BRIEF DESCRIPTION
  48.     -----------------------------------------------------------------------
  49.  
  50.     @{" vectWorld()                   " LINK vectWorld} Initializes a world
  51.  
  52.     @{" addobj()                         " LINK world_addobj} Create and add an object
  53.     @{" setobj()                         " LINK world_setobj} Only add an existing object
  54.     @{" getobj()                         " LINK world_getobj} Get a specified object
  55.     @{" delobj()                         " LINK world_delobj} Delete object
  56.     @{" unlinkobj()                      " LINK world_unlinkobj} Remove an object
  57.     @{" clearobj()                       " LINK world_clearobj} Clear an object
  58.  
  59.     @{" setvertex()                      " LINK world_setvertex} Add vertex to object
  60.     @{" getvertex()                      " LINK world_getvertex} Get vertex of object
  61.     @{" fastsetvert()                    " LINK world_fastsetvert} Fast add vertex
  62.     @{" delvertex()                      " LINK world_delvertex} Delete vertex from object
  63.  
  64.     @{" setline()                        " LINK world_setline} Add line to object
  65.     @{" getline()                        " LINK world_getline} Get line from object
  66.     @{" fastsetline()                    " LINK world_fastsetline} Fast add line
  67.     @{" delline()                        " LINK world_delline} Delete line from object
  68.  
  69.     @{" setsurface()                     " LINK world_setsurface} Add surface to object
  70.     @{" getsurface()                     " LINK world_getsurface} Get surface from object
  71.     @{" delsurface()                     " LINK world_delsurface} Delete surface from object
  72.  
  73.     @{" visible()                        " LINK world_visible} Switch on and off an object
  74.     @{" position()                       " LINK world_position} Move local axes of an object
  75.     @{" scale()                          " LINK world_scale} Scale an object
  76.     @{" applyobj()                       " LINK world_applyobj} Apply transformations to an object
  77.  
  78.     @{" projection()                     " LINK world_projection} 3D -> 2D conversion
  79.     @{" getpoint()                       " LINK world_getpoint} Get projected pixel
  80.     @{" draw()                           " LINK world_draw} Draw wireframe (or points)
  81.     @{" init3D()                         " LINK world_init3d} Initialise filled vectors
  82.     @{" drawfill()                       " LINK world_drawfill} Draw filled vectors
  83.  
  84.     @{" copyobj()                        " LINK world_copyobj} Copy two objects
  85.     @{" cloneobj()                       " LINK world_cloneobj} Duplicate an object
  86.  
  87.     @{" setobserver()                    " LINK world_setobserver} Position observer
  88.     @{" setscale()                       " LINK world_setscale} Scale all objects
  89.     @{" settrasl()                       " LINK world_settrasl} Traslate all objects
  90.     @{" setrot()                         " LINK world_setrot} Rotate all objects
  91.     @{" setafterscale()                  " LINK world_setafterscale} Scale to fit screen
  92.     @{" setaftertrasl()                  " LINK world_setaftertrasl} Traslate origin of axes
  93.     @{" setdisplay()                     " LINK world_setdisplay} Set display features
  94.  
  95.     @{" version()                        " LINK world_version} Version of vectWorld
  96.  
  97. @endnode
  98.  
  99. @node world_o_methods "AFC module: Object_obj methods"
  100.  
  101.     Object_obj methods:
  102.  
  103.     COMMANDS                          BRIEF DESCRIPTION
  104.     -----------------------------------------------------------------------
  105.  
  106.     @{" object_obj()                     " LINK object_obj} Initializes an object
  107.     @{" clear()                          " LINK object_clear} Clear object
  108.  
  109.     @{" name()                           " LINK object_name} Return object name
  110.  
  111.     @{" setvertex()                      " LINK object_setvertex} Add vertex
  112.     @{" getvertex()                      " LINK object_getvertex} Get vertex
  113.     @{" fastsetvert()                    " LINK object_fastsetvert} Fast add vertex
  114.     @{" delvertex()                      " LINK object_delvertex} Delete vertex
  115.  
  116.     @{" setline()                        " LINK object_setline} Add line
  117.     @{" getline()                        " LINK object_getline} Get line
  118.     @{" fastsetline()                    " LINK object_fastsetline} Fast add line
  119.     @{" delline()                        " LINK object_delline} Delete line
  120.  
  121.     @{" setsurface()                     " LINK object_setsurface} Add surface
  122.     @{" getsurface()                     " LINK object_getsurface} Get surface
  123.     @{" delsurface()                     " LINK object_delsurface} Delete surface
  124.  
  125.     @{" position()                       " LINK object_position} Move local axes
  126.     @{" scale()                          " LINK object_scale} Scale object
  127.     @{" apply()                          " LINK object_apply} Apply transformations
  128.  
  129.     @{" projection()                     " LINK object_projection} Project single object
  130.     @{" getpoint()                       " LINK object_getpoint} Get projected pixel
  131.  
  132.     @{" copy()                           " LINK object_copy} Copy object
  133.     @{" clone()                          " LINK object_clone} Duplicate object
  134.  
  135. @endnode
  136.  
  137. @node world_procedures "AFC module: Procedures"
  138.  
  139.     Procedures:
  140.  
  141.     COMMANDS                          BRIEF DESCRIPTION
  142.     -----------------------------------------------------------------------
  143.  
  144.     @{" fillSinTable()                   " LINK world_fillsintable} Initialize table of sines
  145.     @{" limitangle()                     " LINK world_limitangle} Bound angle (0 - 360 degrees)
  146.     @{" crossprod()                      " LINK world_crossprod} Vector product
  147.     @{" dotprod()                        " LINK world_dotprod} Scalar product
  148.  
  149. @endnode
  150.  
  151. @node author "Author(s) Info"
  152.  
  153.     Original By:  Andrea Galimberti
  154.  
  155.     E Version By: Andrea Galimberti
  156.  
  157. @endnode
  158.  
  159. @node world_intro "AFC module: vectWorld / Introduction"
  160.  
  161.  
  162.    vectWorld
  163.    ------------
  164.  
  165.    This Class contains instructions to create, manipulate and draw three
  166. dimensional objects:  they can be rotated, scaled and drawn in a wireframe
  167. and in a filled vector mode; at any time you can add, remove or modify
  168. vertices, lines and surfaces, the system keeping track automatically of
  169. your changes.
  170.  
  171.  
  172.    @{" The objects           " LINK world_i_objects}
  173.    @{" Lines and surfaces    " LINK world_i_lines}
  174.    @{" The coordinate system " LINK world_i_coords}
  175.  
  176. @endnode
  177.  
  178. @node world_i_objects "AFC module: Introduction / objects"
  179.  
  180.    Two are the objects contained in this class:  vectWorld and object_obj.
  181. The latter represents a single 3D object containing its description in
  182. terms of position of vertices, lines and/or surfaces.  The former
  183. represents the world in which to insert the objects before they are
  184. rendered.  You have to keep in mind this:  objects can be manipulated and
  185. drawn on the screen only when they are in a vectWorld, because it's the
  186. vectWorld that contains notions as rotation, traslation, scaling and
  187. observer position.
  188.  
  189.    The methods are accordingly divided in two sets:  one pertaining to the
  190. vectWorld and one to the object_obj.  Most of the methods of the two sets
  191. share the same name, because they do exactly the same thing:  the method of
  192. vectWorld acts on objects already linked to that world, while the
  193. corresponding method of object_obj acts on the single object.
  194.    But why this division can be useful?  I must say that you're invited to
  195. use only the methods of vectWorld (because otherwise, as I said before,
  196. objects cannot be rendered), but perhaps you may want to keep your own
  197. database of objects and link them to a vectWorld only when needed, and this
  198. is where the methods of object_obj come into play.
  199.  
  200. @endnode
  201.  
  202. @node world_i_lines "AFC module: Introduction / lines and surfaces"
  203.  
  204.    An object_obj contains vertices, lines and surfaces.  No doubt you have
  205. to define vertices before defining anything else, but you haven't to define
  206. lines before surfaces:  these two structures are independent but, anyway,
  207. they aren't mutually exclusive.  You need lines if you render the world in
  208. wireframe; otherwise, if you use the filled vector mode you need only
  209. surfaces.
  210.  
  211. @endnode
  212.  
  213. @node world_i_coords "AFC module: Introduction / coordinate system"
  214.  
  215.    There's always a weird (for physicists) peculiarity in the coordinate
  216. system of a computer world:  unfortunately it's left-handed.  The three
  217. axes are directed as follows:
  218.  
  219.               y
  220.                ^   _  z
  221.                |   /|
  222.                |  /
  223.                | /
  224.                |/
  225.                |-----------> x
  226.               0
  227.  
  228. (obviuosly, negative coordinate values are allowed).
  229.  
  230. @endnode
  231.  
  232.  
  233. @node Error_Table "AFC module: vectWorld / Error Table"
  234.  
  235. Val (Hex)  | Description
  236. -----------+------------------------------------------------------
  237.   $0000    | No Memory
  238.   $0001    | AreaInfo not available in init3D()
  239.   $0002    | TempRas not available in init3D()
  240.   $0003    | Vector buffer not available in init3D()
  241.   $0004    | Extra bitplane not available in init3D()
  242.  
  243. @endnode
  244. */
  245. ->///
  246.  
  247. OPT PREPROCESS
  248.  
  249. ->#define WORLD_TEST
  250.  
  251. #ifndef WORLD_TEST
  252.   OPT MODULE
  253.   OPT EXPORT
  254. #endif
  255.  
  256. MODULE 'dos/dos',
  257.        'exec/memory',
  258.        'exec/ports',
  259.        'graphics/gfx',
  260.        'graphics/rastport',
  261.        'graphics/gfxmacros',
  262.        'AFC/nodemaster'
  263.  
  264. #ifdef WORLD_TEST
  265. MODULE 'intuition/intuition',
  266.        'intuition/screens',
  267.        'AFC/bitmapper',
  268.        'graphics/view'
  269. #endif
  270.  
  271.  
  272. ->/// constants
  273. CONST WORLD_NAMELEN=30, WORLD_BASE=$80050000
  274. CONST WORLD_VERSION=1, WORLD_REVISION=0
  275.  
  276. -> exceptions
  277. ENUM WORLD_ERR_MEM=WORLD_BASE, WORLD_ERR_AREAINFO, WORLD_ERR_TEMPRAS,
  278.      WORLD_ERR_VECTBUFFER, WORLD_ERR_BITPLANE
  279. ->///
  280.  
  281. -> /// 3D Objects
  282. OBJECT screen_pixel     -> a pixel (guess what are x AND y)
  283.   x
  284.   y
  285. ENDOBJECT
  286.  
  287. OBJECT vertex_obj      -> vertex structure
  288.   x
  289.   y
  290.   z
  291. ENDOBJECT
  292.  
  293. OBJECT surface_vertex     -> vertex linked TO a surface
  294. PRIVATE
  295.   num:LONG                -> only number (up TO now)
  296. ENDOBJECT
  297.  
  298. OBJECT line_obj        -> line structure:
  299.   startv               -> start vertex
  300.   endv                 -> end vertex
  301.   colour               -> line colour
  302. ENDOBJECT
  303.  
  304. OBJECT surface_obj                -> surface structure:
  305. PRIVATE
  306.   vertex:PTR TO nodemaster        -> LIST OF surface_vertex
  307.   colour                          -> colour
  308. ENDOBJECT
  309.  
  310. OBJECT object_obj                 -> an OBJECT:
  311. PRIVATE
  312.   vertex:PTR TO nodemaster        -> LIST OF vertices
  313.   line:PTR TO nodemaster          -> LIST OF lines
  314.   surface:PTR TO nodemaster       -> LIST OF surfaces
  315.   name                            -> name
  316.   visible                         -> OBJECT visible?
  317.   proj:PTR TO nodemaster          -> LIST OF projected vertices
  318.   tvert:PTR TO nodemaster         -> LIST OF transformed vertices
  319.   pos_x                           -> origin OF local axes
  320.   pos_y
  321.   pos_z
  322.   scale_x                         -> local scaling factor
  323.   scale_y
  324.   scale_z
  325. ENDOBJECT
  326.  
  327. OBJECT vectWorld              -> the whole world
  328. PRIVATE
  329.   numobj                      -> number OF objects
  330.   obj:PTR TO nodemaster       -> LIST OF objects
  331.   rot_x                       -> rotation (degrees)
  332.   rot_y
  333.   rot_z
  334.   scale_x                     -> scale
  335.   scale_y
  336.   scale_z
  337.   trasl_x                     -> traslation
  338.   trasl_y
  339.   trasl_z
  340.   observer_x                  -> observer coords
  341.   observer_y
  342.   observer_z
  343.   scrtrasl_x                  -> traslation after projection
  344.   scrtrasl_y
  345.   scrscale_x                  -> scale after projection
  346.   scrscale_y
  347.   areai:PTR TO areainfo       -> AreaInfo structure
  348.   tras:PTR TO tmpras          -> TmpRas structure
  349.   buffer:PTR TO LONG          -> buffer FOR AreaDraw
  350.   bplane:PTR TO LONG          -> extra bitplane FOR AreaDraw
  351.   d_width                     -> display width   (FOR bplane AND clipping)
  352.   d_height                    -> display height  ( "     "    "     "    )
  353.   dw_old                      -> storage FOR old value OF d_width
  354.   dh_old                      ->    "     "   "    "    " d_height
  355.   surflist:PTR TO nodemaster  -> Z buffer (FOR surface sorting)
  356. ENDOBJECT
  357. -> ///
  358.  
  359. -> /// other DEFs AND PROCs
  360. OBJECT stuff
  361. PRIVATE
  362.   obj:PTR TO CHAR
  363.   surf
  364.   avg
  365. ENDOBJECT
  366.  
  367. DEF sin_table:PTR TO LONG
  368.  
  369. PROC stuff() OF stuff
  370.   self.obj:=String(WORLD_NAMELEN)
  371.   IF self.obj=NIL THEN Raise(WORLD_ERR_MEM)
  372. ENDPROC
  373.  
  374. PROC end() OF stuff
  375.   IF self.obj THEN DisposeLink(self.obj)
  376. ENDPROC
  377.  
  378. #ifdef WORLD_TEST
  379. PROC describe3DException()
  380.  
  381.   IF exception
  382.     SELECT exception
  383.       CASE WORLD_ERR_MEM; WriteF('No Memory\n')
  384.       CASE WORLD_ERR_AREAINFO; WriteF('AreaInfo not available in init3D()\n')
  385.       CASE WORLD_ERR_TEMPRAS; WriteF('TempRas not available in init3D()\n')
  386.       CASE WORLD_ERR_VECTBUFFER; WriteF('Vector buffer not available in init3D()\n')
  387.       CASE WORLD_ERR_BITPLANE; WriteF('Extra bitplane not available in init3D()\n')
  388.     ENDSELECT
  389.   ENDIF
  390. ENDPROC
  391.  
  392. PROC objectList(w:PTR TO vectWorld)
  393.   DEF o:PTR TO object_obj
  394.  
  395.   IF (o:=w.obj.first())
  396.     REPEAT
  397.       WriteF('object_obj: \s\n',o.name)
  398.     UNTIL (o:=w.obj.succ())=FALSE
  399.   ENDIF
  400. ENDPROC
  401.  
  402. PROC dumpObject(o:PTR TO object_obj)
  403.   DEF v:PTR TO vertex_obj, l:PTR TO line_obj
  404.   DEF s:PTR TO surface_obj, sv:PTR TO surface_vertex
  405.  
  406.   WriteF('Name: \s\n',o.name)
  407.   IF (v:=o.vertex.first())
  408.     WriteF('*\n')
  409.     REPEAT
  410.       WriteF('\d vertex:\d  -  x:\d  y:\d  z:\d\n',v,o.vertex.numpos(),v.x,v.y,v.z)
  411.     UNTIL (v:=o.vertex.succ())=FALSE
  412.   ENDIF
  413.   IF (l:=o.line.first())
  414.     WriteF('$\n')
  415.     REPEAT
  416.       WriteF('\d line:\d  -  start:\d  end:\d  colour:\d\n',l,o.line.numpos(),l.startv,l.endv,l.colour)
  417.     UNTIL (l:=o.line.succ())=FALSE
  418.   ENDIF
  419.   IF (s:=o.surface.first())
  420.     WriteF('%\n')
  421.     REPEAT
  422.       WriteF('\d surface:\d  -  v: ',s,o.surface.numpos())
  423.       sv:=s.vertex.first()
  424.       REPEAT
  425.         WriteF('(\d)\d,',sv,sv.num)
  426.       UNTIL (sv:=s.vertex.succ())=FALSE
  427.       WriteF('\n')
  428.     UNTIL (s:=o.surface.succ())=FALSE
  429.   ENDIF
  430.   WriteF('#\n')
  431.   WriteF('pos_x:\d  pos_y:\d  pos_z:\d\n',o.pos_x,o.pos_y,o.pos_z)
  432.   WriteF('sc_x:\d  sc_y:\d  sc_z:\d\n', o.scale_x, o.scale_y, o.scale_z)
  433.   WriteF('visible:\s\n',IF o.visible THEN 'TRUE' ELSE 'FALSE')
  434. ENDPROC
  435. #endif
  436. -> ///
  437.  
  438. -> /// surface functions
  439. PROC surface_obj() OF surface_obj
  440.   NEW self.vertex.nodemaster()
  441. ENDPROC
  442.  
  443. PROC end() OF surface_obj
  444.   DEF v:PTR TO surface_vertex
  445.  
  446.   IF (v:=self.vertex.first())
  447.     REPEAT
  448.       END v
  449.     UNTIL (v:=self.vertex.succ())=FALSE
  450.   ENDIF
  451.   END self.vertex
  452. ENDPROC
  453. -> ///
  454.  
  455.  
  456. -> OBJECT functions
  457.  
  458. ->/// PROC object_obj(name=NIL) OF object_obj
  459. /*
  460. @node object_obj "AFC module: object_obj / object_obj()"
  461.  
  462.           NAME: object_obj(name)
  463.  
  464.    DESCRIPTION: creates an object_obj with name 'name'.  The name
  465.                 parameter is necessary because all objects in a vectWorld
  466.                 are addressed with their names.
  467.                   Objects cannot be rendered independently outside a world;
  468.                 the object_obj methods are supplied to manipulate single
  469.                 objects e.g. for storing purposes:  you can, for example,
  470.                 create a database of objects and then link to an
  471.                 initialized vectWorld only the ones you actually need.
  472.                   To link an already existing object to a vectWorld you use
  473.                 the @{"vectWorld / setobj()" LINK world_setobj} method; alternatively you can
  474.                 directly create and add an object to a world in one step by
  475.                 calling the @{"vectWorld / addobj()" LINK world_addobj} method.
  476.  
  477.         INPUTS: name of the object to be crated (max 30 chars).
  478.  
  479.        RESULTS: NONE
  480.  
  481.       SEE ALSO: @{" vectWorld / addobj() " LINK world_addobj}
  482.                 @{" vectWorld / setobj() " LINK world_setobj}
  483.  
  484. @endnode
  485. */
  486.  
  487. PROC object_obj(name=NIL) OF object_obj
  488.  
  489.   self.name:=String(WORLD_NAMELEN)
  490.   IF self.name
  491.     IF name
  492.       StrCopy(self.name,name)
  493.     ELSE
  494.       StrCopy(self.name,'No_Obj_Name')
  495.     ENDIF
  496.   ELSE
  497.     Raise(WORLD_ERR_MEM)
  498.   ENDIF
  499.   NEW self.vertex.nodemaster()
  500.   NEW self.line.nodemaster()
  501.   NEW self.proj.nodemaster()
  502.   NEW self.tvert.nodemaster()
  503.   NEW self.surface.nodemaster()
  504.   self.visible:=TRUE
  505.   self.pos_x:=0
  506.   self.pos_y:=0
  507.   self.pos_z:=0
  508.   self.scale_x:=100
  509.   self.scale_y:=100
  510.   self.scale_z:=100
  511. ENDPROC
  512. ->///
  513.  
  514. ->/// PROC clear() OF object_obj
  515. /*
  516. @node object_clear "AFC module: object_obj / clear()"
  517.  
  518.           NAME: clear()
  519.  
  520.    DESCRIPTION: clears all object's contents (except its name).
  521.  
  522.         INPUTS: NONE
  523.  
  524.        RESULTS: NONE
  525.  
  526.       SEE ALSO: @{" vectWorld / clearobj() " LINK world_clearobj}
  527.  
  528. @endnode
  529. */
  530.  
  531. PROC clear() OF object_obj
  532.   DEF v:PTR TO vertex_obj
  533.   DEF l:PTR TO line_obj
  534.   DEF p:PTR TO screen_pixel
  535.   DEF s:PTR TO surface_obj
  536.  
  537.   IF (v:=self.vertex.first())<>FALSE
  538.     REPEAT
  539.       END v
  540.     UNTIL (v:=self.vertex.succ())=FALSE
  541.   ENDIF
  542.   IF (l:=self.line.first())<>FALSE
  543.     REPEAT
  544.       END l
  545.     UNTIL (l:=self.line.succ())=FALSE
  546.   ENDIF
  547.   IF (p:=self.proj.first())<>FALSE
  548.     REPEAT
  549.       END p
  550.     UNTIL (p:=self.proj.succ())=FALSE
  551.   ENDIF
  552.   IF (v:=self.tvert.first())<>FALSE
  553.     REPEAT
  554.       END v
  555.     UNTIL (v:=self.tvert.succ())=FALSE
  556.   ENDIF
  557.   IF (s:=self.surface.first())<>FALSE
  558.     REPEAT
  559.       END s
  560.     UNTIL (s:=self.surface.succ())=FALSE
  561.   ENDIF
  562.   self.pos_x:=0
  563.   self.pos_y:=0
  564.   self.pos_z:=0
  565.   self.scale_x:=100
  566.   self.scale_y:=100
  567.   self.scale_z:=100
  568. ENDPROC TRUE
  569. ->///
  570.  
  571. ->/// PROC end() OF object_obj
  572. PROC end() OF object_obj
  573.  
  574.   self.clear()
  575.   END self.vertex
  576.   END self.line
  577.   END self.proj
  578.   END self.tvert
  579.   END self.surface
  580.   IF self.name THEN DisposeLink(self.name)
  581. ENDPROC
  582. ->///
  583.  
  584. ->/// PROC setvertex(num, x, y, z) OF object_obj
  585. /*
  586. @node object_setvertex "AFC module: object_obj / setvertex()"
  587.  
  588.           NAME: setvertex(num, x, y, z)
  589.  
  590.    DESCRIPTION: if 'num' is greater than the number of vertices of the
  591.                 object, then a new vertex is added to the object at the
  592.                 last position (independently of its number); so you cannot
  593.                 leave holes e.g. by adding vertex 4 and then vertex 10:
  594.                 in this case vertex 10 enters in position number 5.
  595.  
  596.                   This underlines one thing you have to care about:
  597.                 vertices have NOT a fixed number; their number it's their
  598.                 position in the list (for speed reasons).  Usually the
  599.                 module takes care of this automatically, but you must
  600.                 remember it when you delete a vertex.
  601.  
  602.                   If 'num' is an already attached vertex, then this
  603.                 instruction modifies the coordinates of that vertex.
  604.  
  605.                   Vertex numbers start from 0 (just like array elements).
  606.  
  607.         INPUTS: num: number of the vertex
  608.                 x, y, z: coordinates of the vertex.
  609.  
  610.        RESULTS: FALSE if num<0, otherwise the number of vertices currently
  611.                 in object.
  612.  
  613.       SEE ALSO: @{" fastsetvert()           " LINK object_fastsetvert}
  614.                 @{" vectWorld / setvertex() " LINK world_setvertex}
  615.  
  616. @endnode
  617. */
  618.  
  619. PROC setvertex(num, x, y, z) OF object_obj
  620.   DEF v:PTR TO vertex_obj
  621.   DEF tv:PTR TO vertex_obj
  622.  
  623.   IF num<0 THEN RETURN FALSE
  624.  
  625.   IF num>(self.vertex.numitems()-1)
  626.     NEW v
  627.     v.x := x
  628.     v.y := y
  629.     v.z := z
  630.     self.vertex.add(v)
  631.     NEW tv
  632.     tv.x:=x
  633.     tv.y:=y
  634.     tv.z:=z
  635.     self.tvert.add(tv)
  636.   ELSE
  637.     v:=self.vertex.item(num)
  638.     v.x := x
  639.     v.y := y
  640.     v.z := z
  641.     tv:=self.tvert.item(num)
  642.     tv.x:=x
  643.     tv.y:=y
  644.     tv.z:=z
  645.   ENDIF
  646. ENDPROC self.vertex.numitems()
  647. ->///
  648.  
  649. ->/// PROC getvertex(num) OF object_obj
  650. /*
  651. @node object_getvertex "AFC module: object_obj / getvertex()"
  652.  
  653.           NAME: getvertex(num)
  654.  
  655.    DESCRIPTION: if num is a valid vertex number (that is to say in the
  656.                 range [0 - ((number of vertices of the object)-1)]), this
  657.                 call returns a pointer to a vertex_obj.
  658.                   A vertex_obj contains three fields:  x, y and z,
  659.                 representing the three coordinates of the vertex.  After
  660.                 you got the pointer to a vertex_obj you can access its
  661.                 coordinates by the usual way:  vertex_obj.x, vertex_obj.y
  662.                 and vertex_obj.z.  I left this structure public because it
  663.                 can be of some use for you.
  664.  
  665.         INPUTS: number of (an existing) vertex; remember: vertex numbers
  666.                 start from 0 (and go to (number of vertices in object)-1).
  667.  
  668.        RESULTS: pointer to a vertex_obj
  669.                 FALSE if num is an illegal number (e.g., num<0)
  670.  
  671.       SEE ALSO: @{" setvertex()             " LINK object_setvertex}
  672.                 @{" vectWorld / getvertex() " LINK world_getvertex}
  673.  
  674. @endnode
  675. */
  676.  
  677. PROC getvertex(num) OF object_obj
  678.  
  679.   IF (num>(self.vertex.numitems()-1)) OR (num<0) THEN RETURN FALSE
  680. ENDPROC self.vertex.item(num)
  681. ->///
  682.  
  683. ->/// PROC fastsetvert(vlist:PTR TO vertex_obj) OF object_obj
  684. /*
  685. @node object_fastsetvert "AFC module: object_obj / fastsetvert()"
  686.  
  687.           NAME: fastsetvert(vertex_list)
  688.  
  689.    DESCRIPTION: adds vertices to the object according to the content of
  690.                 vertex_list.  Vertex_list is a TYPED list of type
  691.                 vertex_obj with the following form:
  692.  
  693.                      [x1,y1,z1, x2,y2,z2, ... ]:vertex_obj
  694.  
  695.                 This command is equivalent to the following code
  696.  
  697.                      FOR k:=0 to (number of vertices)-1
  698.                        o.setvertex(k, x[k], y[k], z[k])
  699.                      ENDFOR
  700.  
  701.                 but it's quicker.
  702.  
  703.         INPUTS: vertex_list: list of vertices to be added.
  704.  
  705.        RESULTS: NONE
  706.  
  707.       SEE ALSO: @{" setvertex()               " LINK object_setvertex}
  708.                 @{" vectWorld / fastsetvert() " LINK world_fastsetvert}
  709.  
  710. @endnode
  711. */
  712.  
  713. PROC fastsetvert(vlist:PTR TO vertex_obj) OF object_obj
  714.   DEF v:PTR TO vertex_obj, tv:PTR TO vertex_obj
  715.   DEF k:REG
  716.  
  717.   FOR k:=0 TO (ListLen(vlist)/3)-1
  718.     NEW v
  719.     v.x:=vlist[k].x
  720.     v.y:=vlist[k].y
  721.     v.z:=vlist[k].z
  722.     self.vertex.add(v)
  723.     NEW tv
  724.     v.x:=vlist[k].x
  725.     v.y:=vlist[k].y
  726.     v.z:=vlist[k].z
  727.     self.tvert.add(tv)
  728.   ENDFOR
  729. ENDPROC TRUE
  730. ->///
  731.  
  732. ->/// PROC delvertex(num) OF object_obj
  733. /*
  734. @node object_delvertex "AFC module: object_obj / delvertex()"
  735.  
  736.           NAME: delvertex(num)
  737.  
  738.    DESCRIPTION: removes a vertex from the object.  Removes all references
  739.                 to that vertex by deleting all lines and/or surfaces
  740.                 attached to the vertex.
  741.                   All vertex numbers will be scaled down one step to fill
  742.                 in the hole leaved by the deletion.
  743.  
  744.         INPUTS: number of vertex to be killed.
  745.  
  746.        RESULTS: FALSE if num is not the number of an existing vertex (e.g.,
  747.                 num<0), otherwise TRUE.
  748.  
  749.       SEE ALSO: @{" setvertex()             " LINK object_setvertex}
  750.                 @{" vectWorld / delvertex() " LINK world_delvertex}
  751.  
  752. @endnode
  753. */
  754.  
  755. PROC delvertex(num) OF object_obj
  756.   DEF v:PTR TO vertex_obj, l:PTR TO line_obj
  757.   DEF s:PTR TO surface_obj, t:PTR TO surface_vertex
  758.   DEF flag
  759.  
  760.   IF (num<0) OR (num>(self.vertex.numitems()-1)) THEN RETURN FALSE
  761.   v:=self.vertex.item(num)
  762.   END v
  763.   self.vertex.del()
  764.   v:=self.tvert.item(num)
  765.   END v
  766.   self.tvert.del()
  767.  
  768.   IF (l:=self.line.first())
  769.     REPEAT
  770.       IF (l.startv=num) OR (l.endv=num)
  771.         END l
  772.         l:=self.line.del()
  773.       ELSE
  774.         IF l.startv>num THEN l.startv:=l.startv-1 -> i vertici non hanno
  775.         IF l.endv>num THEN l.endv:=l.endv-1      -> numeri assoluti e quindi
  776.         l:=self.line.succ()                      -> occorre riscalare tutto.
  777.       ENDIF
  778.     UNTIL l=FALSE
  779.   ENDIF
  780.  
  781.   IF (s:=self.surface.first())
  782.     REPEAT
  783.       flag:=FALSE
  784.       IF (t:=s.vertex.first())
  785.         REPEAT
  786.           IF t.num=num THEN flag:=TRUE
  787.           IF t.num>num THEN t.num:=t.num-1    -> lo stesso qui.
  788.         UNTIL ((t:=s.vertex.succ())=FALSE) OR (flag=TRUE)
  789.       ENDIF
  790.       IF flag
  791.         END s
  792.         s:=self.surface.del()
  793.       ELSE
  794.         s:=self.surface.succ()
  795.       ENDIF
  796.     UNTIL s=FALSE
  797.   ENDIF
  798. ENDPROC TRUE
  799. ->///
  800.  
  801. ->/// PROC setline(num, sv, ev, colour) OF object_obj
  802. /*
  803. @node object_setline "AFC module: object_obj / setline()"
  804.  
  805.           NAME: setline(num, startv, endv, colour)
  806.  
  807.    DESCRIPTION: adds or modifies line number 'num' in object 'name':  the
  808.                 line starts from vertex number 'startv', ends in vertex
  809.                 number 'endv' and has colour 'colour'.
  810.                   If num is greater than the number of lines contained in
  811.                 the object_obj, then the new line will be added as last
  812.                 item; if num points to an existing line, then the new datas
  813.                 will replace the old line definition.
  814.  
  815.                   This underlines one thing you have to care about:
  816.                 lines have NOT a fixed number; their number it's their
  817.                 position in the list (for speed reasons).  Usually the
  818.                 module takes care of this automatically, but you must
  819.                 remember it when you delete a line.
  820.  
  821.                   Line numbers start from 0.
  822.  
  823.         INPUTS: num: line number,
  824.                 startv: starting line vertex,
  825.                 endv: ending line vertex,
  826.                 colour: line colour.
  827.  
  828.        RESULTS: FALSE if num<0 or startv and/or endv outside the range of
  829.                   existing vertices of the object,
  830.                 otherwise the number of lines currently in object.
  831.  
  832.       SEE ALSO: @{" vectWorld / setline() " LINK world_setline}
  833.  
  834. @endnode
  835. */
  836.  
  837. PROC setline(num, sv, ev, colour) OF object_obj
  838.   DEF l:PTR TO line_obj
  839.  
  840.   IF (sv>(self.vertex.numitems()-1)) OR (sv<0) THEN RETURN FALSE
  841.   IF (ev>(self.vertex.numitems()-1)) OR (ev<0) THEN RETURN FALSE
  842.   IF num<0 THEN RETURN FALSE
  843.  
  844.   IF num>(self.line.numitems()-1)
  845.     NEW l
  846.     l.startv := sv
  847.     l.endv   := ev
  848.     l.colour := colour
  849.     self.line.add(l)
  850.   ELSE
  851.     l:=self.line.item(num)
  852.     l.startv := sv
  853.     l.endv   := ev
  854.     l.colour := colour
  855.   ENDIF
  856. ENDPROC self.line.numitems()
  857. ->///
  858.  
  859. ->/// PROC getline(num) OF object_obj
  860. /*
  861. @node object_getline "AFC module: object_obj / getline()"
  862.  
  863.           NAME: getline(num)
  864.  
  865.    DESCRIPTION: returns a description of line number 'num' in the form of a
  866.                 pointer to a line_obj.  An object of type line_obj contains
  867.                 three fields named 'startv', 'endv' and 'colour'; after
  868.                 having received the pointer you access those fields in the
  869.                 usual way:  line_obj.startv, line_obj.endv and
  870.                 line_obj.colour.
  871.                   I left the line_obj object description public because it
  872.                 can be of use to you.
  873.  
  874.         INPUTS: number of line to be inquired.
  875.  
  876.        RESULTS: FALSE if num is outside the valid range of existing line
  877.                  numbers (going from 0 to (number of lines)-1),
  878.                 otherwise a pointer to a line_obj.
  879.  
  880.       SEE ALSO: @{" setline()             " LINK object_setline}
  881.                 @{" vectWorld / getline() " LINK world_getline}
  882.  
  883. @endnode
  884. */
  885.  
  886. PROC getline(num) OF object_obj
  887.  
  888.   IF (num>(self.line.numitems()-1)) OR (num<0) THEN RETURN FALSE
  889. ENDPROC self.line.item(num)
  890. ->///
  891.  
  892. ->/// PROC fastsetline(llist:PTR TO line_obj) OF object_obj
  893. /*
  894. @node object_fastsetline "AFC module: object_obj / fastsetline()"
  895.  
  896.           NAME: fastsetline(line_list)
  897.  
  898.    DESCRIPTION: adds the line descriptions contained in line_list to the
  899.                 object.  Line_list is a TYPED list of type line_obj of the
  900.                 following form:
  901.  
  902.                 [startv1,endv1,colour1, startv2,endv2,colour2, ...]:line_obj
  903.  
  904.                 This command is equivalent to the following code
  905.  
  906.                      FOR k:=0 to (number of lines)-1
  907.                        o.setline(k, startv[k], endv[k], colour[k])
  908.                      ENDFOR
  909.  
  910.                 but it's quicker.
  911.  
  912.                 If a startv or endv exceeds the range of existing vertex
  913.                 numbers for the object, then it is automatically set to
  914.                 vertex number 0.
  915.  
  916.         INPUTS: list of lines to be added.
  917.  
  918.        RESULTS: NONE
  919.  
  920.       SEE ALSO: @{" setline()                 " LINK object_setline}
  921.                 @{" vectWorld / fastsetline() " LINK world_fastsetline}
  922.  
  923. @endnode
  924. */
  925.  
  926. PROC fastsetline(llist:PTR TO line_obj) OF object_obj
  927.   DEF l:PTR TO line_obj
  928.   DEF k:REG, sv,ev
  929.  
  930.   FOR k:=0 TO (ListLen(llist)/3)-1
  931.     sv:=llist[k].startv
  932.     ev:=llist[k].endv
  933.     IF (sv>(self.vertex.numitems()-1)) OR (sv<0) THEN sv:=0
  934.     IF (ev>(self.vertex.numitems()-1)) OR (ev<0) THEN ev:=0
  935.  
  936.     NEW l
  937.     l.startv := sv
  938.     l.endv   := ev
  939.     l.colour := llist[k].colour
  940.     self.line.add(l)
  941.   ENDFOR
  942. ENDPROC TRUE
  943. ->///
  944.  
  945. ->/// PROC delline(num) OF object_obj
  946. /*
  947. @node object_delline "AFC module: object_obj / delline()"
  948.  
  949.           NAME: delline(num)
  950.  
  951.    DESCRIPTION: removes line number 'num' from the object.
  952.                   All line numbers will be scaled down one step to fill in
  953.                 the hole leaved by the deletion.
  954.  
  955.         INPUTS: number of line to be killed.
  956.  
  957.        RESULTS: FALSE if num is outside the valid range for the object.
  958.  
  959.       SEE ALSO: @{" setline()             " LINK object_setline}
  960.                 @{" vectWorld / delline() " LINK world_delline}
  961.  
  962. @endnode
  963. */
  964.  
  965. PROC delline(num) OF object_obj
  966.   DEF l:PTR TO line_obj
  967.  
  968.   IF (num<0) OR (num>(self.line.numitems()-1)) THEN RETURN FALSE
  969.   l:=self.line.item(num)
  970.   END l
  971.   self.line.del()
  972. ENDPROC TRUE
  973. ->///
  974.  
  975. ->/// PROC setsurface(num,vlist:PTR TO LONG,col) OF object_obj
  976. /*
  977. @node object_setsurface "AFC module: object_obj / setsurface()"
  978.  
  979.           NAME: setsurface(num, vertex_list, colour)
  980.  
  981.    DESCRIPTION: adds (or modifies) a surface.  If num is greater than the
  982.                 number of surfaces contained in the object, then the new
  983.                 surface will be added at the end of the list; if num points
  984.                 to an existing surface, then the contents of that surface
  985.                 will be replaced by the new datas.
  986.                   The vertex_list is a list of vertex NUMBERS belonging to
  987.                 the surface, in the following order:  you rotate the object
  988.                 until the surface is visible and then enumerate the
  989.                 vertices in a clockwise direction.
  990.  
  991.                   I want to underline one thing you have to care about:
  992.                 surfaces have NOT a fixed number; their number it's their
  993.                 position in the list (for speed reasons).  Usually the
  994.                 module takes care of this automatically, but you must
  995.                 remember it when you delete a surface.
  996.  
  997.                   Surface numbers start from 0.
  998.  
  999.                 If a vertex number in the list is outside the range of
  1000.                 existing vertices, then it is arbitrarily set to vertex
  1001.                 number 0.
  1002.  
  1003.                   If you modify a surface it doesn't matter if the new
  1004.                 vertex_list is shorter or longer than the previous one.
  1005.  
  1006.         INPUTS: num: number of surface,
  1007.                 vertex_list: list of vertex numbers,
  1008.                 colour: surface colour register.
  1009.  
  1010.        RESULTS: FALSE if num<0,
  1011.                 otherwise the total number of surfaces in the object.
  1012.  
  1013.       SEE ALSO: @{" vectWorld / setsurface() " LINK world_setsurface}
  1014.  
  1015. @endnode
  1016. */
  1017.  
  1018. PROC setsurface(num,vlist:PTR TO LONG,col) OF object_obj
  1019.   DEF s:PTR TO surface_obj, mode=0
  1020.   DEF k:REG, t, v:PTR TO surface_vertex
  1021.  
  1022.   IF num<0 THEN RETURN FALSE
  1023.   IF num>(self.surface.numitems()-1)
  1024.     NEW s.surface_obj()
  1025.     FOR k:=0 TO ListLen(vlist)-1
  1026.       t:=vlist[k]
  1027.       IF (t<0) OR (t>(self.vertex.numitems()-1)) THEN t:=0
  1028.       NEW v
  1029.       v.num:=t
  1030.       s.vertex.add(v)
  1031.     ENDFOR
  1032.     s.colour:=col
  1033.     self.surface.add(s)
  1034.   ELSE
  1035.     s:=self.surface.item(num)
  1036.     IF s.vertex.numitems()>0
  1037.       v:=s.vertex.first()
  1038.       mode:=0  -> replace
  1039.     ELSE
  1040.       mode:=1  -> add
  1041.     ENDIF
  1042.  
  1043.     k:=0
  1044.     REPEAT
  1045.       t:=vlist[k]
  1046.       IF (t<0) OR (t>(self.vertex.numitems()-1)) THEN t:=0
  1047.       IF mode=1 THEN NEW v
  1048.       v.num:=t
  1049.       k:=k+1
  1050.       IF mode=1
  1051.         s.vertex.add(v)
  1052.       ELSE
  1053.         v:=s.vertex.succ()
  1054.         IF v=FALSE THEN mode:=1  -> switch TO add
  1055.       ENDIF
  1056.     UNTIL k>=ListLen(vlist)
  1057.  
  1058.     IF mode=0   -> remove tail
  1059.       FOR k:=s.vertex.numpos() TO s.vertex.numitems()-1
  1060.         END v
  1061.         v:=s.vertex.del()
  1062.       ENDFOR
  1063.     ENDIF
  1064.  
  1065.     s.colour:=col
  1066.   ENDIF
  1067. ENDPROC self.surface.numitems()
  1068. ->///
  1069.  
  1070. ->/// PROC getsurface(num,vnum) OF object_obj
  1071. /*
  1072. @node object_getsurface "AFC module: object_obj / getsurface()"
  1073.  
  1074.           NAME: getsurface(snum, vnum)
  1075.  
  1076.    DESCRIPTION: returns the vertex number contained in position vnum of
  1077.                 surface snum.
  1078.  
  1079.         INPUTS: snum: number of surface to be inquired,
  1080.                 vnum: position of vertex in the surface's list.
  1081.  
  1082.        RESULTS: vertex number contained in position vnum,
  1083.                 FALSE if snum outside the valid range or vnum outside the
  1084.                  valid range for the object.
  1085.  
  1086.       SEE ALSO: @{" setsurface()             " LINK object_setsurface}
  1087.                 @{" vectWorld / getsurface() " LINK world_getsurface}
  1088.  
  1089. @endnode
  1090. */
  1091.  
  1092. PROC getsurface(num,vnum) OF object_obj
  1093.   DEF s:PTR TO surface_obj
  1094.   DEF v:PTR TO surface_vertex
  1095.  
  1096.   IF (num<0) OR (num>(self.surface.numitems()-1)) THEN RETURN FALSE
  1097.   s:=self.surface.item(num)
  1098.   IF (vnum>=0) AND (vnum<=(s.vertex.numitems()-1))
  1099.     v:=s.vertex.item(vnum)
  1100.   ELSE
  1101.     RETURN FALSE
  1102.   ENDIF
  1103. ENDPROC v.num
  1104. ->///
  1105.  
  1106. ->/// PROC delsurface(num) OF object_obj
  1107. /*
  1108. @node object_delsurface "AFC module: object_obj / delsurface()"
  1109.  
  1110.           NAME: delsurface(num)
  1111.  
  1112.    DESCRIPTION: removes surface number 'num' from the object. All surface
  1113.                 numbers will be scaled down by one step to fill in the hole
  1114.                 leaved by the deletion.
  1115.  
  1116.         INPUTS: number of the surface to be killed.
  1117.  
  1118.        RESULTS: FALSE if num is outside the valid range for the object,
  1119.                 otherwise TRUE.
  1120.  
  1121.       SEE ALSO: @{" setsurface()             " LINK object_setsurface}
  1122.                 @{" vectWorld / delsurface() " LINK world_delsurface}
  1123.  
  1124. @endnode
  1125. */
  1126.  
  1127. PROC delsurface(num) OF object_obj
  1128.   DEF s:PTR TO surface_obj
  1129.  
  1130.   IF (num<0) OR (num>(self.surface.numitems()-1)) THEN RETURN FALSE
  1131.   s:=self.surface.item(num)
  1132.   END s
  1133.   self.surface.del()
  1134. ENDPROC TRUE
  1135. ->///
  1136.  
  1137. ->/// PROC projection(obs_x,obs_y,obs_z) OF object_obj
  1138. /*
  1139. @node object_projection "AFC module: object_obj / projection()"
  1140.  
  1141.           NAME: projection(x, y, z)
  1142.  
  1143.    DESCRIPTION: reduces the 3D coordinates of the object in a 2D
  1144.                 representation, according to the position of the observer
  1145.                 (specified with the x, y and z parameters).  Local axes are
  1146.                 not supplied, so you cannot rotate objects individually;
  1147.                 besides, you cannot draw objects individually.  To perform
  1148.                 rotations and drawing you have to link the object to a
  1149.                 vectWorld.
  1150.  
  1151.         INPUTS: position of the observer.
  1152.  
  1153.        RESULTS: NONE
  1154.  
  1155.       SEE ALSO: @{" vectWorld / projection() " LINK world_projection}
  1156.  
  1157. @endnode
  1158. */
  1159.  
  1160. PROC projection(obs_x,obs_y,obs_z) OF object_obj
  1161.   DEF p_x,p_y, den
  1162.   DEF p:PTR TO screen_pixel
  1163.   DEF v:PTR TO vertex_obj
  1164.   DEF b=90, mode=0
  1165.  
  1166.   IF (v:=self.tvert.first())<>FALSE
  1167.     IF (p:=self.proj.first())<>FALSE THEN mode:=1  ->recycle
  1168.     REPEAT
  1169.       den:=v.z-obs_z
  1170.       IF den<=0 THEN den:=1
  1171.       p_x:=Div(Mul(b,v.x-obs_x),den)
  1172.       p_y:=Div(Mul(b,v.y-obs_y),den)
  1173.  
  1174.       IF mode=0 THEN NEW p
  1175.       p.x:=p_x
  1176.       p.y:=p_y
  1177.       IF mode=1
  1178.         IF (p:=self.proj.succ())=FALSE THEN mode:=0  ->switch TO add
  1179.       ELSE
  1180.         self.proj.add(p)
  1181.       ENDIF
  1182.     UNTIL (v:=self.tvert.succ())=FALSE
  1183.   ENDIF
  1184. ENDPROC TRUE
  1185. ->///
  1186.  
  1187. ->/// PROC getpoint(vertex) OF object_obj
  1188. /*
  1189. @node object_getpoint "AFC module: object_obj / getpoint()"
  1190.  
  1191.           NAME: getpoint(vertex)
  1192.  
  1193.    DESCRIPTION: returns the coordinates of a projected vertex in the form
  1194.                 of a pointer to a screen_pixel object.  Such an object is
  1195.                 made of two fields named 'x' and 'y' (guess what they
  1196.                 mean!); after having got the pointer you access the two
  1197.                 coordinates by the usual way:  screen_pixel.x,
  1198.                 screen_pixel.y.
  1199.  
  1200.         INPUTS: number of the vertex to be inquired.
  1201.  
  1202.        RESULTS: pointer to a screen_pixel object,
  1203.                 FALSE if vertex is outside the valid range for the object.
  1204.  
  1205.       SEE ALSO: @{" projection()           " LINK object_projection}
  1206.                 @{" vectWorld / getpoint() " LINK world_getpoint}
  1207.  
  1208. @endnode
  1209. */
  1210.  
  1211. PROC getpoint(vertex) OF object_obj
  1212.   DEF p:PTR TO screen_pixel
  1213.  
  1214.   IF (vertex>(self.proj.numitems()-1)) OR (vertex<0) THEN RETURN FALSE
  1215.  
  1216.   p:=self.proj.item(vertex)
  1217. ENDPROC p.x, p.y
  1218. ->///
  1219.  
  1220. ->/// PROC draw(rp) OF object_obj
  1221. PROC draw(rp) OF object_obj
  1222.   DEF p1:PTR TO screen_pixel
  1223.   DEF p2:PTR TO screen_pixel
  1224.   DEF l:PTR TO line_obj
  1225.  
  1226.   IF (l:=self.line.first())<>FALSE
  1227.     REPEAT
  1228.       IF (p1:=self.proj.item(l.startv))<>FALSE
  1229.         IF (p2:=self.proj.item(l.endv))<>FALSE
  1230.           SetAPen(rp, l.colour)
  1231.           Move(rp, p1.x, p1.y)
  1232.           Draw(rp, p2.x, p2.y)
  1233.         ENDIF
  1234.       ENDIF
  1235.     UNTIL (l:=self.line.succ())=FALSE
  1236.   ELSEIF (p1:=self.proj.first())<>FALSE
  1237.     REPEAT
  1238.       WritePixel(rp,p1.x,p1.y)
  1239.     UNTIL (p1:=self.proj.succ())=FALSE
  1240.   ENDIF
  1241. ENDPROC
  1242. ->///
  1243.  
  1244. ->/// PROC visible(v=-10) OF object_obj
  1245. PROC visible(v=-10) OF object_obj
  1246.   IF v=-10 THEN RETURN self.visible
  1247.   self.visible:=IF v THEN TRUE ELSE FALSE
  1248. ENDPROC TRUE
  1249. ->///
  1250.  
  1251. ->/// PROC position(x,y,z) OF object_obj
  1252. /*
  1253. @node object_position "AFC module: object_obj / position()"
  1254.  
  1255.           NAME: position(x, y, z)
  1256.  
  1257.    DESCRIPTION: moves the origin of the object's local axes to the
  1258.                 position specified.  This means you can always enter the
  1259.                 object's coordinates relative to the object's local origin
  1260.                 and then move the object around in the vectWorld.
  1261.                   This method only sets the origin coordinates to the new
  1262.                 values, and the traslation is performed every time the
  1263.                 object is @{"project()" LINK world_projection}ed within a vectWorld:  this behaviour
  1264.                 obviuosly slows down the projection routine.  If you want
  1265.                 to make the changes permanent (calculated once for ever)
  1266.                 you call the @{"apply()" LINK object_apply} method.
  1267.  
  1268.                   To traslate the whole vectWorld you can use the
  1269.                 @{"settrasl()" LINK world_settrasl} method.
  1270.  
  1271.         INPUTS: coordinates of the local origin.
  1272.  
  1273.        RESULTS: NONE
  1274.  
  1275.       SEE ALSO: @{" apply()                " LINK object_apply}
  1276.                 @{" vectWorld / position() " LINK world_position}
  1277. @endnode
  1278. */
  1279.  
  1280. PROC position(x,y,z) OF object_obj
  1281.  
  1282.   self.pos_x:=x
  1283.   self.pos_y:=y
  1284.   self.pos_z:=z
  1285. ENDPROC TRUE
  1286. ->///
  1287.  
  1288. ->/// PROC scale(x,y,z) OF object_obj
  1289. /*
  1290. @node object_scale "AFC module: object_obj / scale()"
  1291.  
  1292.           NAME: scale(x, y, z)
  1293.  
  1294.    DESCRIPTION: scales the object.
  1295.                   This method only sets the scaling factors to the new
  1296.                 values, and the scaling is performed every time the object
  1297.                 is @{"project()" LINK world_projection}ed within a vectWorld:  this behaviour
  1298.                 obviuosly slows down the projection routine.  If you want
  1299.                 to make the changes permanent (calculated once for ever)
  1300.                 you call the @{"apply()" LINK object_apply} method.
  1301.                   The scaling factors are entered as a percentage:  100
  1302.                 means original dimensions, 50 means a half, and so on...
  1303.  
  1304.                   To scale the whole vectWorld you can use the
  1305.                 @{"setscale()" LINK world_setscale} method.
  1306.  
  1307.         INPUTS: scaling factors.
  1308.  
  1309.        RESULTS: NONE
  1310.  
  1311.       SEE ALSO: @{" apply()             " LINK object_apply}
  1312.                 @{" vectWorld / scale() " LINK world_scale}
  1313.  
  1314. @endnode
  1315. */
  1316.  
  1317. PROC scale(x,y,z) OF object_obj
  1318.  
  1319.   IF x<=0 THEN x:=100
  1320.   IF y<=0 THEN y:=100
  1321.   IF z<=0 THEN z:=100
  1322.   self.scale_x:=x
  1323.   self.scale_y:=y
  1324.   self.scale_z:=z
  1325. ENDPROC TRUE
  1326. ->///
  1327.  
  1328. ->/// PROC copy(dest:PTR TO object_obj) OF object_obj
  1329. /*
  1330. @node object_copy "AFC module: object_obj / copy()"
  1331.  
  1332.           NAME: copy(dest:PTR TO object_obj)
  1333.  
  1334.    DESCRIPTION: copies all the contents of an object (except its name) to
  1335.                 the destination object:  the latter will be @{"clear()" LINK object_clear}ed
  1336.                 before being modified.
  1337.  
  1338.         INPUTS: pointer to an already initialized object_obj.
  1339.  
  1340.        RESULTS: FALSE if dest=NIL, otherwise TRUE.
  1341.                 It may raise exceptions (see the @{"Error Table" LINK Error_Table}).
  1342.  
  1343.       SEE ALSO: @{" clone()               " LINK object_clone}
  1344.                 @{" vectWorld / copyobj() " LINK world_copyobj}
  1345.  
  1346. @endnode
  1347. */
  1348.  
  1349. PROC copy(dest:PTR TO object_obj) OF object_obj
  1350.   DEF fv:PTR TO vertex_obj, dv:PTR TO vertex_obj
  1351.   DEF fl:PTR TO line_obj, dl:PTR TO line_obj
  1352.   DEF fs:PTR TO surface_obj, ds:PTR TO surface_obj
  1353.   DEF fsv:PTR TO surface_vertex, dsv:PTR TO surface_vertex
  1354.  
  1355.   IF (dest=NIL) THEN RETURN FALSE
  1356.  
  1357.   dest.clear()
  1358.   IF (fv:=self.vertex.first())
  1359.     REPEAT
  1360.       NEW dv
  1361.       dv.x:=fv.x
  1362.       dv.y:=fv.y
  1363.       dv.z:=fv.z
  1364.       dest.vertex.add(dv)
  1365.       NEW dv
  1366.       dv.x:=fv.x
  1367.       dv.y:=fv.y
  1368.       dv.z:=fv.z
  1369.       dest.tvert.add(dv)
  1370.     UNTIL (fv:=self.vertex.succ())=FALSE
  1371.   ENDIF
  1372.   IF (fl:=self.line.first())<>FALSE
  1373.     REPEAT
  1374.       NEW dl
  1375.       dl.startv:=fl.startv
  1376.       dl.endv:=fl.endv
  1377.       dl.colour:=fl.colour
  1378.       dest.line.add(dl)
  1379.     UNTIL (fl:=self.line.succ())=FALSE
  1380.   ENDIF
  1381.   IF (fs:=self.surface.first())<>FALSE
  1382.     REPEAT
  1383.       NEW ds.surface_obj()
  1384.       IF (fsv:=fs.vertex.first())
  1385.         REPEAT
  1386.           NEW dsv
  1387.           dsv.num:=fsv.num
  1388.           ds.vertex.add(dsv)
  1389.         UNTIL (fsv:=fs.vertex.succ())=FALSE
  1390.       ENDIF
  1391.       ds.colour:=fs.colour
  1392.       dest.surface.add(ds)
  1393.     UNTIL (fs:=self.surface.succ())=FALSE
  1394.   ENDIF
  1395.   dest.visible:=self.visible
  1396.   dest.pos_x:=self.pos_x
  1397.   dest.pos_y:=self.pos_y
  1398.   dest.pos_z:=self.pos_z
  1399.   dest.scale_x:=self.scale_x
  1400.   dest.scale_y:=self.scale_y
  1401.   dest.scale_z:=self.scale_z
  1402. ENDPROC TRUE
  1403. ->///
  1404.  
  1405. ->/// PROC clone(name=NIL) OF object_obj
  1406. /*
  1407. @node object_clone "AFC module: object_obj / clone()"
  1408.  
  1409.           NAME: clone(newname=NIL)
  1410.  
  1411.    DESCRIPTION: creates a new object_obj and copies the contents of the
  1412.                 current object to the new one.  The newname parameter will
  1413.                 be the name of the newborn object_obj (if it is not
  1414.                 supplied the new name will be something like
  1415.                 'Copy_of_oldname').
  1416.  
  1417.         INPUTS: name of the object to be created.
  1418.  
  1419.        RESULTS: pointer to the new object_obj.
  1420.  
  1421.       SEE ALSO: @{" copy()                 " LINK object_copy}
  1422.                 @{" vectWorld / cloneobj() " LINK world_cloneobj}
  1423.  
  1424. @endnode
  1425. */
  1426.  
  1427. PROC clone(name=NIL) OF object_obj
  1428.   DEF dest=NIL:PTR TO object_obj, s[WORLD_NAMELEN]:STRING
  1429.  
  1430.   IF name
  1431.     StrCopy(s, name)
  1432.   ELSE
  1433.     StringF(s, 'Copy_of_\s', self.name)
  1434.   ENDIF
  1435.   NEW dest.object_obj(s)
  1436.   self.copy(dest)
  1437. ENDPROC dest
  1438. ->///
  1439.  
  1440. ->/// PROC name() OF object_obj
  1441. /*
  1442. @node object_name "AFC module: object_obj / name()"
  1443.  
  1444.           NAME: name()
  1445.  
  1446.    DESCRIPTION: returns the object's name.
  1447.  
  1448.         INPUTS: NONE
  1449.  
  1450.        RESULTS: object's name.
  1451.  
  1452.       SEE ALSO:
  1453.  
  1454. @endnode
  1455. */
  1456.  
  1457. PROC name() OF object_obj IS self.name
  1458. ->///
  1459.  
  1460. ->/// PROC apply() OF object_obj
  1461. /*
  1462. @node object_apply "AFC module: object_obj / apply()"
  1463.  
  1464.           NAME: apply()
  1465.  
  1466.    DESCRIPTION: makes the changes on an object permanent (calculated once
  1467.                 for ever).  Changes such as @{"position()" LINK object_position} or @{"scale()" LINK object_scale} of an
  1468.                 object_obj are affected:  this increases the speed of the
  1469.                 @{"projection()" LINK world_projection} routine, because permanent transformations
  1470.                 are skipped.
  1471.  
  1472.         INPUTS: NONE
  1473.  
  1474.        RESULTS: NONE
  1475.  
  1476.       SEE ALSO: @{" position()             " LINK object_position}
  1477.                 @{" scale()                " LINK object_scale}
  1478.                 @{" vectWorld / applyobj() " LINK world_applyobj}
  1479.  
  1480. @endnode
  1481. */
  1482.  
  1483. PROC apply() OF object_obj
  1484.   DEF v:PTR TO vertex_obj
  1485.  
  1486.   IF (v:=self.vertex.first())
  1487.     IF (self.pos_x<>0) OR (self.pos_y<>0) OR (self.pos_z<>0)
  1488.       REPEAT
  1489.         IF (self.pos_x<>0) THEN v.x:=v.x+self.pos_x
  1490.         IF (self.pos_y<>0) THEN v.y:=v.y+self.pos_y
  1491.         IF (self.pos_z<>0) THEN v.z:=v.z+self.pos_z
  1492.       UNTIL (v:=self.vertex.succ())=FALSE
  1493.     ENDIF
  1494.     IF (self.scale_x<>100) OR (self.scale_y<>100) OR (self.scale_z<>100)
  1495.       v:=self.vertex.first()
  1496.       REPEAT
  1497.         IF (self.scale_x<>100) THEN v.x:=Div(Mul(v.x,self.scale_x),100)
  1498.         IF (self.scale_y<>100) THEN v.y:=Div(Mul(v.y,self.scale_y),100)
  1499.         IF (self.scale_z<>100) THEN v.z:=Div(Mul(v.z,self.scale_z),100)
  1500.       UNTIL (v:=self.vertex.succ())=FALSE
  1501.     ENDIF
  1502.  
  1503.     self.pos_x:=0
  1504.     self.pos_y:=0
  1505.     self.pos_z:=0
  1506.     self.scale_x:=100
  1507.     self.scale_y:=100
  1508.     self.scale_z:=100
  1509.   ENDIF
  1510. ENDPROC TRUE
  1511. -> ///
  1512.  
  1513.  
  1514. -> World Functions
  1515.  
  1516. ->/// PROC vectWorld() OF vectWorld
  1517. /*
  1518. @node vectWorld "AFC module: vectWorld / vectWorld()"
  1519.  
  1520.           NAME: vectWorld()
  1521.  
  1522.    DESCRIPTION: builds a vectWorld object (constructor).
  1523.  
  1524.         INPUTS: NONE
  1525.  
  1526.        RESULTS: NONE
  1527.  
  1528.       SEE ALSO:
  1529.  
  1530. @endnode
  1531. */
  1532.  
  1533. PROC vectWorld() OF vectWorld
  1534.  
  1535.   NEW self.obj.nodemaster()
  1536.  
  1537.   self.rot_x:=0
  1538.   self.rot_y:=0
  1539.   self.rot_z:=0
  1540.   self.scale_x:=100
  1541.   self.scale_y:=100
  1542.   self.scale_z:=100
  1543.   self.trasl_x:=0
  1544.   self.trasl_y:=0
  1545.   self.trasl_z:=0
  1546.   self.scrscale_x:=100
  1547.   self.scrscale_y:=100
  1548.   self.scrtrasl_x:=0
  1549.   self.scrtrasl_y:=0
  1550.   self.observer_x:=0
  1551.   self.observer_y:=0
  1552.   self.observer_z:=-1
  1553.  
  1554.   self.d_width:=320
  1555.   self.d_height:=256
  1556.  
  1557.   IF sin_table=NIL THEN fillSinTable()
  1558. ENDPROC
  1559. ->///
  1560.  
  1561. ->/// PROC end() OF vectWorld
  1562. PROC end() OF vectWorld
  1563.   DEF o:PTR TO object_obj
  1564.   DEF g:PTR TO stuff
  1565.  
  1566.   IF (o:=self.obj.first())<>FALSE
  1567.     REPEAT
  1568.       END o
  1569.     UNTIL (o:=self.obj.succ())=FALSE
  1570.   ENDIF
  1571.   END self.obj
  1572.  
  1573.   IF self.areai THEN END self.areai
  1574.   IF self.tras THEN END self.tras
  1575.   IF self.buffer THEN FreeVec(self.buffer)
  1576.   IF self.bplane THEN FreeRaster(self.bplane,self.d_width,self.d_height)
  1577.   IF self.surflist<>NIL
  1578.     IF (g:=self.surflist.first())<>FALSE
  1579.       REPEAT
  1580.         END g
  1581.       UNTIL (g:=self.surflist.succ())=FALSE
  1582.     ENDIF
  1583.     END self.surflist
  1584.   ENDIF
  1585. ENDPROC
  1586. ->///
  1587.  
  1588. ->/// PROC addobj(name) OF vectWorld
  1589. /*
  1590. @node world_addobj "AFC module: vectWorld / addobj()"
  1591.  
  1592.           NAME: addobj(name)
  1593.  
  1594.    DESCRIPTION: creates an object_obj called 'name' and adds it to the
  1595.                 vectWorld.  The name parameter is necessary because all
  1596.                 objects in a world are recognized by their names.
  1597.  
  1598.         INPUTS: the name of the object to be created (max 30 chars).
  1599.  
  1600.        RESULTS: NONE
  1601.  
  1602.       SEE ALSO: @{" object_obj() " LINK object_obj}
  1603.                 @{" setobj()     " LINK world_setobj}
  1604.  
  1605. @endnode
  1606. */
  1607.  
  1608. PROC addobj(name) OF vectWorld
  1609.   DEF o:PTR TO object_obj
  1610.  
  1611.   NEW o.object_obj(name)
  1612.   self.obj.add(o)
  1613. ENDPROC
  1614. ->///
  1615.  
  1616. ->/// PROC setobj(o) OF vectWorld
  1617. /*
  1618. @node world_setobj "AFC module: vectWorld / setobj()"
  1619.  
  1620.           NAME: setobj(object)
  1621.  
  1622.    DESCRIPTION: links an existing object_obj to the vectWorld.
  1623.  
  1624.         INPUTS: 'object' is the pointer to an object_obj.
  1625.  
  1626.        RESULTS: NONE
  1627.  
  1628.       SEE ALSO: @{" addobj() " LINK world_addobj}
  1629.                 @{" getobj() " LINK world_getobj}
  1630.  
  1631. @endnode
  1632. */
  1633.  
  1634. PROC setobj(o) OF vectWorld
  1635.  
  1636.   IF o THEN self.obj.add(o)
  1637. ENDPROC
  1638. ->///
  1639.  
  1640. ->/// PROC getobj(name) OF vectWorld
  1641. /*
  1642. @node world_getobj "AFC module: vectWorld / getobj()"
  1643.  
  1644.           NAME: getobj(name)
  1645.  
  1646.    DESCRIPTION: returns the pointer to the object_obj named 'name'.
  1647.  
  1648.         INPUTS: name of the object.
  1649.  
  1650.        RESULTS: pointer to an object_obj.
  1651.  
  1652.       SEE ALSO: @{" setobj() " LINK world_setobj}
  1653.                 @{" addobj() " LINK world_addobj}
  1654.  
  1655. @endnode
  1656. */
  1657.  
  1658. PROC getobj(name) OF vectWorld
  1659.   DEF o
  1660.  
  1661.   IF (o:=self.posonobj(name))<>FALSE THEN RETURN o
  1662. ENDPROC FALSE
  1663. ->///
  1664.  
  1665. ->/// PROC delobj(name) OF vectWorld
  1666. /*
  1667. @node world_delobj "AFC module: vectWorld / delobj()"
  1668.  
  1669.           NAME: delobj(name)
  1670.  
  1671.    DESCRIPTION: unlinks from the vectWorld and deletes (freeing all memory
  1672.                 associated with it) the object 'name'.  If such an object
  1673.                 doesn't exist, it does nothing.
  1674.  
  1675.         INPUTS: name of the object to be killed.
  1676.  
  1677.        RESULTS: NONE
  1678.  
  1679.       SEE ALSO: @{" addobj()    " LINK world_addobj}
  1680.                 @{" unlinkobj() " LINK world_unlinkobj}
  1681.  
  1682. @endnode
  1683. */
  1684.  
  1685. PROC delobj(name) OF vectWorld
  1686.   DEF o:PTR TO object_obj
  1687.  
  1688.   IF (o:=self.posonobj(name))<>FALSE
  1689.     END o
  1690.     self.obj.del()
  1691.   ENDIF
  1692. ENDPROC
  1693. ->///
  1694.  
  1695. ->/// PROC unlinkobj(name) OF vectWorld
  1696. /*
  1697. @node world_unlinkobj "AFC module: vectWorld / unlinkobj()"
  1698.  
  1699.           NAME: unlinkobj(name)
  1700.  
  1701.    DESCRIPTION: removes the object 'name' from the vectWorld, without
  1702.                 freeing its memory.  It returns a pointer to an object_obj,
  1703.                 that you must remember to END yourself before exiting the
  1704.                 program.
  1705.  
  1706.         INPUTS: name of the object to unlink.
  1707.  
  1708.        RESULTS: pointer to an object_obj, or FALSE if 'name' not found.
  1709.  
  1710.       SEE ALSO: @{" delobj() " LINK world_delobj}
  1711.  
  1712. @endnode
  1713. */
  1714.  
  1715. PROC unlinkobj(name) OF vectWorld
  1716.   DEF o
  1717.  
  1718.   IF (o:=self.posonobj(name))
  1719.     self.obj.del()
  1720.     RETURN o
  1721.   ENDIF
  1722. ENDPROC FALSE
  1723. ->///
  1724.  
  1725. ->/// PROC posonobj(name) OF vectWorld
  1726. PROC posonobj(name) OF vectWorld
  1727.   DEF o:PTR TO object_obj
  1728.  
  1729.   IF (o:=self.obj.obj())<>NIL
  1730.     IF StrCmp(o.name,name)=FALSE
  1731.       o:=self.obj.first()
  1732.       REPEAT
  1733.         IF StrCmp(o.name,name)=TRUE THEN RETURN o
  1734.       UNTIL (o:=self.obj.succ())=FALSE
  1735.       RETURN FALSE
  1736.     ELSE
  1737.       RETURN o
  1738.     ENDIF
  1739.   ENDIF
  1740. ENDPROC
  1741. ->///
  1742.  
  1743. ->/// PROC setvertex(name, num, x, y, z) OF vectWorld
  1744. /*
  1745. @node world_setvertex "AFC module: vectWorld / setvertex()"
  1746.  
  1747.           NAME: setvertex(name, num, x, y, z)
  1748.  
  1749.    DESCRIPTION: same as @{"object_obj / setvertex()" LINK object_setvertex}
  1750.  
  1751.         INPUTS: name of the object_obj to be modified
  1752.                 num: vertex number
  1753.                 x, y, z: vertex coordinates
  1754.  
  1755.        RESULTS: FALSE if object not found,
  1756.                 otherwise the number of vertices currently in object.
  1757.  
  1758.       SEE ALSO: @{" fastsetvert()            " LINK world_fastsetvert}
  1759.                 @{" object_obj / setvertex() " LINK object_setvertex}
  1760.  
  1761. @endnode
  1762. */
  1763.  
  1764. PROC setvertex(name, num, x, y, z) OF vectWorld
  1765.   DEF o:PTR TO object_obj
  1766.  
  1767.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  1768. ENDPROC o.setvertex(num, x, y, z)
  1769. ->///
  1770.  
  1771. ->/// PROC getvertex(name, num) OF vectWorld
  1772. /*
  1773. @node world_getvertex "AFC module: vectWorld / getvertex()"
  1774.  
  1775.           NAME: getvertex(name, num)
  1776.  
  1777.    DESCRIPTION: same as @{"object_obj / getvertex()" LINK object_getvertex}
  1778.  
  1779.         INPUTS: name of the object to be inquired
  1780.                 num: number of vertex
  1781.  
  1782.        RESULTS: FALSE if object not found, or num outside a valid range,
  1783.                 pointer to vertex_obj if successful.
  1784.  
  1785.       SEE ALSO: @{" setvertex()              " LINK world_setvertex}
  1786.                 @{" object_obj / getvertex() " LINK object_getvertex}
  1787.  
  1788. @endnode
  1789. */
  1790.  
  1791. PROC getvertex(name, num) OF vectWorld
  1792.   DEF o:PTR TO object_obj
  1793.  
  1794.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  1795. ENDPROC o.getvertex(num)
  1796. ->///
  1797.  
  1798. ->/// PROC fastsetvert(name,vlist:PTR TO vertex_obj) OF vectWorld
  1799. /*
  1800. @node world_fastsetvert "AFC module: vectWorld / fastsetvert()"
  1801.  
  1802.           NAME: fastsetvert(name, vertex_list)
  1803.  
  1804.    DESCRIPTION: same as @{"object_obj / fastsetvert()" LINK object_fastsetvert}
  1805.  
  1806.         INPUTS: name of the object to be modified
  1807.                 vertex_list of vertices to be added.
  1808.  
  1809.        RESULTS: FALSE if object not found.
  1810.  
  1811.       SEE ALSO: @{" setvertex()                " LINK world_setvertex}
  1812.                 @{" object_obj / fastsetvert() " LINK object_fastsetvert}
  1813.  
  1814. @endnode
  1815. */
  1816.  
  1817. PROC fastsetvert(name,vlist:PTR TO vertex_obj) OF vectWorld
  1818.   DEF o:PTR TO object_obj
  1819.  
  1820.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  1821. ENDPROC o.fastsetvert(vlist)
  1822. ->///
  1823.  
  1824. ->/// PROC delvertex(name,num) OF vectWorld
  1825. /*
  1826. @node world_delvertex "AFC module: vectWorld / delvertex()"
  1827.  
  1828.           NAME: delvertex(name, num)
  1829.  
  1830.    DESCRIPTION: same as @{"object_obj / delvertex()" LINK object_delvertex}
  1831.  
  1832.         INPUTS: name of the object to be modified
  1833.                 num: number of vertex to be killed.
  1834.  
  1835.        RESULTS: FALSE if object not found, or num outside a valid range,
  1836.                 otherwise TRUE.
  1837.  
  1838.       SEE ALSO: @{" setvertex()              " LINK world_setvertex}
  1839.                 @{" object_obj / delvertex() " LINK object_delvertex}
  1840.  
  1841. @endnode
  1842. */
  1843.  
  1844. PROC delvertex(name,num) OF vectWorld
  1845.   DEF o:PTR TO object_obj
  1846.  
  1847.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  1848. ENDPROC o.delvertex(num)
  1849. ->///
  1850.  
  1851. ->/// PROC setline(name, numline, sv, ev, colour) OF vectWorld
  1852. /*
  1853. @node world_setline "AFC module: vectWorld / setline()"
  1854.  
  1855.           NAME: setline(name, num, startv, endv, colour)
  1856.  
  1857.    DESCRIPTION: same as @{"object_obj / setline()" LINK object_setline}
  1858.  
  1859.         INPUTS: name of the object to be modified,
  1860.                 num: number of line,
  1861.                 startv: line starting vertex,
  1862.                 endv: line ending vertex,
  1863.                 colour: line colour register.
  1864.  
  1865.        RESULTS: FALSE if object not found,
  1866.                 FALSE if num<0 or startv and/or endv outside the range of
  1867.                   existing vertices of the object,
  1868.                 otherwise the number of lines currently in the object.
  1869.  
  1870.       SEE ALSO: @{" fastsetline()          " LINK world_fastsetline}
  1871.                 @{" object_obj / setline() " LINK object_setline}
  1872.  
  1873. @endnode
  1874. */
  1875.  
  1876. PROC setline(name, numline, sv, ev, colour) OF vectWorld
  1877.   DEF o:PTR TO object_obj
  1878.  
  1879.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  1880. ENDPROC o.setline(numline, sv, ev, colour)
  1881. ->///
  1882.  
  1883. ->/// PROC getline(name, numline) OF vectWorld
  1884. /*
  1885. @node world_getline "AFC module: vectWorld / getline()"
  1886.  
  1887.           NAME: getline(name, num)
  1888.  
  1889.    DESCRIPTION: same as @{"object_obj / getline()" LINK object_getline}
  1890.  
  1891.         INPUTS: name of the object,
  1892.                 num: line number.
  1893.  
  1894.        RESULTS: FALSE if object not found, or num outside the range of
  1895.                 existing line numbers.
  1896.  
  1897.       SEE ALSO: @{" setline()              " LINK world_setline}
  1898.                 @{" object_obj / getline() " LINK object_getline}
  1899.  
  1900. @endnode
  1901. */
  1902.  
  1903. PROC getline(name, numline) OF vectWorld
  1904.   DEF o:PTR TO object_obj
  1905.  
  1906.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  1907. ENDPROC o.getline(numline)
  1908. ->///
  1909.  
  1910. ->/// PROC fastsetline(name, llist:PTR TO line_obj) OF vectWorld
  1911. /*
  1912. @node world_fastsetline "AFC module: vectWorld / fastsetline()"
  1913.  
  1914.           NAME: fastsetline(name, line_list)
  1915.  
  1916.    DESCRIPTION: same as @{"object_obj / fastsetline()" LINK object_fastsetline}
  1917.  
  1918.         INPUTS: name of the object to be modified,
  1919.                 line_list: typed list of objects line_obj.
  1920.  
  1921.        RESULTS: FALSE if object not found, otherwise TRUE
  1922.  
  1923.       SEE ALSO: @{" setline()                  " LINK world_setline}
  1924.                 @{" object_obj / fastsetline() " LINK object_fastsetline}
  1925.  
  1926. @endnode
  1927. */
  1928.  
  1929. PROC fastsetline(name, llist:PTR TO line_obj) OF vectWorld
  1930.   DEF o:PTR TO object_obj
  1931.  
  1932.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  1933. ENDPROC o.fastsetline(llist)
  1934. ->///
  1935.  
  1936. ->/// PROC delline(name,num) OF vectWorld
  1937. /*
  1938. @node world_delline "AFC module: vectWorld / delline()"
  1939.  
  1940.           NAME: delline(name, num)
  1941.  
  1942.    DESCRIPTION: same as @{"object_obj / delline()" LINK object_delline}
  1943.  
  1944.         INPUTS: name of the object to be modified,
  1945.                 num: number of line to be killed.
  1946.  
  1947.        RESULTS: FALSE if object not found, or num outside the valid line
  1948.                 numbers range for the object.
  1949.  
  1950.       SEE ALSO: @{" setline()              " LINK world_setline}
  1951.                 @{" object_obj / delline() " LINK object_delline}
  1952.  
  1953. @endnode
  1954. */
  1955.  
  1956. PROC delline(name,num) OF vectWorld
  1957.   DEF o:PTR TO object_obj
  1958.  
  1959.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  1960. ENDPROC o.delline(num)
  1961. ->///
  1962.  
  1963. ->/// PROC setsurface(name,num,vlist:PTR TO LONG,col) OF vectWorld
  1964. /*
  1965. @node world_setsurface "AFC module: vectWorld / setsurface()"
  1966.  
  1967.           NAME: setsurface(name, num, vertex_list, colour)
  1968.  
  1969.    DESCRIPTION: same as @{"object_obj / setsurface()" LINK object_setsurface}
  1970.  
  1971.         INPUTS: name of the object to be modified,
  1972.                 num: number of surface,
  1973.                 vertex_list: list of vertex numbers defining the surface,
  1974.                 colour: surface colour register.
  1975.  
  1976.        RESULTS: FALSE if object not found, or num<0
  1977.  
  1978.       SEE ALSO: @{" object_obj / setsurface() " LINK object_setsurface}
  1979.  
  1980. @endnode
  1981. */
  1982.  
  1983. PROC setsurface(name,num,vlist:PTR TO LONG,col) OF vectWorld
  1984.   DEF o:PTR TO object_obj
  1985.  
  1986.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  1987. ENDPROC o.setsurface(num,vlist,col)
  1988. ->///
  1989.  
  1990. ->/// PROC getsurface(name,num,vnum) OF vectWorld
  1991. /*
  1992. @node world_getsurface "AFC module: vectWorld / getsurface()"
  1993.  
  1994.           NAME: getsurface(name, snum, vnum)
  1995.  
  1996.    DESCRIPTION: same as @{"object_obj / getsurface()" LINK object_getsurface}
  1997.  
  1998.         INPUTS: name of the object,
  1999.                 snum: number of surface to be inquired,
  2000.                 vnum: number of vertex
  2001.  
  2002.        RESULTS: FALSE if object not found or snum outside the valid range
  2003.                  or vnum outside the valid range for the object,
  2004.                 otherwise the vertex number in position vnum.
  2005.  
  2006.       SEE ALSO: @{" setsurface()              " LINK world_setsurface}
  2007.                 @{" object_obj / getsurface() " LINK object_getsurface}
  2008.  
  2009. @endnode
  2010. */
  2011.  
  2012. PROC getsurface(name,num,vnum) OF vectWorld
  2013.   DEF o:PTR TO object_obj
  2014.  
  2015.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  2016. ENDPROC o.getsurface(num,vnum)
  2017. ->///
  2018.  
  2019. ->/// PROC delsurface(name,num) OF vectWorld
  2020. /*
  2021. @node world_delsurface "AFC module: vectWorld / delsurface()"
  2022.  
  2023.           NAME: delsurface(name, num)
  2024.  
  2025.    DESCRIPTION: same as @{"object_obj / delsurface()" LINK object_delsurface}
  2026.  
  2027.         INPUTS: name of the object to be modified,
  2028.                 num: number of surface to be killed.
  2029.  
  2030.        RESULTS: FALSE if object not found or num outside the valid surface
  2031.                  number range for the object,
  2032.                 otherwise TRUE.
  2033.  
  2034.       SEE ALSO: @{" setsurface()              " LINK world_setsurface}
  2035.                 @{" object_obj / delsurface() " LINK object_delsurface}
  2036.  
  2037. @endnode
  2038. */
  2039.  
  2040. PROC delsurface(name,num) OF vectWorld
  2041.   DEF o:PTR TO object_obj
  2042.  
  2043.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  2044. ENDPROC o.delsurface(num)
  2045. ->///
  2046.  
  2047. ->/// PROC getpoint(name,v) OF vectWorld
  2048. /*
  2049. @node world_getpoint "AFC module: vectWorld / getpoint()"
  2050.  
  2051.           NAME: getpoint(name, vertex)
  2052.  
  2053.    DESCRIPTION: same as @{"object_obj / getpoint()" LINK object_getpoint}
  2054.  
  2055.         INPUTS: name of the object,
  2056.                 vertex number to be inquired.
  2057.  
  2058.        RESULTS: FALSE if object not found or vertex number outside the
  2059.                  valid range for the object,
  2060.                 otherwise the pointer to a screen_pixel object.
  2061.  
  2062.       SEE ALSO: @{" object_obj / getpoint() " LINK object_getpoint}
  2063.  
  2064. @endnode
  2065. */
  2066.  
  2067. PROC getpoint(name,v) OF vectWorld
  2068.   DEF o:PTR TO object_obj
  2069.  
  2070.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  2071. ENDPROC o.getpoint(v)
  2072. ->///
  2073.  
  2074. ->/// PROC visible(name,v=-10) OF vectWorld
  2075. /*
  2076. @node world_visible "AFC module: vectWorld / visible()"
  2077.  
  2078.           NAME: visible(name [,v])
  2079.  
  2080.    DESCRIPTION: an object is by default visible, that is to say it will be
  2081.                 drawn on the scene.  If v=FALSE then the object won't
  2082.                 appear on the scene any more, until v is reset to TRUE.  If
  2083.                 v is omitted then the function returns the state of the
  2084.                 object.
  2085.  
  2086.         INPUTS: name of the object to be modified,
  2087.                 v: TRUE if visible, FALSE if not
  2088.  
  2089.        RESULTS: FALSE if object not found, otherwise TRUE; if v is omitted
  2090.                 then the result is the state of the object.
  2091.  
  2092.       SEE ALSO:
  2093.  
  2094. @endnode
  2095. */
  2096.  
  2097. PROC visible(name,v=-10) OF vectWorld
  2098.   DEF o:PTR TO object_obj
  2099.  
  2100.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  2101. ENDPROC o.visible(v)
  2102. ->///
  2103.  
  2104. ->/// PROC position(name, x,y,z) OF vectWorld
  2105. /*
  2106. @node world_position "AFC module: vectWorld / position()"
  2107.  
  2108.           NAME: position(name, x,y,z)
  2109.  
  2110.    DESCRIPTION: same as @{"object_obj / position()" LINK object_position}.
  2111.  
  2112.         INPUTS: name of the object ot be modified,
  2113.                 coordinates of the local origin.
  2114.  
  2115.        RESULTS: FALSE if object not found.
  2116.  
  2117.       SEE ALSO: @{" applyobj()              " LINK world_applyobj}
  2118.                 @{" object_obj / position() " LINK object_position}
  2119.  
  2120. @endnode
  2121. */
  2122.  
  2123. PROC position(name, x,y,z) OF vectWorld
  2124.   DEF o:PTR TO object_obj
  2125.  
  2126.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  2127. ENDPROC o.position(x,y,z)
  2128. ->///
  2129.  
  2130. ->/// PROC scale(name, x,y,z) OF vectWorld
  2131. /*
  2132. @node world_scale "AFC module: vectWorld / scale()"
  2133.  
  2134.           NAME: scale(name, x,y,z)
  2135.  
  2136.    DESCRIPTION: same as @{"object_obj / scale()" LINK object_scale}.
  2137.  
  2138.         INPUTS: name of the object to be modified,
  2139.                 scaling factors.
  2140.  
  2141.        RESULTS: FALSE if object not found.
  2142.  
  2143.       SEE ALSO: @{" applyobj()           " LINK world_applyobj}
  2144.                 @{" object_obj / scale() " LINK object_scale}
  2145.  
  2146. @endnode
  2147. */
  2148.  
  2149. PROC scale(name, x,y,z) OF vectWorld
  2150.   DEF o:PTR TO object_obj
  2151.  
  2152.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  2153. ENDPROC o.scale(x,y,z)
  2154. ->///
  2155.  
  2156. ->/// PROC clearobj(name) OF vectWorld
  2157. /*
  2158. @node world_clearobj "AFC module: vectWorld / clearobj()"
  2159.  
  2160.           NAME: clearobj(name)
  2161.  
  2162.    DESCRIPTION: same as @{"object_obj / clear()" LINK object_clear}.
  2163.  
  2164.         INPUTS: name of the object to be cleared.
  2165.  
  2166.        RESULTS: FALSE if object not found, otherwise TRUE.
  2167.  
  2168.       SEE ALSO: @{" object_obj / clear() " LINK object_clear}
  2169.  
  2170. @endnode
  2171. */
  2172.  
  2173. PROC clearobj(name) OF vectWorld
  2174.   DEF o:PTR TO object_obj
  2175.  
  2176.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  2177. ENDPROC o.clear()
  2178. ->///
  2179.  
  2180. ->/// PROC copyobj(fname, dname) OF vectWorld
  2181. /*
  2182. @node world_copyobj "AFC module: vectWorld / copyobj()"
  2183.  
  2184.           NAME: copyobj(source_name, dest_name)
  2185.  
  2186.    DESCRIPTION: copies the contents of source_name object to dest_name
  2187.                 object (except names).
  2188.  
  2189.         INPUTS: name of two object_obj's.
  2190.  
  2191.        RESULTS: FALSE if either of the objects has not been found.
  2192.  
  2193.       SEE ALSO: @{" cloneobj()          " LINK world_cloneobj}
  2194.                 @{" object_obj / copy() " LINK object_copy}
  2195.  
  2196. @endnode
  2197. */
  2198.  
  2199. PROC copyobj(fname, dname) OF vectWorld
  2200.   DEF o:PTR TO object_obj, d
  2201.  
  2202.   IF (o:=self.posonobj(fname))=FALSE THEN RETURN FALSE
  2203.   IF (d:=self.posonobj(dname))=FALSE THEN RETURN FALSE
  2204. ENDPROC o.copy(d)
  2205. ->///
  2206.  
  2207. ->/// PROC cloneobj(name, cname=NIL) OF vectWorld
  2208. /*
  2209. @node world_cloneobj "AFC module: vectWorld / cloneobj()"
  2210.  
  2211.           NAME: cloneobj(name, new_name=NIL)
  2212.  
  2213.    DESCRIPTION: creates a new object of name new_name (if supplied),
  2214.                 copies the contents of the object_obj 'name' in the newborn
  2215.                 object, and then links the latter to the vectWorld.
  2216.  
  2217.         INPUTS: name of the object to be cloned,
  2218.                 new_name:  name of the new object (if not supplied the
  2219.                  default is 'Copy_of_name').
  2220.  
  2221.        RESULTS: FALSE if object 'name' not found.
  2222.  
  2223.       SEE ALSO: @{" copyobj()            " LINK world_copyobj}
  2224.                 @{" object_obj / clone() " LINK object_clone}
  2225.  
  2226. @endnode
  2227. */
  2228.  
  2229. PROC cloneobj(name, cname=NIL) OF vectWorld
  2230.   DEF o:PTR TO object_obj, c
  2231.  
  2232.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  2233.   c:=o.clone(cname)
  2234.   self.obj.add(c)
  2235. ENDPROC TRUE
  2236. ->///
  2237.  
  2238. ->/// PROC applyobj(name) OF vectWorld
  2239. /*
  2240. @node world_applyobj "AFC module: vectWorld / applyobj()"
  2241.  
  2242.           NAME: applyobj(name)
  2243.  
  2244.    DESCRIPTION: same as @{"object_obj / apply()" LINK object_apply}.
  2245.  
  2246.         INPUTS: name of the object to be modified.
  2247.  
  2248.        RESULTS: FALSE if object not found.
  2249.  
  2250.       SEE ALSO: @{" position()           " LINK world_position}
  2251.                 @{" scale()              " LINK world_scale}
  2252.                 @{" object_obj / apply() " LINK object_apply}
  2253.  
  2254. @endnode
  2255. */
  2256.  
  2257. PROC applyobj(name) OF vectWorld
  2258.   DEF o:PTR TO object_obj
  2259.  
  2260.   IF (o:=self.posonobj(name))=FALSE THEN RETURN FALSE
  2261. ENDPROC o.apply()
  2262. ->///
  2263.  
  2264. ->/// PROC projection() OF vectWorld
  2265. /*
  2266. @node world_projection "AFC module: vectWorld / projection()"
  2267.  
  2268.           NAME: projection()
  2269.  
  2270.    DESCRIPTION: transforms the 3D representation of the world in a 2D
  2271.                 representation, according with the chosen values of
  2272.                 rotantion angles (@{"setrot()" LINK world_setrot} method) and observer position
  2273.                 (@{"setobserver()" LINK world_setobserver} method).
  2274.                   You have to call this instruction before the drawing
  2275.                 routine, if you have performed some changes on the
  2276.                 vectWorld.
  2277.  
  2278.         INPUTS: NONE
  2279.  
  2280.        RESULTS: NONE
  2281.  
  2282.       SEE ALSO: @{" object_obj / projection() " LINK object_projection}
  2283.  
  2284. @endnode
  2285. */
  2286.  
  2287. PROC projection() OF vectWorld
  2288.   DEF o:PTR TO object_obj
  2289.   DEF s,c
  2290.   DEF v:PTR TO vertex_obj, tv:PTR TO vertex_obj
  2291.   DEF tvx,tvy,tvz
  2292.  
  2293.   IF (o:=self.obj.first())<>FALSE
  2294.     REPEAT
  2295.       IF (v:=o.vertex.first())<>FALSE
  2296.         -> copia vertici
  2297.         tv:=o.tvert.first()
  2298.         REPEAT
  2299.           tv.x:=v.x
  2300.           tv.y:=v.y
  2301.           tv.z:=v.z
  2302.           tv:=o.tvert.succ()
  2303.         UNTIL (v:=o.vertex.succ())=FALSE
  2304.         -> trasla locale
  2305.         IF (o.pos_x<>0) OR (o.pos_y<>0) OR (o.pos_z<>0)
  2306.           v:=o.tvert.first()
  2307.           REPEAT
  2308.             IF (o.pos_x<>0) THEN v.x:=v.x+o.pos_x
  2309.             IF (o.pos_y<>0) THEN v.y:=v.y+o.pos_y
  2310.             IF (o.pos_z<>0) THEN v.z:=v.z+o.pos_z
  2311.           UNTIL (v:=o.tvert.succ())=FALSE
  2312.         ENDIF
  2313.         -> scala locale
  2314.         IF (o.scale_x<>100) OR (o.scale_y<>100) OR (o.scale_z<>100)
  2315.           v:=o.tvert.first()
  2316.           REPEAT
  2317.             IF (o.scale_x<>100) THEN v.x:=Div(Mul(v.x,o.scale_x),100)
  2318.             IF (o.scale_y<>100) THEN v.y:=Div(Mul(v.y,o.scale_y),100)
  2319.             IF (o.scale_z<>100) THEN v.z:=Div(Mul(v.z,o.scale_z),100)
  2320.           UNTIL (v:=o.tvert.succ())=FALSE
  2321.         ENDIF
  2322.         -> scala globale
  2323.         IF (self.scale_x<>100) OR (self.scale_y<>100) OR (self.scale_z<>100)
  2324.           v:=o.tvert.first()
  2325.           REPEAT
  2326.             IF (self.scale_x<>100) THEN v.x:=Div(Mul(v.x,self.scale_x),100)
  2327.             IF (self.scale_y<>100) THEN v.y:=Div(Mul(v.y,self.scale_y),100)
  2328.             IF (self.scale_z<>100) THEN v.z:=Div(Mul(v.z,self.scale_z),100)
  2329.           UNTIL (v:=o.tvert.succ())=FALSE
  2330.         ENDIF
  2331.         -> trasla globale
  2332.         IF (self.trasl_x<>0) OR (self.trasl_y<>0) OR (self.trasl_z<>0)
  2333.           v:=o.tvert.first()
  2334.           REPEAT
  2335.             IF (self.trasl_x<>0) THEN v.x:=v.x+self.trasl_x
  2336.             IF (self.trasl_y<>0) THEN v.y:=v.y+self.trasl_y
  2337.             IF (self.trasl_z<>0) THEN v.z:=v.z+self.trasl_z
  2338.           UNTIL (v:=o.tvert.succ())=FALSE
  2339.         ENDIF
  2340.         -> rotazione x
  2341.         IF self.rot_x<>0
  2342.           s:=sin_table[self.rot_x]
  2343.           c:=sin_table[limitangle(self.rot_x+90)]
  2344.           v:=o.tvert.first()
  2345.           REPEAT
  2346.             tvx:=v.x
  2347.             tvy:=Shr(Mul(c,v.y)+Mul(s,v.z),15)
  2348.             tvz:=Shr(Mul(-s,v.y)+Mul(c,v.z),15)
  2349.             v.x:=tvx ; v.y:=tvy ; v.z:=tvz
  2350.           UNTIL (v:=o.tvert.succ())=FALSE
  2351.         ENDIF
  2352.         -> rotazione y
  2353.         IF self.rot_y<>0
  2354.           s:=sin_table[self.rot_y]
  2355.           c:=sin_table[limitangle(self.rot_y+90)]
  2356.           v:=o.tvert.first()
  2357.           REPEAT
  2358.             tvx:=Shr(Mul(c,v.x)+Mul(-s,v.z),15)
  2359.             tvy:=v.y
  2360.             tvz:=Shr(Mul(s,v.x)+Mul(c,v.z),15)
  2361.             v.x:=tvx ; v.y:=tvy ; v.z:=tvz
  2362.           UNTIL (v:=o.tvert.succ())=FALSE
  2363.         ENDIF
  2364.         -> rotazione z
  2365.         IF self.rot_z<>0
  2366.           s:=sin_table[self.rot_z]
  2367.           c:=sin_table[limitangle(self.rot_z+90)]
  2368.           v:=o.tvert.first()
  2369.           REPEAT
  2370.             tvx:=Shr(Mul(c,v.x)+Mul(s,v.y),15)
  2371.             tvy:=Shr(Mul(-s,v.x)+Mul(c,v.y),15)
  2372.             tvz:=v.z
  2373.             v.x:=tvx ; v.y:=tvy ; v.z:=tvz
  2374.           UNTIL (v:=o.tvert.succ())=FALSE
  2375.         ENDIF
  2376.         o.projection(self.observer_x,self.observer_y,self.observer_z)
  2377.       ENDIF
  2378.     UNTIL (o:=self.obj.succ())=FALSE
  2379.   ENDIF
  2380. ENDPROC
  2381. ->///
  2382.  
  2383. ->/// PROC drawcode(rp,o:PTR TO object_obj) OF vectWorld
  2384. PROC drawcode(rp,o:PTR TO object_obj) OF vectWorld
  2385.   DEF p1:PTR TO screen_pixel
  2386.   DEF p2:PTR TO screen_pixel
  2387.   DEF l:PTR TO line_obj
  2388.   DEF dx1,dy1,dx2,dy2
  2389.  
  2390.   IF (l:=o.line.first())<>FALSE  -> ha almeno una linea?
  2391.     REPEAT
  2392.       IF (p1:=o.proj.item(l.startv))<>FALSE
  2393.         IF (p2:=o.proj.item(l.endv))<>FALSE
  2394.  
  2395.           dx1:=self.scrtrasl_x+Div(Mul(self.scrscale_x,p1.x),100)
  2396.           dy1:=self.scrtrasl_y-Div(Mul(self.scrscale_y,p1.y),100)
  2397.           dx2:=self.scrtrasl_x+Div(Mul(self.scrscale_x,p2.x),100)
  2398.           dy2:=self.scrtrasl_y-Div(Mul(self.scrscale_y,p2.y),100)
  2399.  
  2400.           SetAPen(rp, l.colour)
  2401.           Move(rp, dx1, dy1)
  2402.           Draw(rp, dx2, dy2)
  2403.         ENDIF
  2404.       ENDIF
  2405.     UNTIL (l:=o.line.succ())=FALSE
  2406.   ELSEIF (p1:=o.proj.first())<>FALSE  -> altrimenti disegno solo pti
  2407.     REPEAT
  2408.       dx1:=self.scrtrasl_x+Div(Mul(self.scrscale_x,p1.x),100)
  2409.       dy1:=self.scrtrasl_y-Div(Mul(self.scrscale_y,p1.y),100)
  2410.       WritePixel(rp,dx1,dx2)
  2411.     UNTIL (p1:=o.proj.succ())=FALSE
  2412.   ENDIF
  2413. ENDPROC
  2414. ->///
  2415.  
  2416. ->/// PROC draw(rp) OF vectWorld
  2417. /*
  2418. @node world_draw "AFC module: vectWorld / draw()"
  2419.  
  2420.           NAME: draw(rastport)
  2421.  
  2422.    DESCRIPTION: draws the vectWorld in a wireframe fashion.  If an object
  2423.                 has at least one line, then only its lines are drawn; if an
  2424.                 object has no lines, then its vertices are drawn.  Rastport
  2425.                 is the address of a valid rastport in which to draw the
  2426.                 graphics.
  2427.                   The drawing is then traslated and scaled according to the
  2428.                 values entered with the @{"setaftertrasl()" LINK world_setaftertrasl} and
  2429.                 @{"setafterscale()" LINK world_setafterscale} methods.
  2430.                   Remember to @{"projection()" LINK world_projection} the vectWorld before drawing
  2431.                 it (you needn't do this if it's not the first time and
  2432.                 you've made no changes).
  2433.  
  2434.         INPUTS: address of a rastport.
  2435.  
  2436.        RESULTS: NONE
  2437.  
  2438.       SEE ALSO: @{" drawfill()   " LINK world_drawfill}
  2439.                 @{" projection() " LINK world_projection}
  2440.  
  2441. @endnode
  2442. */
  2443.  
  2444. PROC draw(rp) OF vectWorld
  2445.   DEF o:PTR TO object_obj
  2446.  
  2447.   IF (o:=self.obj.first())<>FALSE
  2448.     REPEAT
  2449.       IF o.visible
  2450.         self.drawcode(rp,o)
  2451.       ENDIF
  2452.     UNTIL (o:=self.obj.succ())=FALSE
  2453.   ENDIF
  2454. ENDPROC
  2455. ->///
  2456.  
  2457. ->/// PROC drawfill(rp:PTR TO rastport, onlylines=FALSE) OF vectWorld
  2458. /*
  2459. @node world_drawfill "AFC module: vectWorld / drawfill()"
  2460.  
  2461.           NAME: drawfill(rastport, onlylines=FALSE)
  2462.  
  2463.    DESCRIPTION: draws the projected vectWorld with filled vectors.
  2464.                   The drawing is then traslated and scaled according to the
  2465.                 values entered with the @{"setaftertrasl()" LINK world_setaftertrasl} and
  2466.                 @{"setafterscale()" LINK world_setafterscale} methods.
  2467.                   Clipping is made according to the dimensions of the
  2468.                 screen area entered with the @{"setdisplay()" LINK world_setdisplay} method.
  2469.                   If the onlylines parameter is set to TRUE, then also
  2470.                 objects without surfaces are drawn.
  2471.                   
  2472.                   Remember to @{"projection()" LINK world_projection} the vectWorld before drawing
  2473.                 it (you needn't do this if it's not the first time and
  2474.                 you've made no changes).
  2475.                   You must call the @{"init3D()" LINK world_init3d} routine at least one time
  2476.                 before drawing any filled graphics.
  2477.  
  2478.         INPUTS: address of a rastport in which to draw the graphics.
  2479.  
  2480.        RESULTS: NONE
  2481.  
  2482.       SEE ALSO: Important: @{" init3D() " LINK world_init3d}
  2483.                 @{" projection() " LINK world_projection}
  2484.  
  2485. @endnode
  2486. */
  2487.  
  2488. PROC drawfill(rp:PTR TO rastport, onlylines=FALSE) OF vectWorld
  2489.   DEF o:PTR TO object_obj
  2490.   DEF s:PTR TO surface_obj, flag=FALSE
  2491.   DEF p0:PTR TO vertex_obj, p1:PTR TO vertex_obj, p2:PTR TO vertex_obj
  2492.   DEF rx,ry,rz, q, pippo:PTR TO stuff, sum
  2493.   DEF pix:PTR TO screen_pixel, dx,dy, el:PTR TO stuff
  2494.   DEF sve:PTR TO surface_vertex, ind=0
  2495.  
  2496.   DEF v:PTR TO vertex_obj, w:PTR TO vertex_obj, r:PTR TO vertex_obj
  2497.   DEF look:PTR TO vertex_obj
  2498.  
  2499.   NEW v ; NEW w ; NEW r ; NEW look
  2500.  
  2501.   IF (pippo:=self.surflist.first())
  2502.     REPEAT
  2503.       END pippo
  2504.     UNTIL (pippo:=self.surflist.succ())=FALSE
  2505.     self.surflist.clear()
  2506.   ENDIF
  2507.  
  2508.   IF (o:=self.obj.first())<>FALSE
  2509.     REPEAT
  2510.       IF o.visible
  2511.         IF (s:=o.surface.first())<>FALSE
  2512.           REPEAT
  2513.             IF s.vertex.numitems()>=3
  2514.               sve:=s.vertex.first()       -> vertice 0
  2515.               p0:=o.tvert.item(sve.num)
  2516.               sve:=s.vertex.succ()        -> vertice 1
  2517.               p1:=o.tvert.item(sve.num)
  2518.               sve:=s.vertex.succ()        -> vertice 2
  2519.               p2:=o.tvert.item(sve.num)
  2520.               v.x:=p1.x-p0.x
  2521.               v.y:=p1.y-p0.y
  2522.               v.z:=p1.z-p0.z
  2523.               w.x:=p2.x-p0.x
  2524.               w.y:=p2.y-p0.y
  2525.               w.z:=p2.z-p0.z
  2526.               rx, ry, rz:=crossprod(v,w)
  2527.               r.x:=rx ; r.y:=ry ; r.z:=rz
  2528.               look.x:=p0.x-self.observer_x
  2529.               look.y:=p0.y-self.observer_y
  2530.               look.z:=p0.z-self.observer_z
  2531.               q:=dotprod(look,r)
  2532.  
  2533.               IF q<0    -> dovrebbe essere q>0 ma la terna e' sisistrorsa
  2534.                 NEW pippo.stuff()
  2535.                 StrCopy(pippo.obj,o.name)
  2536.                 pippo.surf:=o.surface.numpos()
  2537.                 sum:=0
  2538.                 sve:=s.vertex.first()
  2539.                 REPEAT
  2540.                   p0:=o.tvert.item(sve.num)
  2541.                   sum:=sum+p0.z
  2542.                 UNTIL (sve:=s.vertex.succ())=FALSE
  2543.                 sum:=Div(sum,s.vertex.numitems())
  2544.                 pippo.avg:=Mul(-1,sum)
  2545.  
  2546.                 IF (el:=self.surflist.first())
  2547.                   flag:=FALSE
  2548.                   REPEAT
  2549.                     IF el.avg>pippo.avg
  2550.                       flag:=TRUE
  2551.                       IF self.surflist.numpos()>0
  2552.                         self.surflist.prev()
  2553.                         self.surflist.insert(pippo)
  2554.                       ELSE
  2555.                         self.surflist.add(pippo,NM_ADD_HEAD)
  2556.                       ENDIF
  2557.                     ELSE
  2558.                       el:=self.surflist.succ()
  2559.                       IF el=FALSE
  2560.                         flag:=TRUE
  2561.                         self.surflist.add(pippo)
  2562.                       ENDIF
  2563.                     ENDIF
  2564.                   UNTIL flag=TRUE
  2565.                 ELSE
  2566.                   self.surflist.add(pippo)
  2567.                 ENDIF
  2568.  
  2569.               ENDIF
  2570.             ENDIF
  2571.           UNTIL (s:=o.surface.succ())=FALSE
  2572.         ELSE -> no surfaces
  2573.           IF onlylines THEN self.drawcode(rp,o)
  2574.         ENDIF
  2575.       ENDIF
  2576.     UNTIL (o:=self.obj.succ())=FALSE
  2577.  
  2578.  
  2579.     IF (pippo:=self.surflist.first())<>FALSE
  2580.       rp.areainfo:=self.areai
  2581.       rp.tmpras:=self.tras
  2582.  
  2583.       REPEAT
  2584.         ind:=0
  2585.         o:=self.posonobj(pippo.obj)
  2586.         s:=o.surface.item(pippo.surf)
  2587.         IF (sve:=s.vertex.first())
  2588.           REPEAT
  2589.             pix:=o.proj.item(sve.num)
  2590.             dx:=self.scrtrasl_x+Div(Mul(self.scrscale_x,pix.x),100)
  2591.             dy:=self.scrtrasl_y-Div(Mul(self.scrscale_y,pix.y),100)
  2592.             ind:=self.clippoint(rp,dx,dy,o,s,ind)
  2593.           UNTIL (sve:=s.vertex.succ())=FALSE
  2594.           SetAPen(rp,s.colour)
  2595.           AreaEnd(rp)
  2596.         ENDIF
  2597.       UNTIL (pippo:=self.surflist.succ())=FALSE
  2598.     ENDIF
  2599.  
  2600.   ENDIF
  2601.  
  2602.   END v ; END w ; END r ; END look
  2603. ENDPROC
  2604. ->///
  2605.  
  2606. ->/// PROC setobserver(ox,oy,oz) OF vectWorld
  2607. /*
  2608. @node world_setobserver "AFC module: vectWorld / setobserver()"
  2609.  
  2610.           NAME: setobserver(x, y, z)
  2611.  
  2612.    DESCRIPTION: sets the observer position.
  2613.  
  2614.         INPUTS: coordinates of the observer.
  2615.  
  2616.        RESULTS: NONE
  2617.  
  2618.       SEE ALSO:
  2619.  
  2620. @endnode
  2621. */
  2622.  
  2623. PROC setobserver(ox,oy,oz) OF vectWorld
  2624.   self.observer_x:=ox
  2625.   self.observer_y:=oy
  2626.   self.observer_z:=oz
  2627. ENDPROC
  2628. ->///
  2629.  
  2630. ->/// PROC setscale(sx,sy,sz) OF vectWorld
  2631. /*
  2632. @node world_setscale "AFC module: vectWorld / setscale()"
  2633.  
  2634.           NAME: setscale(x, y, z)
  2635.  
  2636.    DESCRIPTION: the three scale factors will be applied to the whole
  2637.                 vectWorld before projecting it.  They are entered as a
  2638.                 percentage:  100 means original dimensions, 50 means a
  2639.                 half, and so on...
  2640.                   This is a 3D operation:  compare it with
  2641.                 @{"setafterscale()" LINK world_setafterscale}
  2642.  
  2643.         INPUTS: scaling factors in the three directions.
  2644.  
  2645.        RESULTS: NONE
  2646.  
  2647.       SEE ALSO: @{" setafterscale() " LINK world_setafterscale}
  2648.  
  2649. @endnode
  2650. */
  2651.  
  2652. PROC setscale(sx,sy,sz) OF vectWorld
  2653.   IF sx<=0 THEN sx:=100
  2654.   IF sy<=0 THEN sy:=100
  2655.   IF sz<=0 THEN sz:=100
  2656.   self.scale_x:=sx
  2657.   self.scale_y:=sy
  2658.   self.scale_z:=sz
  2659. ENDPROC
  2660. ->///
  2661.  
  2662. ->/// PROC settrasl(tx,ty,tz) OF vectWorld
  2663. /*
  2664. @node world_settrasl "AFC module: vectWorld / settrasl()"
  2665.  
  2666.           NAME: settrasl(tx, ty, tz)
  2667.  
  2668.    DESCRIPTION: traslates the whole vectWorld by the specified amounts
  2669.                 before projecting it.
  2670.                   This is a 3D operation:  compare it with
  2671.                 @{"setaftertrasl()" LINK world_setaftertrasl}
  2672.  
  2673.                 The traslation is done before any rotation is performed.
  2674.  
  2675.         INPUTS: traslation amounts in the three directions.
  2676.  
  2677.        RESULTS: NONE
  2678.  
  2679.       SEE ALSO: @{" setaftertrasl() " LINK world_setaftertrasl}
  2680.  
  2681. @endnode
  2682. */
  2683.  
  2684. PROC settrasl(tx,ty,tz) OF vectWorld
  2685.   self.trasl_x:=tx
  2686.   self.trasl_y:=ty
  2687.   self.trasl_z:=tz
  2688. ENDPROC
  2689. ->///
  2690.  
  2691. ->/// PROC setrot(rx,ry,rz) OF vectWorld
  2692. /*
  2693. @node world_setrot "AFC module: vectWorld / setrot()"
  2694.  
  2695.           NAME: setrot(x, y, z)
  2696.  
  2697.    DESCRIPTION: rotates the whole vectWorld around the three axes by the
  2698.                 specified amounts.
  2699.  
  2700.         INPUTS: angles of rotation around the three axes (degrees).
  2701.  
  2702.        RESULTS: NONE
  2703.  
  2704.       SEE ALSO:
  2705.  
  2706. @endnode
  2707. */
  2708.  
  2709. PROC setrot(rx,ry,rz) OF vectWorld
  2710.   self.rot_x:=limitangle(rx)
  2711.   self.rot_y:=limitangle(ry)
  2712.   self.rot_z:=limitangle(rz)
  2713. ENDPROC
  2714. ->///
  2715.  
  2716. ->/// PROC setafterscale(sx,sy) OF vectWorld
  2717. /*
  2718. @node world_setafterscale "AFC module: vectWorld / setafterscale()"
  2719.  
  2720.           NAME: setafterscale(x, y)
  2721.  
  2722.    DESCRIPTION: scales the projected world while drawing it to adapt it to
  2723.                 the screen area.  The scaling factors are entered as a
  2724.                 percentage:  100 means original dimensions, 50 means a
  2725.                 half, and so on...
  2726.                   This is a 2D operation:  compare it with @{"setscale()" LINK world_setscale}
  2727.  
  2728.         INPUTS: scaling factors in the two directions.
  2729.  
  2730.        RESULTS: NONE
  2731.  
  2732.       SEE ALSO: @{" setscale() " LINK world_setscale}
  2733.  
  2734. @endnode
  2735. */
  2736.  
  2737. PROC setafterscale(sx,sy) OF vectWorld
  2738.   IF sx<=0 THEN sx:=100
  2739.   IF sy<=0 THEN sy:=100
  2740.   self.scrscale_x:=sx
  2741.   self.scrscale_y:=sy
  2742. ENDPROC
  2743. ->///
  2744.  
  2745. ->/// PROC setaftertrasl(tx,ty) OF vectWorld
  2746. /*
  2747. @node world_setaftertrasl "AFC module: vectWorld / setaftertrasl()"
  2748.  
  2749.           NAME: setaftertrasl(x, y)
  2750.  
  2751.    DESCRIPTION: translates the origin of the screen coordinate system
  2752.                 (default: top left-hand corner, as usual).
  2753.                   This is a 2D operation:  compare it with @{"settrasl()" LINK world_settrasl}
  2754.  
  2755.         INPUTS: traslation factors in the two directions.
  2756.  
  2757.        RESULTS: NONE
  2758.  
  2759.       SEE ALSO: @{" settrasl() " LINK world_settrasl}
  2760.  
  2761. @endnode
  2762. */
  2763.  
  2764. PROC setaftertrasl(tx,ty) OF vectWorld
  2765.   self.scrtrasl_x:=tx
  2766.   self.scrtrasl_y:=ty
  2767. ENDPROC
  2768. ->///
  2769.  
  2770. ->/// PROC setdisplay(w,h) OF vectWorld
  2771. /*
  2772. @node world_setdisplay "AFC module: vectWorld / setdisplay()"
  2773.  
  2774.           NAME: setdisplay(width, height)
  2775.  
  2776.    DESCRIPTION: used to enter the screen area dimensions.  These are used
  2777.                 in the allocation of the extra bitplane in the @{"init3D()" LINK world_init3d}
  2778.                 routine, and in the clipping of graphics in the
  2779.                 @{"drawfill()" LINK world_drawfill} method.
  2780.  
  2781.         INPUTS: width and height of the drawing area (defaults are:
  2782.                 width=320, height=256).
  2783.  
  2784.        RESULTS: NONE
  2785.  
  2786.       SEE ALSO:
  2787.  
  2788. @endnode
  2789. */
  2790.  
  2791. PROC setdisplay(w,h) OF vectWorld
  2792.   IF w<=0 THEN w:=320
  2793.   IF h<=0 THEN h:=256
  2794.  
  2795.   self.d_width:=w
  2796.   self.d_height:=h
  2797. ENDPROC
  2798. ->///
  2799.  
  2800. ->/// PROC init3D(bufon=TRUE,dispon=TRUE) OF vectWorld
  2801. /*
  2802. @node world_init3d "AFC module: vectWorld / init3D()"
  2803.  
  2804.           NAME: init3D(bufon=TRUE, dispon=TRUE)
  2805.  
  2806.    DESCRIPTION: allocates the resources needed by the @{"drawfill()" LINK world_drawfill} method
  2807.                 to draw filled vectors:  you must call this routine before
  2808.                 any call to drawfill() is made.
  2809.                    It allocates a buffer needed by the operating system to
  2810.                 store the vectors before they are drawn, and an extra
  2811.                 bitplane to allow the drawing of filled areas.  If, in a
  2812.                 second time, you change the dimensions of the screen area,
  2813.                 you have to recall this routine to update the dimensions of
  2814.                 the extra bitplane; in the same manner, if you add lots of
  2815.                 surfaces to your world, you have to call this routine to
  2816.                 adapt the buffer dimensions to the new situation (otherwise
  2817.                 you can get only partial rendering).
  2818.                    You needn't do both the operations every time you call
  2819.                 the init3D method, infact the two flags mean:
  2820.  
  2821.                         bufon =TRUE  ->  resize the buffer
  2822.                         dispon=TRUE  ->  resize the extra bitplane.
  2823.  
  2824.                    The dimensions of the screen area are entered with the
  2825.                 @{"setdisplay()" LINK world_setdisplay} method, and they are used also for graphic
  2826.                 clipping purposes.
  2827.  
  2828.         INPUTS: flags described above.
  2829.  
  2830.        RESULTS: raises some exceptions if memory allocation fails (see the
  2831.                 @{"Error Table" LINK Error_Table}).
  2832.  
  2833.       SEE ALSO: @{" drawfill() " LINK world_drawfill}
  2834.  
  2835. @endnode
  2836. */
  2837.  
  2838. PROC init3D(bufon=TRUE,dispon=TRUE) OF vectWorld
  2839.   DEF o:PTR TO object_obj
  2840. ->  DEF s:PTR TO surface_obj
  2841.   DEF sum=0
  2842.  
  2843.   IF (o:=self.obj.first())<>FALSE
  2844.     REPEAT
  2845.  
  2846. /*      IF (s:=o.surface.first())<>FALSE
  2847.         REPEAT
  2848.           sum:=sum+s.vertex.numitems()
  2849.         UNTIL (s:=o.surface.succ())=FALSE
  2850.       ENDIF
  2851. */
  2852.       sum:=sum+o.vertex.numitems()
  2853.     UNTIL (o:=self.obj.succ())=FALSE
  2854.   ENDIF
  2855.  
  2856.   IF sum=0 THEN RETURN
  2857.  
  2858.   IF self.surflist=NIL THEN NEW self.surflist.nodemaster()
  2859.   IF self.areai=NIL
  2860.     NEW self.areai
  2861.     IF self.areai=NIL THEN Raise(WORLD_ERR_AREAINFO)
  2862.   ENDIF
  2863.   IF self.tras=NIL
  2864.     NEW self.tras
  2865.     IF self.tras=NIL THEN Raise(WORLD_ERR_TEMPRAS)
  2866.   ENDIF
  2867.  
  2868.   IF bufon=TRUE
  2869.     IF self.buffer<>NIL
  2870.       FreeVec(self.buffer)
  2871.       self.buffer:=NIL
  2872.     ENDIF
  2873.     self.buffer:=AllocVec(5*(sum*2),MEMF_CLEAR)
  2874.     IF self.buffer=NIL THEN Raise(WORLD_ERR_VECTBUFFER)
  2875.     InitArea(self.areai,self.buffer,(sum*2))
  2876.   ENDIF
  2877.   IF dispon=TRUE
  2878.     IF self.bplane<>NIL
  2879.       FreeRaster(self.bplane,self.dw_old,self.dh_old)
  2880.       self.bplane:=NIL
  2881.     ENDIF
  2882.     self.dw_old:=self.d_width
  2883.     self.dh_old:=self.d_height
  2884.     self.bplane:=AllocRaster(self.d_width,self.d_height)
  2885.     IF self.bplane=NIL THEN Raise(WORLD_ERR_BITPLANE)
  2886.     InitTmpRas(self.tras,self.bplane,RASSIZE(self.d_width,self.d_height))
  2887.   ENDIF
  2888. ENDPROC
  2889. ->///
  2890.  
  2891. ->/// PROC version() OF vectWorld
  2892. /*
  2893. @node world_version "AFC module: vectWorld / version()"
  2894.  
  2895.           NAME: version()
  2896.  
  2897.    DESCRIPTION: returns version and revision of vectWorld module
  2898.  
  2899.         INPUTS: NONE
  2900.  
  2901.        RESULTS: version, revision
  2902.  
  2903.       SEE ALSO:
  2904.  
  2905. @endnode
  2906. */
  2907.  
  2908. PROC version() OF vectWorld IS WORLD_VERSION, WORLD_REVISION
  2909. -> ///
  2910.  
  2911.  
  2912. -> clipping
  2913.  
  2914. ->/// PROC clipx(rp,dx,dy,x,y,rout,ind) OF vectWorld
  2915. PROC clipx(rp,dx,dy,x,y,rout,ind) OF vectWorld
  2916.   DEF m, ndx,ndy
  2917.  
  2918.   IF (x-dx)<>0
  2919.     IF dx<0
  2920.       m:=Mul((dy-y),dx)
  2921.       ndy:=dy+Div(m,(x-dx))
  2922.       IF (ndy>=0) AND (ndy<=(self.d_height-1))
  2923.         IF (ndy>=Min(dy,y)) AND (ndy<=Max(dy,y))
  2924.           rout(rp,0,ndy)
  2925.           ind:=1
  2926.         ENDIF
  2927.       ENDIF
  2928.     ELSE
  2929.       ndx:=dx-(self.d_width-1)
  2930.       m:=Mul((dy-y),ndx)
  2931.       ndy:=dy+Div(m,(x-dx))
  2932.       IF (ndy>=0) AND (ndy<=(self.d_height-1))
  2933.         IF (ndy>=Min(dy,y)) AND (ndy<=Max(dy,y))
  2934.           rout(rp,(self.d_width-1),ndy)
  2935.           ind:=1
  2936.         ENDIF
  2937.       ENDIF
  2938.     ENDIF
  2939.   ENDIF
  2940. ENDPROC ind
  2941. ->///
  2942.  
  2943. ->/// PROC clipy(rp,dx,dy,x,y,rout,ind) OF vectWorld
  2944. PROC clipy(rp,dx,dy,x,y,rout,ind) OF vectWorld
  2945.   DEF m,ndx,ndy
  2946.  
  2947.   IF (dy-y)<>0
  2948.     IF dy<0
  2949.       m:=Mul((x-dx),dy)
  2950.       ndx:=dx+Div(m,(dy-y))
  2951.       IF (ndx>=0) AND (ndx<=(self.d_width-1))
  2952.         IF (ndx>=Min(dx,x)) AND (ndx<=Max(dx,x))
  2953.           rout(rp,ndx,0)
  2954.           ind:=1
  2955.         ENDIF
  2956.       ELSE
  2957.         IF (ndx<0) AND (Min(dx,x)<0) THEN (rout(rp,0,0) BUT ind:=1)
  2958.         IF (ndx>(self.d_width-1)) AND (Max(dx,x)>(self.d_width-1))
  2959.           rout(rp,(self.d_width-1),0)
  2960.           ind:=1
  2961.         ENDIF
  2962.       ENDIF
  2963.     ELSE
  2964.       ndy:=dy-(self.d_height-1)
  2965.       m:=Mul((x-dx),ndy)
  2966.       ndx:=dx+Div(m,(dy-y))
  2967.       IF (ndx>=0) AND (ndx<=(self.d_width-1))
  2968.         IF (ndx>=Min(dx,x)) AND (ndx<=Max(dx,x))
  2969.           rout(rp,ndx,(self.d_height-1))
  2970.           ind:=1
  2971.         ENDIF
  2972.       ELSE
  2973.         IF (ndx<0) AND (Min(dx,x)<0) THEN (rout(rp,0,(self.d_height-1)) BUT ind:=1)
  2974.         IF (ndx>(self.d_width-1)) AND (Max(dx,x)>(self.d_width-1))
  2975.           rout(rp,(self.d_width-1),(self.d_height-1))
  2976.           ind:=1
  2977.         ENDIF
  2978.       ENDIF
  2979.     ENDIF
  2980.   ENDIF
  2981. ENDPROC ind
  2982. ->///
  2983.  
  2984. ->/// PROC firstdraw(rp,x,y)
  2985. PROC firstdraw(rp,x,y) IS AreaMove(rp,x,y)
  2986. ->///
  2987.  
  2988. ->/// PROC nextdraw(rp,x,y)
  2989. PROC nextdraw(rp,x,y) IS AreaDraw(rp,x,y)
  2990. ->///
  2991.  
  2992. ->/// PROC clippoint(rp,dx,dy,o:PTR TO object_obj,s:PTR TO surface_obj,pind) OF vectWorld
  2993. PROC clippoint(rp,dx,dy,o:PTR TO object_obj,s:PTR TO surface_obj,pind) OF vectWorld
  2994.   DEF pdraw:PTR TO LONG, pixset=NIL
  2995.   DEF px,py, pix:PTR TO screen_pixel, sve:PTR TO surface_vertex
  2996.  
  2997.   pdraw:=[{firstdraw},{nextdraw}]
  2998.  
  2999.   IF ((dx>=0) AND (dx<=(self.d_width-1))) AND ((dy>=0) AND (dy<=(self.d_height-1)))
  3000.     pixset:=pdraw[pind] ; pind:=1
  3001.     pixset(rp,dx,dy)
  3002.   ELSE
  3003.     IF ((dy<0) OR (dy>(self.d_height-1)))
  3004.  
  3005.       -> collego con vertice precedente
  3006.       s.vertex.push()
  3007.       IF (sve:=s.vertex.prev())=FALSE
  3008.         sve:=s.vertex.last()
  3009.       ENDIF
  3010.       s.vertex.pop()
  3011.       pix:=o.proj.item(sve.num)
  3012.       px:=self.scrtrasl_x+Div(Mul(self.scrscale_x,pix.x),100)
  3013.       py:=self.scrtrasl_y-Div(Mul(self.scrscale_y,pix.y),100)
  3014.       pind:=self.clipy(rp,dx,dy,px,py,pdraw[pind],pind)
  3015.  
  3016.       -> collego con vertice successivo
  3017.       s.vertex.push()
  3018.       IF (sve:=s.vertex.succ())=FALSE
  3019.         sve:=s.vertex.first()
  3020.       ENDIF
  3021.       s.vertex.pop()
  3022.       pix:=o.proj.item(sve.num)
  3023.       px:=self.scrtrasl_x+Div(Mul(self.scrscale_x,pix.x),100)
  3024.       py:=self.scrtrasl_y-Div(Mul(self.scrscale_y,pix.y),100)
  3025.       pind:=self.clipy(rp,dx,dy,px,py,pdraw[pind],pind)
  3026.     ENDIF
  3027.  
  3028.     IF (dx<0) OR (dx>(self.d_width-1))
  3029.  
  3030.       -> collego con vertice precedente
  3031.       s.vertex.push()
  3032.       IF (sve:=s.vertex.prev())=FALSE
  3033.         sve:=s.vertex.last()
  3034.       ENDIF
  3035.       s.vertex.pop()
  3036.       pix:=o.proj.item(sve.num)
  3037.       px:=self.scrtrasl_x+Div(Mul(self.scrscale_x,pix.x),100)
  3038.       py:=self.scrtrasl_y-Div(Mul(self.scrscale_y,pix.y),100)
  3039.       pind:=self.clipx(rp,dx,dy,px,py,pdraw[pind],pind)
  3040.  
  3041.       -> collego con vertice successivo
  3042.       s.vertex.push()
  3043.       IF (sve:=s.vertex.succ())=FALSE
  3044.         sve:=s.vertex.first()
  3045.       ENDIF
  3046.       s.vertex.pop()
  3047.       pix:=o.proj.item(sve.num)
  3048.       px:=self.scrtrasl_x+Div(Mul(self.scrscale_x,pix.x),100)
  3049.       py:=self.scrtrasl_y-Div(Mul(self.scrscale_y,pix.y),100)
  3050.       pind:=self.clipx(rp,dx,dy,px,py,pdraw[pind],pind)
  3051.     ENDIF
  3052.  
  3053.   ENDIF
  3054. ENDPROC pind
  3055. ->///
  3056.  
  3057.  
  3058. -> General purpose routines
  3059.  
  3060. ->/// PROC limitangle(a)
  3061. /*
  3062. @node world_limitangle "AFC module: procedure / limitangle()"
  3063.  
  3064.           NAME: limitangle(angle)
  3065.  
  3066.    DESCRIPTION: bounds the angle in range [0-359] degrees.
  3067.  
  3068.         INPUTS: angle to be wrapped.
  3069.  
  3070.        RESULTS: angle in the range [0-359] degrees
  3071.  
  3072.       SEE ALSO:
  3073.  
  3074. @endnode
  3075. */
  3076.  
  3077. PROC limitangle(a)
  3078.   IF a<0
  3079.     REPEAT
  3080.       a:=a+360
  3081.     UNTIL a>=0
  3082.   ENDIF
  3083.   IF a>359
  3084.     REPEAT
  3085.       a:=a-360
  3086.     UNTIL a<359
  3087.   ENDIF
  3088. ENDPROC a
  3089. ->///
  3090.  
  3091. ->/// PROC crossprod(a:PTR TO vertex_obj, b:PTR TO vertex_obj)
  3092. /*
  3093. @node world_crossprod "AFC module: procedure / crossprod()"
  3094.  
  3095.           NAME: crossprod(a:PTR TO vertex_obj, b:PTR TO vertex_obj)
  3096.  
  3097.    DESCRIPTION: this is the vector product between the two vectors 'a' and
  3098.                 'b'.  The two arguments are defined as vertex_obj because
  3099.                 points in three-space and three-dimensional vectors share
  3100.                 the same structure (remember:  points can be represented as
  3101.                 vectors from the origin).
  3102.                   The vectors have three fields:  a.x, a.y and a.z; you
  3103.                 fill in these fields and call the routine:  it returns the
  3104.                 three components of the resulting vector.
  3105.  
  3106.         INPUTS: two (pointers to) vectors.
  3107.  
  3108.        RESULTS: three return values, representing the three components of
  3109.                 the resulting vector, in the order:  x, y, z.
  3110.  
  3111.       SEE ALSO: @{" dotprod() " LINK world_dotprod}
  3112.  
  3113. @endnode
  3114. */
  3115.  
  3116. PROC crossprod(a:PTR TO vertex_obj, b:PTR TO vertex_obj)
  3117.   DEF vx,vy,vz
  3118.  
  3119.   vx:=Mul(a.y,b.z)-Mul(a.z,b.y)
  3120.   vy:=Mul(a.z,b.x)-Mul(a.x,b.z)
  3121.   vz:=Mul(a.x,b.y)-Mul(a.y,b.x)
  3122. ENDPROC vx, vy, vz
  3123. ->///
  3124.  
  3125. ->/// PROC dotprod(a:PTR TO vertex_obj, b:PTR TO vertex_obj)
  3126. /*
  3127. @node world_dotprod "AFC module: procedure / dotprod()"
  3128.  
  3129.           NAME: dotprod(a:PTR TO vertex_obj, b:PTR TO vertex_obj)
  3130.  
  3131.    DESCRIPTION:  this is the scalar product between the two vectors 'a' and
  3132.                  'b'.  See the observations about points and vectors in the
  3133.                  @{"crossprod()" LINK world_crossprod} procedure.
  3134.  
  3135.         INPUTS: two (pointers to) vectors.
  3136.  
  3137.        RESULTS: scalar product of the two vectors.
  3138.  
  3139.       SEE ALSO: @{" crossprod() " LINK world_crossprod}
  3140.  
  3141. @endnode
  3142. */
  3143.  
  3144. PROC dotprod(a:PTR TO vertex_obj, b:PTR TO vertex_obj) IS Mul(a.x,b.x)+Mul(a.y,b.y)+Mul(a.z,b.z)
  3145. -> ///
  3146.  
  3147.  
  3148. -> /// fillSinTable()
  3149. /*
  3150. @node world_fillsintable "AFC module: procedure / fillSinTable()"
  3151.  
  3152.           NAME: fillSinTable()
  3153.  
  3154.    DESCRIPTION: this is used to fill in a pointer to the table of sines:
  3155.                 of course, sines for rotations are not calculated realtime,
  3156.                 but peeked from this table.  The table is automatically
  3157.                 filled when you create the first vectWorld object, so, in
  3158.                 general, you have not to do this task by hand.  On the
  3159.                 other hand, if you don't fill the table before accessing it
  3160.                 you can crash your machine.
  3161.  
  3162.         INPUTS: NONE
  3163.  
  3164.        RESULTS: NONE
  3165.  
  3166.       SEE ALSO:
  3167.  
  3168. @endnode
  3169. */
  3170.  
  3171. PROC fillSinTable()
  3172. ->  DEF x,s[15]:STRING
  3173.  
  3174. sin_table:=[0,572,1144,1715,
  3175. 2286,2856,3425,3993,
  3176. 4560,5126,5690,6252,
  3177. 6813,7371,7927,8481,
  3178. 9032,9580,10126,10668,
  3179. 11207,11743,12275,12803,
  3180. 13328,13848,14365,14876,
  3181. 15384,15886,16384,16877,
  3182. 17364,17847,18324,18795,
  3183. 19261,19720,20174,20622,
  3184. 21063,21498,21926,22348,
  3185. 22763,23170,23571,23965,
  3186. 24351,24730,25102,25466,
  3187. 25822,26170,26510,26842,
  3188. 27166,27482,27789,28088,
  3189. 28378,28660,28932,29197,
  3190. 29452,29698,29935,30163,
  3191. 30382,30592,30792,30983,
  3192. 31164,31336,31499,31651,
  3193. 31795,31928,32052,32166,
  3194. 32270,32365,32449,32524,
  3195. 32588,32643,32688,32723,
  3196. 32748,32763,32768,32763,
  3197. 32748,32723,32688,32643,
  3198. 32588,32524,32449,32365,
  3199. 32270,32166,32052,31928,
  3200. 31795,31651,31499,31336,
  3201. 31164,30983,30792,30592,
  3202. 30382,30163,29935,29698,
  3203. 29452,29196,28932,28660,
  3204. 28378,28088,27789,27482,
  3205. 27166,26842,26510,26170,
  3206. 25822,25466,25102,24730,
  3207. 24351,23965,23571,23170,
  3208. 22763,22348,21926,21498,
  3209. 21063,20622,20174,19720,
  3210. 19261,18795,18324,17847,
  3211. 17364,16877,16384,15886,
  3212. 15384,14876,14365,13848,
  3213. 13328,12804,12275,11743,
  3214. 11207,10668,10126,9581,
  3215. 9032,8481,7927,7371,
  3216. 6813,6253,5690,5126,
  3217. 4561,3994,3425,2856,
  3218. 2286,1715,1144,572,
  3219. 0,-572,-1143,-1715,
  3220. -2286,-2856,-3425,-3993,
  3221. -4560,-5126,-5690,-6252,
  3222. -6813,-7371,-7927,-8481,
  3223. -9032,-9580,-10126,-10668,
  3224. -11207,-11743,-12275,-12803,
  3225. -13328,-13848,-14364,-14876,
  3226. -15383,-15886,-16384,-16877,
  3227. -17364,-17847,-18323,-18795,
  3228. -19260,-19720,-20174,-20621,
  3229. -21063,-21498,-21926,-22348,
  3230. -22762,-23170,-23571,-23965,
  3231. -24351,-24730,-25102,-25465,
  3232. -25821,-26169,-26510,-26842,
  3233. -27166,-27481,-27789,-28087,
  3234. -28378,-28659,-28932,-29196,
  3235. -29452,-29698,-29935,-30163,
  3236. -30382,-30591,-30792,-30983,
  3237. -31164,-31336,-31499,-31651,
  3238. -31795,-31928,-32052,-32166,
  3239. -32270,-32365,-32449,-32524,
  3240. -32588,-32643,-32688,-32723,
  3241. -32748,-32763,-32768,-32763,
  3242. -32748,-32723,-32688,-32643,
  3243. -32589,-32524,-32449,-32365,
  3244. -32270,-32166,-32052,-31928,
  3245. -31795,-31652,-31499,-31336,
  3246. -31164,-30983,-30792,-30592,
  3247. -30382,-30163,-29935,-29698,
  3248. -29452,-29197,-28933,-28660,
  3249. -28378,-28088,-27789,-27482,
  3250. -27166,-26842,-26510,-26170,
  3251. -25822,-25466,-25102,-24731,
  3252. -24352,-23965,-23572,-23171,
  3253. -22763,-22348,-21927,-21498,
  3254. -21063,-20622,-20174,-19721,
  3255. -19261,-18795,-18324,-17847,
  3256. -17365,-16877,-16385,-15887,
  3257. -15384,-14877,-14365,-13849,
  3258. -13329,-12804,-12276,-11744,
  3259. -11208,-10669,-10127,-9581,
  3260. -9033,-8482,-7928,-7372,
  3261. -6814,-6253,-5691,-5127,
  3262. -4561,-3994,-3426,-2857,
  3263. -2287,-1716,-1144,-573]
  3264.  
  3265. ->x:=!(sin_table[90]!)/32768.0
  3266. ->WriteF('sin90: \s\n',RealF(s,x,8))
  3267. ENDPROC
  3268. -> ///
  3269.  
  3270. /*
  3271. -> /// buildSinTable()
  3272. PROC buildSinTable()
  3273.   DEF x,t,a,s[20]:STRING
  3274.   DEF y,fh
  3275.  
  3276.   IF (fh:=Open('ram:sin_table',MODE_NEWFILE))=NIL
  3277.     WriteF('no file\n')
  3278.     CleanUp(0)
  3279.   ENDIF
  3280.  
  3281.   a:=0.0
  3282.   FOR t:=0 TO 359
  3283.     x:=!Fsin(!a)
  3284.     y:=!(!x)*32768.0! ;
  3285.     StringF(s,'\d,',y) 
  3286.     Write(fh,s,StrLen(s))
  3287.     IF Mod(t+1,4)=0 THEN Write(fh,'\n',1)
  3288.     a:=!a+0.01745329
  3289.     IF CtrlC()
  3290.       Close(fh)
  3291.       CleanUp(0)
  3292.     ENDIF
  3293.   ENDFOR
  3294.   Close(fh)
  3295. ENDPROC
  3296. -> ///
  3297. */
  3298.  
  3299. #ifdef WORLD_TEST
  3300. PROC main() HANDLE
  3301.   DEF scene:PTR TO vectWorld
  3302.   DEF scr=NIL:PTR TO screen, rp, vp:PTR TO viewport
  3303.   DEF win=NIL:PTR TO window, port:PTR TO mp
  3304.   DEF msg:PTR TO intuimessage, class, code
  3305.   DEF oox,ooy,ooz, rrx,rry,rrz
  3306.   DEF bm2:PTR TO bitmapper, rp2, bitmap2, ri:PTR TO rasinfo
  3307.   DEF usebm=0, scrbm
  3308.  
  3309. ->  fillSinTable()   -> this IS done automatically by the following
  3310.  
  3311.   NEW scene.vectWorld()
  3312.  
  3313.   scene.addobj('cube')
  3314.   scene.addobj('axis')
  3315.   scene.addobj('pyramid')
  3316.  
  3317.   scene.fastsetvert('cube',[-50,50,-50, 50,50,-50, 50,-50,-50, -50,-50,-50,
  3318.                 -50,50,50, 50,50,50, 50,-50,50, -50,-50,50]:vertex_obj)
  3319.  
  3320.   scene.fastsetline('cube',[0,1,2, 1,2,2, 2,3,2, 3,0,2, 4,5,2, 5,6,2, 6,7,2, 7,4,2,
  3321.                       0,4,2, 1,5,2, 2,6,2, 3,7,2]:line_obj)
  3322.  
  3323.   scene.fastsetvert('axis',[0,0,0, 100,0,0, 0,100,0, 0,0,100]:vertex_obj)
  3324.  
  3325.   scene.fastsetline('axis',[0,1,3, 0,2,4, 0,3,5]:line_obj)
  3326.  
  3327.   scene.fastsetvert('pyramid',[0,60,-50, 50,60,-50, 50,60,50, 0,60,50, 25,120,0]:vertex_obj)
  3328.  
  3329.   scene.fastsetline('pyramid',[0,1,6, 1,2,6, 2,3,6, 3,0,6,
  3330.                        0,4,6, 1,4,6, 2,4,6, 3,4,6]:line_obj)
  3331.  
  3332.  
  3333.   scene.setsurface('cube',0,[0,1,2,3],2)
  3334.   scene.setsurface('cube',1,[0,4,5,1],3)
  3335.   scene.setsurface('cube',2,[7,6,5,4],4)
  3336.   scene.setsurface('cube',3,[3,2,6,7],5)
  3337.   scene.setsurface('cube',4,[0,3,7,4],6)
  3338.   scene.setsurface('cube',5,[1,5,6,2],7)
  3339.  
  3340.   scene.setsurface('pyramid',0,[0,1,2,3],3)
  3341.   scene.setsurface('pyramid',1,[0,4,1],2)
  3342.   scene.setsurface('pyramid',2,[3,4,0],4)
  3343.   scene.setsurface('pyramid',3,[2,4,3],5)
  3344.   scene.setsurface('pyramid',4,[1,4,2],6)
  3345.  
  3346. ->  scene.visible('pyramid',FALSE)
  3347. ->  scene.cloneobj('cube', 'cube2')
  3348. ->  scene.position('cube2',-50,-50,-50)
  3349.  
  3350. /*  objectList(scene)
  3351.   WriteF('\n')
  3352.   dumpObject(scene.getobj('cube'))
  3353.   WriteF('\n')
  3354.   dumpObject(scene.getobj('cube2'))
  3355. */
  3356.  
  3357.   scene.setdisplay(320,256)
  3358.   scene.init3D()
  3359.  
  3360.   scene.setaftertrasl(160,128)
  3361.   scene.setobserver(0,0,-200)
  3362.   scene.setafterscale(200,200)
  3363.  
  3364.  
  3365.   scr:=OpenScreenTagList(NIL,[SA_TOP,0,
  3366.                               SA_LEFT,0,
  3367.                               SA_WIDTH,320,
  3368.                               SA_HEIGHT,256,
  3369.                               SA_DEPTH,3,
  3370.                               SA_TITLE,'Routines3D',
  3371.                               SA_SHOWTITLE,FALSE,
  3372.                               0,0])
  3373.   IF scr=NIL THEN Raise("SCR")
  3374.   vp:=scr.viewport
  3375.   ri:=vp.rasinfo
  3376.   scrbm:=ri.bitmap
  3377.  
  3378.   SetRGB4(vp,3,15,0,0)
  3379.   SetRGB4(vp,4,0,15,0)
  3380.   SetRGB4(vp,5,0,0,15)
  3381.   SetRGB4(vp,7,12,12,0)
  3382.  
  3383.   NEW bm2.bitmapper()
  3384.   bm2.allocbitmap(320,256,3,TRUE)
  3385.   rp2:=bm2.rastport()
  3386.   bitmap2:=bm2.bitmap()
  3387.  
  3388.   win:=OpenWindowTagList(NIL,[WA_TOP,0,
  3389.                               WA_LEFT,0,
  3390.                               WA_WIDTH,320,
  3391.                               WA_HEIGHT,256,
  3392.                               WA_TITLE,'Routines3D',
  3393.                               WA_FLAGS,WFLG_ACTIVATE OR WFLG_SMART_REFRESH OR WFLG_BACKDROP OR WFLG_BORDERLESS,
  3394.                               WA_IDCMP,IDCMP_RAWKEY,
  3395.                               WA_CUSTOMSCREEN,scr,
  3396.                               0,0])
  3397.   IF win=NIL THEN Raise("WIN")
  3398.   rp:=win.rport
  3399.   port:=win.userport
  3400.  
  3401.   oox:=0 ; ooy:=0 ; ooz:=-200
  3402.   rrx:=0 ; rry:=0 ; rrz:=0
  3403.  
  3404.   scene.projection()
  3405.   scene.drawfill(rp)
  3406.   usebm:=1-usebm
  3407.  
  3408.   LOOP
  3409.     Wait(Shl(1,port.sigbit))
  3410.     REPEAT
  3411.       IF (msg:=GetMsg(port))<>NIL
  3412.         class:=msg.class
  3413.         code:=msg.code
  3414.         ReplyMsg(msg)
  3415.         SELECT class
  3416.           CASE IDCMP_RAWKEY
  3417.             SELECT code
  3418.               CASE $4C -> up arrow
  3419.                 ooy:=ooy+1
  3420.                 scene.setobserver(oox,ooy,ooz)
  3421.               CASE $4D -> down arrow
  3422.                 ooy:=ooy-1
  3423.                 scene.setobserver(oox,ooy,ooz)
  3424.               CASE $4E -> right arrow
  3425.                 oox:=oox+1
  3426.                 scene.setobserver(oox,ooy,ooz)
  3427.               CASE $4F -> left arrow
  3428.                 oox:=oox-1
  3429.                 scene.setobserver(oox,ooy,ooz)
  3430.               CASE $46 -> del
  3431.                 ooz:=ooz-1
  3432.                 scene.setobserver(oox,ooy,ooz)
  3433.               CASE $5F -> help
  3434.                 ooz:=ooz+1
  3435.                 scene.setobserver(oox,ooy,ooz)
  3436.               CASE $10 -> q
  3437.                 rrx:=rrx-1
  3438.                 scene.setrot(rrx,rry,rrz)
  3439.               CASE $11 -> w
  3440.                 rrx:=rrx+1
  3441.                 scene.setrot(rrx,rry,rrz)
  3442.               CASE $20 -> a
  3443.                 rry:=rry-1
  3444.                 scene.setrot(rrx,rry,rrz)
  3445.               CASE $21 -> s
  3446.                 rry:=rry+1
  3447.                 scene.setrot(rrx,rry,rrz)
  3448.               CASE $31 -> z
  3449.                 rrz:=rrz-1
  3450.                 scene.setrot(rrx,rry,rrz)
  3451.               CASE $32 -> x
  3452.                 rrz:=rrz+1
  3453.                 scene.setrot(rrx,rry,rrz)
  3454.               CASE $40 -> space
  3455.                 oox:=0 ; ooy:=0 ; ooz:=-200
  3456.                 rrx:=0 ; rry:=0 ; rrz:=0
  3457.                 scene.setobserver(oox,ooy,ooz)
  3458.                 scene.setrot(rrx,rry,rrz)
  3459.               CASE $45 -> esc
  3460.                 REPEAT
  3461.                   IF (msg:=GetMsg(port))<>NIL THEN ReplyMsg(msg)
  3462.                 UNTIL msg=NIL
  3463.                 Raise("end")
  3464.               CASE $22 -> d
  3465.                 ->scene.delsurface('cube',4)
  3466.                 ->scene.setsurface('cube',3,[3,2,6],5)
  3467.                 ->scene.setscale(100,50,100)
  3468.                 ->scene.settrasl(100,0,0)
  3469.             ENDSELECT
  3470.         ENDSELECT
  3471.       ENDIF
  3472.     UNTIL msg=NIL
  3473.     scene.projection()
  3474.     SetAPen(IF usebm=0 THEN rp ELSE rp2, 0)
  3475.     RectFill(IF usebm=0 THEN rp ELSE rp2, 0,0,320,256)
  3476.     scene.drawfill(IF usebm=0 THEN rp ELSE rp2)
  3477.  
  3478.     IF usebm=0          -> double buffering a mano (in uno schermo)
  3479.       ri.bitmap:=scrbm
  3480.     ELSE
  3481.       ri.bitmap:=bitmap2
  3482.     ENDIF
  3483.     WaitTOF()
  3484.     ScrollVPort(vp)
  3485.     usebm:=1-usebm
  3486.   ENDLOOP
  3487.  
  3488. EXCEPT DO
  3489.   IF win THEN CloseWindow(win)
  3490.   IF scr
  3491.     ri.bitmap:=scrbm
  3492.     CloseScreen(scr)
  3493.   ENDIF
  3494.   IF scene THEN END scene
  3495.   IF bm2 THEN END bm2
  3496.   describe3DException()
  3497.   CleanUp(0)
  3498. ENDPROC
  3499. #endif
  3500.  
  3501.