home *** CD-ROM | disk | FTP | other *** search
/ 3D World 4 (Spanish) / 3DWorld_04.iso / mac / ARTIC / W_PROG / CUBO.C next >
C/C++ Source or Header  |  1998-04-04  |  13KB  |  421 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.  
  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]; //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.  
  96.   //Se aplica la transformacion de rotacion a los vertices
  97.   for(ind=0;ind<8; ind++)
  98.       V4XM44(VERTICES[ind], mat_rot, VERTransf[ind]);
  99.   calcula_tras_a_camara();
  100.   calcula_proy_a_camara();
  101.   M44XM44(mat_tras,mat_proy,mat_fin);
  102.   for(ind=0;ind<8;ind++)
  103.     {
  104.         V4XM44(VERTransf[ind],mat_fin,VERTransf[ind]);
  105.         //linea alternativa para no rotar
  106.         //V4XM44(VERTICES[ind], mat_fin, VERTransf[ind]);
  107.         calcula_perspectiva(VERTransf[ind][2]);
  108.         V4XM44(VERTransf[ind],mat_d,VERTransf[ind]);
  109.     }
  110.   //  Selecci¢n del boundig box del cubo (xmax,xmin,ymax,ymin)
  111.   boundig_box(VERTransf,&xmin,&xmax,&ymin,&ymax);
  112.  
  113.   //  C†lculo de las normales por cara
  114.   for(ind=0;ind<6; ind++){
  115.         for(ind1=0;ind1<3; ind1++){
  116.          vectemp1[ind1]=VERTransf[CARAS[ind][1]][ind1]-
  117.                           VERTransf[CARAS[ind][0]][ind1];
  118.          vectemp2[ind1]=VERTransf[CARAS[ind][2]][ind1]-
  119.                           VERTransf[CARAS[ind][1]][ind1];
  120.          }
  121.        cross(vectemp1,vectemp2,normal);
  122.        if(normal[2]<=1.e-15 ) CARAS[ind][4]=0.; //cara oculta
  123.        else  CARAS[ind][4]=1.;                  //cara visible
  124.       }
  125.   _setcolor(8);
  126.  
  127.   //ciclo de barrido de pantalla por el bounding box
  128.   /*
  129.   for(ejex=xmin; ejex<=xmax; ejex++)
  130.     for(ejey=ymin; ejey<=ymax; ejey++)
  131.        for(ind=0;ind<6; ind++){//ciclo por las caras
  132.          if(CARAS[ind][4]==1.){ //filtro de caras visibles
  133.            if( interior_a_poly((float)ejex, (float)ejey, ind )==1)
  134.              _setpixel(ejex,ejey);
  135.            }
  136.          }
  137.   */
  138.   // Se dibujan las aristas visibles del cubo
  139.   
  140.   _setcolor(10);
  141.   
  142.   for(ind=0;ind<6; ind++)  {
  143.      if(CARAS[ind][4]==1.){
  144.      _moveto( (int)VERTransf[ CARAS[ind][0] ][0], (int) VERTransf[ CARAS[ind][0] ][1]);
  145.      for(ind1=1;ind1<4; ind1++)
  146.      _lineto( (int)VERTransf[ CARAS[ind][ind1] ][0], (int) VERTransf[ CARAS[ind][ind1]][1]);
  147.      _lineto( (int)VERTransf[ CARAS[ind][0] ][0], (int) VERTransf[ CARAS[ind][0] ][1]);
  148.      }
  149.    }
  150.   ind3++;
  151.   
  152.   if (getch()==27)
  153.     break;
  154.   _clearscreen(_GCLEARSCREEN);
  155.  
  156.   }//fin de ciclo de angulo
  157. _setvideomode(_DEFAULTMODE);
  158. }//fin de main
  159.  
  160.  
  161. //Funci¢n para la obtencion de la matriz concatenada de rotaci¢n
  162. //alrededor de un eje arbitrario con cosenos directores cx,cy,cz, en
  163. //un †ngulo de rotacion angrot.
  164.  
  165. void calcula_mat_rot(double cx,double cy,double cz,double angrot)
  166. {
  167. double d;
  168. float Rx[4][4],Rxinv[4][4],Ry[4][4],Ryinv[4][4],Rdelta[4][4];
  169.  
  170. if(angrot==0.)
  171.   {//Devuelve la matriz identidad si angrot=0
  172.   vec4_set(mat_rot[0],1.,0.,0.,0.);
  173.   vec4_set(mat_rot[1],0.,1.,0.,0.);
  174.   vec4_set(mat_rot[2],0.,0.,1.,0.);
  175.   vec4_set(mat_rot[3],0.,0.,0.,1.);
  176.   }
  177.  
  178. else
  179.   {
  180.   d=sqrt(cy*cy + cz*cz);
  181.  
  182.   if(d==0.0)
  183.     {//si el eje de rotaci¢n coincide con el eje x
  184.     vec4_set(mat_rot[0],1.,0.,0.,0.);
  185.     vec4_set(mat_rot[1],0.,cos(angrot),sin(angrot),0.);
  186.     vec4_set(mat_rot[2],0.,-sin(angrot),cos(angrot),0.);
  187.     vec4_set(mat_rot[3],0.,0.,0.,1.);
  188.     }
  189.  
  190.   else
  191.     {
  192.     //Formacion de las matrices de rotacion
  193.  
  194.     //Matriz de transformacion alrededor del eje x
  195.     vec4_set(Rx[0],1.0,0.,0.,0.);
  196.     vec4_set(Rx[1],0.,cz/d,cy/d,0.);
  197.     vec4_set(Rx[2],0.,-cy/d,cz/d,0.);
  198.     vec4_set(Rx[3],0.,0.,0.,1.);
  199.  
  200.     //Inversa de la matriz de transformacion alrededor del eje x
  201.     vec4_set(Rxinv[0],1.0,0.,0.,0.);
  202.     vec4_set(Rxinv[1],0.,cz/d,-cy/d,0.);
  203.     vec4_set(Rxinv[2],0.,cy/d,cz/d,0.);
  204.     vec4_set(Rxinv[3],0.,0.,0.,1.);
  205.  
  206.     //Matriz de transformacion alrededor del eje y
  207.     vec4_set(Ry[0],d,0.,cx,0.);
  208.     vec4_set(Ry[1],0.,1.,0.,0.);
  209.     vec4_set(Ry[2],-cx,0.,d,0.);
  210.     vec4_set(Ry[3],0.,0.,0.,1.);
  211.  
  212.     //Inversa de la matriz de transformacion alrededor del eje y
  213.     vec4_set(Ryinv[0],d,0.,-cx,0.);
  214.     vec4_set(Ryinv[1],0.,1.,0.,0.);
  215.     vec4_set(Ryinv[2],cx,0.,d,0.);
  216.     vec4_set(Ryinv[3],0.,0.,0.,1.);
  217.  
  218.     //Matriz de rotacion alrededor del eje  arbitrario
  219.     vec4_set(Rdelta[0],cos(angrot),sin(angrot),0.,0.);
  220.     vec4_set(Rdelta[1],-sin(angrot),cos(angrot),0.,0.);
  221.     vec4_set(Rdelta[2],0.,0.,1.,0.);
  222.     vec4_set(Rdelta[3],0.,0.,0.,1.);
  223.  
  224.     //Obtencion de la matriz concatenada de transformacion
  225.     M44XM44(Rx, Ry,mat_rot);
  226.     M44XM44a(mat_rot, Rdelta);
  227.     M44XM44a(mat_rot, Ryinv);
  228.     M44XM44a(mat_rot, Rxinv);
  229.     }
  230.   }
  231. }
  232.  
  233. //----------------------------------------------------
  234. //  Multiplica un vector a[4] por una matriz 4x4:
  235. //  c = a*b;
  236. //  El resultado se almacena en el vector c
  237. //  -----------------------------------------------------
  238.  
  239. void V4XM44(float a[4], float b[4][4], float c[4])
  240. {
  241.    int j;
  242.    float work[4];
  243.    
  244.    for (j=0; j<4; j++) {
  245.       work[j] = a[0]*b[0][j] + a[1]*b[1][j] + a[2]*b[2][j] + a[3]*b[3][j];
  246.       }
  247.    memcpy(c, work, 4*sizeof(float));
  248. }
  249.  
  250. //----------------------------------------------------
  251. //  Multiply dos matrices matrices 4x4:
  252. //  c = a*b;
  253. //  El resultado se almacena en c
  254. //  -----------------------------------------------------
  255. void M44XM44(float a[4][4], float b[4][4], float c[4][4])
  256. {
  257.    int j;
  258.    float work[4][4];
  259.    
  260.    for (j=0; j<4;j++) {
  261.       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];
  262.       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];
  263.       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];
  264.       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];
  265.       }
  266.    memcpy(c, work, 16*sizeof(float));
  267. }
  268.  
  269. //----------------------------------------------------
  270. //  Multiplica dos matrices 4x4:
  271. //  a = a*b;
  272. //  El resultado se almacena en a
  273. //  -----------------------------------------------------
  274. void M44XM44a(float a[4][4], float b[4][4])
  275. {
  276.    int j;
  277.    float work[4][4];
  278.    
  279.    for (j=0; j<4;j++) {
  280.       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];
  281.       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];
  282.       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];
  283.       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];
  284.       }
  285.    memcpy(a, work, 16*sizeof(float));
  286. }
  287.  
  288. void rellena_vertices(float lad )
  289. {
  290.    int ind;
  291.    //Rellena el array de VERTICES con las coordenadas de los vertices del cubo
  292.  
  293.    vec4_set(VERTICES[0],lad, lad, -lad, 1.);
  294.    vec4_set(VERTICES[1],-lad, lad, -lad, 1.);
  295.    vec4_set(VERTICES[2],-lad, lad, lad, 1.);
  296.    vec4_set(VERTICES[3],lad, lad, lad, 1.);
  297.    vec4_set(VERTICES[4],lad, -lad, -lad, 1.);
  298.    vec4_set(VERTICES[5],lad, -lad, lad, 1.);
  299.    vec4_set(VERTICES[6],-lad, -lad, lad, 1.);
  300.    vec4_set(VERTICES[7],-lad, -lad, -lad, 1.);
  301. }
  302. void rellena_caras()
  303. {
  304. //Rellena el aray de CARAS con el indice de los vertices que componen cada cara
  305. vec4_set(CARAS[0],0,1,2,3); //superior
  306. vec4_set(CARAS[1],4,5,6,7); //inferior
  307. vec4_set(CARAS[2],5,3,2,6); //delantera
  308. vec4_set(CARAS[3],4,7,1,0); //trasera
  309. vec4_set(CARAS[4],4,0,3,5); //derecha
  310. vec4_set(CARAS[5],7,6,2,1); //izquierda
  311. }
  312.  
  313. //Normaliza al vector de componentes (x,y,z)
  314. normaliza(float *x, float *y, float *z)
  315. {
  316.         //se devuelve el vector normalizado
  317.         double modulo,xx,yy,zz;
  318.         xx=(*x);
  319.         yy=(*y);
  320.         zz=(*z);
  321.         modulo=sqrt(CUAD(xx)+CUAD(yy)+CUAD(zz));
  322.         if (modulo<ROUNDOFF)  {
  323.                         return(FALSE);
  324.                         }
  325.         *x = (xx/modulo);
  326.         *y = (yy/modulo);
  327.         *z = (zz/modulo);
  328.         return(TRUE);
  329. }
  330.  
  331. //Calcula el producto vectorial de dos vectores c=a x b
  332. void cross(float *a, float *b, float *c)
  333. {
  334.   c[0] = a[1]*b[2] - a[2]*b[1];
  335.   c[1] = a[2]*b[0] - a[0]*b[2];
  336.   c[2] = a[0]*b[1] - a[1]*b[0];
  337. }
  338.  
  339. //Determina el bounding box de un conjunto de puntos
  340. void boundig_box(float V[NUMVERT][4],float *xmin,float *xmax,float *ymin,float *ymax)
  341. {
  342. int ind;
  343. *ymin=999999.;
  344. *ymax=-999999.;
  345. *xmin=999999.;
  346. *xmax=-999999.;
  347.  
  348. for(ind=0;ind<NUMVERT; ind++)
  349.     {
  350.     *ymin=*ymin>V[ind][1]?V[ind][1]:*ymin;
  351.     *ymax=*ymax<V[ind][1]?V[ind][1]:*ymax;
  352.     *xmin=*xmin>V[ind][0]?V[ind][0]:*xmin;
  353.     *xmax=*xmax<V[ind][0]?V[ind][0]:*xmax;
  354.     }
  355. }
  356.  
  357. // Rutina que determina si un punto es interior o exterior al poligono
  358. //de cuatro lados formado por los cuatro vertices de cada cara
  359. //proyectados en el plano xy
  360.  
  361. int interior_a_poly(float x, float y, int i )
  362. {
  363. unsigned ss,cort;
  364. float trasl[4][2];
  365.  
  366.   for(ss=0 ; ss<4 ; ss++)
  367.      {
  368.      trasl[ss][0]=VERTransf[ CARAS[i][ss] ][0]- x   ;
  369.      trasl[ss][1]=VERTransf[ CARAS[i][ss] ][1] - y   ;
  370.      }
  371.   for (cort=ss=0;ss<4;ss++)
  372.      if ((trasl[ss][1]*trasl[(ss+1)%4][1]<0.0) && (( (trasl[ss][0]>0.0) &&
  373.      (trasl[(ss+1)%4][0]>0.0)) ||
  374.      ((trasl[ss][0]-(trasl[ss][1]*(trasl[(ss+1)%4][0]-trasl[ss][0]))/(trasl[(ss+1)%4][1]-
  375.      trasl[ss][1]))>0.0) ) ) cort ++;
  376.  
  377.   if ((cort%2) !=0)
  378.      return(1); //pto. interior
  379.  
  380.   return(0); //pto. exterior
  381. }
  382.  
  383. /*
  384. void calcula_foco()
  385. {
  386.   vec4_set(mat_foc[0],vecfoco[1]/sqrt(1-vecfoco[2]*vecfoco[2]),-vecfoco[1]/sqrt(1-vecfoco[2]*vecfoco[2]),vecfoco[1],0);
  387.   vec4_set(mat_foc[1],-vecfoco[0]*vecfoco[2]/sqrt(1-vecfoco[2]*vecfoco[2]),-vecfoco[1]*vecfoco[2]/sqrt(1-vecfoco[2]*vecfoco[2]),vecfoco[1],0);
  388.   vec4_set(mat_foc[2],0,sqrt(1-vecfoco[2]*vecfoco[2]),vecfoco[2],0);
  389.   vec4_set(mat_foc[3],0,0,0,1);
  390. }
  391. */
  392. void calcula_proy_a_camara()
  393. {
  394.   vec4_set(mat_proy[0],U[0],V[0],N[0],0);
  395.   vec4_set(mat_proy[1],U[1],V[1],N[1],0);
  396.   vec4_set(mat_proy[2],U[2],V[2],N[2],0);
  397.   vec4_set(mat_proy[3],0,0,0,1);
  398. }
  399.  
  400. void calcula_camrot()
  401. {  
  402.   vec4_set(mat_rotcam[0],cos(ang),sin(ang),0,0);
  403.   vec4_set(mat_rotcam[1],-sin(ang),cos(ang),0,0);
  404.   vec4_set(mat_rotcam[2],0,0,1,0);
  405.   vec4_set(mat_rotcam[3],0,0,0,1);
  406. }
  407. void calcula_tras_a_camara()
  408. {
  409.   vec4_set(mat_tras[0],1,0,0,0);
  410.   vec4_set(mat_tras[1],0,1,0,0);
  411.   vec4_set(mat_tras[2],0,0,1,0);
  412.   vec4_set(mat_tras[3],-veccamera[0],-veccamera[1],-veccamera[2],1);
  413. }
  414. void calcula_perspectiva(float d)
  415. {
  416.   vec4_set(mat_d[0],zoom/d/1.333,0,0,0);
  417.   vec4_set(mat_d[1],0,zoom/d,0,0);
  418.   vec4_set(mat_d[2],0,0,1,0);
  419.   vec4_set(mat_d[3],0,0,0,1);
  420. }
  421.