home *** CD-ROM | disk | FTP | other *** search
/ 3D World 3 (Spanish) / 3DWorld_03.iso / mac / ARTIC / W_PROG / CUBO.C
C/C++ Source or Header  |  1997-03-04  |  11KB  |  339 lines

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <stdlib.h>
  4. #include <graph.h>
  5.  
  6. #define CUAD(a) a*a
  7. #define NUMVERT 8
  8. #define TRUE 1
  9. #define FALSE 0
  10. #define ROUNDOFF 1.e-6
  11. #define vec4_set(a,b,c,d,e)  {a[0]=b;a[1]=c;a[2]=d;a[3]=e;}
  12.  
  13. void calcula_mat_rot(double cx,double cy,double cz,double angrot);
  14. void V4XM44(float a[4], float b[4][4], float c[4]);
  15. void M44XM44(float a[4][4], float b[4][4], float c[4][4]);
  16. void M44XM44a(float a[4][4], float b[4][4]);
  17. void rellena_vertices(float lad );
  18. void rellena_caras();
  19. int normaliza(float *x, float *y, float *z);
  20. void cross(float *a, float *b, float *c);
  21. void boundig_box(float V[NUMVERT][4],float *xmin,float *xmax,float *ymin,float *ymax);
  22. int interior_a_poly(float x, float y, int i );
  23.  
  24. float mat_rot[4][4]; //matriz de rotaci¢n
  25. float VERTICES[NUMVERT][4];  //array inicial de vertices
  26. float VERTransf[NUMVERT][4]; //array de vertices rotados
  27. int CARAS[6][5]; //array de caras. Por cada cara contiene el indice
  28.                  //de los vertices que la componen y un flag de visibilidad
  29.                  //0 -cara aculta
  30.                  //1 -cara visible
  31.  
  32.  
  33.  
  34. main(){
  35. float vecrot[3]; //vector del eje de rotaci¢n
  36. float normal[3]; //vector normal
  37. float angrot; //angulo de rotaci¢n en radianes
  38. float l; //lado del cubo
  39. float vectemp1[3],vectemp2[3]; //vectores temporales
  40. float modulo;
  41. float xmin,xmax,ymin,ymax;
  42. int ind, ind1,ind3;
  43. int ejey, ejex;
  44.  
  45. _setvideomode( _VRES16COLOR);
  46. _setvieworg(320,200);
  47.  
  48.  
  49. l=100.;
  50. //Se define el vector del eje de rotacion
  51. vecrot[0]=1.;
  52. vecrot[1]=0.5;
  53. vecrot[2]=0.5;
  54.  
  55. rellena_vertices(l/2.);
  56. rellena_caras();
  57. ind3=0;
  58. for(; ;){ //ciclo de rotacion
  59.   angrot=3.1416*ind3/180.;
  60.  
  61.   //Normalizaci¢n del vector de rotaci¢n
  62.   normaliza( &vecrot[0],&vecrot[1],&vecrot[2]);
  63.   //C†lculo de la matriz de rotaci¢n
  64.   calcula_mat_rot(vecrot[0],vecrot[1],vecrot[2],angrot);
  65.  
  66.   //Se aplica la transformacion de rotacion a los vertices
  67.   for(ind=0;ind<8; ind++)
  68.       V4XM44(VERTICES[ind], mat_rot, VERTransf[ind]);
  69.  
  70.   //Selecci¢n del boundig box del cubo (xmax,xmin,ymax,ymin)
  71.   boundig_box(VERTransf,&xmin,&xmax,&ymin,&ymax);
  72.  
  73.   //C†lculo de las normales por cara
  74.   for(ind=0;ind<6; ind++){
  75.        for(ind1=0;ind1<3; ind1++){
  76.          vectemp1[ind1]=VERTransf[CARAS[ind][1]][ind1]-
  77.                           VERTransf[CARAS[ind][0]][ind1];
  78.          vectemp2[ind1]=VERTransf[CARAS[ind][2]][ind1]-
  79.                           VERTransf[CARAS[ind][1]][ind1];
  80.          }
  81.        cross(vectemp1,vectemp2,normal);
  82.        if(normal[2]<=1.e-15 ) CARAS[ind][4]=0.; //cara oculta
  83.        else  CARAS[ind][4]=1.;                  //cara visible
  84.       }
  85.   _setcolor(8);
  86.  
  87.   //ciclo de barrido de pantalla por el bounding box
  88.   for(ejex=xmin; ejex<=xmax; ejex++)
  89.     for(ejey=ymin; ejey<=ymax; ejey++)
  90.        for(ind=0;ind<6; ind++){//ciclo por las caras
  91.          if(CARAS[ind][4]==1.){ //filtro de caras visibles
  92.            if( interior_a_poly((float)ejex, (float)ejey, ind )==1)
  93.              _setpixel(ejex,ejey);
  94.            }
  95.          }
  96.   //se dibujan las aristas visibles del cubo
  97.   _setcolor(10);
  98.   for(ind=0;ind<6; ind++){
  99.      if(CARAS[ind][4]==1.){
  100.       _moveto( (int)VERTransf[ CARAS[ind][0] ][0], (int) VERTransf[ CARAS[ind][0] ][1] );
  101.       for(ind1=1;ind1<4; ind1++)
  102.         _lineto( (int)VERTransf[ CARAS[ind][ind1] ][0], (int) VERTransf[ CARAS[ind][ind1] ][1] );
  103.        _lineto( (int)VERTransf[ CARAS[ind][0] ][0], (int) VERTransf[ CARAS[ind][0] ][1] );
  104.       }
  105.    }
  106.   ind3++;
  107.   if (getch()==27)
  108.     break;
  109.   _clearscreen(_GCLEARSCREEN);
  110.  
  111.   }//fin de ciclo de angulo
  112. _setvideomode(_DEFAULTMODE);
  113. }//fin de main
  114.  
  115.  
  116. //Funci¢n para la obtencion de la matriz concatenada de rotaci¢n
  117. //alrededor de un eje arbitrario con cosenos directores cx,cy,cz, en
  118. //un †ngulo de rotacion angrot.
  119.  
  120. void calcula_mat_rot(double cx,double cy,double cz,double angrot)
  121. {
  122. double d;
  123. float Rx[4][4],Rxinv[4][4],Ry[4][4],Ryinv[4][4],Rdelta[4][4];
  124.  
  125. if(angrot==0.)
  126.   {//Devuelve la matriz identidad si angrot=0
  127.   vec4_set(mat_rot[0],1.,0.,0.,0.);
  128.   vec4_set(mat_rot[1],0.,1.,0.,0.);
  129.   vec4_set(mat_rot[2],0.,0.,1.,0.);
  130.   vec4_set(mat_rot[3],0.,0.,0.,1.);
  131.   }
  132.  
  133. else
  134.   {
  135.   d=sqrt(cy*cy + cz*cz);
  136.  
  137.   if(d==0.0)
  138.     {//si el eje de rotaci¢n coincide con el eje x
  139.     vec4_set(mat_rot[0],1.,0.,0.,0.);
  140.     vec4_set(mat_rot[1],0.,cos(angrot),sin(angrot),0.);
  141.     vec4_set(mat_rot[2],0.,-sin(angrot),cos(angrot),0.);
  142.     vec4_set(mat_rot[3],0.,0.,0.,1.);
  143.     }
  144.  
  145.   else
  146.     {
  147.     //Formacion de las matrices de rotacion
  148.  
  149.     //Matriz de transformacion alrededor del eje x
  150.     vec4_set(Rx[0],1.0,0.,0.,0.);
  151.     vec4_set(Rx[1],0.,cz/d,cy/d,0.);
  152.     vec4_set(Rx[2],0.,-cy/d,cz/d,0.);
  153.     vec4_set(Rx[3],0.,0.,0.,1.);
  154.  
  155.     //Inversa de la matriz de transformacion alrededor del eje x
  156.     vec4_set(Rxinv[0],1.0,0.,0.,0.);
  157.     vec4_set(Rxinv[1],0.,cz/d,-cy/d,0.);
  158.     vec4_set(Rxinv[2],0.,cy/d,cz/d,0.);
  159.     vec4_set(Rxinv[3],0.,0.,0.,1.);
  160.  
  161.     //Matriz de transformacion alrededor del eje y
  162.     vec4_set(Ry[0],d,0.,cx,0.);
  163.     vec4_set(Ry[1],0.,1.,0.,0.);
  164.     vec4_set(Ry[2],-cx,0.,d,0.);
  165.     vec4_set(Ry[3],0.,0.,0.,1.);
  166.  
  167.     //Inversa de la matriz de transformacion alrededor del eje y
  168.     vec4_set(Ryinv[0],d,0.,-cx,0.);
  169.     vec4_set(Ryinv[1],0.,1.,0.,0.);
  170.     vec4_set(Ryinv[2],cx,0.,d,0.);
  171.     vec4_set(Ryinv[3],0.,0.,0.,1.);
  172.  
  173.     //Matriz de rotacion alrededor del eje  arbitrario
  174.     vec4_set(Rdelta[0],cos(angrot),sin(angrot),0.,0.);
  175.     vec4_set(Rdelta[1],-sin(angrot),cos(angrot),0.,0.);
  176.     vec4_set(Rdelta[2],0.,0.,1.,0.);
  177.     vec4_set(Rdelta[3],0.,0.,0.,1.);
  178.  
  179.     //Obtencion de la matriz concatenada de transformacion
  180.     M44XM44(Rx, Ry,mat_rot);
  181.     M44XM44a(mat_rot, Rdelta);
  182.     M44XM44a(mat_rot, Ryinv);
  183.     M44XM44a(mat_rot, Rxinv);
  184.     }
  185.   }
  186. }
  187.  
  188. //----------------------------------------------------
  189. //  Multiplica un vector a[4] por una matriz 4x4:
  190. //  c = a*b;
  191. //  El resultado se almacena en el vector c
  192. //  -----------------------------------------------------
  193.  
  194. void V4XM44(float a[4], float b[4][4], float c[4])
  195. {
  196.    int j;
  197.    float work[4];
  198.    
  199.    for (j=0; j<4; j++) {
  200.       work[j] = a[0]*b[0][j] + a[1]*b[1][j] + a[2]*b[2][j] + a[3]*b[3][j];
  201.       }
  202.    memcpy(c, work, 4*sizeof(float));
  203. }
  204.  
  205. //----------------------------------------------------
  206. //  Multiply dos matrices matrices 4x4:
  207. //  c = a*b;
  208. //  El resultado se almacena en c
  209. //  -----------------------------------------------------
  210. void M44XM44(float a[4][4], float b[4][4], float c[4][4])
  211. {
  212.    int j;
  213.    float work[4][4];
  214.    
  215.    for (j=0; j<4;j++) {
  216.       work[0][j] = a[0][0]*b[0][j] + a[0][1]*b[1][j] + a[0][2]*b[2][j] + a[0][3]*b[3][j];
  217.       work[1][j] = a[1][0]*b[0][j] + a[1][1]*b[1][j] + a[1][2]*b[2][j] + a[1][3]*b[3][j];
  218.       work[2][j] = a[2][0]*b[0][j] + a[2][1]*b[1][j] + a[2][2]*b[2][j] + a[2][3]*b[3][j];
  219.       work[3][j] = a[3][0]*b[0][j] + a[3][1]*b[1][j] + a[3][2]*b[2][j] + a[3][3]*b[3][j];
  220.       }
  221.    memcpy(c, work, 16*sizeof(float));
  222. }
  223.  
  224. //----------------------------------------------------
  225. //  Multiplica dos matrices 4x4:
  226. //  a = a*b;
  227. //  El resultado se almacena en a
  228. //  -----------------------------------------------------
  229. void M44XM44a(float a[4][4], float b[4][4])
  230. {
  231.    int j;
  232.    float work[4][4];
  233.    
  234.    for (j=0; j<4;j++) {
  235.       work[0][j] = a[0][0]*b[0][j] + a[0][1]*b[1][j] + a[0][2]*b[2][j] + a[0][3]*b[3][j];
  236.       work[1][j] = a[1][0]*b[0][j] + a[1][1]*b[1][j] + a[1][2]*b[2][j] + a[1][3]*b[3][j];
  237.       work[2][j] = a[2][0]*b[0][j] + a[2][1]*b[1][j] + a[2][2]*b[2][j] + a[2][3]*b[3][j];
  238.       work[3][j] = a[3][0]*b[0][j] + a[3][1]*b[1][j] + a[3][2]*b[2][j] + a[3][3]*b[3][j];
  239.       }
  240.    memcpy(a, work, 16*sizeof(float));
  241. }
  242.  
  243. void rellena_vertices(float lad )
  244. {
  245.    int ind;
  246.    //Rellena el array de VERTICES con las coordenadas de los vertices del cubo
  247.  
  248.    vec4_set(VERTICES[0],lad, lad, -lad, 0.);
  249.    vec4_set(VERTICES[1],-lad, lad, -lad, 0.);
  250.    vec4_set(VERTICES[2],-lad, lad, lad, 0.);
  251.    vec4_set(VERTICES[3],lad, lad, lad, 0.);
  252.    vec4_set(VERTICES[4],lad, -lad, -lad, 0.);
  253.    vec4_set(VERTICES[5],lad, -lad, lad, 0.);
  254.    vec4_set(VERTICES[6],-lad, -lad, lad, 0.);
  255.    vec4_set(VERTICES[7],-lad, -lad, -lad, 0.);
  256. }
  257. void rellena_caras()
  258. {
  259. //Rellena el aray de CARAS con el indice de los vertices que componen cada cara
  260. vec4_set(CARAS[0],0,1,2,3); //superior
  261. vec4_set(CARAS[1],4,5,6,7); //inferior
  262. vec4_set(CARAS[2],5,3,2,6); //delantera
  263. vec4_set(CARAS[3],4,7,1,0); //trasera
  264. vec4_set(CARAS[4],4,0,3,5); //derecha
  265. vec4_set(CARAS[5],7,6,2,1); //izquierda
  266. }
  267.  
  268. //Normaliza al vector de componentes (x,y,z)
  269. normaliza(float *x, float *y, float *z)
  270. {
  271.         //se devuelve el vector normalizado
  272.         double modulo,xx,yy,zz;
  273.         xx=(*x);
  274.         yy=(*y);
  275.         zz=(*z);
  276.         modulo=sqrt(CUAD(xx)+CUAD(yy)+CUAD(zz));
  277.         if (modulo<ROUNDOFF)  {
  278.                         return(FALSE);
  279.                         }
  280.         *x = (xx/modulo);
  281.         *y = (yy/modulo);
  282.         *z = (zz/modulo);
  283.         return(TRUE);
  284. }
  285.  
  286. //Calcula el producto vectorial de dos vectores c=a x b
  287. void cross(float *a, float *b, float *c)
  288. {
  289.   c[0] = a[1]*b[2] - a[2]*b[1];
  290.   c[1] = a[2]*b[0] - a[0]*b[2];
  291.   c[2] = a[0]*b[1] - a[1]*b[0];
  292. }
  293.  
  294. //Determina el bounding box de un conjunto de puntos
  295. void boundig_box(float V[NUMVERT][4],float *xmin,float *xmax,float *ymin,float *ymax)
  296. {
  297. int ind;
  298. *ymin=999999.;
  299. *ymax=-999999.;
  300. *xmin=999999.;
  301. *xmax=-999999.;
  302.  
  303. for(ind=0;ind<NUMVERT; ind++)
  304.     {
  305.     *ymin=*ymin>V[ind][1]?V[ind][1]:*ymin;
  306.     *ymax=*ymax<V[ind][1]?V[ind][1]:*ymax;
  307.     *xmin=*xmin>V[ind][0]?V[ind][0]:*xmin;
  308.     *xmax=*xmax<V[ind][0]?V[ind][0]:*xmax;
  309.     }
  310. }
  311.  
  312. // Rutina que determina si un punto es interior o exterior al poligono
  313. //de cuatro lados formado por los cuatro vertices de cada cara
  314. //proyectados en el plano xy
  315.  
  316. int interior_a_poly(float x, float y, int i )
  317. {
  318. unsigned ss,cort;
  319. float trasl[4][2];
  320.  
  321.   for(ss=0 ; ss<4 ; ss++)
  322.      {
  323.      trasl[ss][0]=VERTransf[ CARAS[i][ss] ][0]- x   ;
  324.      trasl[ss][1]=VERTransf[ CARAS[i][ss] ][1] - y   ;
  325.      }
  326.   for (cort=ss=0;ss<4;ss++)
  327.      if ((trasl[ss][1]*trasl[(ss+1)%4][1]<0.0) && (( (trasl[ss][0]>0.0) &&
  328.      (trasl[(ss+1)%4][0]>0.0)) ||
  329.      ((trasl[ss][0]-(trasl[ss][1]*(trasl[(ss+1)%4][0]-trasl[ss][0]))/(trasl[(ss+1)%4][1]-
  330.      trasl[ss][1]))>0.0) ) ) cort ++;
  331.  
  332.   if ((cort%2) !=0)
  333.      return(1); //pto. interior
  334.  
  335.   return(0); //pto. exterior
  336. }
  337.  
  338.  
  339.