home *** CD-ROM | disk | FTP | other *** search
/ 3D World 5 (Spanish) / 3DWorld_05.iso / mac / ARTIC / W_PROG / CUBO.C next >
C/C++ Source or Header  |  1997-05-09  |  14KB  |  446 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_tras_a_camara();
  14. void calcula_camrot();
  15. void calcula_proy_a_camara();
  16. void calcula_perspectiva(float p);
  17. void calcula_mat_rot(double cx,double cy,double cz,double angrot);
  18. void V4XM44(float a[4], float b[4][4], float c[4]);
  19. void M44XM44(float a[4][4], float b[4][4], float c[4][4]);
  20. void M44XM44a(float a[4][4], float b[4][4]);
  21. void rellena_vertices(float lad );
  22. void rellena_caras();
  23. int normaliza(float *x, float *y, float *z);
  24. void cross(float *a, float *b, float *c);
  25. void boundig_box(float V[NUMVERT][4],float *xmin,float *xmax,float *ymin,float *ymax);
  26. int interior_a_poly(float x, float y, int i );
  27.  
  28. float zoom;
  29. float culling;
  30. float mat_rot[4][4]; //matriz de rotaci¢n
  31. float VERTICES[NUMVERT][4];  //array inicial de vertices
  32. float VERTransf[NUMVERT][4]; //array de vertices rotados
  33. int CARAS[6][5]; //array de caras. Por cada cara contiene el indice
  34.                  //de los vertices que la componen y un flag de visibilidad
  35.                  //0 -cara aculta
  36.                  //1 -cara visible
  37.  
  38. float mat_tras[4][4];
  39. float mat_rotcam[4][4];
  40. float mat_proy[4][4];
  41. float mat_fin[4][4];
  42. float mat_d[4][4];
  43. float N[3];
  44. float V[3];
  45. float U[3];
  46. //float v[3];
  47. float veccamera[3];
  48. float vecfoco[3];
  49. float ang; //angulo de rotacion de camara
  50.  
  51. main(){
  52. float vecrot[3]; //vector del eje de rotaci¢n
  53. float normal[3]; //vector normal
  54. float angrot; //angulo de rotaci¢n en radianes
  55. float vectemp1[3],vectemp2[3],vectemp3[3]; //vectores temporales
  56. float modulo;
  57. float xmin,xmax,ymin,ymax;
  58. int ind, ind1,ind3;
  59. int ejey, ejex;
  60.  
  61. _setvideomode( _VRES16COLOR);
  62. _setvieworg(320,200);
  63. //factor de zoom de camara
  64. zoom = 200;
  65. //Se define el vector del eje de rotacion
  66. vecrot[0]=1.;
  67. vecrot[1]=0.5;
  68. vecrot[2]=0.5;
  69. printf("Introduce el punto del camara\n");
  70. scanf("%f, %f, %f",&veccamera[0],&veccamera[1],&veccamera[2]);
  71. printf("Introduce el punto del foco\n");
  72. scanf("%f, %f, %f",&vecfoco[0],&vecfoco[1],&vecfoco[2]);
  73. _clearscreen(_GCLEARSCREEN); 
  74. rellena_vertices(5); //rellenamos con un cubo de lado 5
  75. rellena_caras();
  76.  
  77. ind3=0;
  78. N[0]=vecfoco[0]-veccamera[0];
  79. N[1]=vecfoco[1]-veccamera[1];
  80. N[2]=vecfoco[2]-veccamera[2];
  81. normaliza( &N[0],&N[1],&N[2]);
  82.  
  83. V[0]=0-N[2]*N[0];
  84. V[1]=0-N[2]*N[1];
  85. V[2]=1-N[2]*N[2];
  86. normaliza( &V[0],&V[1],&V[2]);
  87. cross(N,V,U);
  88. normaliza( &U[0],&U[1],&U[2]);
  89. for(; ;){ //ciclo de rotacion
  90.   angrot=3.1416*ind3/180.;
  91.   //Normalizaci¢n del vector de rotaci¢n
  92.   normaliza( &vecrot[0],&vecrot[1],&vecrot[2]);
  93.   //C†lculo de la matriz de rotaci¢n
  94.   calcula_mat_rot(vecrot[0],vecrot[1],vecrot[2],angrot);
  95.   //Se aplica la transformacion de rotacion a los vertices
  96.   for(ind=0;ind<8; ind++)
  97.       V4XM44(VERTICES[ind], mat_rot, VERTransf[ind]);
  98.   for(ind=0;ind<6; ind++){
  99.         for(ind1=0;ind1<3; ind1++){
  100.          
  101.          vectemp1[ind1]=VERTransf[CARAS[ind][1]][ind1]-
  102.                           VERTransf[CARAS[ind][0]][ind1];
  103.          vectemp2[ind1]=VERTransf[CARAS[ind][2]][ind1]-
  104.                           VERTransf[CARAS[ind][1]][ind1];
  105.          vectemp3[ind1]=veccamera[ind1]-VERTransf[CARAS[ind][0]][ind1];
  106.          
  107.          }
  108.        cross(vectemp1,vectemp2,normal);
  109.        culling=normal[0]*vectemp3[0]+normal[1]*vectemp3[1]+normal[2]*vectemp3[2];
  110.        if(culling < 0.) CARAS[ind][4]=0.; //cara oculta
  111.        else  CARAS[ind][4]=1.;                  //cara visible
  112.       }            
  113.   
  114.   
  115.   calcula_tras_a_camara();
  116.   calcula_proy_a_camara();
  117.   M44XM44(mat_tras,mat_proy,mat_fin);
  118.   for(ind=0;ind<8;ind++)
  119.     {
  120.          
  121.         V4XM44(VERTransf[ind],mat_fin,VERTransf[ind]);
  122.         //linea alternativa para no rotar
  123.         //V4XM44(VERTICES[ind], mat_fin, VERTransf[ind]);
  124.         calcula_perspectiva(VERTransf[ind][2]);
  125.         V4XM44(VERTransf[ind],mat_d,VERTransf[ind]);
  126.     }
  127.   //  Selecci¢n del boundig box del cubo (xmax,xmin,ymax,ymin)
  128.   boundig_box(VERTransf,&xmin,&xmax,&ymin,&ymax);
  129.  
  130.   //  C†lculo de las normales por cara
  131.   _setcolor(8);
  132.  
  133.   //ciclo de barrido de pantalla por el bounding box
  134.   
  135.   for(ejex=xmin; ejex<=xmax; ejex++)
  136.     for(ejey=ymin; ejey<=ymax; ejey++)
  137.        for(ind=0;ind<6; ind++){//ciclo por las caras
  138.          if(CARAS[ind][4]==1.){ //filtro de caras visibles
  139.            if( interior_a_poly((float)ejex, (float)ejey, ind )==1)
  140.              _setpixel(ejex,ejey);
  141.            }                    
  142.          }
  143.   
  144.   // Se dibujan las aristas visibles del cubo
  145.   
  146.   _setcolor(10);
  147.   
  148.   for(ind=0;ind<6; ind++)  {
  149.          if(CARAS[ind][4]==1.){
  150.            _moveto( (int)VERTransf[ CARAS[ind][0] ][0], (int) VERTransf[ CARAS[ind][0] ][1]);
  151.            for(ind1=1;ind1<4; ind1++)
  152.            _lineto( (int)VERTransf[ CARAS[ind][ind1] ][0], (int) VERTransf[ CARAS[ind][ind1]][1]);
  153.            _lineto( (int)VERTransf[ CARAS[ind][0] ][0], (int) VERTransf[ CARAS[ind][0] ][1]);
  154.            }
  155.         }
  156.   ind3++;
  157.   
  158.   if (getch()==27)
  159.     break;
  160.   _clearscreen(_GCLEARSCREEN);
  161.  
  162.   }//fin de ciclo de angulo
  163. _setvideomode(_DEFAULTMODE);
  164. }//fin de main
  165.  
  166.  
  167. //Funci¢n para la obtencion de la matriz concatenada de rotaci¢n
  168. //alrededor de un eje arbitrario con cosenos directores cx,cy,cz, en
  169. //un †ngulo de rotacion angrot.
  170.  
  171. void calcula_mat_rot(double cx,double cy,double cz,double angrot)
  172. {
  173. double d;
  174. float Rx[4][4],Rxinv[4][4],Ry[4][4],Ryinv[4][4],Rdelta[4][4];
  175.  
  176. if(angrot==0.)
  177.   {//Devuelve la matriz identidad si angrot=0
  178.   vec4_set(mat_rot[0],1.,0.,0.,0.);
  179.   vec4_set(mat_rot[1],0.,1.,0.,0.);
  180.   vec4_set(mat_rot[2],0.,0.,1.,0.);
  181.   vec4_set(mat_rot[3],0.,0.,0.,1.);
  182.   }
  183.  
  184. else
  185.   {
  186.   d=sqrt(cy*cy + cz*cz);
  187.  
  188.   if(d==0.0)
  189.     {//si el eje de rotaci¢n coincide con el eje x
  190.     vec4_set(mat_rot[0],1.,0.,0.,0.);
  191.     vec4_set(mat_rot[1],0.,cos(angrot),sin(angrot),0.);
  192.     vec4_set(mat_rot[2],0.,-sin(angrot),cos(angrot),0.);
  193.     vec4_set(mat_rot[3],0.,0.,0.,1.);
  194.     }
  195.  
  196.   else
  197.     {
  198.     //Formacion de las matrices de rotacion
  199.  
  200.     //Matriz de transformacion alrededor del eje x
  201.     vec4_set(Rx[0],1.0,0.,0.,0.);
  202.     vec4_set(Rx[1],0.,cz/d,cy/d,0.);
  203.     vec4_set(Rx[2],0.,-cy/d,cz/d,0.);
  204.     vec4_set(Rx[3],0.,0.,0.,1.);
  205.  
  206.     //Inversa de la matriz de transformacion alrededor del eje x
  207.     vec4_set(Rxinv[0],1.0,0.,0.,0.);
  208.     vec4_set(Rxinv[1],0.,cz/d,-cy/d,0.);
  209.     vec4_set(Rxinv[2],0.,cy/d,cz/d,0.);
  210.     vec4_set(Rxinv[3],0.,0.,0.,1.);
  211.  
  212.     //Matriz de transformacion alrededor del eje y
  213.     vec4_set(Ry[0],d,0.,cx,0.);
  214.     vec4_set(Ry[1],0.,1.,0.,0.);
  215.     vec4_set(Ry[2],-cx,0.,d,0.);
  216.     vec4_set(Ry[3],0.,0.,0.,1.);
  217.  
  218.     //Inversa de la matriz de transformacion alrededor del eje y
  219.     vec4_set(Ryinv[0],d,0.,-cx,0.);
  220.     vec4_set(Ryinv[1],0.,1.,0.,0.);
  221.     vec4_set(Ryinv[2],cx,0.,d,0.);
  222.     vec4_set(Ryinv[3],0.,0.,0.,1.);
  223.  
  224.     //Matriz de rotacion alrededor del eje  arbitrario
  225.     vec4_set(Rdelta[0],cos(angrot),sin(angrot),0.,0.);
  226.     vec4_set(Rdelta[1],-sin(angrot),cos(angrot),0.,0.);
  227.     vec4_set(Rdelta[2],0.,0.,1.,0.);
  228.     vec4_set(Rdelta[3],0.,0.,0.,1.);
  229.  
  230.     //Obtencion de la matriz concatenada de transformacion
  231.     M44XM44(Rx, Ry,mat_rot);
  232.     M44XM44a(mat_rot, Rdelta);
  233.     M44XM44a(mat_rot, Ryinv);
  234.     M44XM44a(mat_rot, Rxinv);
  235.     }
  236.   }
  237. }
  238.  
  239. //----------------------------------------------------
  240. //  Multiplica un vector a[4] por una matriz 4x4:
  241. //  c = a*b;
  242. //  El resultado se almacena en el vector c
  243. //  -----------------------------------------------------
  244.  
  245. void V4XM44(float a[4], float b[4][4], float c[4])
  246. {
  247.    int j;
  248.    float work[4];
  249.    
  250.    for (j=0; j<4; j++) {
  251.       work[j] = a[0]*b[0][j] + a[1]*b[1][j] + a[2]*b[2][j] + a[3]*b[3][j];
  252.       }
  253.    memcpy(c, work, 4*sizeof(float));
  254. }
  255.  
  256. //----------------------------------------------------
  257. //  Multiply dos matrices matrices 4x4:
  258. //  c = a*b;
  259. //  El resultado se almacena en c
  260. //  -----------------------------------------------------
  261. void M44XM44(float a[4][4], float b[4][4], float c[4][4])
  262. {
  263.    int j;
  264.    float work[4][4];
  265.    
  266.    for (j=0; j<4;j++) {
  267.       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];
  268.       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];
  269.       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];
  270.       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];
  271.       }
  272.    memcpy(c, work, 16*sizeof(float));
  273. }
  274.  
  275. //----------------------------------------------------
  276. //  Multiplica dos matrices 4x4:
  277. //  a = a*b;
  278. //  El resultado se almacena en a
  279. //  -----------------------------------------------------
  280. void M44XM44a(float a[4][4], float b[4][4])
  281. {
  282.    int j;
  283.    float work[4][4];
  284.    
  285.    for (j=0; j<4;j++) {
  286.       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];
  287.       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];
  288.       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];
  289.       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];
  290.       }
  291.    memcpy(a, work, 16*sizeof(float));
  292. }
  293.  
  294. void rellena_vertices(float lad )
  295. {
  296.    int ind;
  297.    //Rellena el array de VERTICES con las coordenadas de los vertices del cubo
  298.  
  299.    vec4_set(VERTICES[0],lad, lad, -lad, 1.);
  300.    vec4_set(VERTICES[1],-lad, lad, -lad, 1.);
  301.    vec4_set(VERTICES[2],-lad, lad, lad, 1.);
  302.    vec4_set(VERTICES[3],lad, lad, lad, 1.);
  303.    vec4_set(VERTICES[4],lad, -lad, -lad, 1.);
  304.    vec4_set(VERTICES[5],lad, -lad, lad, 1.);
  305.    vec4_set(VERTICES[6],-lad, -lad, lad, 1.);
  306.    vec4_set(VERTICES[7],-lad, -lad, -lad, 1.);
  307. }
  308. void rellena_caras()
  309. {
  310. //Rellena el aray de CARAS con el indice de los vertices que componen cada cara
  311. vec4_set(CARAS[0],0,1,2,3); //superior
  312. vec4_set(CARAS[1],4,5,6,7); //inferior
  313. vec4_set(CARAS[2],5,3,2,6); //delantera
  314. vec4_set(CARAS[3],4,7,1,0); //trasera
  315. vec4_set(CARAS[4],4,0,3,5); //derecha
  316. vec4_set(CARAS[5],7,6,2,1); //izquierda
  317. }
  318.  
  319. //Normaliza al vector de componentes (x,y,z)
  320. normaliza(float *x, float *y, float *z)
  321. {
  322.         //se devuelve el vector normalizado
  323.         double modulo,xx,yy,zz;
  324.         xx=(*x);
  325.         yy=(*y);
  326.         zz=(*z);
  327.         modulo=sqrt(CUAD(xx)+CUAD(yy)+CUAD(zz));
  328.         if (modulo<ROUNDOFF)  {
  329.                         return(FALSE);
  330.                         }
  331.         *x = (xx/modulo);
  332.         *y = (yy/modulo);
  333.         *z = (zz/modulo);
  334.         return(TRUE);
  335. }
  336.  
  337. //Calcula el producto vectorial de dos vectores c=a x b
  338. void cross(float *a, float *b, float *c)
  339. {
  340.   c[0] = a[1]*b[2] - a[2]*b[1];
  341.   c[1] = a[2]*b[0] - a[0]*b[2];
  342.   c[2] = a[0]*b[1] - a[1]*b[0];
  343. }
  344.  
  345. //Determina el bounding box de un conjunto de puntos
  346. void boundig_box(float V[NUMVERT][4],float *xmin,float *xmax,float *ymin,float *ymax)
  347. {
  348. int ind;
  349. *ymin=999999.;
  350. *ymax=-999999.;
  351. *xmin=999999.;
  352. *xmax=-999999.;
  353.  
  354. for(ind=0;ind<NUMVERT; ind++)
  355.     {
  356.     *ymin=*ymin>V[ind][1]?V[ind][1]:*ymin;
  357.     *ymax=*ymax<V[ind][1]?V[ind][1]:*ymax;
  358.     *xmin=*xmin>V[ind][0]?V[ind][0]:*xmin;
  359.     *xmax=*xmax<V[ind][0]?V[ind][0]:*xmax;
  360.     }
  361. }
  362.  
  363. // Rutina que determina si un punto es interior o exterior al poligono
  364. //de cuatro lados formado por los cuatro vertices de cada cara
  365. //proyectados en el plano xy
  366.  
  367. int interior_a_poly(float x, float y, int i )
  368. {
  369. unsigned ss,cort;
  370. float trasl[4][2];
  371.  
  372.   for(ss=0 ; ss<4 ; ss++)
  373.      {
  374.      trasl[ss][0]=VERTransf[ CARAS[i][ss] ][0]- x   ;
  375.      trasl[ss][1]=VERTransf[ CARAS[i][ss] ][1] - y   ;
  376.      }
  377.   for (cort=ss=0;ss<4;ss++)
  378.      if ((trasl[ss][1]*trasl[(ss+1)%4][1]<0.0) && (( (trasl[ss][0]>0.0) &&
  379.      (trasl[(ss+1)%4][0]>0.0)) ||
  380.      ((trasl[ss][0]-(trasl[ss][1]*(trasl[(ss+1)%4][0]-trasl[ss][0]))/(trasl[(ss+1)%4][1]-
  381.      trasl[ss][1]))>0.0) ) ) cort ++;
  382.  
  383.   if ((cort%2) !=0)
  384.      return(1); //pto. interior
  385.  
  386.   return(0); //pto. exterior
  387. }
  388.  
  389. void calcula_proy_a_camara()
  390. {
  391.   vec4_set(mat_proy[0],U[0],V[0],N[0],0);
  392.   vec4_set(mat_proy[1],U[1],V[1],N[1],0);
  393.   vec4_set(mat_proy[2],U[2],V[2],N[2],0);
  394.   vec4_set(mat_proy[3],0,0,0,1);
  395. }
  396.  
  397. void calcula_camrot()
  398. {  
  399.   vec4_set(mat_rotcam[0],cos(ang),sin(ang),0,0);
  400.   vec4_set(mat_rotcam[1],-sin(ang),cos(ang),0,0);
  401.   vec4_set(mat_rotcam[2],0,0,1,0);
  402.   vec4_set(mat_rotcam[3],0,0,0,1);
  403. }
  404. void calcula_tras_a_camara()
  405. {
  406.   vec4_set(mat_tras[0],1,0,0,0);
  407.   vec4_set(mat_tras[1],0,1,0,0);
  408.   vec4_set(mat_tras[2],0,0,1,0);
  409.   vec4_set(mat_tras[3],-veccamera[0],-veccamera[1],-veccamera[2],1);
  410. }
  411. void calcula_perspectiva(float d)
  412. {
  413.   vec4_set(mat_d[0],zoom/d/1.333,0,0,0);
  414.   vec4_set(mat_d[1],0,zoom/d,0,0);
  415.   vec4_set(mat_d[2],0,0,1,0);
  416.   vec4_set(mat_d[3],0,0,0,1);
  417. }
  418. /*
  419. intersect( float a[2], float b[2], int caso, int wMin[2], int wMax[2],float salida[2])
  420. {
  421. float m;
  422. if (a[0]!=b[0]) m=(a[1]-b[1])/(a[0]-b[0]);
  423. else m=1;
  424. switch (caso){
  425. case 1:  //LEFT
  426.       salida[0]=wMin[0]; 
  427.       salida[1]=b[1]+(wMin[0]-b[0])*m;
  428.       break;
  429. case 2: //RIGHT
  430.       salida[0]=wMax[0]; 
  431.       salida[1]=b[1]+(wMax[0]-b[0])*m;
  432.       break;
  433. case 3: //BOTTOM
  434.       salida[1]=wMin[1]; 
  435.       if(a[0]!=b[0]) salida[0]=b[1]+(wMin[1]-b[0])/m;
  436.       else salida[0]=b[0];
  437.       break;
  438. case 4: //TOP
  439.       salida[1]=wMax[1]; 
  440.       if(a[0]!=b[0]) salida[0]=b[1]+(wMax[1]-b[0])/m;
  441.       else salida[0]=b[0];
  442.       break;
  443.  }
  444. }
  445. */
  446.