Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #include "zgl.h"
  2.  
  3. void glopNormal(GLContext * c, GLParam * p)
  4. {
  5.     V3 v;
  6.  
  7.     v.X = p[1].f;
  8.     v.Y = p[2].f;
  9.     v.Z = p[3].f;
  10.  
  11.     c->current_normal.X = v.X;
  12.     c->current_normal.Y = v.Y;
  13.     c->current_normal.Z = v.Z;
  14.     c->current_normal.W = 0;
  15. }
  16.  
  17. void glopTexCoord(GLContext * c, GLParam * p)
  18. {
  19.     c->current_tex_coord.X = p[1].f;
  20.     c->current_tex_coord.Y = p[2].f;
  21.     c->current_tex_coord.Z = p[3].f;
  22.     c->current_tex_coord.W = p[4].f;
  23. }
  24.  
  25. void glopEdgeFlag(GLContext * c, GLParam * p)
  26. {
  27.     c->current_edge_flag = p[1].i;
  28. }
  29.  
  30. void glopColor(GLContext * c, GLParam * p)
  31. {
  32.  
  33.     c->current_color.X = p[1].f;
  34.     c->current_color.Y = p[2].f;
  35.     c->current_color.Z = p[3].f;
  36.     c->current_color.W = p[4].f;
  37.     c->longcurrent_color[0] = p[5].ui;
  38.     c->longcurrent_color[1] = p[6].ui;
  39.     c->longcurrent_color[2] = p[7].ui;
  40.  
  41.     if (c->color_material_enabled) {
  42.         GLParam q[7];
  43.         q[0].op = OP_Material;
  44.         q[1].i = c->current_color_material_mode;
  45.         q[2].i = c->current_color_material_type;
  46.         q[3].f = p[1].f;
  47.         q[4].f = p[2].f;
  48.         q[5].f = p[3].f;
  49.         q[6].f = p[4].f;
  50.         glopMaterial(c, q);
  51.     }
  52. }
  53.  
  54.  
  55. void gl_eval_viewport(GLContext * c)
  56. {
  57.     GLViewport *v;
  58.     float zsize = (1 << (ZB_Z_BITS + ZB_POINT_Z_FRAC_BITS));
  59.  
  60.     v = &c->viewport;
  61.  
  62.     v->trans.X = ((v->xsize - 0.5) / 2.0) + v->xmin;
  63.     v->trans.Y = ((v->ysize - 0.5) / 2.0) + v->ymin;
  64.     v->trans.Z = ((zsize - 0.5) / 2.0) + ((1 << ZB_POINT_Z_FRAC_BITS)) / 2;
  65.  
  66.     v->scale.X = (v->xsize - 0.5) / 2.0;
  67.     v->scale.Y = -(v->ysize - 0.5) / 2.0;
  68.     v->scale.Z = -((zsize - 0.5) / 2.0);
  69. }
  70.  
  71. void glopBegin(GLContext * c, GLParam * p)
  72. {
  73.     int type;
  74.     M4 tmp;
  75.  
  76.     assert(c->in_begin == 0);
  77.  
  78.     type = p[1].i;
  79.     c->begin_type = type;
  80.     c->in_begin = 1;
  81.     c->vertex_n = 0;
  82.     c->vertex_cnt = 0;
  83.  
  84.     if (c->matrix_model_projection_updated) {
  85.  
  86.         if (c->lighting_enabled) {
  87.             /* precompute inverse modelview */
  88.             gl_M4_Inv(&tmp, c->matrix_stack_ptr[0]);
  89.             gl_M4_Transpose(&c->matrix_model_view_inv, &tmp);
  90.         } else {
  91.             float *m = &c->matrix_model_projection.m[0][0];
  92.             /* precompute projection matrix */
  93.             gl_M4_Mul(&c->matrix_model_projection,
  94.                       c->matrix_stack_ptr[1],
  95.                       c->matrix_stack_ptr[0]);
  96.             /* test to accelerate computation */
  97.             c->matrix_model_projection_no_w_transform = 0;
  98.             if (m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0)
  99.                 c->matrix_model_projection_no_w_transform = 1;
  100.         }
  101.  
  102.         /* test if the texture matrix is not Identity */
  103.         c->apply_texture_matrix = !gl_M4_IsId(c->matrix_stack_ptr[2]);
  104.  
  105.         c->matrix_model_projection_updated = 0;
  106.     }
  107.     /*  viewport */
  108.     if (c->viewport.updated) {
  109.         gl_eval_viewport(c);
  110.         c->viewport.updated = 0;
  111.     }
  112.     /* triangle drawing functions */
  113.     if (c->render_mode == GL_SELECT) {
  114.         c->draw_triangle_front = gl_draw_triangle_select;
  115.         c->draw_triangle_back = gl_draw_triangle_select;
  116.     } else {
  117.         switch (c->polygon_mode_front) {
  118.         case GL_POINT:
  119.             c->draw_triangle_front = gl_draw_triangle_point;
  120.             break;
  121.         case GL_LINE:
  122.             c->draw_triangle_front = gl_draw_triangle_line;
  123.             break;
  124.         default:
  125.             c->draw_triangle_front = gl_draw_triangle_fill;
  126.             break;
  127.         }
  128.  
  129.         switch (c->polygon_mode_back) {
  130.         case GL_POINT:
  131.             c->draw_triangle_back = gl_draw_triangle_point;
  132.             break;
  133.         case GL_LINE:
  134.             c->draw_triangle_back = gl_draw_triangle_line;
  135.             break;
  136.         default:
  137.             c->draw_triangle_back = gl_draw_triangle_fill;
  138.             break;
  139.         }
  140.     }
  141. }
  142.  
  143. /* coords, tranformation , clip code and projection */
  144. /* TODO : handle all cases */
  145. static inline void gl_vertex_transform(GLContext * c, GLVertex * v)
  146. {
  147.     float *m;
  148.     V4 *n;
  149.  
  150.     if (c->lighting_enabled) {
  151.         /* eye coordinates needed for lighting */
  152.  
  153.         m = &c->matrix_stack_ptr[0]->m[0][0];
  154.         v->ec.X = (v->coord.X * m[0] + v->coord.Y * m[1] +
  155.                    v->coord.Z * m[2] + m[3]);
  156.         v->ec.Y = (v->coord.X * m[4] + v->coord.Y * m[5] +
  157.                    v->coord.Z * m[6] + m[7]);
  158.         v->ec.Z = (v->coord.X * m[8] + v->coord.Y * m[9] +
  159.                    v->coord.Z * m[10] + m[11]);
  160.         v->ec.W = (v->coord.X * m[12] + v->coord.Y * m[13] +
  161.                    v->coord.Z * m[14] + m[15]);
  162.  
  163.         /* projection coordinates */
  164.         m = &c->matrix_stack_ptr[1]->m[0][0];
  165.         v->pc.X = (v->ec.X * m[0] + v->ec.Y * m[1] +
  166.                    v->ec.Z * m[2] + v->ec.W * m[3]);
  167.         v->pc.Y = (v->ec.X * m[4] + v->ec.Y * m[5] +
  168.                    v->ec.Z * m[6] + v->ec.W * m[7]);
  169.         v->pc.Z = (v->ec.X * m[8] + v->ec.Y * m[9] +
  170.                    v->ec.Z * m[10] + v->ec.W * m[11]);
  171.         v->pc.W = (v->ec.X * m[12] + v->ec.Y * m[13] +
  172.                    v->ec.Z * m[14] + v->ec.W * m[15]);
  173.  
  174.         m = &c->matrix_model_view_inv.m[0][0];
  175.         n = &c->current_normal;
  176.  
  177.         v->normal.X = (n->X * m[0] + n->Y * m[1] + n->Z * m[2]);
  178.         v->normal.Y = (n->X * m[4] + n->Y * m[5] + n->Z * m[6]);
  179.         v->normal.Z = (n->X * m[8] + n->Y * m[9] + n->Z * m[10]);
  180.  
  181.         if (c->normalize_enabled) {
  182.             gl_V3_Norm(&v->normal);
  183.         }
  184.     } else {
  185.         /* no eye coordinates needed, no normal */
  186.         /* NOTE: W = 1 is assumed */
  187.         m = &c->matrix_model_projection.m[0][0];
  188.  
  189.         v->pc.X = (v->coord.X * m[0] + v->coord.Y * m[1] +
  190.                    v->coord.Z * m[2] + m[3]);
  191.         v->pc.Y = (v->coord.X * m[4] + v->coord.Y * m[5] +
  192.                    v->coord.Z * m[6] + m[7]);
  193.         v->pc.Z = (v->coord.X * m[8] + v->coord.Y * m[9] +
  194.                    v->coord.Z * m[10] + m[11]);
  195.         if (c->matrix_model_projection_no_w_transform) {
  196.             v->pc.W = m[15];
  197.         } else {
  198.             v->pc.W = (v->coord.X * m[12] + v->coord.Y * m[13] +
  199.                        v->coord.Z * m[14] + m[15]);
  200.         }
  201.     }
  202.  
  203.     v->clip_code = gl_clipcode(v->pc.X, v->pc.Y, v->pc.Z, v->pc.W);
  204. }
  205.  
  206. void glopVertex(GLContext * c, GLParam * p)
  207. {
  208.     GLVertex *v;
  209.     int n, i, cnt;
  210.  
  211.     assert(c->in_begin != 0);
  212.  
  213.     n = c->vertex_n;
  214.     cnt = c->vertex_cnt;
  215.     cnt++;
  216.     c->vertex_cnt = cnt;
  217.  
  218.     /* quick fix to avoid crashes on large polygons */
  219.     if (n >= c->vertex_max) {
  220.         GLVertex *newarray;
  221.         c->vertex_max <<= 1;    /* just double size */
  222.         newarray = gl_malloc(sizeof(GLVertex) * c->vertex_max);
  223.         if (!newarray) {
  224.             gl_fatal_error("unable to allocate GLVertex array.\n");
  225.         }
  226.         memcpy(newarray, c->vertex, n * sizeof(GLVertex));
  227.         gl_free(c->vertex);
  228.         c->vertex = newarray;
  229.     }
  230.     /* new vertex entry */
  231.     v = &c->vertex[n];
  232.     n++;
  233.  
  234.     v->coord.X = p[1].f;
  235.     v->coord.Y = p[2].f;
  236.     v->coord.Z = p[3].f;
  237.     v->coord.W = p[4].f;
  238.  
  239.     gl_vertex_transform(c, v);
  240.  
  241.     /* color */
  242.  
  243.     if (c->lighting_enabled) {
  244.         gl_shade_vertex(c, v);
  245.     } else {
  246.         v->color = c->current_color;
  247.     }
  248.  
  249.     /* tex coords */
  250.  
  251.     if (c->texture_2d_enabled) {
  252.         if (c->apply_texture_matrix) {
  253.             gl_M4_MulV4(&v->tex_coord, c->matrix_stack_ptr[2], &c->current_tex_coord);
  254.         } else {
  255.             v->tex_coord = c->current_tex_coord;
  256.         }
  257.     }
  258.     /* precompute the mapping to the viewport */
  259.     if (v->clip_code == 0)
  260.         gl_transform_to_viewport(c, v);
  261.  
  262.         /* edge flag */
  263.  
  264.     v->edge_flag = c->current_edge_flag;
  265.  
  266.     switch (c->begin_type) {
  267.     case GL_POINTS:
  268.         gl_draw_point(c, &c->vertex[0]);
  269.         n = 0;
  270.         break;
  271.  
  272.     case GL_LINES:
  273.         if (n == 2) {
  274.             gl_draw_line(c, &c->vertex[0], &c->vertex[1]);
  275.             n = 0;
  276.         }
  277.         break;
  278.     case GL_LINE_STRIP:
  279.     case GL_LINE_LOOP:
  280.         if (n == 1) {
  281.             c->vertex[2] = c->vertex[0];
  282.         } else if (n == 2) {
  283.             gl_draw_line(c, &c->vertex[0], &c->vertex[1]);
  284.             c->vertex[0] = c->vertex[1];
  285.             n = 1;
  286.         }
  287.         break;
  288.  
  289.     case GL_TRIANGLES:
  290.         if (n == 3) {
  291.                 gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
  292.             n = 0;
  293.         }
  294.         break;
  295.     case GL_TRIANGLE_STRIP:
  296.         if (cnt >= 3) {
  297.             if (n == 3)
  298.                 n = 0;
  299.             /* needed to respect triangle orientation */
  300.             switch(cnt & 1) {
  301.             case 0:
  302.                 gl_draw_triangle(c,&c->vertex[2],&c->vertex[1],&c->vertex[0]);
  303.                 break;
  304.             default:
  305.             case 1:
  306.                 gl_draw_triangle(c,&c->vertex[0],&c->vertex[1],&c->vertex[2]);
  307.                 break;
  308.             }
  309.         }
  310.         break;
  311.     case GL_TRIANGLE_FAN:
  312.         if (n == 3) {
  313.             gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
  314.             c->vertex[1] = c->vertex[2];
  315.             n = 2;
  316.         }
  317.         break;
  318.  
  319.     case GL_QUADS:
  320.         if (n == 4) {
  321.             c->vertex[2].edge_flag = 0;
  322.             gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
  323.             c->vertex[2].edge_flag = 1;
  324.             c->vertex[0].edge_flag = 0;
  325.             gl_draw_triangle(c, &c->vertex[0], &c->vertex[2], &c->vertex[3]);
  326.             n = 0;
  327.         }
  328.         break;
  329.  
  330.     case GL_QUAD_STRIP:
  331.         if (n == 4) {
  332.             gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
  333.             gl_draw_triangle(c, &c->vertex[1], &c->vertex[3], &c->vertex[2]);
  334.             for (i = 0; i < 2; i++)
  335.                 c->vertex[i] = c->vertex[i + 2];
  336.             n = 2;
  337.         }
  338.         break;
  339.     case GL_POLYGON:
  340.         break;
  341.     default:
  342.         gl_fatal_error("glBegin: type %x not handled\n", c->begin_type);
  343.     }
  344.  
  345.     c->vertex_n = n;
  346. }
  347.  
  348. void glopEnd(GLContext * c, GLParam * param)
  349. {
  350.     assert(c->in_begin == 1);
  351.  
  352.     if (c->begin_type == GL_LINE_LOOP) {
  353.         if (c->vertex_cnt >= 3) {
  354.             gl_draw_line(c, &c->vertex[0], &c->vertex[2]);
  355.         }
  356.     } else if (c->begin_type == GL_POLYGON) {
  357.         int i = c->vertex_cnt;
  358.         while (i >= 3) {
  359.             i--;
  360.             gl_draw_triangle(c, &c->vertex[i], &c->vertex[0], &c->vertex[i - 1]);
  361.         }
  362.     }
  363.     c->in_begin = 0;
  364. }
  365.