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

  1. Newsgroups: comp.sources.misc
  2. From: michaelr@spider.co.uk ("Michael S. A. Robb")
  3. Subject: v38i018:  tessel - Polygon shading and rendering using triangular tesselation., Part02/02
  4. Message-ID: <1993Jun20.234856.23310@sparky.imd.sterling.com>
  5. X-Md4-Signature: 19ce8fd619046a4c52d830d8749549e4
  6. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sun, 20 Jun 1993 23:48:56 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 18
  13. Archive-name: tessel/part02
  14. Environment: IBM PC with Hercules Graphics Station Card, Borland C
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  24bit.h macros.h main.c protos.h readme.txt tessel.h
  21. #   tessel.txt tmsmodes.c triangle.h
  22. # Wrapped by kent@sparky on Sun Jun 20 18:34:48 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 2 (of 2)."'
  26. if test -f '24bit.h' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'24bit.h'\"
  28. else
  29.   echo shar: Extracting \"'24bit.h'\" \(609 characters\)
  30.   sed "s/^X//" >'24bit.h' <<'END_OF_FILE'
  31. X/*+-----------------------------------------------------------------------+
  32. X *| The following type definitions are used to access the TMS34010        |
  33. X *| I/O registers and memory.                                             |
  34. X *|                                                                       |
  35. X *| Author: Michael S. A. Robb         Version: 1.1        Date: 16/06/93 |
  36. X *+-----------------------------------------------------------------------+
  37. X */
  38. X
  39. X#include "hardware.h"
  40. X#include "colours.h"
  41. X#include "tmsmodes.h"
  42. X#include "protos.h"
  43. X#include "macros.h"
  44. X#include "triangle.h"
  45. X#include "tessel.h"
  46. X
  47. END_OF_FILE
  48.   if test 609 -ne `wc -c <'24bit.h'`; then
  49.     echo shar: \"'24bit.h'\" unpacked with wrong size!
  50.   fi
  51.   # end of '24bit.h'
  52. fi
  53. if test -f 'macros.h' -a "${1}" != "-c" ; then 
  54.   echo shar: Will not clobber existing file \"'macros.h'\"
  55. else
  56.   echo shar: Extracting \"'macros.h'\" \(1597 characters\)
  57.   sed "s/^X//" >'macros.h' <<'END_OF_FILE'
  58. X/*+-----------------------------------------------------------------------+
  59. X *| TMS34020 Hardware Specifics                                           |
  60. X *|                                                                       |
  61. X *| Author: Michael S. A. Robb         Version: 1.1        Date: 16/06/93 |
  62. X *+-----------------------------------------------------------------------+
  63. X */
  64. X
  65. X#define READ_ZBUFFER( A, Z )\
  66. X  { tms34010_setaddress( A );\
  67. X    Z.zbuf_hilo.zbuf_hi = tms34010_gethostregister( CPU_SLOWDATA );\
  68. X    Z.zbuf_hilo.zbuf_lo = tms34010_gethostregister( CPU_SLOWDATA ); }
  69. X
  70. X#define WRITE_ZBUFFER( A, Z )\
  71. X  { tms34010_setaddress( A );\
  72. X    tms34010_sethostregister( CPU_SLOWDATA, Z.zbuf_hilo.zbuf_hi );\
  73. X    tms34010_sethostregister( CPU_SLOWDATA, Z.zbuf_hilo.zbuf_lo ); }
  74. X
  75. X#define READ_PIXEL( A, P )\
  76. X  { tms34010_setaddress( A );\
  77. X    P.col_hilo.col_hi = tms34010_gethostregister( CPU_SLOWDATA );\
  78. X    P.col_hilo.col_lo = tms34010_gethostregister( CPU_SLOWDATA ); }
  79. X
  80. X#define WRITE_PIXEL( A, P )\
  81. X  { tms34010_setaddress( A );\
  82. X    tms34010_sethostregister( CPU_SLOWDATA, P.col_hilo.col_hi );\
  83. X    tms34010_sethostregister( CPU_SLOWDATA, P.col_hilo.col_lo ); }
  84. X
  85. X#define HARDWARE_PREPARE()\
  86. X    tms34010_sethostregister( CPU_CONTROL, HOST_AUTOINCR );
  87. X
  88. X#define HARDWARE_RESTORE()\
  89. X    tms34010_sethostregister( CPU_CONTROL, HOST_NOINCR );
  90. X
  91. X#define GRAPHICS_OPEN()\
  92. X  { tms34010_mode( &mode512x256x32bit );\
  93. X    tms34010_fillblockaddr32( 0L, 0,   0, 512, 256, 0x0L );\
  94. X    tms34010_fillblockaddr32( 0L, 0, 256, 512, 256, ZBUFFER_MAX ); }
  95. X
  96. X#define GRAPHICS_CLOSE()\
  97. X    tms34010_setvga()
  98. END_OF_FILE
  99.   if test 1597 -ne `wc -c <'macros.h'`; then
  100.     echo shar: \"'macros.h'\" unpacked with wrong size!
  101.   fi
  102.   # end of 'macros.h'
  103. fi
  104. if test -f 'main.c' -a "${1}" != "-c" ; then 
  105.   echo shar: Will not clobber existing file \"'main.c'\"
  106. else
  107.   echo shar: Extracting \"'main.c'\" \(3857 characters\)
  108.   sed "s/^X//" >'main.c' <<'END_OF_FILE'
  109. X/*+-----------------------------------------------------------------------+
  110. X *| This file contains subroutines used to demonstrate how polygons may   |
  111. X *| may be rendered by tesselation and smooth shading.                    |
  112. X *|                                                                       |
  113. X *| Author: Michael S. A. Robb         Version: 1.2        Date: 16/06/93 |
  114. X *+-----------------------------------------------------------------------+
  115. X */
  116. X
  117. X#include <stdio.h>
  118. X#include <stdlib.h>
  119. X#include <conio.h>
  120. X#include <math.h>
  121. X#include <time.h>
  122. X
  123. X#include "24bit.h"
  124. X
  125. X#define POLY_WIDTH  20
  126. X#define POLY_HEIGHT 20
  127. X
  128. X#define POLY_NUMBER 1000
  129. X
  130. X/*+-----------------------------------------------------------------------+
  131. X *| This subroutine is used to time the speed of the rendering software.  |
  132. X *+-----------------------------------------------------------------------+
  133. X */
  134. X
  135. Xvoid polygon_demo1()
  136. X  {
  137. X  COORD vlist[3];
  138. X  int   n, m;
  139. X  long  start, finish;
  140. X
  141. X  GRAPHICS_OPEN();
  142. X
  143. X  polygon_setproc( render_triangle );      /* Call-back routine. */
  144. X
  145. X  start = time( 0L );                      /* Starting time */
  146. X
  147. X  for ( n = 0; n < POLY_NUMBER; n++ )      /* For all the polygons */
  148. X    {
  149. X    vlist[0].c_xpos = random(screen_width -(POLY_WIDTH  <<1) ) + POLY_WIDTH;
  150. X    vlist[0].c_ypos = random(screen_height-(POLY_HEIGHT <<1) ) + POLY_HEIGHT;
  151. X
  152. X    vlist[1].c_xpos = vlist[0].c_xpos + random(POLY_WIDTH  <<1 ) - POLY_WIDTH;
  153. X    vlist[1].c_ypos = vlist[0].c_ypos + random(POLY_HEIGHT <<1) - POLY_HEIGHT;
  154. X
  155. X    vlist[2].c_xpos = vlist[0].c_xpos + random(POLY_WIDTH  <<1 ) - POLY_WIDTH;
  156. X    vlist[2].c_ypos = vlist[0].c_ypos + random(POLY_HEIGHT <<1 ) - POLY_HEIGHT;
  157. X
  158. X    for ( m = 0; m < 3; m++ )           /* For each vertex. */
  159. X      {
  160. X      vlist[m].c_zpos  = 0;
  161. X      vlist[m].c_red   = random( 256 ); /* Choose random colours */
  162. X      vlist[m].c_green = random( 256 );
  163. X      vlist[m].c_blue  = random( 256 );
  164. X      vlist[m].c_blend = 0;
  165. X      }
  166. X
  167. X    polygon_tesselate( 3, vlist );
  168. X    }
  169. X
  170. X  finish = time( 0L ) - start; /* Number of seconds that have elapsed. */
  171. X
  172. X  GRAPHICS_CLOSE();
  173. X
  174. X  printf( "For %d polygons, %lf seconds",     /* Display results */
  175. X          POLY_NUMBER,
  176. X          (double) POLY_NUMBER / finish );
  177. X  }
  178. X
  179. X/*+-----------------------------------------------------------------------+
  180. X *| This subroutine is used to generate a random polygon.                 |
  181. X *+-----------------------------------------------------------------------+
  182. X */
  183. X
  184. Xvoid polygon_random( num, vlist )
  185. X  int num;
  186. X  COORD *vlist;
  187. X  {
  188. X  int    n;
  189. X  double angle, radius, mult = M_PI * 2.0 / num;
  190. X  static int col = 0;
  191. X
  192. X  randomize();
  193. X
  194. X  col = ( ++col == 8 ? 1 : col );
  195. X
  196. X  for ( n = 0; n < num; n++, vlist++ )
  197. X    {
  198. X    angle            = mult * n;
  199. X    radius           = random( 80 ) + 45;
  200. X
  201. X    vlist -> c_xpos  = 256 + (long)( cos( angle ) * radius * 2 );
  202. X    vlist -> c_ypos  = 128 + (long)( sin( angle ) * radius );
  203. X    vlist -> c_zpos  = 0;
  204. X
  205. X    vlist -> c_red   = random( 256 ) * (  col     & 0x01 );
  206. X    vlist -> c_green = random( 256 ) * ( (col>>1) & 0x01 );
  207. X    vlist -> c_blue  = random( 256 ) * ( (col>>2) & 0x01 );
  208. X
  209. X    vlist -> c_blend = 0;
  210. X    }
  211. X  }
  212. X
  213. X#define NUM_POINTS    16
  214. X#define POLY          polygon
  215. X
  216. Xvoid polygon_demo2( void )
  217. X  {
  218. X  COORD   polygon[NUM_POINTS];             /* Used for random polygons. */
  219. X
  220. X  GRAPHICS_OPEN();
  221. X
  222. X  polygon_setproc( render_triangle );      /* Call-back routine. */
  223. X
  224. X  while ( !kbhit() )
  225. X    {
  226. X    polygon_random(    NUM_POINTS, POLY );
  227. X
  228. X    polygon_tesselate( NUM_POINTS, POLY ); /* Render the polygon. */
  229. X    }
  230. X
  231. X  GRAPHICS_CLOSE();
  232. X  }
  233. X
  234. X/*+-----------------------------------------------------------------------+
  235. X *| This is the first subroutine to be executed.                          |
  236. X *+-----------------------------------------------------------------------+
  237. X */
  238. X
  239. Xvoid main( void )
  240. X  {
  241. X  polygon_demo1();
  242. X  }
  243. END_OF_FILE
  244.   if test 3857 -ne `wc -c <'main.c'`; then
  245.     echo shar: \"'main.c'\" unpacked with wrong size!
  246.   fi
  247.   # end of 'main.c'
  248. fi
  249. if test -f 'protos.h' -a "${1}" != "-c" ; then 
  250.   echo shar: Will not clobber existing file \"'protos.h'\"
  251. else
  252.   echo shar: Extracting \"'protos.h'\" \(793 characters\)
  253.   sed "s/^X//" >'protos.h' <<'END_OF_FILE'
  254. X/*+-----------------------------------------------------------------------+
  255. X *| Function Prototypes.                                                  |
  256. X *|                                                                       |
  257. X *| Author: Michael S. A. Robb         Version: 1.1        Date: 29/05/93 |
  258. X *+-----------------------------------------------------------------------+
  259. X */
  260. X
  261. Xvoid tms34010_sethostregister( ADDRESS        address, WORD data );
  262. XWORD tms34010_gethostregister( ADDRESS        address            );
  263. Xvoid tms34010_setaddress(      ADDRESS        address            );
  264. Xvoid tms34010_setregister(     ADDRESS        address, WORD data );
  265. XWORD tms34010_getregister(     ADDRESS        address            );
  266. Xvoid tms34010_setmode(         TMS34010_MODE *mode               );
  267. END_OF_FILE
  268.   if test 793 -ne `wc -c <'protos.h'`; then
  269.     echo shar: \"'protos.h'\" unpacked with wrong size!
  270.   fi
  271.   # end of 'protos.h'
  272. fi
  273. if test -f 'readme.txt' -a "${1}" != "-c" ; then 
  274.   echo shar: Will not clobber existing file \"'readme.txt'\"
  275. else
  276.   echo shar: Extracting \"'readme.txt'\" \(2358 characters\)
  277.   sed "s/^X//" >'readme.txt' <<'END_OF_FILE'
  278. X==========================================================================
  279. X==  TESSEL - Source code to demonstrate polygon tesselation and smooth  ==
  280. X==           shading in 24-bit colour for the Hercules Graphics Station ==
  281. X==           Card.                                                      ==
  282. X==                                                                      ==
  283. X== Author: Michael S. A. Robb       Version: 1.4         Date: 31/05/93 ==
  284. X==         (michaelr@spider.co.uk)                                      ==
  285. X==                                                                      ==
  286. X==========================================================================
  287. X
  288. XContents:
  289. X---------
  290. X
  291. XSize    Name          Description
  292. X
  293. X12347   tessel.c      Source code to tesselate convex/concave polygons
  294. X15235   triangle.c    Source code to smooth shade/Z-buffer a triangle
  295. X 8777   tmsmodes.c    Source code to open and close 24-bit graphics modes
  296. X
  297. X 3857   main.c        The demonstration program
  298. X
  299. X 2386   tessel.h      Data structures used for polygon tesselation
  300. X 2640   triangle.h    Data structures used for triangle shading
  301. X 2737   tmsmodes.h    Data structures used for defining 32-bit video modes
  302. X13583   hardware.h    Register definitions for the TMS34010 TIGA board
  303. X 4210   colours.h     Data structures for 32-bit pixels and Z-buffer
  304. X 1597   macros.h      Some useful macros for performing matrix operations
  305. X  793   protos.h      Function prototypes
  306. X  609   24bit.h       Used to include all the above header files
  307. X
  308. X 9383   tessel.txt    Article from the news group "comp.graphics" on which the
  309. X                      tesselation software is based.
  310. X
  311. X 2358   readme.txt    This file
  312. X
  313. X   44   build.bat     Batch file to create the demonstration program
  314. X
  315. X
  316. XAbout the software
  317. X------------------
  318. X
  319. XThis software has been designed to be compiled using Borland C 6.0 in the
  320. X"Medium" model. In its current form, it will only execute properly with a
  321. XHercules Graphics Station Card. Porting it to use other 24-bit graphics
  322. Xcards should not be difficult (then again I have not programmed any other 
  323. X24-bit graphics cards). No TIGA command driver or on-board RAM is required.
  324. X
  325. X
  326. XDistribution policy
  327. X-------------------
  328. X
  329. XThis is public domain software. You may use it, modify it or distribute it in
  330. Xany way you like. No liability is accepted. See warning above.
  331. X
  332. X
  333. END_OF_FILE
  334.   if test 2358 -ne `wc -c <'readme.txt'`; then
  335.     echo shar: \"'readme.txt'\" unpacked with wrong size!
  336.   fi
  337.   # end of 'readme.txt'
  338. fi
  339. if test -f 'tessel.h' -a "${1}" != "-c" ; then 
  340.   echo shar: Will not clobber existing file \"'tessel.h'\"
  341. else
  342.   echo shar: Extracting \"'tessel.h'\" \(2386 characters\)
  343.   sed "s/^X//" >'tessel.h' <<'END_OF_FILE'
  344. X/*+-----------------------------------------------------------------------+
  345. X *| This header file is for use with the 'C' source module 'tessel.c'.    |
  346. X *|                                                                       |
  347. X *| Author: Michael S. A. Robb         Version: 1.1        Date: 29/05/93 |
  348. X *+-----------------------------------------------------------------------+
  349. X */
  350. X
  351. X#define CONSTANT_ONE   0x10000L
  352. Xtypedef long MATDATA;
  353. X
  354. X/*+-----------------------------------------------------------------------+
  355. X *| Function prototypes.                                                  |
  356. X *+-----------------------------------------------------------------------+
  357. X */
  358. X
  359. Xvoid polygon_tesselate(            int nverts, COORD *vlist );
  360. Xvoid polygon_tesselate_convex(     int nverts, COORD *vlist );
  361. Xvoid polygon_tesselate_concave(    int nverts, COORD *vlist );
  362. Xvoid polygon_tesselate_complex(    int nverts, COORD *vlist );
  363. Xvoid polygon_tesselate_noncomplex( int nverts, COORD *vlist );
  364. X
  365. Xint  polygon_clockwise(            int nverts, COORD *vlist );
  366. Xvoid polygon_reverse(              int nverts, COORD *vlist );
  367. Xint  polygon_convex(               int nverts, COORD *vlist );
  368. Xint  polygon_complex(              int nverts, COORD *vlist );
  369. X
  370. Xvoid polygon_setproc(           void (*polygon_proc)( COORD *triangle ) );
  371. X
  372. X/*+-----------------------------------------------------------------------+
  373. X *| Some useful macros for angle/polygon/coordinate/triangle tests.       |
  374. X *+-----------------------------------------------------------------------+
  375. X */
  376. X
  377. X#define MATRIX_DET_2X2( C1, C2, C3, C4 )\
  378. X          ( ( (MATDATA) (C2).c_xpos - (MATDATA) (C1).c_xpos )\
  379. X          * ( (MATDATA) (C4).c_ypos - (MATDATA) (C3).c_ypos )\
  380. X          - ( (MATDATA) (C4).c_xpos - (MATDATA) (C3).c_xpos )\
  381. X          * ( (MATDATA) (C2).c_ypos - (MATDATA) (C1).c_ypos ))
  382. X
  383. X#define COORD_ANGLE( VL, C1, C2, C3 )\
  384. X            MATRIX_DET_2X2( VL[C3], VL[C1], VL[C2], VL[C1] )
  385. X
  386. X#define ANGLE_NONCONVEX( VL, C1, C2, C3 )\
  387. X            ( COORD_ANGLE( VL, C1, C2, C3 ) >= 0 )
  388. X
  389. X#define ANGLE_CONVEX( VL, C1, C2, C3 )\
  390. X            ( COORD_ANGLE( VL, C1, C2, C3 ) < 0 )
  391. X
  392. X#define COORD_OUTSIDE_TRIANGLE( VL, T1, T2, T3, C )\
  393. X          ( MATRIX_DET_2X2( VL[T2], VL[T1], VL[C], VL[T1] )< 0 ||\
  394. X            MATRIX_DET_2X2( VL[T3], VL[T2], VL[C], VL[T2] )< 0 ||\
  395. X            MATRIX_DET_2X2( VL[T1], VL[T3], VL[C], VL[T3] )< 0 )
  396. X
  397. END_OF_FILE
  398.   if test 2386 -ne `wc -c <'tessel.h'`; then
  399.     echo shar: \"'tessel.h'\" unpacked with wrong size!
  400.   fi
  401.   # end of 'tessel.h'
  402. fi
  403. if test -f 'tessel.txt' -a "${1}" != "-c" ; then 
  404.   echo shar: Will not clobber existing file \"'tessel.txt'\"
  405. else
  406.   echo shar: Extracting \"'tessel.txt'\" \(9383 characters\)
  407.   sed "s/^X//" >'tessel.txt' <<'END_OF_FILE'
  408. XFrom mango@nova.esd.sgi.com (Eric Manghise) to "comp.graphics"
  409. X
  410. X|> 
  411. X|>     - Is there a simple way of subdividing a 2D polygon with 
  412. X|>         holes into convex pieces?  (Where the holes are
  413. X|>         2D polygons that are wholly contained in the 
  414. X|>         polygon that delineates the exterior boundary.)
  415. X
  416. X        No there is no simple way to decompose a polygon
  417. X        into convex pieces. I assume you want to decompose
  418. X        it into triangles. There are alot of different ways
  419. X        to do this. I might refer you to 
  420. X
  421. X            Triangulating a Simple Polygon in Linear Time
  422. X            Bernard Chazelle
  423. X            Department of Computer Science
  424. X            Princeton University.
  425. X
  426. X        When you add holes you create a whole world of problems.
  427. X        Also when you compound this with the case of concave polygons
  428. X        life become very complicated.
  429. X
  430. X
  431. X        Here is another article I sucked off the net along time ago.
  432. X
  433. X
  434. XConcave or Convex?
  435. X
  436. XThe cruz of your problem is determining whether an angle is convex (< 180
  437. Xdegrees) or not.  Given three distinct points P0, P1, and P2 in the plane,
  438. Xhow do we tell it the angle formed by line segments P0P1 and P1P2 is con-
  439. Xvex or not?  Before we answer this, we must be clear about our point of
  440. Xview:  We assume that we are ABOVE the xy-plane (i.e., at some point with
  441. Xa positive z-coordinate), looking down.  In addition, we define the angle
  442. Xbetween P0P1 and P1P2 by measuring the arc swept out by rotating P1P2
  443. Xabout P1 in a COUNTERCLOCKWISE direction until we meet segment P0P1.
  444. X
  445. XWe don't actually need to determine the exact angle.  We simply want to
  446. Xknow if it is < 180 degrees or not.  Thus, we can conceptualize the pro-
  447. Xblem in a bit different way:  Consider the infinite line oriented FROM P0
  448. XTO P1.  Where is P2 in relation to this line?
  449. X
  450. X    P2 is on the left:   The angle is < 180 degrees
  451. X    P2 is on the line:   The angle is = 180 degrees
  452. X    P2 is on the right:  The angle is > 180 degrees
  453. X
  454. XSo now the problem boils down to figuring out which side of a line that
  455. Xa point is on.  This is easily determined.  If L(x, y) = 0 is the ORIEN-
  456. XTED equation of a line, where L(x, y) = ax + by + c, then for any point P,
  457. X
  458. X    L(P) > 0:  Point P is on the left of the line
  459. X    L(P) = 0:  Point P is on the line
  460. X    L(P) < 0:  Point P is on the right of the line
  461. X
  462. XThus, to tell whether angle P0P1P2 is convex, do this:  Determine the
  463. Xoriented equation of the line FROM P0 TO P1, and plug P2 into the equa-
  464. Xtion.  If the result is > 0, then the angle is convex.
  465. X
  466. XWARNING:  As always when working with floating point arithmetic, all 
  467. Xcomparisons should involve an epsilon.  Furthermore, to be safe, the
  468. Xequation of the line should be normalized by dividing all coefficients
  469. Xby sqrt(a*a + b*b).  Then when the equation is evalutated at a point,
  470. Xthe result is actually the signed distance of the point from the line,
  471. Xwhich can be compared against an epsilon to see where the point is in
  472. Xrelation to the line.
  473. X
  474. XA shortcut to the above method of determining a line equation is to use
  475. Xthis determinant, where Ph = (xh, yh), Pi = (xi, yi), and Pj = (xj, yj):
  476. X
  477. X            | xh yh 1 |
  478. X        D = | xi yi 1 |
  479. X            | xj yj 1 |
  480. X
  481. XIf D > 0 then Pj lies on the left of the line FROM Ph TO Pi.  If D = 0,
  482. Xthe three points are collinear.  If D < 0 then Pj lies on the right of the 
  483. Xline FROM Ph TO Pi.  (Lying on the left means angle PhPiPj is convex, and
  484. Xlying on the right means the angle is nonconvex.)
  485. X
  486. XDISCLAIMER:  The above determinant should be checked.  I am recalling it 
  487. Xfrom memory, and it may not be quite right.
  488. X
  489. XUsing this determinant is not really different from the method already de-
  490. Xscribed.  Calculating the determinant is exactly the same as determining 
  491. Xthe equation of the line from point Ph to point Pi and then plugging Pj 
  492. Xinto the equation.  Also, a warning is in order, because no normalization
  493. Xis done.
  494. X
  495. XSo now we have a way to tell if an angle is convex or not.  This operation
  496. Xis the basic primitive for all the following algorithms.
  497. X
  498. X
  499. X
  500. XClockwise or Counterclockwise?
  501. X
  502. XSay we are given an array of n >= 3 distinct points labeled P0, P1, ..., 
  503. XPn-1, which are the vertices of a well-formed simple polygon P.  Say that
  504. Xthe n vertices are in order, but we don't know if the order is clockwise
  505. Xor counterclockwise.  How do we tell?  Here is a simple algorithm:
  506. X
  507. XScan the set of vertices and find the one with least x-coordinate.  If 
  508. Xthere is more than one vertex with least x-coordinate, then pick the one 
  509. Xof them which has least y-coordinate.  The resulting vertex is unique.  
  510. X(If not, the polygon is ill-formed because its vertices are not distinct 
  511. Xpoints.) Call this vertex Pi.
  512. X
  513. XLet Ph be the vertex preceding Pi, and let Pj be the vertex following Pi.  
  514. XThen test if angle PhPiPj is convex.  If it is, then the vertices of poly-
  515. Xgon P are oriented counterclockwise in our input array.  Otherwise, the
  516. Xvertices are ordered clockwise.  In the latter case, reverse the elements
  517. Xof P to put the vertices in counterclockwise order.
  518. X
  519. X
  520. X
  521. XDecomposing a 2-d polygon in the xy-plane into triangles
  522. X
  523. XGiven a well-formed simple polygon P with n >= 3 vertices labeled P0, 
  524. XP1, ..., Pn-1, we want to decompose P into triangles.  We assume that
  525. Xthe vertices are oriented in a counterclockwise direction as seen from 
  526. Xabove.
  527. X
  528. XBefore presenting a general algorithm which handles all cases, it is 
  529. Xworthwhile to consider the case when it is known that the polygon is
  530. Xconvex (i.e., all angles < 180 degrees).  Then the polygon is easily
  531. Xdecomposed into n-2 triangles by drawing diagonals from vertex 0 to 
  532. Xthe n-3 vertices P2, P3, ..., Pn-2, resulting in these triangles:
  533. X
  534. X    P0,P1,P2
  535. X    P0,P2,P3
  536. X    P0,P3,P4
  537. X    . . .
  538. X    P0,Pn-2,Pn-1
  539. X
  540. XIf it is known that many of the polygons to be processed are likely to
  541. Xbe convex, then it is a good idea to test each polygon to see if it is
  542. Xconvex, and if so, apply the above simple algorithm.  Only when a non-
  543. Xconvex polygon is encountered is it necessary to apply the general al-
  544. Xgorithm.
  545. X
  546. XHere is the general algorithm:
  547. X
  548. XLet Pi be any vertex of the polygon.  Let Ph be the vertex preceding Pi,
  549. Xand let Pj be the vertex following Pi.  Test if angle PhPiPj is convex.
  550. XIf not, increment i, determine h and j from i, and test again.  If a 
  551. Xconvex angle is not found by this process, there is an error in the 
  552. Xpolygon.  It is either not well-formed, or it is oriented clockwise.
  553. X
  554. XOnce a convex angle PhPiPj is found, the triangle formed by the three 
  555. Xpoints is a candidate.  However, it is ONLY a candidate.  It must be
  556. Xtested like this:  For every vertex V of the polygon other than the three
  557. Xforming the triangle, test if V is OUTSIDE the triangle (note that V 
  558. Xmust not be ON the boundary of the triangle).  If some vertex is found
  559. Xwhich is either on the boundary of or inside of the triangle, then the
  560. Xtriangle must be rejected.  In this case, increment i and continue 
  561. Xsearching for a convex angle.
  562. X
  563. XIf all V are outside of the triangle, then slice the triangle off the
  564. Xpolygon by removing vertex Pi.  If the number of points in the resulting
  565. Xpolygon is 3, then the decomposition is finished.  Otherwise, search
  566. Xagain from a convex angle.
  567. X
  568. XHere is a more detailed version of the algorithm:
  569. X
  570. X  i = n-1;
  571. X
  572. X  while (n > 3)
  573. X    {
  574. X    h = i;
  575. X    i = (i == n-1 ? 0 : i+1);
  576. X    j = (i == n-1 ? 0 : i+1);
  577. X
  578. X    if (angle PhPiPj nonconvex)
  579. X      continue;
  580. X
  581. X    k = (j == n-1 ? 0 : j+1);         /* k is vertex after j  */
  582. X    m = n-3;
  583. X
  584. X    while (m--)
  585. X      if (Pk outside triangle PhPiPj)
  586. X        k = (k == n-1 ? 0 : k+1);
  587. X      else
  588. X        break;
  589. X
  590. X      if (k != h)                      /* Vertex k not outside */
  591. X        continue;                      /*   triangle PhPiPj    */
  592. X
  593. X    Store triangle PhPiPj;
  594. X
  595. X    Remove vertex Pi from polygon P;
  596. X    n--;
  597. X    i = (i == 0 ? n-1 : i-1);
  598. X    }
  599. X
  600. X  Store triangle P0P1P2 as the final triangle of the decomposition;
  601. X
  602. X
  603. XThe above algorithm always produces exactly n-2 triangles.  Also, every
  604. Xvertex of every triangle produced by the algorithm is a vertex of the 
  605. Xoriginal polygon.  In other words, no new points are created by this al-
  606. Xgorithm.
  607. X
  608. X
  609. X
  610. XNow Back to 3-Space
  611. X
  612. XSince your original problem has to do with a polygon in 3-space, we need
  613. Xto consider how to get from there to the xy-plane.  Say that the input
  614. Xis an array Q of n >= 3 3-points, Q0, Q1, ..., Qn-1 which are the vertices 
  615. Xof a well-formed simple planar polygon.
  616. X
  617. XIf the plane of the polygon is not vertical (consider the xy-plane to be
  618. Xhorizontal), then simply set up a 2-d polygon P with the points Q, ignor-
  619. Xing the z-coordinate.  In effect, this projects polygon Q onto the xy-
  620. Xplane.  Now check if P is counterclockwise, and, if not, reverse its ele-
  621. Xments so it is counterclockwise.  Then decompose P into triangles.  Note
  622. Xthat if the z-coordinates are carried in polygon P (they will never be
  623. Xused because all algorithms above use only x- and y-coordinates), then
  624. Xthe triangles produced by the decomposition will in fact be polygons in
  625. X3-space with correct z-coordinates.  Thus, the input polygon is decom-
  626. Xposed as desired.
  627. X
  628. XIf the input polygon is in a vertical plane (which can be determined by
  629. Xchecking to see if the projection onto the xy-plane is a straight line),
  630. Xthen simply swap the x- and z-coordinates of the input vertices, apply
  631. Xthe algorithm in the preceding paragraph, and then swap the x- and z-
  632. Xcoordinates of the resulting triangles.
  633. X
  634. XNote that this method of going from 3-space to 2-space works because a 
  635. Xparallel projection of a polygon does not change any convex angles to
  636. Xnonconvex ones, or vice versa.
  637. END_OF_FILE
  638.   if test 9383 -ne `wc -c <'tessel.txt'`; then
  639.     echo shar: \"'tessel.txt'\" unpacked with wrong size!
  640.   fi
  641.   # end of 'tessel.txt'
  642. fi
  643. if test -f 'tmsmodes.c' -a "${1}" != "-c" ; then 
  644.   echo shar: Will not clobber existing file \"'tmsmodes.c'\"
  645. else
  646.   echo shar: Extracting \"'tmsmodes.c'\" \(8777 characters\)
  647.   sed "s/^X//" >'tmsmodes.c' <<'END_OF_FILE'
  648. X/*+-----------------------------------------------------------------------+
  649. X *| The following module contains routines which access the advanced      |
  650. X *| graphics modes of a Hercules Graphics Station Card.                   |
  651. X *|                                                                       |
  652. X *| Author: Michael S. A. Robb         Version: 1.1        Date: 16/06/93 |
  653. X *+-----------------------------------------------------------------------+
  654. X */
  655. X
  656. X#include <stdio.h>
  657. X#include <stdlib.h>
  658. X#include <conio.h>
  659. X#include <dos.h>
  660. X#include <mem.h>
  661. X
  662. X#include "hardware.h"
  663. X#include "colours.h"
  664. X#include "tmsmodes.h"
  665. X
  666. X/*+-----------------------------------------------------------------------+
  667. X *| The following variables are used to store the current dimensions of   |
  668. X *| the screen.                                                           |
  669. X *+-----------------------------------------------------------------------+
  670. X */
  671. X
  672. XWORD     screen_width;     /* Stores screen pixel width    */
  673. XWORD     screen_height;    /* Stores screen pixel height.  */
  674. XLONG     screen_pitch;     /* Stores screen line pitch.    */
  675. XLONG     screen_vramwidth; /* Stores VRAM width in pixels. */
  676. X
  677. X/*+-----------------------------------------------------------------------+
  678. X *| The following data defines the 512 x 256 x 32 bit graphics mode.      |
  679. X *+-----------------------------------------------------------------------+
  680. X */
  681. X
  682. XTMS34010_MODE mode512x256x32bit =
  683. X  {
  684. X  "512 x 256 x 32 bits",
  685. X  8,   12,   76,   80,             /* Horizontal timings.   */
  686. X  1,   35,  547,  548,             /* Vertical   timings.   */
  687. X
  688. X  MODE_UNINTERLACED | MODE_2KBYTE, /* Display    controls.  */
  689. X  0xFFFD,
  690. X  0x0000,
  691. X
  692. X  CLOCK_20000MHZ,                  /* External   controls.  */
  693. X  PIXEL_SIZE32,
  694. X  VSCAN_UNINTERLACED,
  695. X  DEFAULT_24BIT,
  696. X
  697. X  512, 256, 32,                    /* Screen dimensions.    */
  698. X  0x4000,                          /* Display pitch - bits. */
  699. X  };
  700. X
  701. X/*+-----------------------------------------------------------------------+
  702. X *| The following data defines the 512 x 480 x 32 bit graphics mode.      |
  703. X *+-----------------------------------------------------------------------+
  704. X */
  705. X
  706. XTMS34010_MODE mode512x480x32bit =
  707. X  {
  708. X  "512 x 480 x 32 bits",
  709. X  8,   12,   76,   80,             /* Horizontal timings.   */
  710. X  1,   35,  515,  525,             /* Vertical   timings.   */
  711. X
  712. X  MODE_UNINTERLACED | MODE_2KBYTE, /* Display    controls.  */
  713. X  0xFFFC,
  714. X  0x0000,
  715. X
  716. X  CLOCK_20000MHZ,                  /* External   controls.  */
  717. X  PIXEL_SIZE32,
  718. X  VSCAN_UNINTERLACED,
  719. X  DEFAULT_24BIT,
  720. X
  721. X  512, 480, 32,                    /* Screen dimensions.    */
  722. X  0x4000,                          /* Display pitch - bits. */
  723. X  };
  724. X
  725. X/*+-----------------------------------------------------------------------+
  726. X *| The following data defines the 512 x 512 x 32 bit graphics mode.      |
  727. X *+-----------------------------------------------------------------------+
  728. X */
  729. X
  730. XTMS34010_MODE mode512x512x32bit =
  731. X  {
  732. X  "512 x 512 x 32 bits",
  733. X   8,  12,   76,  80,              /* Horizontal timings.   */
  734. X   1,  16,  528, 544,              /* Vertical   timings.   */
  735. X
  736. X  MODE_UNINTERLACED | MODE_2KBYTE, /* Display    controls.  */
  737. X  0xFFFC,
  738. X  0x0000,
  739. X
  740. X  CLOCK_20000MHZ,                  /* External   controls.  */
  741. X  PIXEL_SIZE32,
  742. X  VSCAN_UNINTERLACED,
  743. X  DEFAULT_24BIT,
  744. X
  745. X  512, 512, 32,                    /* Screen dimensions.    */
  746. X  0x4000,                          /* Display pitch - bits. */
  747. X  };
  748. X
  749. X/*+-----------------------------------------------------------------------+
  750. X *| The following routine is used to set the value of a TMS34010 host     |
  751. X *| interface register.                                                   |
  752. X *+-----------------------------------------------------------------------+
  753. X */
  754. X
  755. Xvoid tms34010_sethostregister( address, data )
  756. X  ADDRESS   address;
  757. X  WORD      data;
  758. X  {
  759. X  *( (WORD far *) address ) = data;
  760. X  }
  761. X
  762. X/*+-----------------------------------------------------------------------+
  763. X *| The following routine is used to get the value of a TMS34010 host     |
  764. X *| interface register.                                                   |
  765. X *+-----------------------------------------------------------------------+
  766. X */
  767. X
  768. XWORD tms34010_gethostregister( address )
  769. X  ADDRESS address;
  770. X  {
  771. X  return( *( (WORD far *) address) );
  772. X  }
  773. X
  774. X/*+-----------------------------------------------------------------------+
  775. X *| The following routine is used to set the address accessed via the     |
  776. X *| TMS34010 host registers.                                              |
  777. X *+-----------------------------------------------------------------------+
  778. X */
  779. X
  780. Xvoid tms34010_setaddress( address )
  781. X  ADDRESS address;
  782. X  {
  783. X  tms34010_sethostregister( CPU_ADDRLO,   (WORD) ( address &  0xFFFFL ) );
  784. X  tms34010_sethostregister( CPU_ADDRHI,   (WORD) ( address >> 16L     ) );
  785. X  }
  786. X
  787. X/*+-----------------------------------------------------------------------+
  788. X *| The following routine is used to set the value of TMS34010 registers. |
  789. X *+-----------------------------------------------------------------------+
  790. X */
  791. X
  792. Xvoid tms34010_setregister( address, data )
  793. X  ADDRESS address;
  794. X  WORD    data;
  795. X  {
  796. X  tms34010_sethostregister( CPU_ADDRLO,   (WORD) ( address &  0xFFFFL ) );
  797. X  tms34010_sethostregister( CPU_ADDRHI,   (WORD) ( address >> 16L     ) );
  798. X  tms34010_sethostregister( CPU_SLOWDATA, data );
  799. X  }
  800. X
  801. X/*+-----------------------------------------------------------------------+
  802. X *| The following routine is used to get the value of TMS34010 registers. |
  803. X *+-----------------------------------------------------------------------+
  804. X */
  805. X
  806. XWORD tms34010_getregister( address )
  807. X  ADDRESS address;
  808. X  {
  809. X  tms34010_sethostregister( CPU_ADDRLO,   (WORD) ( address &  0xFFFFL ) );
  810. X  tms34010_sethostregister( CPU_ADDRHI,   (WORD) ( address >> 16L     ) );
  811. X
  812. X  return( tms34010_gethostregister( CPU_SLOWDATA ) );
  813. X  }
  814. X
  815. X/*+-----------------------------------------------------------------------+
  816. X *| The following routine is used to set up a TMS34010 graphics mode.     |
  817. X *+-----------------------------------------------------------------------+
  818. X */
  819. X
  820. Xvoid tms34010_mode( mode )
  821. X  TMS34010_MODE *mode;
  822. X  {
  823. X  WORD n, *data = &mode -> tms_hesync;
  824. X
  825. X  tms34010_sethostregister(   CPU_CONTROL,    HOST_AUTOINCR );
  826. X  tms34010_setaddress(        IO_HESYNC                   );
  827. X
  828. X  for ( n = 10; n--; data++ )
  829. X    tms34010_sethostregister( CPU_SLOWDATA, *data );
  830. X
  831. X  tms34010_sethostregister( CPU_CONTROL,    HOST_NOINCR   );
  832. X  tms34010_setregister(     IO_DPYTAP,      mode -> tms_dpytap );
  833. X  tms34010_setregister(     CONFIG1_WRITE,  mode -> tms_clockbase | 0x0008 );
  834. X  tms34010_setregister(     CONFIG2_WRITE,  mode -> tms_pixelsize |
  835. X                                            mode -> tms_videotiming );
  836. X
  837. X  tms34010_setregister(     RAMDAC_COMMAND, mode -> tms_ramdac      );
  838. X  tms34010_setregister(     CONFIG1_WRITE,  mode -> tms_clockbase & 0x00F7 );
  839. X  tms34010_setaddress(      NULL );
  840. X
  841. X  screen_width     = mode -> tms_xmax;
  842. X  screen_height    = mode -> tms_ymax;
  843. X  screen_pitch     = mode -> tms_dpitch;
  844. X
  845. X  screen_vramwidth = mode -> tms_dpitch / mode -> tms_psize;
  846. X  }
  847. X
  848. X/*+-----------------------------------------------------------------------+
  849. X *| The following routine is used to restore the VGA graphics mode.       |
  850. X *+-----------------------------------------------------------------------+
  851. X */
  852. X
  853. Xvoid tms34010_setvga( void )
  854. X  {
  855. X  tms34010_sethostregister( CPU_CONTROL,   HOST_AUTOINCR );
  856. X
  857. X  tms34010_setregister(     CONFIG1_WRITE, 0x000A        );
  858. X  tms34010_setregister(     CONFIG2_WRITE, 0x000C        );
  859. X
  860. X  outportb(                 0x03C6,        0x004B );
  861. X
  862. X  tms34010_setregister(     CONFIG1_WRITE, 0x0002        );
  863. X  tms34010_sethostregister( CPU_CONTROL,   HOST_NOINCR   );
  864. X
  865. X  textmode( 0x00 );
  866. X  textmode( 0x03 );
  867. X
  868. X  clrscr();
  869. X  }
  870. X
  871. X/*+----------------------------------------------------------------------+
  872. X *| This subroutine is used to fill a block of memory with a specific    |
  873. X *| colour.                                                              |
  874. X *+----------------------------------------------------------------------+
  875. X */
  876. X
  877. Xvoid tms34010_fillblockaddr32( base, xlo, ylo, width, height, col )
  878. X  ADDRESS  base;
  879. X  WORD     xlo, ylo;
  880. X  WORD     width, height;
  881. X  long     col;
  882. X  {
  883. X  WORD y, size;
  884. X  WORD col_lo = col & 0xFFFFL;
  885. X  WORD col_hi = col >> 16;
  886. X
  887. X  ADDRESS address = (( (ADDRESS) xlo + (ADDRESS) ylo * 512 ) << 5) + base;
  888. X
  889. X  tms34010_sethostregister( CPU_CONTROL, HOST_AUTOINCR  );
  890. X
  891. X  for ( y = height; y--; address += 0x4000L )
  892. X    {
  893. X    tms34010_setaddress( address );
  894. X
  895. X    for ( size = width; size--; )
  896. X      {
  897. X      tms34010_sethostregister( CPU_SLOWDATA, col_hi );
  898. X      tms34010_sethostregister( CPU_SLOWDATA, col_lo );
  899. X      }
  900. X    }
  901. X
  902. X  tms34010_sethostregister( CPU_CONTROL, HOST_NOINCR );
  903. X  }
  904. X
  905. X
  906. X
  907. END_OF_FILE
  908.   if test 8777 -ne `wc -c <'tmsmodes.c'`; then
  909.     echo shar: \"'tmsmodes.c'\" unpacked with wrong size!
  910.   fi
  911.   # end of 'tmsmodes.c'
  912. fi
  913. if test -f 'triangle.h' -a "${1}" != "-c" ; then 
  914.   echo shar: Will not clobber existing file \"'triangle.h'\"
  915. else
  916.   echo shar: Extracting \"'triangle.h'\" \(2640 characters\)
  917.   sed "s/^X//" >'triangle.h' <<'END_OF_FILE'
  918. X/*
  919. X *+-------------------------------------------------------------------------+
  920. X *| "triangle.h" - Header file for data structure and constants.            |
  921. X *|                                                                         |
  922. X *| Author: Michael S. A. Robb         Version: 1.4          Date: 30/05/93 |
  923. X *+-------------------------------------------------------------------------+
  924. X */
  925. X
  926. X#define FIXED_POINT  16  /* Number of bits in the fraction */
  927. X
  928. X/*
  929. X *+-------------------------------------------------------------------------+
  930. X *| The following data structure is used to represent the coordinate of a   |
  931. X *| polygon vertex.                                                         |
  932. X *+-------------------------------------------------------------------------+
  933. X */
  934. X
  935. Xtypedef struct coord_st
  936. X  {
  937. X  long c_xpos;    /* X coordinate.       */
  938. X  long c_ypos;    /* Y coordinate.       */
  939. X  long c_zpos;    /* Z coordinate.       */
  940. X  long c_red;     /* Amount of red.      */
  941. X  long c_green;   /* Amount of green.    */
  942. X  long c_blue;    /* Amount of blue.     */
  943. X  long c_blend;   /* Amount of blending. */
  944. X  } COORD;
  945. X
  946. X/*
  947. X *+-------------------------------------------------------------------------+
  948. X *| The following data structure is used to represent a single edge of the  |
  949. X *| triangle.                                                               |
  950. X *+-------------------------------------------------------------------------+
  951. X */
  952. X
  953. Xtypedef struct edge_st
  954. X  {
  955. X  long e_xpos;    /* Current X     coordinate */
  956. X  long e_ypos;    /* Current Y     coordinate */
  957. X  long e_zpos;    /* Current Z     coordinate */
  958. X  long e_red;     /* Current RED   component  */
  959. X  long e_green;   /* Current GREEN component  */
  960. X  long e_blue;    /* Current BLUE  component  */
  961. X  long e_blend;   /* Current BLEND component  */
  962. X
  963. X  long e_dxpos;   /* Incremental X coordinate */
  964. X  long e_deltay;  /* Incremental Y coordinate */
  965. X  long e_dzpos;   /* Incremental Z coordinate */
  966. X  long e_dred;    /* Incremental RED   value  */
  967. X  long e_dgreen;  /* Incremental GREEN value  */
  968. X  long e_dblue;   /* Incremental BLUE  value  */
  969. X  long e_dblend;  /* Incremental BLEND value  */
  970. X  } EDGE;
  971. X
  972. X/*
  973. X *+-----------------------------------------------------------------------+
  974. X *| Function prototypes.                                                  |
  975. X *+-----------------------------------------------------------------------+
  976. X */
  977. X
  978. Xvoid render_horizontal_line( void );
  979. X
  980. Xvoid edge_update( EDGE *edge );
  981. Xvoid edge_init(   EDGE *edge, COORD  *v1, COORD *v2 );
  982. Xvoid render_half( EDGE *e1,   EDGE *e2, long deltay, long ypos );
  983. X
  984. Xvoid render_triangle( COORD *tlist );
  985. END_OF_FILE
  986.   if test 2640 -ne `wc -c <'triangle.h'`; then
  987.     echo shar: \"'triangle.h'\" unpacked with wrong size!
  988.   fi
  989.   # end of 'triangle.h'
  990. fi
  991. echo shar: End of archive 2 \(of 2\).
  992. cp /dev/null ark2isdone
  993. MISSING=""
  994. for I in 1 2 ; do
  995.     if test ! -f ark${I}isdone ; then
  996.     MISSING="${MISSING} ${I}"
  997.     fi
  998. done
  999. if test "${MISSING}" = "" ; then
  1000.     echo You have unpacked both archives.
  1001.     rm -f ark[1-9]isdone
  1002. else
  1003.     echo You still must unpack the following archives:
  1004.     echo "        " ${MISSING}
  1005. fi
  1006. exit 0
  1007. exit 0 # Just in case...
  1008.