EngBcub.cpp
上传用户:lhwx1029
上传日期:2013-03-07
资源大小:1173k
文件大小:20k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. /** 3DGPL *************************************************
  2.  * ()                                                     *
  3.  * Functions for bicubic patches.                         *
  4.  *                                                        *
  5.  * Ifdefs:                                                *
  6.  *  _CI_                     Colour/Intensity model;      *
  7.  *  _RGB_                    RGB model;                   *
  8.  *  _Z_BUFFER_               Depth array;                 *
  9.  *  _PAINTER_                Back to front rendering.     *
  10.  *                                                        *
  11.  * Defines:                                               *
  12.  *  M_init_bicubic           Allocate structure elements; *
  13.  *  M_shade_bicubic          Compute shading intensities; *
  14.  *  M_render_bicubic         Rendering as set of polygons;*
  15.  *  M_init_bicubic_object    Every patch in the object;   *
  16.  *  M_shade_bicubic_object   Shade the patches;           *
  17.  *  M_render_bicubic_object  Rendering as set of patches. *
  18.  *                                                        *
  19.  * Internals:                                             *
  20.  *  MI_render_square         Single square of the patch;  *
  21.  *  MI_find_bezier_points    Finding points on the curve; *
  22.  *  MI_find_bezier_tangents  Finding the tengents.        *
  23.  *                                                        *
  24.  * (c) 1995-98 Sergei Savchenko, (savs@cs.mcgill.ca)      *
  25. **********************************************************/
  26. #include "Graphics.h"           /* 2-D rendering */
  27. #include "Trans.h"                 /* 3-D transformations */
  28. #include "Clipper.h"             /* 2-D/3-D clipping */
  29. #include "Engine.h"               /* 3-D engine */
  30. #include <stdlib.h>                         /* NULL */
  31. #if defined(_CI_)
  32. int M_square_v[20]=                         /* static data for a square */
  33. {
  34.  2,0,0,0,
  35.  3,0,0,0,
  36.  1,0,0,0,
  37.  0,0,0,0,
  38.  2,0,0,0
  39. };
  40. struct M_polygon M_square={M_QUAD_XY,0,
  41.                            0,
  42.                            0,NULL,4,M_square_v,NULL
  43.                           };
  44. #endif
  45. #if defined(_RGB_)
  46. int M_square_v[30]=                         /* static data for a square */
  47. {
  48.  2,0,0,0,0,0,
  49.  3,0,0,0,0,0,
  50.  1,0,0,0,0,0,
  51.  0,0,0,0,0,0,
  52.  2,0,0,0,0,0
  53. };
  54. struct M_polygon M_square={M_QUAD_XY,0,
  55.                            0,0,0,
  56.                            0,NULL,4,M_square_v,NULL
  57.                           };
  58. #endif
  59. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  60.  * INTERNAL: Rendering a single square of tesselated     *
  61.  * --------- bicubic.                                    *
  62. * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  63. void MI_render_square(int no1,int no2,int* vertices,int *intensities,
  64.                       int *textures
  65.                      )
  66. {
  67.  int tmp_vert[T_LNG_VECTOR*4];              /* X Y Z */
  68.  int tmp_colr[CL_LNG_COLOUR*4];             /* intensity or R G B */
  69.  int tmp_texture[8];                        /* Tx Ty */
  70.  HW_copy_int(vertices+no1*T_LNG_VECTOR,tmp_vert,T_LNG_VECTOR*2);
  71.  HW_copy_int(vertices+no2*T_LNG_VECTOR,tmp_vert+T_LNG_VECTOR*2,T_LNG_VECTOR*2);
  72.                                             /* getting rid of fractions */
  73.  tmp_vert[0]>>=M_PB; tmp_vert[1]>>=M_PB; tmp_vert[2]>>=M_PB;
  74.  tmp_vert[4]>>=M_PB; tmp_vert[5]>>=M_PB; tmp_vert[6]>>=M_PB;
  75.  tmp_vert[8]>>=M_PB; tmp_vert[9]>>=M_PB; tmp_vert[10]>>=M_PB;
  76.  tmp_vert[12]>>=M_PB; tmp_vert[13]>>=M_PB; tmp_vert[14]>>=M_PB;
  77.  if(intensities!=NULL)
  78.  {
  79.   HW_copy_int(intensities+no1*CL_LNG_COLOUR,tmp_colr,CL_LNG_COLOUR*2);
  80.   HW_copy_int(intensities+no2*CL_LNG_COLOUR,tmp_colr+CL_LNG_COLOUR*2,CL_LNG_COLOUR*2);
  81.   HW_copy_int(textures+no1*2,tmp_texture,4);
  82.   HW_copy_int(textures+no2*2,tmp_texture+4,4);
  83.  }
  84. #if defined(_CI_)
  85.  M_square.m_intensity=tmp_colr[0];
  86. #endif
  87. #if defined(_RGB_)
  88.  M_square.m_red=tmp_colr[0];
  89.  M_square.m_green=tmp_colr[1];
  90.  M_square.m_blue=tmp_colr[2];
  91. #endif
  92.  M_render_polygon(&M_square,tmp_vert,tmp_colr,tmp_texture);
  93. }
  94. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  95.  * INTERNAL: Filling an array with the coordinates of    *
  96.  * --------- points on the Bezier curve cpecified        *
  97.  *           through its controls b1,...,b4.             *
  98.  *                                                       *
  99.  * RECURSIVE: Calls itself twice.                        *
  100.  * ----------                                            *
  101. * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  102. void MI_evaluate_bezier_points(int *b1,int *b2,int *b3,int *b4,
  103.                               int *points,int dimension,int length,int top,
  104.                               int rendering
  105.                              )
  106. {
  107.  int b12[T_LNG_VECTOR],b23[T_LNG_VECTOR],b34[T_LNG_VECTOR];
  108.  int b123[T_LNG_VECTOR],b234[T_LNG_VECTOR],*b1234;
  109.  if(top)                                    /* during top level call */
  110.  {
  111.   if(rendering)
  112.   {                                         /* increasing precision */
  113.    b1[0]<<=M_PB; b1[1]<<=M_PB; b1[2]<<=M_PB;/* by adding fractional bits */
  114.    b2[0]<<=M_PB; b2[1]<<=M_PB; b2[2]<<=M_PB;
  115.    b3[0]<<=M_PB; b3[1]<<=M_PB; b3[2]<<=M_PB;
  116.    b4[0]<<=M_PB; b4[1]<<=M_PB; b4[2]<<=M_PB;
  117.   }
  118.   HW_copy_int(b1,points,3);                 /* setting border values */
  119.   HW_copy_int(b4,points+(length-1)*dimension,3);
  120.  }
  121.  if(length>2)
  122.  {
  123.   b1234=points+(length/2)*dimension;
  124.   b12[0]=(b1[0]+b2[0])/2; b12[1]=(b1[1]+b2[1])/2; b12[2]=(b1[2]+b2[2])/2;
  125.   b23[0]=(b2[0]+b3[0])/2; b23[1]=(b2[1]+b3[1])/2; b23[2]=(b2[2]+b3[2])/2;
  126.   b34[0]=(b3[0]+b4[0])/2; b34[1]=(b3[1]+b4[1])/2; b34[2]=(b3[2]+b4[2])/2;
  127.   b123[0]=(b12[0]+b23[0])/2; b123[1]=(b12[1]+b23[1])/2; b123[2]=(b12[2]+b23[2])/2;
  128.   b234[0]=(b23[0]+b34[0])/2; b234[1]=(b23[1]+b34[1])/2; b234[2]=(b23[2]+b34[2])/2;
  129.   b1234[0]=(b123[0]+b234[0])/2;
  130.   b1234[1]=(b123[1]+b234[1])/2;
  131.   b1234[2]=(b123[2]+b234[2])/2;
  132.   MI_evaluate_bezier_points(b1,b12,b123,b1234,points,dimension,length/2+1,0,rendering);
  133.   MI_evaluate_bezier_points(b1234,b234,b34,b4,b1234,dimension,length/2+1,0,rendering);
  134.  }
  135. }
  136. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  137.  * INTERNAL: Filling an array with the tangents of the   *
  138.  * --------- Bezier curve cpecified through its          *
  139.  *           controls b1,...,b4.                         *
  140.  *                                                       *
  141.  * RECURSIVE: Calls itself twice.                        *
  142.  * ----------                                            *
  143. * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  144. void MI_evaluate_bezier_tangents(int *b1,int *b2,int *b3,int *b4,
  145.                                  int *tangents,int dimension,int length,int top
  146.                                 )
  147. {
  148.  int b12[T_LNG_VECTOR],b23[T_LNG_VECTOR],b34[T_LNG_VECTOR];
  149.  int b123[T_LNG_VECTOR],b234[T_LNG_VECTOR],b1234[T_LNG_VECTOR],*mid;
  150.  if(top)                                    /* during top level call */
  151.  {
  152.   T_vector(b1,b2,tangents,3);               /* setting border values */
  153.   T_vector(b3,b4,tangents+(length-1)*dimension,3);
  154.  }
  155.  if(length>2)
  156.  {
  157.   mid=tangents+(length/2)*dimension;
  158.   b12[0]=(b1[0]+b2[0])/2; b12[1]=(b1[1]+b2[1])/2; b12[2]=(b1[2]+b2[2])/2;
  159.   b23[0]=(b2[0]+b3[0])/2; b23[1]=(b2[1]+b3[1])/2; b23[2]=(b2[2]+b3[2])/2;
  160.   b34[0]=(b3[0]+b4[0])/2; b34[1]=(b3[1]+b4[1])/2; b34[2]=(b3[2]+b4[2])/2;
  161.   b123[0]=(b12[0]+b23[0])/2; b123[1]=(b12[1]+b23[1])/2; b123[2]=(b12[2]+b23[2])/2;
  162.   b234[0]=(b23[0]+b34[0])/2; b234[1]=(b23[1]+b34[1])/2; b234[2]=(b23[2]+b34[2])/2;
  163.   T_vector(b123,b234,mid,3);
  164.   b1234[0]=(b123[0]+b234[0])/2;
  165.   b1234[1]=(b123[1]+b234[1])/2;
  166.   b1234[2]=(b123[2]+b234[2])/2;
  167.   MI_evaluate_bezier_tangents(b1,b12,b123,b1234,tangents,dimension,length/2+1,0);
  168.   MI_evaluate_bezier_tangents(b1234,b234,b34,b4,mid,dimension,length/2+1,0);
  169.  }
  170. }
  171. /**********************************************************
  172.  * Allocating the intensity table based on the foreseen   *
  173.  * number of polygons into which the patch will be        *
  174.  * tesselated.                                            *
  175. **********************************************************/
  176. void M_init_bicubic(struct M_bicubic *bicubic)
  177. {
  178.  int tangents1[M_MAX_RENDER_SIZE*M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  179.  int tangents2[M_MAX_RENDER_SIZE*M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  180.  int tmpb1[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  181.  int tmpb2[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  182.  int tmpb3[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  183.  int tmpb4[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  184.  int *c=bicubic->m_controls;
  185.  int i,size=(1<<bicubic->m_log_render_size)+1;
  186.  if(size>=M_MAX_RENDER_SIZE)
  187.   HW_error("(Engine) Can't subdivide a bicubic this much.n");
  188.  bicubic->m_normals=(int*)malloc(sizeof(int)*T_LNG_VECTOR*size*size);
  189.  bicubic->m_intensities=(int*)malloc(sizeof(int)*CL_LNG_COLOUR*size*size);
  190.  if((bicubic->m_normals==NULL)||(bicubic->m_intensities==NULL))
  191.   HW_error("(Engine) Not enough memory.n");
  192.  MI_evaluate_bezier_points(c,c+T_LNG_VECTOR,c+T_LNG_VECTOR*2,
  193.                            c+T_LNG_VECTOR*3,tmpb1,T_LNG_VECTOR,size,1,0
  194.                           );
  195.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*4,c+T_LNG_VECTOR*5,c+T_LNG_VECTOR*6,
  196.                            c+T_LNG_VECTOR*7,tmpb2,T_LNG_VECTOR,size,1,0
  197.                           );
  198.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*8,c+T_LNG_VECTOR*9,c+T_LNG_VECTOR*10,
  199.                            c+T_LNG_VECTOR*11,tmpb3,T_LNG_VECTOR,size,1,0
  200.                           );
  201.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*12,c+T_LNG_VECTOR*13,c+T_LNG_VECTOR*14,
  202.                            c+T_LNG_VECTOR*15,tmpb4,T_LNG_VECTOR,size,1,0
  203.                           );
  204.  for(i=0;i<size;i++)
  205.   MI_evaluate_bezier_tangents(tmpb1+i*T_LNG_VECTOR,tmpb2+i*T_LNG_VECTOR,
  206.                               tmpb3+i*T_LNG_VECTOR,tmpb4+i*T_LNG_VECTOR,
  207.                               tangents1+i*T_LNG_VECTOR,T_LNG_VECTOR*size,size,1
  208.                              );
  209.  MI_evaluate_bezier_points(c,c+T_LNG_VECTOR*4,c+T_LNG_VECTOR*8,
  210.                            c+T_LNG_VECTOR*12,tmpb1,T_LNG_VECTOR,size,1,0
  211.                           );
  212.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*1,c+T_LNG_VECTOR*5,c+T_LNG_VECTOR*9,
  213.                            c+T_LNG_VECTOR*13,tmpb2,T_LNG_VECTOR,size,1,0
  214.                           );
  215.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*2,c+T_LNG_VECTOR*6,c+T_LNG_VECTOR*10,
  216.                            c+T_LNG_VECTOR*14,tmpb3,T_LNG_VECTOR,size,1,0
  217.                           );
  218.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*3,c+T_LNG_VECTOR*7,c+T_LNG_VECTOR*11,
  219.                            c+T_LNG_VECTOR*15,tmpb4,T_LNG_VECTOR,size,1,0
  220.                           );
  221.  for(i=0;i<size;i++)
  222.   MI_evaluate_bezier_tangents(tmpb1+i*T_LNG_VECTOR,tmpb2+i*T_LNG_VECTOR,
  223.                               tmpb3+i*T_LNG_VECTOR,tmpb4+i*T_LNG_VECTOR,
  224.                               tangents2+i*size*T_LNG_VECTOR,T_LNG_VECTOR,size,1
  225.                              );
  226.  for(i=0;i<size*size;i++)
  227.   T_normal_vectors(tangents1+i*T_LNG_VECTOR,tangents2+i*T_LNG_VECTOR,
  228.                   bicubic->m_normals+i*T_LNG_VECTOR
  229.                  );
  230. }
  231. /**********************************************************
  232.  * Using precomputed normals to shade the bicubic         *
  233. **********************************************************/
  234. void M_shade_bicubic(struct M_bicubic *bicubic,
  235.                      int x,int y,int z,
  236.                      int alp,int bet,int gam,
  237.                      int no_lights,struct M_light **lights
  238.                     )
  239. {
  240.  int c[16*T_LNG_VECTOR];
  241.  int points[M_MAX_RENDER_SIZE*M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  242.  int normals[M_MAX_RENDER_SIZE*M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  243.  int tmpb1[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  244.  int tmpb2[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  245.  int tmpb3[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  246.  int tmpb4[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  247.  int *intensity,*position,*normal;
  248.  int i,size=(1<<bicubic->m_log_render_size)+1;
  249.  if(size>M_MAX_RENDER_SIZE)
  250.   HW_error("(Engine) Can't subdivide a bicubic this much.n");
  251.  T_set_self_rotation(alp,bet,gam);          /* shading happens in world space */
  252.  T_self_rotation(bicubic->m_normals,normals,size*size);
  253.  T_self_rotation(bicubic->m_controls,c,16);
  254.  T_translation(c,c,16,x,y,z);
  255.  MI_evaluate_bezier_points(c,c+T_LNG_VECTOR*4,c+T_LNG_VECTOR*8,
  256.                            c+T_LNG_VECTOR*12,tmpb1,T_LNG_VECTOR,size,1,0
  257.                           );
  258.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*1,c+T_LNG_VECTOR*5,c+T_LNG_VECTOR*9,
  259.                            c+T_LNG_VECTOR*13,tmpb2,T_LNG_VECTOR,size,1,0
  260.                           );
  261.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*2,c+T_LNG_VECTOR*6,c+T_LNG_VECTOR*10,
  262.                            c+T_LNG_VECTOR*14,tmpb3,T_LNG_VECTOR,size,1,0
  263.                           );
  264.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*3,c+T_LNG_VECTOR*7,c+T_LNG_VECTOR*11,
  265.                            c+T_LNG_VECTOR*15,tmpb4,T_LNG_VECTOR,size,1,0
  266.                           );
  267.  for(i=0;i<size;i++)
  268.   MI_evaluate_bezier_points(tmpb1+i*T_LNG_VECTOR,tmpb2+i*T_LNG_VECTOR,
  269.                             tmpb3+i*T_LNG_VECTOR,tmpb4+i*T_LNG_VECTOR,
  270.                             points+i*size*T_LNG_VECTOR,T_LNG_VECTOR,size,1,0
  271.                            );
  272.  intensity=bicubic->m_intensities;
  273.  position=points;
  274.  normal=normals;
  275.  for(i=0;i<size*size;i++)
  276.  {
  277.   M_shade_vertex(intensity,position,normal,
  278.                  no_lights,lights
  279.                 );
  280.   intensity+=CL_LNG_COLOUR;
  281.   position+=T_LNG_VECTOR;
  282.   normal+=T_LNG_VECTOR;
  283.  }
  284. }
  285. /**********************************************************
  286.  * Rendering a bicubic by tesselating it into polygons.   *
  287. **********************************************************/
  288. void M_render_bicubic(struct M_bicubic *bicubic,
  289.                       int x,int y,int z,
  290.                       int alp,int bet,int gam
  291.                      )
  292. {
  293.  int c[16*T_LNG_VECTOR];
  294.  int points[M_MAX_RENDER_SIZE*M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  295.  int textures[M_MAX_RENDER_SIZE*M_MAX_RENDER_SIZE*2];
  296.  int numbers[M_MAX_RENDER_SIZE*M_MAX_RENDER_SIZE];
  297.  int tmpb1[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  298.  int tmpb2[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  299.  int tmpb3[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  300.  int tmpb4[M_MAX_RENDER_SIZE*T_LNG_VECTOR];
  301.  int *texture,incr,cur_x,cur_y,max;
  302.  int i,j,size=(1<<bicubic->m_log_render_size)+1;
  303.  if(size>M_MAX_RENDER_SIZE)
  304.   HW_error("(Engine) Can't subdivide a bicubic this much.n");
  305.  T_set_self_rotation(alp,bet,gam);          /* the transformations */
  306.  T_cancatinate_self_world(x+M_camera_x,y+M_camera_y,z+M_camera_z);
  307.  T_cancatinated_rotation(bicubic->m_controls,c,16);
  308.  incr=bicubic->m_log_texture_space_size-bicubic->m_log_render_size;
  309.  if(incr<=0) HW_error("(Engine) Too small a texture to fit onto a bicubic.n");
  310.  M_square.m_colour=bicubic->m_colour;
  311.  M_square.m_log_texture_space_size=incr;
  312.  M_square.m_texture=bicubic->m_texture;     /* transfer info to a square */
  313.  incr=1<<incr;
  314.  max=1<<bicubic->m_log_texture_space_size;
  315.  texture=textures;
  316.  for(i=0,cur_y=max;i<size;i++,cur_y-=incr)  /* building a set of texture */
  317.  {                                          /* coordinates */
  318.   for(j=0,cur_x=0;j<size;j++,cur_x+=incr)
  319.   {
  320.    *texture++=cur_x;
  321.    *texture++=cur_y;
  322.   }
  323.  }
  324.  MI_evaluate_bezier_points(c,c+T_LNG_VECTOR*4,c+T_LNG_VECTOR*8,
  325.                            c+T_LNG_VECTOR*12,tmpb1,T_LNG_VECTOR,size,1,1
  326.                           );
  327.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*1,c+T_LNG_VECTOR*5,c+T_LNG_VECTOR*9,
  328.                            c+T_LNG_VECTOR*13,tmpb2,T_LNG_VECTOR,size,1,1
  329.                           );
  330.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*2,c+T_LNG_VECTOR*6,c+T_LNG_VECTOR*10,
  331.                            c+T_LNG_VECTOR*14,tmpb3,T_LNG_VECTOR,size,1,1
  332.                           );
  333.  MI_evaluate_bezier_points(c+T_LNG_VECTOR*3,c+T_LNG_VECTOR*7,c+T_LNG_VECTOR*11,
  334.                            c+T_LNG_VECTOR*15,tmpb4,T_LNG_VECTOR,size,1,1
  335.                           );
  336.  for(i=0;i<size;i++)                        /* tesselating the bicubic */
  337.   MI_evaluate_bezier_points(tmpb1+i*T_LNG_VECTOR,tmpb2+i*T_LNG_VECTOR,
  338.                             tmpb3+i*T_LNG_VECTOR,tmpb4+i*T_LNG_VECTOR,
  339.                             points+i*size*T_LNG_VECTOR,T_LNG_VECTOR,size,1,0
  340.                           );                /* beware 0 at the end - */
  341.                                             /* precision increased just once */
  342.  for(i=0;i<size*size;i++) numbers[i]=i;     /* prepare for sorting */
  343. #if defined(_PAINTER_)
  344.  M_sort_elements(points+2,T_LNG_VECTOR,numbers,size*size);
  345. #endif
  346.  for(i=0;i<size*size;i++)                   /* rendering back to front */
  347.   if((numbers[i]%size!=size-1)&&(numbers[i]/size!=size-1))
  348.    MI_render_square(numbers[i],numbers[i]+size,points,bicubic->m_intensities,textures);
  349. }
  350. /**********************************************************
  351.  * Initializing all patches in the object, computing      *
  352.  * approximate centres of the patches.                    *
  353. **********************************************************/
  354. void M_init_bicubic_object(struct M_bicubic_object *object)
  355. {
  356.  int i,j;
  357.  object->m_centres=(int*)malloc(sizeof(int)*T_LNG_VECTOR*object->m_no_patches);
  358.  if(object->m_centres==NULL)
  359.   HW_error("(Engine) Not enough memory.n");
  360.  for(i=0;i<object->m_no_patches;i++)
  361.  {
  362.   M_init_bicubic(object->m_patches[i]);
  363.   object->m_centres[i*T_LNG_VECTOR]=0;
  364.   object->m_centres[i*T_LNG_VECTOR+1]=0;
  365.   object->m_centres[i*T_LNG_VECTOR+2]=0;
  366.   for(j=0;j<16;j++)
  367.   {
  368.    object->m_centres[i*T_LNG_VECTOR]+=object->m_patches[i]->m_controls[j*T_LNG_VECTOR];
  369.    object->m_centres[i*T_LNG_VECTOR+1]+=object->m_patches[i]->m_controls[j*T_LNG_VECTOR+1];
  370.    object->m_centres[i*T_LNG_VECTOR+2]+=object->m_patches[i]->m_controls[j*T_LNG_VECTOR+2];
  371.   }
  372.   object->m_centres[i*T_LNG_VECTOR]/=16;
  373.   object->m_centres[i*T_LNG_VECTOR+1]/=16;
  374.   object->m_centres[i*T_LNG_VECTOR+2]/=16;
  375.  }
  376. }
  377. /**********************************************************
  378.  * Shading all patches in the object.                     *
  379. **********************************************************/
  380. void M_shade_bicubic_object(struct M_bicubic_object *object,
  381.                             int x,int y,int z,
  382.                             int alp,int bet,int gam,
  383.                             int no_lights,struct M_light **lights
  384.                            )
  385. {
  386.  int i;
  387.  for(i=0;i<object->m_no_patches;i++)
  388.   M_shade_bicubic(object->m_patches[i],x,y,z,alp,bet,gam,no_lights,lights);
  389. }
  390. /**********************************************************
  391.  * Rendering all patches. In the case of _PAINTER_        *
  392.  * performing sorting of the patches centres first and    *
  393.  * rendering in the back to front order.                  *
  394. **********************************************************/
  395. void M_render_bicubic_object(struct M_bicubic_object *object,
  396.                              int x,int y,int z,
  397.                              int alp,int bet,int gam
  398.                             )
  399. {
  400.  int i;
  401. #if defined(_PAINTER_)
  402.  int centres[M_MAX_PATCHES*T_LNG_VECTOR];
  403. #endif
  404.  int numbers[M_MAX_PATCHES];
  405.  int oldtmap=M_force_linear_tmapping;
  406.  M_force_linear_tmapping=1;                 /* polygons will be small enough */
  407.  if(object->m_no_patches>M_MAX_PATCHES)
  408.   HW_error("(Engine) Too many bicubic patches per object.n");
  409.  for(i=0;i<object->m_no_patches;i++) numbers[i]=i;
  410. #if defined(_PAINTER_)                      /* probably there are few patches */
  411.  T_set_self_rotation(alp,bet,gam);          /* don't cancatinate transforms */
  412.  T_self_rotation(object->m_centres,centres,object->m_no_patches);
  413.  T_world_rotation(centres,centres,object->m_no_patches);
  414.  M_sort_elements(centres+2,T_LNG_VECTOR,numbers,object->m_no_patches);
  415. #endif
  416.  for(i=0;i<object->m_no_patches;i++)
  417.   M_render_bicubic(object->m_patches[numbers[i]],x,y,z,alp,bet,gam);
  418.  M_force_linear_tmapping=oldtmap;
  419. }
  420. /**********************************************************/