ref: de0622960ecb4ac77edb7633744e18b33835c226
dir: /src/vertex.c/
#include "zgl.h" #include <string.h> void glopNormal(GLContext* c, GLParam* p) { V3 v; v.X = p[1].f; v.Y = p[2].f; v.Z = p[3].f; c->current_normal.X = v.X; c->current_normal.Y = v.Y; c->current_normal.Z = v.Z; c->current_normal.W = 0; } void glopTexCoord(GLContext* c, GLParam* p) { c->current_tex_coord.X = p[1].f; c->current_tex_coord.Y = p[2].f; c->current_tex_coord.Z = p[3].f; c->current_tex_coord.W = p[4].f; } void glopEdgeFlag(GLContext* c, GLParam* p) { c->current_edge_flag = p[1].i; } void glopColor(GLContext* c, GLParam* p) { c->current_color.X = p[1].f; c->current_color.Y = p[2].f; c->current_color.Z = p[3].f; c->current_color.W = p[4].f; if (c->color_material_enabled) { GLParam q[7]; q[0].op = OP_Material; q[1].i = c->current_color_material_mode; q[2].i = c->current_color_material_type; q[3].f = p[1].f; q[4].f = p[2].f; q[5].f = p[3].f; q[6].f = p[4].f; glopMaterial(c, q); } } void gl_eval_viewport(GLContext* c) { GLViewport* v; GLfloat zsize = (1 << (ZB_Z_BITS + ZB_POINT_Z_FRAC_BITS)); v = &c->viewport; v->trans.X = ((v->xsize - 0.5) / 2.0) + v->xmin; v->trans.Y = ((v->ysize - 0.5) / 2.0) + v->ymin; v->trans.Z = ((zsize - 0.5) / 2.0) + ((1 << ZB_POINT_Z_FRAC_BITS)) / 2; v->scale.X = (v->xsize - 0.5) / 2.0; v->scale.Y = -(v->ysize - 0.5) / 2.0; v->scale.Z = -((zsize - 0.5) / 2.0); } void glopBegin(GLContext* c, GLParam* p) { GLint type; M4 tmp; #if TGL_FEATURE_ERROR_CHECK == 1 if(c->in_begin != 0) #define ERROR_FLAG GL_INVALID_OPERATION #include "error_check.h" #else //if(c->in_begin != 0)return; //<COST> #endif type = p[1].i; c->begin_type = type; c->in_begin = 1; c->vertex_n = 0; c->vertex_cnt = 0; if (c->matrix_model_projection_updated) { if (c->lighting_enabled) { /* precompute inverse modelview */ gl_M4_Inv(&tmp, c->matrix_stack_ptr[0]); gl_M4_Transpose(&c->matrix_model_view_inv, &tmp); } else { GLfloat* m = &c->matrix_model_projection.m[0][0]; /* precompute projection matrix */ gl_M4_Mul(&c->matrix_model_projection, c->matrix_stack_ptr[1], c->matrix_stack_ptr[0]); /* test to accelerate computation */ c->matrix_model_projection_no_w_transform = 0; if (m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0) c->matrix_model_projection_no_w_transform = 1; } /* test if the texture matrix is not Identity */ c->apply_texture_matrix = !gl_M4_IsId(c->matrix_stack_ptr[2]); c->matrix_model_projection_updated = 0; } /* viewport */ if (c->viewport.updated) { gl_eval_viewport(c); c->viewport.updated = 0; } /* triangle drawing functions */ if (c->render_mode == GL_SELECT) { c->draw_triangle_front = gl_draw_triangle_select; c->draw_triangle_back = gl_draw_triangle_select; }else if (c->render_mode == GL_FEEDBACK){ c->draw_triangle_front = gl_draw_triangle_feedback; c->draw_triangle_back = gl_draw_triangle_feedback; } else { switch (c->polygon_mode_front) { case GL_POINT: c->draw_triangle_front = gl_draw_triangle_point; break; case GL_LINE: c->draw_triangle_front = gl_draw_triangle_line; break; //case GL_FILL: default: c->draw_triangle_front = gl_draw_triangle_fill; break; } switch (c->polygon_mode_back) { case GL_POINT: c->draw_triangle_back = gl_draw_triangle_point; break; case GL_LINE: c->draw_triangle_back = gl_draw_triangle_line; break; default: c->draw_triangle_back = gl_draw_triangle_fill; break; } } } static inline void gl_transform_to_viewport_vertex_c(GLContext* c, GLVertex* v) { { GLfloat winv = 1.0 / v->pc.W; v->zp.x = (GLint)(v->pc.X * winv * c->viewport.scale.X + c->viewport.trans.X); v->zp.y = (GLint)(v->pc.Y * winv * c->viewport.scale.Y + c->viewport.trans.Y); v->zp.z = (GLint)(v->pc.Z * winv * c->viewport.scale.Z + c->viewport.trans.Z); } v->zp.r = (GLuint)(v->color.v[0] * COLOR_CORRECTED_MULT_MASK + COLOR_MIN_MULT) & COLOR_MASK; v->zp.g = (GLuint)(v->color.v[1] * COLOR_CORRECTED_MULT_MASK + COLOR_MIN_MULT) & COLOR_MASK; v->zp.b = (GLuint)(v->color.v[2] * COLOR_CORRECTED_MULT_MASK + COLOR_MIN_MULT) & COLOR_MASK; if (c->texture_2d_enabled) { v->zp.s = (GLint)(v->tex_coord.X * (ZB_POINT_S_MAX - ZB_POINT_S_MIN) + ZB_POINT_S_MIN); //MARKED v->zp.t = (GLint)(v->tex_coord.Y * (ZB_POINT_T_MAX - ZB_POINT_T_MIN) + ZB_POINT_T_MIN); //MARKED } } static inline void gl_vertex_transform(GLContext* c, GLVertex* v) { GLfloat* m; if (c->lighting_enabled) { /* eye coordinates needed for lighting */ V4* n; m = &c->matrix_stack_ptr[0]->m[0][0]; v->ec.X = (v->coord.X * m[0] + v->coord.Y * m[1] + v->coord.Z * m[2] + m[3]); v->ec.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + v->coord.Z * m[6] + m[7]); v->ec.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + v->coord.Z * m[10] + m[11]); v->ec.W = (v->coord.X * m[12] + v->coord.Y * m[13] + v->coord.Z * m[14] + m[15]); /* projection coordinates */ m = &c->matrix_stack_ptr[1]->m[0][0]; v->pc.X = (v->ec.X * m[0] + v->ec.Y * m[1] + v->ec.Z * m[2] + v->ec.W * m[3]); v->pc.Y = (v->ec.X * m[4] + v->ec.Y * m[5] + v->ec.Z * m[6] + v->ec.W * m[7]); v->pc.Z = (v->ec.X * m[8] + v->ec.Y * m[9] + v->ec.Z * m[10] + v->ec.W * m[11]); v->pc.W = (v->ec.X * m[12] + v->ec.Y * m[13] + v->ec.Z * m[14] + v->ec.W * m[15]); m = &c->matrix_model_view_inv.m[0][0]; n = &c->current_normal; v->normal.X = (n->X * m[0] + n->Y * m[1] + n->Z * m[2]); v->normal.Y = (n->X * m[4] + n->Y * m[5] + n->Z * m[6]); v->normal.Z = (n->X * m[8] + n->Y * m[9] + n->Z * m[10]); if (c->normalize_enabled) { gl_V3_Norm_Fast(&v->normal); } } else { /* no eye coordinates needed, no normal */ /* NOTE: W = 1 is assumed */ m = &c->matrix_model_projection.m[0][0]; v->pc.X = (v->coord.X * m[0] + v->coord.Y * m[1] + v->coord.Z * m[2] + m[3]); v->pc.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + v->coord.Z * m[6] + m[7]); v->pc.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + v->coord.Z * m[10] + m[11]); if (c->matrix_model_projection_no_w_transform) { v->pc.W = m[15]; } else { v->pc.W = (v->coord.X * m[12] + v->coord.Y * m[13] + v->coord.Z * m[14] + m[15]); } } v->clip_code = gl_clipcode(v->pc.X, v->pc.Y, v->pc.Z, v->pc.W); } void glopVertex(GLContext* c, GLParam* p) { GLVertex* v; GLint n, i, cnt; #if TGL_FEATURE_ERROR_CHECK == 1 if(c->in_begin == 0) #define ERROR_FLAG GL_INVALID_OPERATION #include "error_check.h" #else //assert(c->in_begin != 0); #endif n = c->vertex_n; cnt = c->vertex_cnt; cnt++; c->vertex_cnt = cnt; /* quick fix to avoid crashes on large polygons */ #if TGL_FEATURE_GL_POLYGON == 1 if (n >= c->vertex_max) { GLVertex* newarray; c->vertex_max <<= 1; /* just double size */ newarray = gl_malloc(sizeof(GLVertex) * c->vertex_max); #if TGL_FEATURE_ERROR_CHECK == 1 if (!newarray) #define ERROR_FLAG GL_OUT_OF_MEMORY #include "error_check.h" #else if (!newarray) exit(1); #endif memcpy(newarray, c->vertex, n * sizeof(GLVertex)); gl_free(c->vertex); c->vertex = newarray; } #endif /* new vertex entry */ v = &c->vertex[n]; n++; v->coord.X = p[1].f; v->coord.Y = p[2].f; v->coord.Z = p[3].f; v->coord.W = p[4].f; gl_vertex_transform(c, v); /* color */ if (c->lighting_enabled) { gl_shade_vertex(c, v); #include "error_check.h" //^ Don't proceed on an OUT OF MEMORY error. } else { v->color = c->current_color; } /* tex coords */ if (c->texture_2d_enabled) { #if TGL_FEATURE_LIT_TEXTURES == 1 if (!(c->lighting_enabled)) v->color = gl_V4_New(1, 1, 1, 0); // Fix by GEK for unlit textured models. #endif if (c->apply_texture_matrix) { gl_M4_MulV4(&v->tex_coord, c->matrix_stack_ptr[2], &c->current_tex_coord); } else { v->tex_coord = c->current_tex_coord; } } /* precompute the mapping to the viewport */ if (v->clip_code == 0) gl_transform_to_viewport_vertex_c(c, v); /* edge flag */ v->edge_flag = c->current_edge_flag; switch (c->begin_type) { case GL_POINTS: gl_draw_point(c, &c->vertex[0]); n = 0; break; case GL_LINES: if (n == 2) { gl_draw_line(c, &c->vertex[0], &c->vertex[1]); n = 0; } break; case GL_LINE_STRIP: case GL_LINE_LOOP: switch(n){ case 1: { c->vertex[2] = c->vertex[0]; } break; case 2: { gl_draw_line(c, &c->vertex[0], &c->vertex[1]); c->vertex[0] = c->vertex[1]; n = 1; } break; default: break; }; break; case GL_TRIANGLES: if (n == 3) { gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); n = 0; } break; case GL_TRIANGLE_STRIP: if (cnt >= 3) { if (n == 3) n = 0; /* needed to respect triangle orientation */ switch (cnt & 1) { case 0: gl_draw_triangle(c, &c->vertex[2], &c->vertex[1], &c->vertex[0]); break; default: case 1: gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); break; } } break; case GL_TRIANGLE_FAN: if (n == 3) { gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); c->vertex[1] = c->vertex[2]; n = 2; } break; case GL_QUADS: if (n == 4) { c->vertex[2].edge_flag = 0; gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); c->vertex[2].edge_flag = 1; c->vertex[0].edge_flag = 0; gl_draw_triangle(c, &c->vertex[0], &c->vertex[2], &c->vertex[3]); n = 0; } break; case GL_QUAD_STRIP: if (n == 4) { gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); gl_draw_triangle(c, &c->vertex[1], &c->vertex[3], &c->vertex[2]); for (i = 0; i < 2; i++) c->vertex[i] = c->vertex[i + 2]; n = 2; } break; #if TGL_FEATURE_GL_POLYGON == 1 case GL_POLYGON:break; #endif #if TGL_FEATURE_ERROR_CHECK == 1 default: gl_fatal_error("glBegin: type %x not handled\n", c->begin_type); #else default:break; #endif } c->vertex_n = n; } void glopEnd(GLContext* c, GLParam* param) { #if TGL_FEATURE_ERROR_CHECK == 1 if(c->in_begin != 1) #define ERROR_FLAG GL_INVALID_OPERATION #include "error_check.h" #else //assert(c->in_begin == 1); //Assume it went alright. #endif //#if TGL_FEATURE_GL_POLYGON == 1 if (c->begin_type == GL_LINE_LOOP) { if (c->vertex_cnt >= 3) { gl_draw_line(c, &c->vertex[0], &c->vertex[2]); } } //#endif #if TGL_FEATURE_GL_POLYGON == 1 else if (c->begin_type == GL_POLYGON) { GLint i = c->vertex_cnt; while (i >= 3) { i--; gl_draw_triangle(c, &c->vertex[i], &c->vertex[0], &c->vertex[i - 1]); } } #endif c->in_begin = 0; }