home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume38 / tessel / part01 < prev    next >
Encoding:
Text File  |  1993-06-19  |  52.6 KB  |  1,245 lines

  1. Newsgroups: comp.sources.misc
  2. From: michaelr@spider.co.uk ("Michael S. A. Robb")
  3. Subject: v38i017:  tessel - Polygon shading and rendering using triangular tesselation., Part01/02
  4. Message-ID: <csm-v38i017=tessel.184654@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: a125d5fff831b3074e1444105730413d
  6. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sun, 20 Jun 1993 23:48:23 GMT
  9. Approved: kent@sparky.imd.sterling.com
  10.  
  11. Submitted-by: michaelr@spider.co.uk ("Michael S. A. Robb")
  12. Posting-number: Volume 38, Issue 17
  13. Archive-name: tessel/part01
  14. Environment: IBM PC with Hercules Graphics Station Card, Borland C
  15.  
  16. This is version 1.4 of TESSEL. with is source code to demonstrate polygon
  17. tesselation and smooth shading in 24-bit colour for the Hercules Graphics
  18. Station Card.
  19.  
  20.  About the software
  21.  ------------------
  22.  
  23. This software has been designed to be compiled using Borland C 6.0 in the
  24. "Medium" model. In its current form, it will only execute properly with a
  25. Hercules Graphics Station Card. Porting it to use other 24-bit graphics
  26. cards should not be difficult (then again I have not programmed any other 
  27. 24-bit graphics cards). No TIGA command driver or on-board RAM is required.
  28.  
  29.  Distribution policy
  30.  -------------------
  31.  
  32. This is public domain software. You may use it, modify it or distribute it in
  33. any way you like. No liability is accepted. See warning above.
  34.  
  35. Michael S. A. Robb (michaelr@spider.co.uk)
  36. --------------------------------------------------------------------------
  37. #! /bin/sh
  38. # This is a shell archive.  Remove anything before this line, then feed it
  39. # into a shell via "sh file" or similar.  To overwrite existing files,
  40. # type "sh file -c".
  41. # Contents:  build.bat colours.h hardware.h tessel.c tmsmodes.h
  42. #   triangle.c
  43. # Wrapped by kent@sparky on Sun Jun 20 18:34:47 1993
  44. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  45. echo If this archive is complete, you will see the following message:
  46. echo '          "shar: End of archive 1 (of 2)."'
  47. if test -f 'build.bat' -a "${1}" != "-c" ; then 
  48.   echo shar: Will not clobber existing file \"'build.bat'\"
  49. else
  50.   echo shar: Extracting \"'build.bat'\" \(44 characters\)
  51.   sed "s/^X//" >'build.bat' <<'END_OF_FILE'
  52. Xbcc tessel.c tmsmodes.c triangle.c main.c 
  53. X
  54. END_OF_FILE
  55.   if test 44 -ne `wc -c <'build.bat'`; then
  56.     echo shar: \"'build.bat'\" unpacked with wrong size!
  57.   fi
  58.   # end of 'build.bat'
  59. fi
  60. if test -f 'colours.h' -a "${1}" != "-c" ; then 
  61.   echo shar: Will not clobber existing file \"'colours.h'\"
  62. else
  63.   echo shar: Extracting \"'colours.h'\" \(4210 characters\)
  64.   sed "s/^X//" >'colours.h' <<'END_OF_FILE'
  65. X/*
  66. X *+-----------------------------------------------------------------------+
  67. X *| This header file contains definitions for 32-bit colour pixels and    |
  68. X *| Z-buffer.                                                             |
  69. X *|                                                                       |
  70. X *| Author: Michael S. A. Robb         Version: 1.2        Date: 16/06/93 |
  71. X *+-----------------------------------------------------------------------+
  72. X */
  73. X
  74. Xtypedef unsigned long ADDRESS; /* 32-bit memory address.   */
  75. Xtypedef unsigned int  WORD;    /* 16-bit data.             */
  76. Xtypedef unsigned char BYTE;    /*  8-bit data.             */
  77. Xtypedef unsigned long LONG;    /* 32-bit unsigned integer. */
  78. X
  79. X/*
  80. X *+-----------------------------------------------------------------------+
  81. X *| The following data structure is used to represent a 32-bit Z-buffer   |
  82. X *| value.                                                                |
  83. X *+-----------------------------------------------------------------------+
  84. X */
  85. X
  86. Xtypedef struct zbufferhl_st
  87. X  {
  88. X  WORD zbuf_lo;
  89. X  WORD zbuf_hi;
  90. X  } ZBUFFER_HL;
  91. X
  92. Xtypedef union zbuffer_st
  93. X  {
  94. X  long       zbuf_value;       /* Used for calculations.             */
  95. X  ZBUFFER_HL zbuf_hilo;        /* Used for read/writing TIGA memory. */
  96. X  } ZBUFFER;
  97. X
  98. X#define ZBUFFER_MAX 0x7FFFFFFFL
  99. X
  100. X#define MAX_BLEND   255        /* Maximum blend value         */
  101. X#define PIXEL_SIZE   32        /* 1 pixel = 32 bits           */
  102. X#define ZBUFFER_SIZE 32        /* 1 Z-buffer entry = 32 bits. */
  103. X
  104. X/*+-----------------------------------------------------------------------+
  105. X *| Hercules Video RAM is located at location 0x00000000 and is 1 Mbyte   |
  106. X *| in size. However, the TMS34010 addresses memory using bit addresses.  |
  107. X *| So in fact, the end of video RAM is at location 0x800000.             |
  108. X *|                                                                       |
  109. X *| Since each pixel is 32-bits in length, this makes it possible for the |
  110. X *| graphics board to have two 512x256x32 bit screens. Alternatively, the |
  111. X *| second screen can be used as a 32-bit Z-buffer. If the optional 2     |
  112. X *| Mbytes of DRAM is present, this allows the use of two screens with    |
  113. X *| 512x256x32 resolution, both of which have Z-buffers.                  |
  114. X *+-----------------------------------------------------------------------+
  115. X */
  116. X
  117. X#define OFFSET_VRAM             0x0L           /* Start of VRAM       */
  118. X#define OFFSET_ZBUFFER          0x400000L      /* Second half of VRAM */
  119. X
  120. X/*+-----------------------------------------------------------------------+
  121. X *| Useful macros for converting XY addresses to linear offsets.          |
  122. X *+-----------------------------------------------------------------------+
  123. X */
  124. X
  125. X#define ADDRESS_PIXEL(X,Y)\
  126. X  (( (ADDRESS)(X)+(ADDRESS)(Y)*screen_width)*PIXEL_SIZE+OFFSET_VRAM)
  127. X
  128. X#define ADDRESS_ZBUFFER(X,Y)\
  129. X  (( (ADDRESS)(X)+(ADDRESS)(Y+256)*screen_width)*PIXEL_SIZE+OFFSET_ZBUFFER)
  130. X
  131. X/*+-----------------------------------------------------------------------+
  132. X *| The following data structure is used to represent a 32-bit colour     |
  133. X *| pixel plus an 8-bit overlay.                                          |
  134. X *+-----------------------------------------------------------------------+
  135. X */
  136. X
  137. Xtypedef struct rgb32_st
  138. X  {
  139. X  BYTE  col_blue;              /* Amount of BLUE.    */
  140. X  BYTE  col_overlay;           /* Amount of OVERLAY. */
  141. X  BYTE  col_green;             /* Amount of GREEN.   */
  142. X  BYTE  col_red;               /* Amount of RED.     */
  143. X  } RGB32;
  144. X
  145. Xtypedef struct rgb32hl_st
  146. X  {
  147. X  WORD  col_lo;                /* Low 16 bits  */
  148. X  WORD  col_hi;                /* High 16 bits */
  149. X  } RGB32_HL;
  150. X
  151. X/*+-----------------------------------------------------------------------+
  152. X *| The following data structure is used to represent a 32-bit colour     |
  153. X *| pixel as well as permitting Boolean operations such as AND, OR & NOT. |
  154. X *+-----------------------------------------------------------------------+
  155. X */
  156. X
  157. Xtypedef union colour32
  158. X  {
  159. X  RGB32    col_rgb;            /* Structured representation. */
  160. X  RGB32_HL col_hilo;           /* Integer    representation. */
  161. X  ADDRESS  col_value;          /* Integer    representation. */
  162. X  } COLOUR32;
  163. X
  164. X
  165. END_OF_FILE
  166.   if test 4210 -ne `wc -c <'colours.h'`; then
  167.     echo shar: \"'colours.h'\" unpacked with wrong size!
  168.   fi
  169.   # end of 'colours.h'
  170. fi
  171. if test -f 'hardware.h' -a "${1}" != "-c" ; then 
  172.   echo shar: Will not clobber existing file \"'hardware.h'\"
  173. else
  174.   echo shar: Extracting \"'hardware.h'\" \(13583 characters\)
  175.   sed "s/^X//" >'hardware.h' <<'END_OF_FILE'
  176. X/*+-----------------------------------------------------------------------+
  177. X *| The following table defines the internal I/O registers contained      |
  178. X *| within the TMS34010 microprocessor.                                   |
  179. X *|                                                                       |
  180. X *| Author: Michael S. A. Robb         Version: 1.1        Date: 16/06/93 |
  181. X *+-----------------------------------------------------------------------+
  182. X */
  183. X
  184. X#define IO_HESYNC      0xC0000000L     /* Horizontal End     Sync  */
  185. X#define IO_HEBLNK      0xC0000010L     /* Horizontal End     Blank */
  186. X#define IO_HSBLNK      0xC0000020L     /* Horizontal Start   Blank */
  187. X#define IO_HTOTAL      0xC0000030L     /* Horizontal Total         */
  188. X#define IO_VESYNC      0xC0000040L     /* Vertical   End     Sync  */
  189. X#define IO_VEBLNK      0xC0000050L     /* Vertical   End     Blank */
  190. X#define IO_VSBLNK      0xC0000060L     /* Vertical   Start   Blank */
  191. X#define IO_VTOTAL      0xC0000070L     /* Video      Total         */
  192. X#define IO_DPYCTL      0xC0000080L     /* Display    Control       */
  193. X#define IO_DPYSTRT     0xC0000090L     /* Display    Start         */
  194. X#define IO_DPYINT      0xC00000A0L     /* Display    Interrupt     */
  195. X#define IO_CONTROL     0xC00000B0L     /* Control                  */
  196. X#define IO_HSTDATA     0xC00000C0L     /* Host       Data          */
  197. X#define IO_HSTADRL     0xC00000D0L     /* Host       Address Low   */
  198. X#define IO_HSTADRH     0xC00000E0L     /* Host       Address High  */
  199. X#define IO_HSTCTLL     0xC00000F0L     /* Host       Control Low   */
  200. X#define IO_HSTCTLH     0xC0000100L     /* Host       Control High  */
  201. X#define IO_INTENB      0xC0000110L     /* Interrupt  Enable        */
  202. X#define IO_INTPEND     0xC0000120L     /* Interrupt  Pending       */
  203. X#define IO_CONVSP      0xC0000130L     /* Conversion (Src. Pitch)  */
  204. X#define IO_CONVDP      0xC0000140L     /* Conversion (Dst. Pitch)  */
  205. X#define IO_PSIZE       0xC0000150L     /* Pixel      Size          */
  206. X#define IO_PMASK       0xC0000160L     /* Plane      Mask          */
  207. X#define IO_RESERVED1   0xC0000170L     /* Reserved                 */
  208. X#define IO_RESERVED2   0xC0000180L     /* Reserved                 */
  209. X#define IO_RESERVED3   0xC0000190L     /* Reserved                 */
  210. X#define IO_RESERVED4   0xC00001A0L     /* Reserved                 */
  211. X#define IO_DPYTAP      0xC00001B0L     /* Display    Tap Point     */
  212. X#define IO_HCOUNT      0xC00001C0L     /* Horizontal Count         */
  213. X#define IO_VCOUNT      0xC00001D0L     /* Vertical   Count         */
  214. X#define IO_DPYADR      0xC00001E0L     /* Display    Address       */
  215. X#define IO_REFCNT      0xC00001F0L     /* DRAM       Refresh Count */
  216. X
  217. X/*+-----------------------------------------------------------------------+
  218. X *| The following table defines other external I/O registers accessible   |
  219. X *| via the TMS34010 microprocessor bus.                                  |
  220. X *+-----------------------------------------------------------------------+
  221. X */
  222. X
  223. X#define RAMDAC_WRITE   0x06000000L     /* Write address for data.  */
  224. X#define RAMDAC_DATA    0x06000010L     /* Data address.            */
  225. X#define RAMDAC_COMMAND 0x06000020L     /* Command address.         */
  226. X#define RAMDAC_READ    0x06000030L     /* Read address for data.   */
  227. X
  228. X/*+-----------------------------------------------------------------------+
  229. X *| The following constants define the read and write addresses for the   |
  230. X *| CONFIGURATION 1 REGISTER.                                             |
  231. X *|                                                                       |
  232. X *|  15 14 13 12 11 10  9  8  7  6  5  4   3  2  1  0                     |
  233. X *| +-----------------------------------+---+--------+                    |
  234. X *| |  RESERVED                         |RS2|  VCLK  |                    |
  235. X *| +-----------------------------------+---+--------+                    |
  236. X *|                                                                       |
  237. X *| Bits 0-2  - Selects the clock frequency for the screen refresh.       |
  238. X *|             See CLOCK_ENUM.                                           |
  239. X *|                                                                       |
  240. X *| Bit    3  - Controls access to overlay and command access.            |
  241. X *|             See ACCESS_ENUM.                                          |
  242. X *|                                                                       |
  243. X *| Bits 4-15 - Not Used.                                                 |
  244. X *+-----------------------------------------------------------------------+
  245. X */
  246. X
  247. X#define CONFIG1_WRITE  0x060000C0L     /* External timing write.   */
  248. X#define CONFIG1_READ   0x060001C0L     /* Default configuration.   */
  249. X
  250. X/*+-----------------------------------------------------------------------+
  251. X *| The following constants define the read and write addresses for the   |
  252. X *| CONFIGURATION 2 REGISTER.                                             |
  253. X *|                                                                       |
  254. X *|  15 14 13 12 11 10  9  8  7  6  5    4     3    2  1  0               |
  255. X *| +--------------------------------+----+-----+-----+----+              |
  256. X *| |  RESERVED                      |HINT|VSYNC|HSYNC|PSEL|              |
  257. X *| +--------------------------------+----+-----+-----+----+              |
  258. X *|                                                                       |
  259. X *| Bits 0-1  - 00 = VGA Control Video RAM                                |
  260. X *|             01 = 32 bits per pixel                                    |
  261. X *|             10 = 16 bits per pixel                                    |
  262. X *|             11 =  8 bits per pixel                                    |
  263. X *|                                                                       |
  264. X *| Bit    2  - Horizontal sync: 0 = Positive, 1 = Negative.              |
  265. X *|                                                                       |
  266. X *| Bit    3  - Vertical   sync: 0 = Positive, 1 = Negative.              |
  267. X *|                                                                       |
  268. X *| Bit    4  - Host interrupts: 0 = Disabled, 1 = Enabled.               |
  269. X *|                                                                       |
  270. X *| Bits 5-15 - Not used.                                                 |
  271. X *+-----------------------------------------------------------------------+
  272. X */
  273. X
  274. X#define CONFIG2_WRITE  0x060000E0L     /* Display Pitch.           */
  275. X#define CONFIG2_READ   0x060001E0L
  276. X
  277. X/*+-----------------------------------------------------------------------+
  278. X *| The following table defines the TMS34010 registers which may be       |
  279. X *| accessed via the main CPU's data bus ie. the 80x86.                   |
  280. X *+-----------------------------------------------------------------------+
  281. X */
  282. X
  283. X#define CPU_ADDRLO     0xC0007E00L     /* Host Address Low  Word   */
  284. X#define CPU_ADDRHI     0xC0007F00L     /* Host Address High Word   */
  285. X#define CPU_CONTROL    0xC0007D00L     /* Host Control             */
  286. X#define CPU_SLOWDATA   0xC0007000L     /* Host Data Registers      */
  287. X#define CPU_FASTDATA   0xA0000000L     /* Host Data Registers      */
  288. X
  289. X#define HOST_AUTOINCR       0xD800     /* Automatic increments.    */
  290. X#define HOST_NOINCR         0xC000     /* No increments.           */
  291. X
  292. X/*+-----------------------------------------------------------------------+
  293. X *| The following constants define the various clock speeds that may be   |
  294. X *| used to drive the video monitor.                                      |
  295. X *|                                                                       |
  296. X *| Stored in the 'tms_clockbase' field of the TMS34010_MODE structure.   |
  297. X *+-----------------------------------------------------------------------+
  298. X */
  299. X
  300. X#define CLOCK_14280MHZ      0x00       /* 14.280MHz ???  pixels ?? */
  301. X#define CLOCK_20000MHZ      0x01       /* 20.000MHz 512  pixels 24 */
  302. X#define CLOCK_VGA           0x02       /* Current VGA Clock        */
  303. X#define CLOCK_36000MHZ      0x03       /* 36.000MHz 800  pixels  8 */
  304. X#define CLOCK_44900MHZ      0x04       /* 44.900MHz 1024 pixels I8 */
  305. X#define CLOCK_64000MHZ      0x05       /* 64.000MHz 1024 pixels U8 */
  306. X#define CLOCK_25175MHZ      0x06       /* 25.175MHz 640  pixels 16 */
  307. X#define CLOCK_50350MHZ      0x07       /* 50.350MHz 640  pixels  8 */
  308. X
  309. X/*+-----------------------------------------------------------------------+
  310. X *| The following constants define the format of the current video mode.  |
  311. X *+-----------------------------------------------------------------------+
  312. X */
  313. X
  314. X#define VSCAN_INTERLACED    0x00       /* Interlaced scan.         */
  315. X#define VSCAN_UNINTERLACED  0x0C       /* Uninterlaced scan.       */
  316. X
  317. X/*+-----------------------------------------------------------------------+
  318. X *| The following constants are used to select the size of pixels in the  |
  319. X *| current video mode.                                                   |
  320. X *+-----------------------------------------------------------------------+
  321. X */
  322. X
  323. X#define PIXEL_SIZE8         0x03       /* Pixel depth -  8 bits.   */
  324. X#define PIXEL_SIZE16        0x02       /* Pixel depth - 16 bits.   */
  325. X#define PIXEL_SIZE32        0x01       /* Pixel depth - 32 bits.   */
  326. X
  327. X/*+-----------------------------------------------------------------------+
  328. X *| The following constants are used to select the format of the overlay  |
  329. X *| option.                                                               |
  330. X *+-----------------------------------------------------------------------+
  331. X */
  332. X
  333. X#define OVERLAY_4BITS       0x00       /* 4-bit overlay.           */
  334. X#define OVERLAY_1BIT        0x02       /* 1-bit overlay.           */
  335. X#define OVERLAY_NONE        0x03       /* No    overlay.           */
  336. X
  337. X/*+-----------------------------------------------------------------------+
  338. X *| The following bit-masks are used with the Display Control register    |
  339. X *| DPYCTL.                                                               |
  340. X *+-----------------------------------------------------------------------+
  341. X */
  342. X
  343. X#define HC_ENV              0x8000     /* Enable video.               */
  344. X#define HC_NIL              0x4000     /* Noninterlaced video enable. */
  345. X#define HC_DXV              0x2000     /* Disable external video.     */
  346. X#define HC_SRE              0x1000     /* Screen refresh enable.      */
  347. X#define HC_SRT              0x0800     /* Shift register enable.      */
  348. X#define HC_ORG              0x0400     /* Screen origin select.       */
  349. X#define HC_HSD              0x0001     /* Horizontal sync direction.  */
  350. X
  351. X/*+-----------------------------------------------------------------------+
  352. X *| These values are used to select the display pitch for the VRAM shift  |
  353. X *| registers.                                                            |
  354. X *+-----------------------------------------------------------------------+
  355. X */
  356. X
  357. X#define HC_DUDATE0          0x0000     /* Number of bytes per line.   */
  358. X#define HC_DUDATE1          0x0004
  359. X#define HC_DUDATE2          0x0008
  360. X#define HC_DUDATE4          0x0010     /*  512 bytes per line.        */
  361. X#define HC_DUDATE8          0x0020     /* 1024 bytes per line.        */
  362. X#define HC_DUDATE16         0x0040     /* 2048 bytes per line.        */
  363. X#define HC_DUDATE32         0x0080
  364. X#define HC_DUDATE64         0x0100
  365. X#define HC_DUDATE128        0x0200
  366. X
  367. X/*+-----------------------------------------------------------------------+
  368. X *| These values are specific to the Hercules Graphics Station Card.      |
  369. X *+-----------------------------------------------------------------------+
  370. X */
  371. X
  372. X#define MODE_UNINTERLACED    (HC_ENV|HC_DXV|HC_SRE|HC_NIL)
  373. X#define MODE_INTERLACED      (HC_ENV|HC_DXV|HC_SRE)
  374. X#define MODE_4KBYTE           HC_DUDATE32
  375. X#define MODE_2KBYTE           HC_DUDATE16
  376. X#define MODE_1KBYTE           HC_DUDATE8
  377. X#define MODE_512BYTES         HC_DUDATE4
  378. X
  379. X/*+-----------------------------------------------------------------------+
  380. X *| The following table shows the organisation of the CLUT control bits.  |
  381. X *|                                                                       |
  382. X *|                 Bits 3-2                                              |
  383. X *|                                                                       |
  384. X *|                        00            01          10         11        |
  385. X *|                  00    24/LU         24/NLU      NA         NA        |
  386. X *|  Bits 7-6        01    24/LU         24/NLU      8G/LU      8G/NLU    |
  387. X *|                  10    24/LU         24/NLU      NA         NA        |
  388. X *|                  11    NA            NA          NA         16/NLU    |
  389. X *|                                                                       |
  390. X *+-----------------------------------------------------------------------+
  391. X */
  392. X
  393. X/*+-----------------------------------------------------------------------+
  394. X *| The following constants are for use with the BrookTree 473 palette    |
  395. X *| chip.                                                                 |
  396. X *+-----------------------------------------------------------------------+
  397. X */
  398. X
  399. X#define MODE_24BIT_NOCLUT       0x34        /* 00xx01xx */
  400. X#define MODE_24BIT_CLUT         0x10        /* 00xx00xx */
  401. X#define MODE_16BIT              0xDC        /* 11xx11xx */
  402. X#define MODE_8BIT_NOCLUT        0x5C        /* 01xx11xx */
  403. X#define MODE_8BIT_CLUT          0x58        /* 01xx10xx */
  404. X
  405. X#define DEFAULT_8BIT            (MODE_8BIT_CLUT    | OVERLAY_NONE)
  406. X#define DEFAULT_16BIT           (MODE_16BIT        | OVERLAY_NONE)
  407. X#define DEFAULT_24BIT           (MODE_24BIT_NOCLUT | OVERLAY_NONE)
  408. X
  409. END_OF_FILE
  410.   if test 13583 -ne `wc -c <'hardware.h'`; then
  411.     echo shar: \"'hardware.h'\" unpacked with wrong size!
  412.   fi
  413.   # end of 'hardware.h'
  414. fi
  415. if test -f 'tessel.c' -a "${1}" != "-c" ; then 
  416.   echo shar: Will not clobber existing file \"'tessel.c'\"
  417. else
  418.   echo shar: Extracting \"'tessel.c'\" \(12347 characters\)
  419.   sed "s/^X//" >'tessel.c' <<'END_OF_FILE'
  420. X/*+-----------------------------------------------------------------------+
  421. X *| This file contains subroutines used to tesselate convex and concave   |
  422. X *| N-point polygons into triangles. At present, it does not handle       |
  423. X *| complex polygons.                                                     |
  424. X *|                                                                       |
  425. X *| Author: Michael S. A. Robb         Version: 1.1        Date: 29/05/93 |
  426. X *+-----------------------------------------------------------------------+
  427. X */
  428. X
  429. X#include <stdio.h>
  430. X#include <stdlib.h>
  431. X
  432. X#include "triangle.h"
  433. X#include "tessel.h"
  434. X
  435. X/*
  436. X *+-----------------------------------------------------------------------+
  437. X *| These global variables are used to reference the polygon vertex list. |
  438. X *+-----------------------------------------------------------------------+
  439. X */
  440. X
  441. Xvoid (*polygon_proc)( COORD *triangle );    /* User defined function.    */
  442. X
  443. X/*                                                                                                    
  444. X *+-----------------------------------------------------------------------+
  445. X *| This subroutine is used to set the user-defined procedure called to   |
  446. X *| render a triangle.                                                    |
  447. X *+-----------------------------------------------------------------------+
  448. X */
  449. X
  450. Xvoid polygon_setproc( proc )
  451. X  void (*proc)();
  452. X  {
  453. X  polygon_proc = proc;                    /* Set the polygon procedure.  */
  454. X  }
  455. X
  456. X/*
  457. X *+-----------------------------------------------------------------------+
  458. X *| This subroutine is used to reverse the coordinates in the polygon     |
  459. X *| vertex list. Used to handle anti-clockwise ordering of vertices.      |
  460. X *+-----------------------------------------------------------------------+
  461. X */
  462. X
  463. Xvoid polygon_reverse( nverts, vlist )
  464. X  int nverts;
  465. X  COORD *vlist;
  466. X  {
  467. X  COORD temp;                             /* Used for copying.           */
  468. X  int   from = 0, to = nverts;            /* Start and finish of list.   */
  469. X
  470. X  while ( ++from < --to )                 /* Swap until both ends meet.  */
  471. X    {
  472. X    temp        = vlist[from];
  473. X    vlist[from] = vlist[to];
  474. X    vlist[to]   = temp;
  475. X    }
  476. X  }
  477. X
  478. X/*
  479. X *+------------------------------------------------------------------------+
  480. X *| This suboutine is used to determine the intersection between the line  |
  481. X *| vectors from P1 to P2 and P3 to P4. A result of TRUE is returned if    |
  482. X *| the two vectors intersect within the end-points, and <point> is filled |
  483. X *| with the point of intersection. Otherwise, a result of FALSE occurs.   |
  484. X *+------------------------------------------------------------------------+
  485. X */
  486. X
  487. Xint coord_intersection( point, p1, p2, p3, p4 )
  488. X  COORD *point,
  489. X        *p1, *p2,
  490. X        *p3, *p4;
  491. X  {
  492. X  MATDATA val_det, val_t, val_s;           /* Determinants of matrices.  */
  493. X
  494. X  val_det = MATRIX_DET_2X2( *p1, *p2, *p3, *p4 );
  495. X
  496. X  if ( val_det != 0 )                      /* Intersection point exists? */
  497. X    {
  498. X    val_t = MATRIX_DET_2X2( *p1, *p3, *p3, *p4 )
  499. X          * CONSTANT_ONE / val_det;
  500. X
  501. X    val_s = MATRIX_DET_2X2( *p1, *p2, *p3, *p1 )
  502. X          * CONSTANT_ONE / val_det;
  503. X
  504. X    if ( val_t <= 0L && val_s >= CONSTANT_ONE || /* Within range of edge */
  505. X         val_s <= 0L && val_t >= CONSTANT_ONE )  /* segments?            */
  506. X      /* Do nothing */
  507. X      {}
  508. X    else
  509. X    if ( val_t >= 0 && val_t <= CONSTANT_ONE && /* Are results within    */
  510. X         val_s >= 0 && val_s <= CONSTANT_ONE )  /* bounds of the two     */
  511. X      {                                         /* edges?                */
  512. X
  513. X      point -> c_xpos                           /* Calculate X coordinate. */
  514. X          = p1 -> c_xpos
  515. X          + (int)( val_t * ( p2 -> c_xpos - p1 -> c_xpos ) / CONSTANT_ONE );
  516. X
  517. X      point -> c_ypos                           /* Calculate Y coordinate. */
  518. X          = p1 -> c_ypos
  519. X          + (int)( val_t * ( p2 -> c_ypos - p1 -> c_ypos ) / CONSTANT_ONE );
  520. X
  521. X      return( 1 );
  522. X      }
  523. X    }
  524. X
  525. X  return( 0 );
  526. X  }
  527. X
  528. X/*
  529. X *+-----------------------------------------------------------------------+
  530. X *| This subroutine is used to determine whether the given polygon is     |
  531. X *| bow-tied or not (has edges which cross over ie. bow-tie). A result of |
  532. X *| TRUE is returned if the polygon is bow-tied. Otherwise, a result of   |
  533. X *| FALSE is returned.                                                    |
  534. X *+-----------------------------------------------------------------------+
  535. X */
  536. X
  537. Xint polygon_complex( nverts, vertlist )
  538. X  int    nverts;
  539. X  COORD *vertlist;
  540. X  {
  541. X  int          m, n, i, j;                  /* Loop counters             */
  542. X  static COORD point;                       /* Point of intersection.    */
  543. X
  544. X  if ( nverts <= 3 )                        /* Triangles can never be    */
  545. X    return( 0 );                            /* bow-tied.                 */
  546. X
  547. X  for ( m = 0, n = 1; n < nverts; m++, n++) /* First edge segment.       */
  548. X    for ( i = n; i < nverts; i++ )          /* Second edge segment.      */
  549. X      {
  550. X      j = ( i+1 == nverts ? 0 : i+1 );
  551. X
  552. X      if ( coord_intersection( &point,      /* Check for intersection of */
  553. X             vertlist+m, vertlist+n,        /* edges.                    */
  554. X             vertlist+i, vertlist+j ) )
  555. X        return( 1 );                        /* Intersection exists, so   */
  556. X      }                                     /* the polygon is bow-tied.  */
  557. X
  558. X  return( 0 );                              /* Polygon is not bow-tied.  */
  559. X  }
  560. X
  561. X/*
  562. X *+-----------------------------------------------------------------------+
  563. X *| This subroutine is used to determine whether the vertices of the      |
  564. X *| polygon are ordered clockwise or anticlockwise. A result of TRUE is   |
  565. X *| returned for clockwise polygons. A result of FALSE is returned for    |
  566. X *| anticlockwise polygons.                                               |
  567. X *+-----------------------------------------------------------------------+
  568. X */
  569. X
  570. Xint polygon_clockwise( nverts, vlist )
  571. X  int    nverts;
  572. X  COORD *vlist;
  573. X  {
  574. X  int  n, p, q = 0, r;                      /* Vertex indices/counters.  */
  575. X  MATDATA lowx_val = vlist[0].c_xpos;       /* Used for X coord. checks. */
  576. X  MATDATA lowy_val = vlist[0].c_ypos;       /* Used for Y coord. checks. */
  577. X
  578. X  for ( n = 1; n < nverts; n++ )            /* For each vertex.          */
  579. X    if ( vlist[n].c_xpos < lowx_val )       /* Vertex has lower X coord? */
  580. X      {
  581. X      q        = n;                         /* Yes, so set index and     */
  582. X      lowx_val = vlist[n].c_xpos;           /* the best X coordinate.    */
  583. X      lowy_val = vlist[n].c_ypos;
  584. X      }
  585. X    else
  586. X      if (vlist[n].c_xpos == lowx_val &&    /* No, but is X coord. equal */
  587. X          vlist[n].c_ypos  < lowy_val )     /* and Y coordinate lower?   */
  588. X        {
  589. X        q        = n;                       /* Yes, so set index and the */
  590. X        lowy_val = vlist[n].c_ypos;         /* best Y coordinate.        */
  591. X        }
  592. X
  593. X  p = ( q > 0        ? q-1 : nverts-1 );    /* Find index values of the  */
  594. X  r = ( q < nverts-1 ? q+1 : 0        );    /* adjacent vertices.        */
  595. X
  596. X  return( ANGLE_CONVEX( vlist, p, q, r ) ); /* Then return the result of */
  597. X  }                                         /* the convex angle test.    */
  598. X
  599. X/*
  600. X *+-----------------------------------------------------------------------+
  601. X *| This subroutine is used to determine whether the polygon is convex or |
  602. X *| not. It returns a Boolean value of TRUE for convex polygons. FALSE is |
  603. X *| returned for concave polygons.                                        |
  604. X *+-----------------------------------------------------------------------+
  605. X */
  606. X
  607. Xint polygon_convex( nverts, vlist )
  608. X  int    nverts;
  609. X  COORD *vlist;
  610. X  {
  611. X  int p = 0, q = 1, r = 2;                  /* Vertex indices/counters.  */
  612. X
  613. X  if ( nverts == 3 )                        /* Triangle is always convex */
  614. X    return( 1 );                            /* So return immediately.    */
  615. X
  616. X  for ( p = 0; p < nverts; p++ )            /* For each vertex.          */
  617. X    {
  618. X    if ( ANGLE_NONCONVEX( vlist, p, q, r) ) /* Is angle <= 90 degrees?   */
  619. X      return( 0 );                          /* Yes, polygon is concave.  */
  620. X
  621. X    q = ( ++q == nverts ? 0 : q );          /* Update second vertex.     */
  622. X    r = ( ++r == nverts ? 0 : r );          /* Update third vertex.      */
  623. X    }
  624. X                                                                                                
  625. X  return( 1 );                              /* Polygon is convex.        */
  626. X  }
  627. X
  628. X/* 
  629. X *+-----------------------------------------------------------------------+
  630. X *| This subroutine is used to render the polygon in the display buffer.  |
  631. X *+-----------------------------------------------------------------------+
  632. X */
  633. X
  634. Xvoid store_triangle( vlist, p, q, r )
  635. X  COORD *vlist;
  636. X  int p, q, r;
  637. X  {
  638. X  static COORD triangle_table[3];           /* Used to render triangle.  */
  639. X
  640. X  triangle_table[0] = vlist[p];             /* Copy the three vertices.  */
  641. X  triangle_table[1] = vlist[q];
  642. X  triangle_table[2] = vlist[r];
  643. X
  644. X  (*polygon_proc)( triangle_table );        /* Call the user process.    */
  645. X  }
  646. X
  647. X/*
  648. X *+-----------------------------------------------------------------------+
  649. X *| This subroutine is used to process simple (convex) polygons.          |
  650. X *+-----------------------------------------------------------------------+
  651. X */
  652. X
  653. Xvoid polygon_tesselate_convex( nverts, vlist )
  654. X  int    nverts;
  655. X  COORD *vlist;
  656. X  {
  657. X  int n, p = 0, q = 1, r = 2;               /* Vertex indices/counters.  */
  658. X
  659. X  for ( n = 0; n < nverts - 2; n++ )        /* For each vertex.          */
  660. X    {
  661. X    store_triangle( vlist, p, q, r );       /* Render triangle PQR.      */
  662. X
  663. X    q = ( q+1 == nverts ? 0 : q+1 );        /* P remains the same, but Q */
  664. X    r = ( r+1 == nverts ? 0 : r+1 );        /* and R are incremented.    */
  665. X    }
  666. X  }
  667. X
  668. X/*
  669. X *+-----------------------------------------------------------------------+
  670. X *| This subroutine is used to process complex (concave) polygons.        |
  671. X *+-----------------------------------------------------------------------+
  672. X */
  673. X
  674. X#define REMOVE_VERTEX( CL, I, N )\
  675. X  { int v; for ( v = (I); v < (N); v++ ) CL[v] = CL[v+1]; }
  676. X
  677. Xvoid polygon_tesselate_concave( n, cl )
  678. X  int    n;
  679. X  COORD *cl;
  680. X  {
  681. X  int h, i, j, k, m;
  682. X
  683. X  i = n-1;
  684. X
  685. X  while (n > 3 )
  686. X    {
  687. X    h = i;
  688. X    i = (i == n-1 ? 0 : i+1);
  689. X    j = (i == n-1 ? 0 : i+1);
  690. X
  691. X    if ( ANGLE_NONCONVEX( cl, h, i, j ) )
  692. X      continue;
  693. X
  694. X    k = (j == n-1 ? 0 : j+1);               /* k is vertex after j  */
  695. X    m = n-3;
  696. X
  697. X    while (m--)
  698. X      if ( COORD_OUTSIDE_TRIANGLE( cl, h, i, j, k ) )
  699. X        k = (k == n-1 ? 0 : k+1);
  700. X      else
  701. X        break;
  702. X
  703. X      if (k != h)                            /* Vertex k not outside */
  704. X        continue;                            /*   triangle PhPiPj    */
  705. X
  706. X    store_triangle( cl, h, i, j );
  707. X
  708. X    REMOVE_VERTEX( cl, i, n );
  709. X    n--;
  710. X    i = (i == 0 ? n-1 : i-1);
  711. X    }
  712. X
  713. X  store_triangle( cl, 0, 1, 2 );            /* Final triangle.      */
  714. X  }
  715. X
  716. X/*
  717. X *+-----------------------------------------------------------------------+
  718. X *| This subroutine is used to render non-complex polygons.               |
  719. X *+-----------------------------------------------------------------------+
  720. X */
  721. X
  722. Xvoid polygon_tesselate_noncomplex( num, vl )
  723. X  int    num;
  724. X  COORD *vl;
  725. X  {
  726. X  if ( !polygon_clockwise( num, vl ) )      
  727. X    polygon_reverse( num, vl );             
  728. X
  729. X  if ( polygon_convex( num, vl ) )          
  730. X    polygon_tesselate_convex( num, vl );    
  731. X  else                                      
  732. X    polygon_tesselate_concave( num, vl );   
  733. X  }                                         
  734. X
  735. X/*
  736. X *+-----------------------------------------------------------------------+
  737. X *| This subroutine is used to render complex polygons.                   |
  738. X *+-----------------------------------------------------------------------+
  739. X */
  740. X
  741. Xvoid polygon_tesselate_complex( num, vl )
  742. X  int    num;
  743. X  COORD *vl;
  744. X  {
  745. X  /* ... to be implemented in the near future ... */
  746. X  }
  747. X
  748. X/*
  749. X *+-----------------------------------------------------------------------+
  750. X *| This subroutine is used to render all types of polygon.               |
  751. X *+-----------------------------------------------------------------------+
  752. X */
  753. X
  754. Xvoid polygon_tesselate( num, vl )
  755. X  int    num;                               
  756. X  COORD *vl;                                
  757. X  {
  758. X  if ( polygon_complex( num, vl ) )         
  759. X    polygon_tesselate_complex( num, vl );   
  760. X  else
  761. X    polygon_tesselate_noncomplex( num, vl );
  762. X  }                                         
  763. END_OF_FILE
  764.   if test 12347 -ne `wc -c <'tessel.c'`; then
  765.     echo shar: \"'tessel.c'\" unpacked with wrong size!
  766.   fi
  767.   # end of 'tessel.c'
  768. fi
  769. if test -f 'tmsmodes.h' -a "${1}" != "-c" ; then 
  770.   echo shar: Will not clobber existing file \"'tmsmodes.h'\"
  771. else
  772.   echo shar: Extracting \"'tmsmodes.h'\" \(2737 characters\)
  773.   sed "s/^X//" >'tmsmodes.h' <<'END_OF_FILE'
  774. X/*+-----------------------------------------------------------------------+
  775. X *| This header file defines the data structure used to represent a       |
  776. X *| TMS34010 graphics mode.                                               |
  777. X *|                                                                       |
  778. X *| Author: Michael S. A. Robb         Version: 1.1        Date: 29/05/93 |
  779. X *+-----------------------------------------------------------------------+
  780. X */
  781. X
  782. X/*+-----------------------------------------------------------------------+
  783. X *| The following data structure is used to store the register settings   |
  784. X *| which define the state of a TMS34010 graphics mode.                   |
  785. X *+-----------------------------------------------------------------------+
  786. X */
  787. X
  788. Xtypedef struct tms34010_mode_st
  789. X  {
  790. X  char  tms_name[32];    /* Generic name for the video mode.         */
  791. X
  792. X  WORD  tms_hesync;      /* Left-hand  edge of left border.          */
  793. X  WORD  tms_heblnk;      /* Left-hand  edge of active display.       */
  794. X  WORD  tms_hsblnk;      /* Right-hand edge of active display.       */
  795. X  WORD  tms_htotal;      /* Right-hand edge of right border.         */
  796. X
  797. X  WORD  tms_vesync;      /* Top        edge of top border.           */
  798. X  WORD  tms_veblnk;      /* Top        edge of active display.       */
  799. X  WORD  tms_vsblnk;      /* Bottom     edge of active display.       */
  800. X  WORD  tms_vtotal;      /* Bottom     edge of bottom border.        */
  801. X
  802. X  WORD  tms_dpyctl;      /* Used to control video timing.            */
  803. X  WORD  tms_dpystrt;     /* Address of the first pixel displayed.    */
  804. X  WORD  tms_dpytap;      /* Horizontal panning offset.               */
  805. X
  806. X  WORD  tms_clockbase;   /* Clock frequency for horizontal timing.   */
  807. X  WORD  tms_pixelsize;   /* Size of pixels.                          */
  808. X  WORD  tms_videotiming; /* Interlaced mode / sync signals.          */
  809. X  WORD  tms_ramdac;      /* Used to select pixel size/overlay mode.  */
  810. X
  811. X  WORD  tms_xmax;        /* No. of pixels in horizontal axis.        */
  812. X  WORD  tms_ymax;        /* No. of pixels in vertical   axis.        */
  813. X  WORD  tms_psize;       /* No. of bits per pixel.                   */
  814. X  WORD  tms_dpitch;      /* Display pitch of each scan line in bits. */
  815. X  } TMS34010_MODE;
  816. X
  817. X/*+-----------------------------------------------------------------------+
  818. X *| The following data structures define the various screen modes.        |
  819. X *+-----------------------------------------------------------------------+
  820. X */
  821. X
  822. Xextern WORD   colourxmax;
  823. Xextern WORD   colourymax;
  824. X
  825. Xextern WORD   screen_width;
  826. Xextern WORD   screen_height;
  827. X
  828. Xextern TMS34010_MODE mode512x512x32bit;
  829. Xextern TMS34010_MODE mode512x256x32bit;
  830. Xextern TMS34010_MODE mode512x480x32bit;
  831. X
  832. X
  833. END_OF_FILE
  834.   if test 2737 -ne `wc -c <'tmsmodes.h'`; then
  835.     echo shar: \"'tmsmodes.h'\" unpacked with wrong size!
  836.   fi
  837.   # end of 'tmsmodes.h'
  838. fi
  839. if test -f 'triangle.c' -a "${1}" != "-c" ; then 
  840.   echo shar: Will not clobber existing file \"'triangle.c'\"
  841. else
  842.   echo shar: Extracting \"'triangle.c'\" \(15235 characters\)
  843.   sed "s/^X//" >'triangle.c' <<'END_OF_FILE'
  844. X/*+-----------------------------------------------------------------------+
  845. X *| This file contains subroutines used to smooth shade a triangle.       |
  846. X *|                                                                       |
  847. X *| Author: Michael S. A. Robb         Version: 1.5        Date: 15/06/93 |
  848. X *+-----------------------------------------------------------------------+
  849. X */
  850. X
  851. X#include <mem.h>
  852. X
  853. X#include "24bit.h"
  854. X
  855. X/*+-----------------------------------------------------------------------+
  856. X *| These variables are used for smooth shading.                          |
  857. X *+-----------------------------------------------------------------------+
  858. X */
  859. X
  860. Xlong hdred, hdgreen, hdblue, hdblend, hdzpos; /* Horizontal increments.  */
  861. Xlong red,   green,   blue,   blend,   zpos;   /* Current colour values.  */
  862. X
  863. Xint  xstart, xend, ypos;                      /* Current scan line.      */
  864. X
  865. X/*+-----------------------------------------------------------------------+
  866. X *| These variables are used to sub-divide the triangle.                  |
  867. X *+-----------------------------------------------------------------------+
  868. X */
  869. X
  870. XCOORD triangle[3]; /* Triangle vertices. */
  871. XEDGE  edge[3];     /* Triangle edges.    */
  872. X
  873. X/*+-----------------------------------------------------------------------+
  874. X *| This macro is used to implement blending between fixed point values.  |
  875. X *| All values are expected to be in fixed point format. The colours are  |
  876. X *| blended according to the formula:                                     |
  877. X *|                                                                       |
  878. X *| C = BLEND * ( OC - NC ) + NC                                          |
  879. X *+-----------------------------------------------------------------------+
  880. X */
  881. X
  882. X#define BLEND_FUNC( FC, OC, NC, COL, BLEND )\
  883. X  FC.col_rgb.COL = (((BLEND*(OC.col_rgb.COL-NC.col_rgb.COL))>>FIXED_POINT )\
  884. X                 + NC.col_rgb.COL)
  885. X
  886. X#define BLEND_PIXEL( F, O, N, B )\
  887. X  { BLEND_FUNC( F, O, N, col_red,   B );\
  888. X    BLEND_FUNC( F, O, N, col_green, B );\
  889. X    BLEND_FUNC( F, O, N, col_blue,  B );\
  890. X    F.col_rgb.col_overlay = O.col_rgb.col_overlay; }
  891. X
  892. X/*+-----------------------------------------------------------------------+
  893. X *| This macro is used to convert a set of Red/Green/Blue/Overlay         |
  894. X *| components into a single 32-bit integer.                              |
  895. X *|                                                                       |
  896. X *| Note that this this macro is hardware specific to the graphics        |
  897. X *| board.                                                                |
  898. X *|                                                                       |
  899. X *| Each pixel is represented by the following format:                    |
  900. X *|                                                                       |
  901. X *| 31 MSB  24 23    16 15      8  7    LSB 0                             |
  902. X *| +---------+---------+-------------------+                             |
  903. X *| |   Red   |  Green  | Overlay |   Blue  |                             |
  904. X *| +---------+---------+---------+---------+                             |
  905. X *+-----------------------------------------------------------------------+
  906. X */
  907. X
  908. X#define CONVERT_RGB( R, G, B )\
  909. X ( ( ( (R)&0x00FF0000L ) <<8  )+\
  910. X   ( ( (G)&0x00FF0000L )      )+\
  911. X   ( ( (B)&0x00FF0000L ) >>16 ) )
  912. X
  913. X/*+-----------------------------------------------------------------------+
  914. X *| This subroutine is used to render a horizontal line using Gouraud     |
  915. X *| shading.                                                              |
  916. X *|                                                                       |
  917. X *| Uses the following variables:                                         |
  918. X *|                                                                       |
  919. X *| xstart  = X pixel start coordinate                                    |
  920. X *| xend    = X pixel end coordinate                                      |
  921. X *| ypos    = Y pixel coordinate                                          |
  922. X *| red     = Current value of red component                              |
  923. X *| green   = Current value of green component                            |
  924. X *| blue    = Current value of blue component                             |
  925. X *| blend   = Current value of blending component                         |
  926. X *| hdred   = Incremental for red component                               |
  927. X *| hdgreen = Incremental for green component.                            |
  928. X *| hdblue  = Incremental for blue component.                             |
  929. X *| blend   = Incremental for blending component.                         |
  930. X *+-----------------------------------------------------------------------+
  931. X */
  932. X
  933. Xvoid render_horizontal_line()
  934. X  {
  935. X  COLOUR32 nc; /* New colour */
  936. X  COLOUR32 oc; /* Old colour */
  937. X  COLOUR32 fc; /* Final colour */
  938. X
  939. X  ADDRESS  addr    = ADDRESS_PIXEL(   xstart, ypos );
  940. X  ADDRESS  zbuffer = ADDRESS_ZBUFFER( xstart, ypos );
  941. X
  942. X  ZBUFFER  zval;
  943. X
  944. X  while ( xstart++ < xend )                   /* For each pixel in row     */
  945. X    {
  946. X    nc.col_value = CONVERT_RGB( red, green, blue ); /* Convert to pixel.   */
  947. X
  948. X    READ_PIXEL(   addr,    oc   );            /* Read old pixel.           */
  949. X    READ_ZBUFFER( zbuffer, zval );            /* Read old Z-buffer value.  */
  950. X
  951. X    if ( zpos<=zval.zbuf_value && zpos >= 0 ) /* Test Z-buffer.            */
  952. X      {
  953. X      zval.zbuf_value = zpos;
  954. X
  955. X      BLEND_PIXEL( fc, oc, nc, blend );       /* Blend colours.            */
  956. X      WRITE_PIXEL( addr, fc );                /* Write new pixel.          */
  957. X      WRITE_ZBUFFER( zbuffer, zval );         /* Write new Z-buffer value. */
  958. X      }
  959. X
  960. X    red   += hdred;                           /* Add incrementals.         */
  961. X    green += hdgreen;
  962. X    blue  += hdblue;
  963. X    blend += hdblend;
  964. X    zpos  += hdzpos;
  965. X
  966. X    addr    += PIXEL_SIZE;                    /* Update Addresses.         */
  967. X    zbuffer += ZBUFFER_SIZE;
  968. X    }
  969. X  }
  970. X
  971. X/*+-----------------------------------------------------------------------+
  972. X *| This macro is used to calculate the size of the increments used when  |
  973. X *| moving vertically down an edge vector.                                |
  974. X *+-----------------------------------------------------------------------+
  975. X */
  976. X
  977. X#define EDGE_DIFF( F, D )\
  978. X  ( ( ( fin->F - strt->F ) << FIXED_POINT ) / (D) )
  979. X
  980. X/*+-----------------------------------------------------------------------+
  981. X *| This subroutine is used to initialise a vector given the start and    |
  982. X *| finishing coordinates.                                                |
  983. X *+-----------------------------------------------------------------------+
  984. X */
  985. X
  986. Xvoid edge_init( vec, strt, fin )
  987. X  EDGE *vec;
  988. X  COORD *strt;
  989. X  COORD *fin;
  990. X  {
  991. X  long delta_y    =  fin  -> c_ypos - strt -> c_ypos;
  992. X
  993. X  vec -> e_deltay =  delta_y;
  994. X  vec -> e_xpos   =  strt -> c_xpos  << FIXED_POINT;
  995. X  vec -> e_ypos   =  strt -> c_ypos;
  996. X  vec -> e_zpos   =  strt -> c_zpos  << FIXED_POINT;
  997. X
  998. X  vec -> e_red    =  strt -> c_red   << FIXED_POINT;
  999. X  vec -> e_green  =  strt -> c_green << FIXED_POINT;
  1000. X  vec -> e_blue   =  strt -> c_blue  << FIXED_POINT;
  1001. X  vec -> e_blend  = (strt -> c_blend << FIXED_POINT) / MAX_BLEND;
  1002. X
  1003. X  if ( delta_y != 0 )
  1004. X    {
  1005. X    vec -> e_dxpos  = EDGE_DIFF( c_xpos,  delta_y );
  1006. X    vec -> e_dzpos  = EDGE_DIFF( c_zpos,  delta_y );
  1007. X    vec -> e_dred   = EDGE_DIFF( c_red,   delta_y );
  1008. X    vec -> e_dgreen = EDGE_DIFF( c_green, delta_y );
  1009. X    vec -> e_dblue  = EDGE_DIFF( c_blue,  delta_y );
  1010. X    vec -> e_dblend = EDGE_DIFF( c_blend, (MAX_BLEND * delta_y) );
  1011. X    }
  1012. X  else
  1013. X    {
  1014. X    vec -> e_dxpos  =
  1015. X    vec -> e_dzpos  =
  1016. X    vec -> e_dred   =
  1017. X    vec -> e_dgreen =
  1018. X    vec -> e_dblue  =
  1019. X    vec -> e_dblend = 0;
  1020. X    }
  1021. X  }
  1022. X
  1023. X/*+-----------------------------------------------------------------------+
  1024. X *| This subroutine is used to update the vector after every scan-line.   |
  1025. X *+-----------------------------------------------------------------------+
  1026. X */
  1027. X
  1028. Xvoid edge_update( vec )
  1029. X  EDGE *vec;
  1030. X  {
  1031. X  vec -> e_xpos  += vec -> e_dxpos;
  1032. X  vec -> e_zpos  += vec -> e_dzpos;
  1033. X  vec -> e_red   += vec -> e_dred;
  1034. X  vec -> e_green += vec -> e_dgreen;
  1035. X  vec -> e_blue  += vec -> e_dblue;
  1036. X  vec -> e_blend += vec -> e_dblend;
  1037. X  }
  1038. X
  1039. X/*+-----------------------------------------------------------------------+
  1040. X *| This macro is used to calculate the size of the increments used when  |
  1041. X *| moving horizontally across a scan-line.                               |
  1042. X *+-----------------------------------------------------------------------+
  1043. X */
  1044. X
  1045. X#define HORIZ_INCREMENT( F )\
  1046. X  ((eright -> F - eleft -> F ) / delta_x )
  1047. X
  1048. X/*+-----------------------------------------------------------------------+
  1049. X *| This subroutine is used to render a sub-triangle given the vertex     |
  1050. X *| coordinate and the two other left and right hand vertices.            |
  1051. X *+-----------------------------------------------------------------------+
  1052. X */
  1053. X
  1054. Xvoid render_half( eleft, eright, delta_y, ystart )
  1055. X  EDGE *eleft, *eright;
  1056. X  long    delta_y, ystart;
  1057. X  {
  1058. X  long delta_x;
  1059. X
  1060. X  ypos = ystart;                            /* Initial Y coordinate.       */
  1061. X
  1062. X  while ( delta_y-- >= 0 )                  /* For every scan line.        */
  1063. X    {
  1064. X    xstart  = eleft ->e_xpos>>FIXED_POINT;  /* Starting X coordinate.      */
  1065. X    xend    = eright->e_xpos>>FIXED_POINT;  /* Finishing X coordinate.     */
  1066. X
  1067. X    delta_x = xend - xstart;                /* Width of scan-line.         */
  1068. X
  1069. X    zpos    = eleft -> e_zpos;
  1070. X    red     = eleft -> e_red;               /* Iniitial colour values.     */
  1071. X    green   = eleft -> e_green;
  1072. X    blue    = eleft -> e_blue;
  1073. X    blend   = eleft -> e_blend;
  1074. X
  1075. X    if ( delta_x != 0 )                     /* Any change in X coordinate? */
  1076. X      {
  1077. X      hdzpos  = HORIZ_INCREMENT( e_zpos  ); /* Yes, so get incrementals.  */
  1078. X      hdred   = HORIZ_INCREMENT( e_red   );
  1079. X      hdgreen = HORIZ_INCREMENT( e_green );
  1080. X      hdblue  = HORIZ_INCREMENT( e_blue  );
  1081. X      hdblend = HORIZ_INCREMENT( e_blend );
  1082. X      }
  1083. X
  1084. X    render_horizontal_line();               /* Then render the line.       */
  1085. X
  1086. X    edge_update( eleft  );                  /* Update left edge vector.    */
  1087. X    edge_update( eright );                  /* Update right edge vector.   */
  1088. X
  1089. X    ypos++;                                 /* Update Y coordinate.        */
  1090. X    }
  1091. X  }
  1092. X
  1093. X/*+-----------------------------------------------------------------------+
  1094. X *| This macro is used to perform a comparison and swap (if required) on  |
  1095. X *| the two pairs of coordinates.                                         |
  1096. X *+-----------------------------------------------------------------------+
  1097. X */
  1098. X
  1099. X#define COMPARE_VERTICES( X, A, B, F, T )\
  1100. X  if ((X)[(A)].F > (X)[(B)].F )\
  1101. X    {\
  1102. X    (T)      = (X)[(A)];\
  1103. X    (X)[(A)] = (X)[(B)];\
  1104. X    (X)[(B)] = (T);\
  1105. X    }
  1106. X
  1107. X/*+-----------------------------------------------------------------------+
  1108. X *| This subroutine is used to smooth shade a triangle. It takes an       |
  1109. X *| array of coordinates/colours as a parameter.                          |
  1110. X *+-----------------------------------------------------------------------+
  1111. X */
  1112. X
  1113. Xvoid render_triangle( coord )
  1114. X  COORD *coord;
  1115. X  {
  1116. X  COORD swapbuf; /* Used for swapping */
  1117. X
  1118. X  HARDWARE_PREPARE();
  1119. X
  1120. X  memcpy( triangle, coord, 3*sizeof(COORD) );   /* Make copy of coords. */
  1121. X
  1122. X  /*+-------------------------------------------------------------+
  1123. X   *| [1] Sort by Y coordinate so that vertices with the smallest |
  1124. X   *|     Y coordinate are at the top of the vertex list.         |
  1125. X   *+-------------------------------------------------------------+
  1126. X   */
  1127. X
  1128. X  COMPARE_VERTICES( triangle, 0, 1, c_ypos, swapbuf );
  1129. X  COMPARE_VERTICES( triangle, 1, 2, c_ypos, swapbuf );
  1130. X  COMPARE_VERTICES( triangle, 0, 1, c_ypos, swapbuf );
  1131. X
  1132. X  /*+----------------------------------------------------------------+
  1133. X   *| [2] Sort by X coordinate so that vertices which have identical |
  1134. X   *|     Y coordinates but smaller X coordinates are at the top of  |
  1135. X   *|     the vertex list.                                           |
  1136. X   *+----------------------------------------------------------------+
  1137. X   */
  1138. X
  1139. X  if ( triangle[0].c_ypos == triangle[1].c_ypos )
  1140. X    COMPARE_VERTICES( triangle, 0, 1, c_xpos, swapbuf );
  1141. X
  1142. X  if ( triangle[1].c_ypos == triangle[2].c_ypos )
  1143. X    {
  1144. X    COMPARE_VERTICES( triangle, 1, 2, c_xpos, swapbuf );
  1145. X
  1146. X    if ( triangle[0].c_ypos == triangle[1].c_ypos )
  1147. X      COMPARE_VERTICES( triangle, 0, 1, c_xpos, swapbuf );
  1148. X    }
  1149. X
  1150. X  /*+-----------------------------------------------------------------+
  1151. X   *| [3] Initialise three edge vectors by calculating incrementals.  |
  1152. X   *+-----------------------------------------------------------------+
  1153. X   */
  1154. X
  1155. X  edge_init( edge+0, &triangle[0], &triangle[1] ); /* Top edge.     */
  1156. X  edge_init( edge+1, &triangle[0], &triangle[2] ); /* Longest edge. */
  1157. X  edge_init( edge+2, &triangle[1], &triangle[2] ); /* Bottom edge.  */
  1158. X
  1159. X  /*+-----------------------------------------------------------------+
  1160. X   *| [4.1] The bottom two Y coordinates are identical, so only the   |
  1161. X   *|       top half of the triangle has to be rendered.              |
  1162. X   *+-----------------------------------------------------------------+
  1163. X   */
  1164. X
  1165. X  if ( triangle[1].c_ypos == triangle[2].c_ypos )
  1166. X      render_half( edge+0, edge+1, edge[0].e_deltay, edge[0].e_ypos );
  1167. X  else
  1168. X
  1169. X  /*+-----------------------------------------------------------------+
  1170. X   *| [4.2] The top two Y coordinates are identical, so only the      |
  1171. X   *|       bottom half of the triangle has to be rendered.           |
  1172. X   *+-----------------------------------------------------------------+
  1173. X   */
  1174. X
  1175. X  if ( triangle[0].c_ypos == triangle[1].c_ypos )
  1176. X      render_half( edge+1, edge+2, edge[2].e_deltay, edge[2].e_ypos );
  1177. X  else
  1178. X
  1179. X  /*+-----------------------------------------------------------------+
  1180. X   *| [4.3] Both top and bottom half-triangles must be rendered.      |
  1181. X   *|       However, a check must be performed to determine whether   |
  1182. X   *|       the longest edge is on the left or right hand side.       |
  1183. X   *+-----------------------------------------------------------------+
  1184. X   */
  1185. X
  1186. X    {
  1187. X    long mult, div, delta;
  1188. X    int  new_xpos;
  1189. X
  1190. X    mult     = (long) triangle[1].c_ypos - (long) triangle[0].c_ypos;
  1191. X    div      = (long) triangle[2].c_ypos - (long) triangle[0].c_ypos;
  1192. X
  1193. X    delta    = (long) triangle[2].c_xpos - (long) triangle[0].c_xpos;
  1194. X    new_xpos = (long) triangle[0].c_xpos + (long) (delta * mult) / div;
  1195. X
  1196. X    if ( new_xpos < triangle[1].c_xpos )
  1197. X      {
  1198. X      /*+-------------------------------------------------------------+
  1199. X       *| Render triangle with longest edge on the left hand side.    |
  1200. X       *+-------------------------------------------------------------+
  1201. X       */
  1202. X
  1203. X      render_half( edge+1, edge+0, edge[0].e_deltay-1, edge[0].e_ypos );
  1204. X      render_half( edge+1, edge+2, edge[2].e_deltay,   edge[2].e_ypos );
  1205. X      }
  1206. X    else
  1207. X      {
  1208. X      /*+-------------------------------------------------------------+
  1209. X       *| Render triangle with longest edge on the right hand side.   |
  1210. X       *+-------------------------------------------------------------+
  1211. X       */
  1212. X
  1213. X      render_half( edge+0, edge+1, edge[0].e_deltay-1, edge[0].e_ypos );
  1214. X      render_half( edge+2, edge+1, edge[2].e_deltay,   edge[2].e_ypos );
  1215. X      }
  1216. X    }
  1217. X
  1218. X  HARDWARE_RESTORE();
  1219. X  }
  1220. X
  1221. X
  1222. END_OF_FILE
  1223.   if test 15235 -ne `wc -c <'triangle.c'`; then
  1224.     echo shar: \"'triangle.c'\" unpacked with wrong size!
  1225.   fi
  1226.   # end of 'triangle.c'
  1227. fi
  1228. echo shar: End of archive 1 \(of 2\).
  1229. cp /dev/null ark1isdone
  1230. MISSING=""
  1231. for I in 1 2 ; do
  1232.     if test ! -f ark${I}isdone ; then
  1233.     MISSING="${MISSING} ${I}"
  1234.     fi
  1235. done
  1236. if test "${MISSING}" = "" ; then
  1237.     echo You have unpacked both archives.
  1238.     rm -f ark[1-9]isdone
  1239. else
  1240.     echo You still must unpack the following archives:
  1241.     echo "        " ${MISSING}
  1242. fi
  1243. exit 0
  1244. exit 0 # Just in case...
  1245.