home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / tools / libs / graphics3d / src / library / graphics3df_i.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-13  |  29.7 KB  |  1,304 lines

  1. /*
  2. **      $VER: graphics3Df_i.c 10.10 (16.02.98)
  3. **
  4. **      Internal functions for graphics3D.library
  5. **
  6. **      (C) Copyright 97 Patrizio Biancalani
  7. **      All Rights Reserved.
  8. **
  9. **    Note: this code is traslate from the blitzbasic 3d graphics engine 
  10. **          V 0.9 of Maciej R. Gorny.
  11. */
  12.  
  13. #include <exec/types.h>
  14. #include <exec/memory.h>
  15. #include <proto/exec.h>
  16. #include <proto/intuition.h>
  17. #include <intuition/intuition.h>
  18. #include <intuition/screens.h>
  19.  
  20. #include <graphics/rastport.h>
  21. #include <graphics/clip.h>
  22. #include <graphics/regions.h>
  23. #include <graphics/gfx.h>
  24. #include <graphics/gfxmacros.h>
  25. #include <graphics/layers.h>
  26.  
  27. #include "graphics3Dc.h"
  28. #include "graphics3D.h"
  29.  
  30. /** prototipi locali **/
  31. struct objectnode *resetobj(in);
  32. struct objectnode *nextobj(in);
  33. struct objectnode *pobj(in);
  34.  
  35. /*** funzioni esterne solo matematiche ***/
  36. extern void matidentity4x4(struct matrix4x4 *imatrix); 
  37. extern void matzero4x4(struct matrix4x4 imatrix);
  38. extern void matcopy4x4(struct matrix4x4 *s_m,struct matrix4x4 *d_m);
  39. extern void matmult4x4(struct matrix4x4 *a,struct matrix4x4 *b,
  40.         struct matrix4x4 *r);
  41. extern void matmult4x4s(struct matrix4x4 *a,struct matrix4x4 *b,
  42.         struct matrix4x4 *r);
  43. extern void matmult1x4s(struct matrix1x4 *a,struct matrix4x4 *b,
  44.         struct matrix1x4 *r);
  45. extern void makevector3d(struct vertex *a,struct vertex *b,
  46.          struct vector *result);
  47. extern long int vectormag3d(struct vector *a);
  48. extern void normalpol(struct vertex *v0,struct vertex *v1,
  49.      struct vertex *v2,struct vector *normal);
  50. extern long int dotproduct(struct vector *u,struct vector *v);
  51. extern long int sqri(long int v);
  52. extern long int abs(long int val);
  53.  
  54. /************************************/
  55. /* costruzione tavole seno e coseno */
  56. /************************************/
  57. void buildlookuptables(in)
  58. struct ambient3d *in;
  59. {
  60. long int *sn,*cn,i,ii;
  61. long int t[]=
  62. {    
  63. /** val. seno angolo (0,90) e moltiplicato per 256 **/
  64.     0,4,9,13,17,22,26,30,35,39,43,47,52,
  65.     56,60,65,69,73,77,81,85,89,93,98,101,105,
  66.     109,113,117,121,125,129,132,136,140,143,
  67.     147,151,154,157,161,164,167,171,174,177,
  68.     180,183,186,189,192,195,198,200,203,206,
  69.     208,211,213,216,218,220,222,225,227,229,
  70.     230,232,234,236,238,239,241,242,243,245,
  71.     246,247,248,249,250,251,252,253,253,254,
  72.     254,255,255,255,256
  73. };
  74.  
  75. /*
  76. #ifdef DEBUG
  77. char dbg[80];
  78. #endif
  79. */
  80.  
  81. sn=in->sintable;
  82. cn=in->costable;
  83. /** val. seno angolo (0,90) e moltiplicato per 1024 **/
  84. /*
  85. t:=[0,17,35,53,71,89,
  86.     106,124,142,160,177,195,212,230,247,264,282,299,
  87.     316,333,350,366,383,399,416,432,448,464,480,496,
  88.     511,527,542,557,572,587,601,615,630,644,657,671,
  89.     684,698,711,723,736,748,760,772,784,795,806,817,
  90.     828,838,848,858,868,877,886,895,903,912,920,927,
  91.     935,942,949,955,962,968,973,979,984,988,993,997,
  92.     1001,1005,1008,1011,1013,1016,1018,1020,1021,1022,
  93.     1023,1023,1024]:LONG
  94. */
  95. ii=0;
  96. for(i=0; i<361; i++)
  97.     {
  98.     if (i<91)
  99.         {
  100.         sn[i]=t[ii];
  101.         cn[i]=t[90-ii];
  102.         }
  103.     else if (i<181) 
  104.         {
  105.         sn[i]=t[90-ii];
  106.         cn[i]=-t[ii];
  107.         }
  108.     else if (i<271)
  109.         {
  110.         sn[i]=-t[ii];
  111.         cn[i]=-t[90-ii];
  112.         }
  113.     else
  114.         {
  115.         sn[i]=-t[90-ii];
  116.         cn[i]=t[ii];
  117.         }
  118. /*
  119. #ifdef DEBUG
  120. sprintf(dbg,"t[%ld]=%ld sn[%ld]=%ld cn[%ld]=%ld\n",ii,t[ii],i,sn[i],i,cn[i]);
  121. write_dbg(dbg);
  122. #endif
  123. */
  124.     ii++;
  125.     if (ii>90) ii=1;
  126.     }
  127. }
  128.  
  129. /*******************************************************/
  130. /** crea la matrice di trasformazione inversa globale **/
  131. /** usata per passare da coordinate del mondo in      **/
  132. /** coordinate della camera                  **/
  133. /** Crea matrice in.global_view per capirci.          **/
  134. /*******************************************************/
  135. void createworldtocamera(in)
  136. struct ambient3d *in;
  137. {
  138. long int temp,active_axes;
  139. struct matrix4x4 translate,rotate_x,rotate_y,rotate_z;
  140. struct matrix4x4 result_1,result_2,*g_v;
  141. struct vector *v_p;
  142. struct dir3d *v_a;
  143. long int *cos,*sin;
  144.  
  145. cos=in->costable;
  146. sin=in->sintable;
  147. v_a=&in->view_angle;
  148. v_p=&in->view_point;
  149. g_v=&in->global_view;
  150.  
  151. active_axes=0;
  152.  
  153. matidentity4x4(&translate);
  154. translate.r3c0=-v_p->x;
  155. translate.r3c1=-v_p->y;
  156. translate.r3c2=-v_p->z;
  157.  
  158. if (v_a->angx!=NULL AND v_a->angx!=360)
  159.     {
  160.     matidentity4x4(&rotate_x);
  161.     rotate_x.r1c1=cos[v_a->angx];
  162.     rotate_x.r1c2=sin[v_a->angx];
  163.     rotate_x.r2c1=-sin[v_a->angx];
  164.     rotate_x.r2c2=cos[v_a->angx];
  165.     active_axes=active_axes+1;
  166.     }
  167.  
  168. if (v_a->angy!=NULL AND v_a->angy!=360)
  169.     {
  170.     matidentity4x4(&rotate_y);
  171.     rotate_y.r0c0=cos[v_a->angy];
  172.     rotate_y.r0c2=sin[v_a->angy];
  173.     rotate_y.r2c0=-sin[v_a->angy];
  174.     rotate_y.r2c2=cos[v_a->angy];
  175.     active_axes=active_axes+2;
  176.     }
  177.  
  178. if (v_a->angz!=NULL AND v_a->angz!=360)
  179.     {
  180.     matidentity4x4(&rotate_z);
  181.     rotate_z.r0c0=cos[v_a->angz];
  182.     rotate_z.r0c1=-sin[v_a->angz];
  183.     rotate_z.r1c0=sin[v_a->angz];
  184.     rotate_z.r1c1=cos[v_a->angz];
  185.     active_axes=active_axes+4;
  186.     }
  187.  
  188. switch (active_axes)
  189.     {
  190.     case (0):
  191.         matcopy4x4(&translate,g_v);
  192.         break;
  193.  
  194.     case (1):
  195.         matcopy4x4(&rotate_x,g_v);
  196.         g_v->r3c0=-v_p->x;
  197.         temp=-v_p->y*cos[v_a->angy] - v_p->z*sin[v_a->angy];
  198.         g_v->r3c1=temp >> SFIXV;
  199.         temp=v_p->y*sin[v_a->angy] - v_p->z*cos[v_a->angy];
  200.         g_v->r3c2=temp >> SFIXV;
  201.         break;
  202.  
  203.     case (2):
  204.         matcopy4x4(&rotate_y,g_v);
  205.         temp=-v_p->x*cos[v_a->angy]+v_p->z*sin[v_a->angy];
  206.         g_v->r3c0=temp >> SFIXV;
  207.         g_v->r3c1=-v_p->y;
  208.         temp=-v_p->y*sin[v_a->angy]-v_p->z*cos[v_a->angy];
  209.         g_v->r3c2=temp >> SFIXV;
  210.         break;
  211.  
  212.     case (3):
  213.         matmult4x4s(&translate,&rotate_x,&result_1);
  214.         matmult4x4s(&result_1,&rotate_y,g_v);
  215.         break;
  216.  
  217.     case (4):
  218.         matcopy4x4(&rotate_z,g_v);
  219.         temp=-v_p->x*cos[v_a->angz]-v_p->y*sin[v_a->angz];
  220.         g_v->r3c0=temp >> SFIXV;
  221.         temp= v_p->x*sin[v_a->angz]-v_p->y*cos[v_a->angz];
  222.         g_v->r3c1=temp >> SFIXV;
  223.         g_v->r3c3=-v_p->z;
  224.         break;
  225.  
  226.     case (5):
  227.         matmult4x4s(&translate,&rotate_x,&result_1);
  228.         matmult4x4s(&result_1,&rotate_z,g_v);
  229.         break;
  230.  
  231.     case (6):
  232.         matmult4x4s(&translate,&rotate_y,&result_1);
  233.         matmult4x4s(&result_1,&rotate_z,g_v);
  234.         break;
  235.  
  236.     case (7):
  237.         matmult4x4s(&translate,&rotate_x,&result_1);
  238.         matmult4x4s(&result_1,&rotate_y,&result_2);
  239.         matmult4x4s(&result_2,&rotate_z,g_v);
  240.         
  241.     }
  242. }
  243.  
  244. /*****************************************************/
  245. /** determina se l'intero oggetto corrente e' fuori **/
  246. /** dal volume compreso nella visuale o inattivo.   **/
  247. /** Se si rimosso ,ritorna un valore <>0        **/
  248. /*****************************************************/
  249. long int t_removeobject(in)
  250. struct ambient3d *in;
  251. {
  252. long int n_z,f_z;
  253. long int temp,x_bsphere,y_bsphere,z_bsphere;
  254. long int xmax,ymax,zmax,xmin,ymin,zmin,x_compare,y_compare;
  255. struct objectnode *obj;
  256. struct matrix4x4 *g_v;
  257.  
  258. #ifdef DEBUG
  259. char dbg[100];
  260. #endif
  261.  
  262. /* trasformo da interi a fixpoint */
  263. f_z=in->far_z * FIXV;
  264. n_z=in->near_z * FIXV;
  265.  
  266. obj=pobj(in);
  267. g_v=&in->global_view;
  268.  
  269. /* test se oggetto disattivato ,quindi invisibile */
  270. if (!obj->state) return(1);
  271.     
  272. /* segnalo oggetto non clippato per default */
  273. obj->clipped=0;
  274.  
  275. xmax=obj->xmax;
  276. ymax=obj->ymax;
  277. zmax=obj->zmax;
  278. xmin=obj->xmin;
  279. ymin=obj->ymin;
  280. zmin=obj->zmin;
  281.  
  282. temp=obj->worldposx*g_v->r0c0 + obj->worldposy*g_v->r1c0 +
  283.     obj->worldposz*g_v->r2c0;
  284. x_bsphere=(temp>>SFIXV) + g_v->r3c0;
  285. temp=obj->worldposx*g_v->r0c1 + obj->worldposy*g_v->r1c1 +
  286.       obj->worldposz*g_v->r2c1;
  287. y_bsphere=(temp>>SFIXV) + g_v->r3c1;
  288. temp=obj->worldposx*g_v->r0c2 + obj->worldposy*g_v->r1c2 +
  289.       obj->worldposz*g_v->r2c2;
  290. z_bsphere=(temp>>SFIXV) + g_v->r3c2;
  291.  
  292. #ifdef DEBUG
  293. sprintf(dbg,"r0c2=%ld r1c2=%ld r2c2=%ld r3c2=%ld\n",g_v->r0c1,g_v->r1c2,
  294.     g_v->r2c2,g_v->r3c2);
  295. write_dbg(dbg);
  296. sprintf(dbg,"temp=%ld x=%ld y=%ld z=%ld\n",temp,obj->worldposx,
  297.     obj->worldposy,obj->worldposz);
  298. write_dbg(dbg);
  299. sprintf(dbg,"far=%ld near=%ld zmax=%ld zmin=%ld\n",f_z,n_z,zmax,zmin);
  300. write_dbg(dbg);
  301. sprintf(dbg,"xmax=%ld xmin=%ld ymax=%ld ymin=%ld\n",xmax,xmin,ymax,ymin);
  302. write_dbg(dbg);
  303. sprintf(dbg,"x=%ld y=%ld z=%ld\n",x_bsphere,y_bsphere,z_bsphere);
  304. write_dbg(dbg);
  305. sprintf(dbg,"clipmode ZPLANE\n");
  306. if (in->clip_mode!=ZPLANE) sprintf(dbg,"clipmode FRUSTUM\n");
  307. write_dbg(dbg);
  308. #endif
  309.  
  310. /* clip con bounding box */
  311. if (in->clip_mode==ZPLANE)
  312.     {
  313.     if (z_bsphere+zmax>f_z OR z_bsphere+zmin<n_z) 
  314.         {
  315.         obj->clipped=1;
  316. #ifdef DEBUG
  317. sprintf(dbg,"oggetto clippato 2\n");
  318. write_dbg(dbg);
  319. #endif
  320.         return(2);
  321.         }
  322.     else
  323.         {
  324. #ifdef DEBUG
  325. sprintf(dbg,"oggetto non clippato\n");
  326. write_dbg(dbg);
  327. #endif
  328.         return(0);
  329.         }    
  330.     }
  331. else   
  332.     {
  333.     /* esegue un completo test su XYZ */
  334.     if ((z_bsphere+zmax)>f_z OR (z_bsphere+zmin)<n_z)
  335.         {
  336.         obj->clipped=1;
  337. #ifdef DEBUG
  338. sprintf(dbg,"oggetto clippato 3\n");
  339. write_dbg(dbg);
  340. #endif
  341.         return(3);
  342.         }
  343.     temp=in->half_screen_width*z_bsphere;
  344.     x_compare=temp/in->viewing_distance;
  345. #ifdef DEBUG
  346. sprintf(dbg,"x_comp=%ld\n",x_compare);
  347. write_dbg(dbg);
  348. #endif
  349.     if ((x_bsphere+xmax)>x_compare OR (x_bsphere+xmin)<-x_compare)
  350.         {
  351.         obj->clipped=1;
  352. #ifdef DEBUG
  353. sprintf(dbg,"oggetto clippato 4\n");
  354. write_dbg(dbg);
  355. #endif
  356.         return(4);
  357.         }
  358.     temp=(in->half_screen_height*z_bsphere)/in->viewing_distance;
  359.     y_compare=(temp*in->inv_aspect_ratio) >> SFIXV;
  360. #ifdef DEBUG
  361. sprintf(dbg,"temp=%ld iv_a_r=%ld y_comp=%ld\n",temp,in->inv_aspect_ratio,
  362.     y_compare);
  363. write_dbg(dbg);
  364. #endif
  365.     if ((y_bsphere+ymax)>y_compare OR (y_bsphere+ymin)<-y_compare)
  366.         {
  367.         obj->clipped=1;
  368. #ifdef DEBUG
  369. sprintf(dbg,"oggetto clippato 5\n");
  370. write_dbg(dbg);
  371. #endif
  372.         return(5);
  373.         }
  374.     }
  375. #ifdef DEBUG
  376. sprintf(dbg,"oggetto non clippato\n");
  377. write_dbg(dbg);
  378. #endif
  379.  
  380. return(0);
  381. }
  382.  
  383. /*******************************************************
  384.  ** trasla le coordinate locali dell'oggetto corrente **
  385.  ** nelle coordinate del mondo                   **
  386.  *******************************************************
  387.  *** INPUT :                           * 
  388.  * in -> valore > 0 restituito da display3d.           *
  389.  *** OUTPUT:                           *
  390.  * nessuno.                           *
  391.  *******************************************************/
  392. void localtoworld(in)
  393. struct ambient3d *in;
  394. {
  395. struct objectnode *obj;
  396. long int index;
  397. struct vertex *vg,*vl;
  398. struct polygon *pl;
  399. long int wx,wy,wz;
  400.  
  401. obj=pobj(in);
  402. vg=obj->vcamera;
  403. vl=obj->vlocal;
  404. pl=obj->polys;
  405. wx=obj->worldposx;
  406. wy=obj->worldposy;
  407. wz=obj->worldposz;
  408.  
  409. for (index=0; index<obj->numverts; index++)
  410.     {
  411.     vg[index].x=vl[index].x+wx;
  412.     vg[index].y=vl[index].y+wy;
  413.     vg[index].z=vl[index].z+wz;
  414.     }
  415. /* resetta flag di invisibilita' */
  416. for (index=0; index<obj->numpolys; index++)
  417.     {
  418.     pl[index].visible=1;
  419.     pl[index].clipped=0;
  420.     }
  421. }
  422.  
  423. /***************************************************
  424.  ** converte le coordinate nel mondo dell'oggetto **
  425.  ** corrente nelle coordinate della camera        **
  426.  ***************************************************
  427.  *** INPUT :                        * 
  428.  * in -> valore > 0 restituito da display3d.       *
  429.  *** OUTPUT:                       *
  430.  * nessuno.                       *
  431.  ***************************************************/
  432. void worldtocamera(in)
  433. struct ambient3d *in;
  434. {
  435. struct objectnode *obj;
  436. long int index,temp,tempx,tempy,tempz,active_axes;
  437. struct vertex *vc;
  438. struct matrix4x4 gv,*g_v;
  439. struct dir3d *vang;
  440.  
  441. obj=pobj(in);
  442. vc=obj->vcamera;
  443. vang=&in->view_angle;
  444. g_v=&in->global_view;
  445.  
  446. active_axes=0;
  447.  
  448. if (vang->angx!=NULL) active_axes=active_axes+1; 
  449. if (vang->angy!=NULL) active_axes=active_axes+2;
  450. if (vang->angz!=NULL) active_axes=active_axes+4;
  451.  
  452. switch (active_axes)
  453.     {
  454.     case (0):
  455.         for (index=0; index<obj->numverts; index++)
  456.             {    
  457.             vc[index].x=vc[index].x+g_v->r3c0;
  458.             vc[index].y=vc[index].y+g_v->r3c1;
  459.             vc[index].z=vc[index].z+g_v->r3c2;
  460.             }
  461.         break;
  462.     case (1):
  463.         for (index=0; index<obj->numverts; index++)
  464.             {    
  465.             vc[index].x=vc[index].x+g_v->r3c0;
  466.             tempy=vc[index].y*g_v->r1c1+vc[index].z*g_v->r2c1;
  467.             tempz=vc[index].y*g_v->r1c2+vc[index].z*g_v->r2c2;
  468.             vc[index].z=(tempz >> SFIXV)+g_v->r3c2;
  469.             vc[index].y=(tempy >> SFIXV)+g_v->r3c1;
  470.             }
  471.         break;
  472.  
  473.     case (2):
  474.         for (index=0; index<obj->numverts; index++)
  475.             {    
  476.             tempx=vc[index].x*g_v->r0c0+vc[index].z*g_v->r2c0;
  477.             vc[index].y=vc[index].y+g_v->r3c1;
  478.             tempz=vc[index].x*g_v->r0c2+vc[index].z*g_v->r2c2;
  479.             vc[index].z=(tempz >> SFIXV)+g_v->r3c2;
  480.             vc[index].x=(tempx >> SFIXV)+g_v->r3c0;
  481.             }
  482.         break;
  483.  
  484.     case (4):
  485.         for (index=0; index<obj->numverts; index++)
  486.             {    
  487.             tempx=vc[index].x*g_v->r0c0+vc[index].y*g_v->r1c0;
  488.             tempy=vc[index].x*g_v->r0c1+vc[index].y*g_v->r1c1;
  489.             vc[index].y=(tempy >> SFIXV)+g_v->r3c1;
  490.             vc[index].x=(tempx >> SFIXV)+g_v->r3c0;
  491.             vc[index].z=vc[index].z+g_v->r3c2;
  492.             }
  493.         break;
  494.  
  495.     default :
  496.         for (index=0; index<obj->numverts; index++)
  497.             {    
  498.             tempx=vc[index].x*g_v->r0c0+vc[index].y*g_v->r1c0+
  499.                 vc[index].z*g_v->r2c0;
  500.             tempy=vc[index].x*g_v->r0c1+vc[index].y*g_v->r1c1+
  501.                 vc[index].z*g_v->r2c1;        
  502.             tempz=vc[index].x*g_v->r0c2+vc[index].y*g_v->r1c2+
  503.                 vc[index].z*g_v->r2c2;        
  504.             vc[index].x=(tempx >> SFIXV)+g_v->r3c0;
  505.             vc[index].y=(tempy >> SFIXV)+g_v->r3c1;
  506.             vc[index].z=(tempz >> SFIXV)+g_v->r3c2;
  507.             }
  508.     }    
  509. }
  510.  
  511. /******************************************************/
  512. /** rimuove le facce posteriori dell'oggetto corrente**/
  513. /** e calcola il flat shading dell'oggetto           **/
  514. /******************************************************/
  515. void removebackfacesandshade(in)
  516. struct ambient3d *in;
  517. {
  518. struct objectnode *obj;
  519. struct vector *vp, *ls;
  520. struct vertex *v0,*v1,*v2;
  521. struct polygon *pol;
  522. long int x,ms1,ms,al,sha_org,shading,curr_poly,dp,intensity;
  523. struct vector u,v;
  524. struct vector normal,norm,sight;
  525. long int norml;
  526.  
  527. vp=&in->view_point;
  528. ls=&in->light_source;
  529. obj=pobj(in);
  530. shading=obj->shade;
  531. sha_org=shading;
  532.  
  533. x=ls->x;
  534.  
  535. ms=in->maxintensity;
  536. ms1=ms << SFIXV;
  537. al=in->ambient_light >> SFIXV;
  538. for (curr_poly=0; curr_poly<obj->numpolys; curr_poly++)
  539.    {
  540.    shading=sha_org;
  541.    pol=&obj->polys[curr_poly];       
  542.    if (pol->twosided==NULL AND pol->numpoints>2)
  543.     {
  544.     v0=&obj->vcamera[pol->vertexlist0];
  545.     v1=&obj->vcamera[pol->vertexlist1];
  546.     v2=&obj->vcamera[pol->vertexlist2];
  547.         
  548.     normalpol(v0,v1,v2,&normal);
  549.     
  550.     sight.x=vp->x - v0->x;
  551.     sight.y=vp->y - v0->y;
  552.     sight.z=vp->z - v0->z;
  553.  
  554.     dp=dotproduct(&normal,&sight);
  555.     if (dp>=NULL)
  556. /* poligono ad una faccia */
  557.        {
  558.        pol->visible=1;
  559.        switch(shading)
  560.          {
  561.          case(FLAT):
  562.     /* calcolo lunghezza normale poligono */
  563.           dp=dotproduct(&normal,ls);
  564.           if (dp>NULL)
  565.          {
  566.                v0=&obj->vlocal[pol->vertexlist0];
  567.              v1=&obj->vlocal[pol->vertexlist1];
  568.                v2=&obj->vlocal[pol->vertexlist2];
  569.                normalpol(v0,v1,v2,&normal);
  570.  
  571.                norml=vectormag3d(&normal);
  572.                if (norml==NULL) norml=FIXV;
  573.              intensity=al+(ms1*dp)/norml;
  574.          if (intensity>ms) intensity=ms;
  575.        /* intensity e' compreso ora tra 0 e ms ,si usera' questo valore */
  576.        /* per trovare l'indice di sfumatura */
  577.          pol->shade=pol->color+intensity;
  578.          }
  579.           else
  580.          {
  581.              pol->shade=pol->color+al;    
  582.              }
  583.           break;
  584.  
  585.          case(SOLID):
  586.            pol->shade=pol->color + (ms>>1);
  587.           break;
  588.  
  589.          default:
  590.     /* se tipo di shading <> da flat si assume solid */
  591.            pol->shade=pol->color;
  592.          }
  593.        }
  594.     else
  595.        {
  596.        pol->visible=0;           
  597.        }
  598.     }
  599.    else if (pol->numpoints>2)
  600.     {
  601. /* poligono a due facce */
  602.     pol->visible=1;
  603.     if (pol->numpoints<3) shading=SOLID; 
  604.     switch (shading)
  605.      {
  606.      case(FLAT):
  607.        v0=&obj->vcamera[pol->vertexlist0];
  608.        v1=&obj->vcamera[pol->vertexlist1];
  609.        v2=&obj->vcamera[pol->vertexlist2];
  610.         
  611.        normalpol(v0,v1,v2,&normal);
  612.     
  613.        dp=dotproduct(&normal,ls);
  614.        if (dp>NULL)
  615.           {
  616.     /* calcolo lunghezza normale poligono */
  617.           v0=&obj->vlocal[pol->vertexlist0];
  618.           v1=&obj->vlocal[pol->vertexlist1];
  619.           v2=&obj->vlocal[pol->vertexlist2];
  620.           normalpol(v0,v1,v2,&normal);
  621.  
  622.           norml=vectormag3d(&normal);
  623.           if (norml==NULL) norml=FIXV;
  624.           intensity=al+(ms1*dp)/norml;
  625.           if (intensity>ms) intensity=ms;
  626.           pol->shade=pol->color+intensity;
  627.           }
  628.        else
  629.           {
  630.           pol->shade=pol->color+al;
  631.           }
  632.        break;
  633.  
  634.      case(SOLID):    
  635.        pol->shade=pol->color + (ms>>1) ;
  636.        break;
  637.  
  638.      default:
  639.     /* se tipo di shading <> da flat si assume solid */
  640.         pol->shade=pol->color ;
  641.      }    
  642.     }
  643.     else
  644.     {
  645.     pol->visible=1;
  646.     pol->shade=pol->color + (ms>>1) ;
  647.     }
  648.    }
  649.  
  650. }
  651.  
  652. /****************************************************/
  653. /** clippa le coordinate della camera dell'oggetto **/
  654. /** corrente rispetto al volume della visuale      **/
  655. /****************************************************/
  656. void clipobject3d(in)
  657. struct ambient3d *in;
  658. {
  659. long int n_z, f_z, curr_poly;
  660. long int x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4;
  661. long int x1_cmp, y1_cmp, x2_cmp, y2_cmp, x3_cmp, y3_cmp, x4_cmp, y4_cmp;
  662. long int vert0, vert1, vert2, vert3, fov_width, fov_height;
  663. struct objectnode *obj;
  664. struct vertex *vc;
  665. struct polygon *pol;
  666.  
  667. obj=pobj(in);
  668.  
  669. vc=obj->vcamera;
  670. pol=obj->polys;
  671.  
  672. /* converto in fixpoint */
  673. n_z=in->near_z*FIXV;
  674. f_z=in->far_z*FIXV;
  675.  
  676. if (in->clip_mode==ZPLANE)
  677.     {
  678. /* cerca di clippare ogni poligono con il volume della visuale */
  679.     for (curr_poly=0 ;curr_poly<obj->numpolys ;curr_poly++)
  680.         {
  681.     /* test di quanti lati */ 
  682.         switch(pol[curr_poly].numpoints)
  683.             {
  684.             case(1):
  685.                 z1=vc[pol[curr_poly].vertexlist0].z;
  686.                 z2=z1;
  687.                 z3=z1;
  688.                 z4=z4;
  689.                 break;
  690.  
  691.             case(2):
  692.                 z1=vc[pol[curr_poly].vertexlist0].z;
  693.                 z2=vc[pol[curr_poly].vertexlist1].z;
  694.                 z3=z2;
  695.                 z4=z2;
  696.                 break;
  697.  
  698.             case(3):
  699.                 z1=vc[pol[curr_poly].vertexlist0].z;
  700.                 z2=vc[pol[curr_poly].vertexlist1].z;
  701.                 z3=vc[pol[curr_poly].vertexlist2].z;
  702.                 z4=z3;
  703.                 break;
  704.  
  705.             case(4):
  706.                 z1=vc[pol[curr_poly].vertexlist0].z;
  707.                 z2=vc[pol[curr_poly].vertexlist1].z;
  708.                 z3=vc[pol[curr_poly].vertexlist2].z;
  709.                 z4=vc[pol[curr_poly].vertexlist3].z;
  710.                 break;
  711.             }
  712.  
  713.         if ((z1<n_z AND z2<n_z AND z3<n_z AND z4<n_z) OR
  714.            (z1>f_z AND z2>f_z AND z3>f_z AND z4>f_z))
  715.             pol[curr_poly].clipped=1;
  716.         }
  717.     }
  718. else
  719.     {
  720. /* FRUSTUM MODE CLIP */
  721.     /* calcolo i campi visivi in fixpoint */
  722.     fov_width=(in->half_screen_width*FIXV)/in->viewing_distance;
  723.     fov_height=((in->half_screen_height*in->inv_aspect_ratio) / 
  724.             in->viewing_distance);
  725.     for (curr_poly=0 ;curr_poly<obj->numpolys ;curr_poly++)        
  726.         {
  727.  
  728.     /* test di quanti lati */
  729.         switch(pol[curr_poly].numpoints)
  730.             {
  731.             case(1):
  732.                 vert0=pol[curr_poly].vertexlist0;
  733.                 x1=vc[vert0].x;
  734.                 y1=vc[vert0].y;
  735.                 z1=vc[vert0].z;
  736.                 x2=x1;
  737.                 y2=y1;
  738.                 z2=z1;
  739.                 x3=x1;
  740.                 y3=y1;
  741.                 z3=z1;
  742.                 x4=x1;
  743.                 y4=y1;
  744.                 z4=z1;
  745.                 break;
  746.             case(2):
  747.                 vert0=pol[curr_poly].vertexlist0;
  748.                 vert1=pol[curr_poly].vertexlist1;
  749.                 x1=vc[vert0].x;
  750.                 y1=vc[vert0].y;
  751.                 z1=vc[vert0].z;
  752.                 x2=vc[vert1].x;
  753.                 y2=vc[vert1].y;
  754.                 z2=vc[vert1].z;
  755.                 x3=x2;
  756.                 y3=y2;
  757.                 z3=z2;
  758.                 x4=x2;
  759.                 y4=y2;
  760.                 z4=z2;
  761.                 break;
  762.             case(3):
  763.                 vert0=pol[curr_poly].vertexlist0;
  764.                 vert1=pol[curr_poly].vertexlist1;
  765.                 vert2=pol[curr_poly].vertexlist2;    
  766.                 x1=vc[vert0].x;
  767.                 y1=vc[vert0].y;
  768.                 z1=vc[vert0].z;
  769.                 x2=vc[vert1].x;
  770.                 y2=vc[vert1].y;
  771.                 z2=vc[vert1].z;
  772.                 x3=vc[vert2].x;
  773.                 y3=vc[vert2].y;
  774.                 z3=vc[vert2].z;
  775.                 x4=x3;
  776.                 y4=y3;
  777.                 z4=z3;
  778.                 break;
  779.             case(4):
  780.                 vert0=pol[curr_poly].vertexlist0;
  781.                 vert1=pol[curr_poly].vertexlist1;
  782.                 vert2=pol[curr_poly].vertexlist2;    
  783.                 vert3=pol[curr_poly].vertexlist3;
  784.                 x1=vc[vert0].x;
  785.                 y1=vc[vert0].y;
  786.                 z1=vc[vert0].z;
  787.                 x2=vc[vert1].x;
  788.                 y2=vc[vert1].y;
  789.                 z2=vc[vert1].z;
  790.                 x3=vc[vert2].x;
  791.                 y3=vc[vert2].y;
  792.                 z3=vc[vert2].z;
  793.                 x4=vc[vert3].x;
  794.                 y4=vc[vert3].y;
  795.                 z4=vc[vert3].z;
  796.                 break;
  797.             }
  798.         if (z1<n_z AND z2<n_z AND z3<n_z AND z4<n_z) 
  799.             {
  800.             pol[curr_poly].clipped=1;
  801.             continue;
  802.             }
  803.         if (z1>f_z AND z2>f_z AND z3>f_z AND z4>f_z)
  804.             {
  805.             pol[curr_poly].clipped=1;
  806.             continue;
  807.             }
  808.  
  809.         x1_cmp=(fov_width*z1) >> SFIXV;
  810.         x2_cmp=(fov_width*z2) >> SFIXV;
  811.         x3_cmp=(fov_width*z3) >> SFIXV;
  812.         x4_cmp=(fov_width*z4) >> SFIXV;
  813.  
  814.         if (!((x1>-x1_cmp OR x2>-x2_cmp OR x3>-x3_cmp OR x4>-x4_cmp)
  815.            AND (x1<x1_cmp OR x2<x2_cmp OR x3<x3_cmp OR x4<x4_cmp)))
  816.             {
  817.             pol[curr_poly].clipped=1;
  818.             continue;
  819.             }
  820.         y1_cmp=(fov_height*z1) >> SFIXV;
  821.         y2_cmp=(fov_height*z2) >> SFIXV;
  822.         y3_cmp=(fov_height*z3) >> SFIXV;
  823.         y4_cmp=(fov_height*z4) >> SFIXV;
  824.  
  825.         if (!((y1>-y1_cmp OR y2>-y2_cmp OR y3>-y3_cmp OR y4>-y4_cmp)
  826.            AND (y1<y1_cmp OR y2<y2_cmp OR y3<y3_cmp OR y4<y4_cmp)))
  827.             {
  828.             pol[curr_poly].clipped=1;
  829.             continue;
  830.             }
  831.         }
  832.     }
  833. }    
  834.  
  835. /******************************************************/
  836. /** crea la lista di tutti i poligoni visibili nella **/
  837. /** frame corrente e li memorizza gia' proiettati    **/
  838. /** e' gia' stato ottimizzato il piu' possibile.     **/
  839. /** Ora si calcola la distanza tra il punto medio del**/
  840. /** poligono e l'osservatore per il succ. riordino.  **/
  841. /******************************************************/
  842. void generatepolylist(in)
  843. struct ambient3d *in;
  844. {
  845. long int *iwp;
  846. long int id,fix1,fix,curr_poly,i,ii,mz,mx,my,x,y,z;
  847. struct pixel *pt;
  848. struct objectnode *obj;
  849. struct vertex *vc;
  850. struct polygon *pol;
  851. struct polytemp *wpl;
  852.  
  853. #ifdef DEBUG
  854. char dbg[100];
  855. #endif
  856.  
  857. iwp=in->iwpolys;
  858. pt=(struct pixel *)in->temp;
  859. obj=resetobj(in);
  860. id=0;
  861. curr_poly=0;
  862. fix=(in->aspect_ratio*in->viewing_distance) >> SFIXV;
  863. fix1=in->aspect_ratio;
  864.  
  865. #ifdef DEBUG
  866. sprintf(dbg,"\n--- ciclo generatepolylist ---\n");
  867. write_dbg(dbg);
  868. sprintf(dbg,"view distance=%ld fix=%ld\n",in->viewing_distance,fix);
  869. write_dbg(dbg);
  870. #endif
  871.  
  872. do 
  873.    {    
  874.    if (obj->clipped==0 AND obj->state!=0) 
  875.     {
  876.     /** proietto tutti i punti dell'oggetto corrente **/
  877.     switch(in->projection_type)
  878.         {
  879.         case(PROSP_P) :
  880.     /* uso proiezione prospettica */
  881.             for(i=0 ;i<obj->numverts ;i++ ) 
  882.                 {
  883.                 vc=&obj->vcamera[i];
  884.                 z=vc->z;
  885.                 if (z==NULL) z=FIXV;    
  886.                 pt[i].x=in->half_screen_width +
  887.                      (vc->x*in->viewing_distance)/z;
  888.                 pt[i].y=in->half_screen_height -
  889.                      (vc->y*fix)/z;
  890.  
  891. #ifdef DEBUG
  892. sprintf(dbg,"vertice #%ld\nxp=%ld yp=%ld \n",i,pt[i].x,pt[i].y);
  893. write_dbg(dbg);
  894. sprintf(dbg,"x=%ld y=%ld z=%ld\n",vc->x,vc->y,z);
  895. write_dbg(dbg);
  896. #endif
  897.         
  898.                 }
  899.                 break;
  900.         case(PARAL_P) :
  901.     /* uso proiezione parallela */
  902.             for(i=0 ;i<obj->numverts ;i++ ) 
  903.                 {
  904.                 vc=&obj->vcamera[i];
  905.                 pt[i].x=in->half_screen_width + 
  906.                     (vc->x >> SFIXV);
  907.                 pt[i].y=in->half_screen_height + 
  908.                     ((vc->y*fix1) >> (2*SFIXV));
  909.                 }
  910.                 break;
  911.         }
  912.     /* genero lista di poligoni gia' proiettati */
  913.     vc=obj->vcamera;
  914.     for(curr_poly=0 ;curr_poly<obj->numpolys ;curr_poly++) 
  915.         {
  916.         pol=&obj->polys[curr_poly];
  917.         if (pol->visible!=NULL AND pol->clipped==NULL)
  918.             {
  919.     /* reinizializzo puntatore a indice su lista poligoni */
  920.     /* per velocizzare il successivo riordino          */
  921.             wpl=&in->worldpolys[id];
  922.             iwp[id++]=(long int )wpl;
  923.             mx=0;
  924.             my=0;
  925.             mz=0;
  926.             wpl->numpoints=pol->numpoints;
  927.             wpl->shade=pol->shade;
  928.             wpl->vmode=obj->shade;        
  929.             wpl->obj=obj->id;    
  930.             wpl->npol=curr_poly;
  931.         
  932.             i=pol->vertexlist0;
  933.             wpl->x1=pt[i].x;
  934.             wpl->y1=pt[i].y;
  935.             mx=mx+vc[i].x;
  936.             my=my+vc[i].y;
  937.             mz=mz+vc[i].z;
  938.             
  939.             if (pol->numpoints>=2)            
  940.                 {
  941.                 i=pol->vertexlist1;
  942.                 wpl->x2=pt[i].x;
  943.                 wpl->y2=pt[i].y;
  944.                 mx=mx+vc[i].x;
  945.                 my=my+vc[i].y;
  946.                 mz=mz+vc[i].z;
  947.                 }
  948.  
  949.             if (pol->numpoints>=3)        
  950.                 {
  951.                 i=pol->vertexlist2;
  952.                 wpl->x3=pt[i].x;
  953.                 wpl->y3=pt[i].y;
  954.                 mx=mx+vc[i].x;
  955.                 my=my+vc[i].y;
  956.                 mz=mz+vc[i].z;
  957.             
  958.                 wpl->x4=wpl->x1;
  959.                 wpl->y4=wpl->y1;    
  960.                 }
  961.  
  962.             if (pol->numpoints==4) 
  963.                 {
  964.                 i=pol->vertexlist3;
  965.                 wpl->x4=pt[i].x;
  966.                 wpl->y4=pt[i].y;
  967.                 mx=mx+vc[i].x;
  968.                 my=my+vc[i].y;
  969.                 mz=mz+vc[i].z;
  970.  
  971.                 wpl->x5=wpl->x1;
  972.                 wpl->y5=wpl->y1;
  973.                 }
  974. /* calcolo ora il punto medio */    
  975.             ii=pol->numpoints << SFIXV;
  976.             mx=mx/ii ;
  977.             my=my/ii ;
  978.             mz=mz/ii ;
  979. /* 
  980.    ora calcolo la distanza, considerando che l'osservatore ora 
  981.    e' nell'origine
  982.    (non calcolo la radice quadrata, poiche' altrimenti aumento l'errore
  983.     e il tempo di calcolo).
  984. */
  985.  
  986.             wpl->svalue=mx*mx + my*my + mz*mz;
  987. #ifdef DEBUG
  988. sprintf(dbg,"dist=%ld\n",wpl->svalue);
  989. write_dbg(dbg);
  990. #endif
  991.             }
  992.         }
  993.     }
  994.    obj=nextobj(in);
  995.    }while(obj!=NULL);
  996.  
  997. in->total_polys=id;
  998.  
  999. /********************/
  1000. }
  1001.  
  1002. /**********************************************
  1003.  ** riporto oggetto attuale sul primo e      **
  1004.  ** resituisco puntatore a oggetto.          **
  1005.  **********************************************
  1006.  *** INPUT :                      * 
  1007.  * in -> valore > 0 restituito da display3d.  *
  1008.  *** OUTPUT:                      *
  1009.  * puntatore a struttura 1# oggetto.          *
  1010.  **********************************************/
  1011. struct objectnode *resetobj(in)
  1012. struct ambient3d *in;
  1013. {
  1014.  
  1015. in->attuale=0;
  1016.  
  1017. return (pobj(in));
  1018. }
  1019.  
  1020. /**********************************************
  1021.  ** sposto oggetto attuale su prossimo se    **
  1022.  ** finiti restituisco 0 altrimenti puntore  **
  1023.  ** a oggetto.                     **
  1024.  **********************************************
  1025.  *** INPUT :                      * 
  1026.  * in -> valore > 0 restituito da display3d.  *
  1027.  *** OUTPUT:                      *
  1028.  * >0 - puntatore a oggetto successivo.       *
  1029.  * =0 - oggetti finiti.                  *
  1030.  **********************************************/
  1031. struct objectnode *nextobj(in)
  1032. struct ambient3d *in;
  1033. {
  1034.  
  1035. if (in->attuale==in->total_objects-1) return(0); 
  1036.  
  1037. in->attuale=in->attuale+1;
  1038.  
  1039. return (pobj(in));
  1040.  
  1041. /*******************************************
  1042.  ** restituisce indirizzo oggetto attuale **
  1043.  *******************************************/
  1044.  
  1045. struct objectnode *pobj(in)
  1046. struct ambient3d *in;
  1047. {
  1048.  
  1049. return(&in->objects[in->attuale]);
  1050.  
  1051. }
  1052.  
  1053. /************************************************
  1054.  ** aggiorna tutti i valori precalcolati sul   **
  1055.  ** oggetto corrente.                     **
  1056.  ************************************************
  1057.  *** INPUT :                        * 
  1058.  * in -> valore > 0 restituito da display3d.    *
  1059.  *** OUTPUT:                    *
  1060.  * nessuno.                    *
  1061.  ************************************************/
  1062. void aggobj(in)
  1063. struct ambient3d *in;
  1064. {
  1065.  
  1066. computeobjectbox(in);
  1067.  
  1068. }
  1069.  
  1070. /**********************************************/
  1071. /** calcola il bounding box dell'oggetto at- **/
  1072. /** tuale per il controllo delle collisioni  **/
  1073. /**********************************************/
  1074. void computeobjectbox(in)
  1075. struct ambient3d *in;
  1076. {
  1077. struct objectnode *ob;
  1078. struct vertex *vt;
  1079. long int xmax,ymax,zmax,xmin,ymin,zmin;
  1080. long int x,y,z,i;
  1081.  
  1082. ob=pobj(in);
  1083.  
  1084. vt=ob->vlocal;
  1085.  
  1086. xmax=vt[0].x;
  1087. ymax=vt[0].y;
  1088. zmax=vt[0].z;
  1089. xmin=vt[0].x;
  1090. ymin=vt[0].y;
  1091. zmin=vt[0].z;
  1092.  
  1093. for(i=1 ;i<ob->numverts ; i++)
  1094.     {
  1095.     x=vt[i].x;
  1096.     y=vt[i].y;
  1097.     z=vt[i].z;
  1098.     if (x>xmax) xmax=x;
  1099.     if (x<xmin) xmin=x;
  1100.     if (y>ymax) ymax=y;
  1101.     if (y<ymin) ymin=y;
  1102.     if (z>zmax) zmax=z;
  1103.     if (z<zmin) zmin=z;
  1104.     }
  1105.  
  1106. ob->xmax=xmax;
  1107. ob->ymax=ymax;
  1108. ob->zmax=zmax;
  1109. ob->xmin=xmin;
  1110. ob->ymin=ymin;
  1111. ob->zmin=zmin;
  1112.  
  1113. }
  1114.  
  1115. /************************************
  1116.  ** routin richiamata da quicksort **
  1117.  ** occhio e' recursiva.       **
  1118.  ** I parametri non possono percio'**
  1119.  ** essere passati tramite registri**
  1120.  ************************************/
  1121. void qsort(lo0,hi0,pol,count)
  1122. long int lo0;
  1123. long int hi0;
  1124. long int *pol;
  1125. long int *count;
  1126. {
  1127. long int it, lo, hi, mid, t;
  1128. struct polytemp *wpl;
  1129.  
  1130. lo=lo0;
  1131. hi=hi0;
  1132. it=count[0];
  1133.  
  1134. if (hi0>lo0)
  1135. /* stabilisco arbitrariamente il pivot point nel mezzo dell'array */
  1136.     {
  1137.     wpl=(struct polytemp *)pol[(lo0+hi0)>>1];
  1138.     mid=wpl->svalue;
  1139.  
  1140. /* eseguo il loop finche non incrocio indici */
  1141.     while(lo<=hi)
  1142. /* trovo il primo elemento minore o uguale a mid partendo da sinistra */
  1143.         {
  1144.         wpl=(struct polytemp *)pol[lo];
  1145.         while(lo<hi0 AND wpl->svalue>mid)
  1146.             {
  1147.             lo++;
  1148.             wpl=(struct polytemp *)pol[lo];
  1149.             it++;
  1150.             }
  1151. /* trovo il primo elemento maggiore o uguale a mid partendo da destra */
  1152.         wpl=(struct polytemp *)pol[hi];
  1153.         while(hi>lo0 AND wpl->svalue<mid)
  1154.             {    
  1155.             hi--;
  1156.             wpl=(struct polytemp *)pol[hi];
  1157.             it++;
  1158.             }
  1159. /* se gli indici non si sono incrociati scambio elementi */
  1160.         if (lo<=hi)
  1161.             {
  1162.             t=pol[hi];
  1163.             pol[hi]=pol[lo];
  1164.             pol[lo]=t;
  1165.             lo++;
  1166.             hi--;
  1167.             }
  1168.         }
  1169.     }        
  1170.  
  1171. count[0]=it;
  1172.  
  1173. if (lo0<hi) qsort(lo0,hi,pol,count);
  1174.  
  1175. if (lo<hi0) qsort(lo,hi0,pol,count);
  1176.  
  1177. }
  1178.  
  1179. /******************************************************
  1180.  ** visualizza un gruppo di poligoni nella rastport  **
  1181.  ** corrente(purche di 3 o 4 lati).              **    
  1182.  ** E' ottimizzata il piu' possibile.             **
  1183.  ******************************************************
  1184.  **** INPUT :                         ** 
  1185.  **  graf ->valore non 0 ritornato da ini_g().         **
  1186.  **  iwp  ->puntatore ad array di puntatori a strut- **
  1187.  **         ture polytemp.                 ** 
  1188.  **  total_polys ->n# totale elementi nell'array iwp **
  1189.  **  colb ->se >=0 allora poligoni con bordo di quel **
  1190.  **         colore.                     **
  1191.  **** OUTPUT:                         **
  1192.  ** nessuno.                         **
  1193.  ******************************************************/
  1194. void paintpol(graf,iwp,total_polys,colb)
  1195. struct grafica *graf;
  1196. long int *iwp;
  1197. long int total_polys;
  1198. long int colb;
  1199. {
  1200. struct RastPort *rast;
  1201. struct polytemp *wpl;
  1202. long int i,f,f1;
  1203. long int ob,m1,mx;
  1204. short int *pvert;
  1205.  
  1206. if ((long int)graf<=NULL OR (long int)(graf->rast)<=NULL) return(0); 
  1207.  
  1208. rast=graf->rast;
  1209. mx=graf->lb_af;
  1210. /* default bordo poligoni assente */
  1211. BNDRYOFF(rast)
  1212. if (colb>=NULL) SetOutlinePen(rast,colb);
  1213.  
  1214. f1=((struct polytemp *)iwp[0])->shade;
  1215. SetAPen(rast,f1);
  1216. m1=NULL;
  1217. ob=((struct polytemp *)iwp[0])->obj;
  1218. for (i=0;i<total_polys;i++)
  1219.     {
  1220.     wpl=(struct polytemp *)iwp[i];
  1221.     pvert=(short int *)wpl;
  1222.     /* visualizzo il poligono */ 
  1223. /** visualizza un poligono proiettato **/
  1224.     f=wpl->shade;
  1225.     if (f1!=f)
  1226.         {
  1227.         SetAPen(rast,f);
  1228.         f1=f;
  1229.         }    
  1230.     switch(wpl->numpoints)
  1231.         {
  1232.         case (1) :
  1233.     /* 1 vertice -> disegno un punto */
  1234.             WritePixel(rast,pvert[0],pvert[1]);
  1235.             break;
  1236.         case (2) :
  1237.     /* 2 vertici -> disegno una linea */
  1238.             Move(rast,pvert[0],pvert[1]);
  1239.             Draw(rast,pvert[2],pvert[3]);
  1240.             break;
  1241.         case (3) :
  1242.     /* 3 vertici -> poligono triangolare disegno in base a wpl->vmode */
  1243.             if (wpl->vmode!=WIREF) 
  1244.                 {
  1245.                 AreaMove(rast,pvert[0],pvert[1]);
  1246.                 AreaDraw(rast,pvert[2],pvert[3]);
  1247.                 AreaDraw(rast,pvert[4],pvert[5]);
  1248.                 AreaEnd(rast);
  1249.                 }
  1250.             else
  1251.                 {
  1252.                 Move(rast,pvert[0],pvert[1]);
  1253.                 PolyDraw(rast,4,pvert);
  1254.                 }
  1255.             break;
  1256.         case (4) :
  1257.     /* 4 vertici -> poligono quadrangolare disegno in base a wpl->vmode*/
  1258.             if (wpl->vmode!=WIREF) 
  1259.                 {
  1260.                 AreaMove(rast,pvert[0],pvert[1]);
  1261.                 AreaDraw(rast,pvert[2],pvert[3]);
  1262.                 AreaDraw(rast,pvert[4],pvert[5]);
  1263.                 AreaDraw(rast,pvert[6],pvert[7]);
  1264.                 AreaEnd(rast);
  1265.                 }
  1266.             else
  1267.                 {
  1268.                 Move(rast,pvert[0],pvert[1]);
  1269.                 PolyDraw(rast,5,pvert);
  1270.                 }
  1271.             break;
  1272.         }
  1273.     }
  1274.  
  1275. }
  1276.  
  1277. /**********************************************
  1278.  ** effettuo ordinamento poligoni proiettati **
  1279.  ** via quicksort                 **
  1280.  ** mediamente 4 volte piu' veloce dello     ** 
  1281.  ** shellsort.                     **
  1282.  **********************************************
  1283.  **** INPUT :                     **
  1284.  ** len -> numero di poligoni da riordinare  **
  1285.  ** pol -> array di puntatori alle strutture **
  1286.  **        polytemp, da riordinare.          **
  1287.  **** OUTPUT:                     **
  1288.  ** n# di passi effettuati per l'ordinamento.** 
  1289.  **********************************************/
  1290. long int quicksort(len,pol)
  1291. long int len;
  1292. long int *pol;
  1293. {
  1294. long int itera;
  1295.  
  1296. itera=0;
  1297.  
  1298. if (len>NULL) qsort(0,len-1,pol,&itera);
  1299.  
  1300. return(itera);
  1301. }
  1302. /*******************************************************************/
  1303.