void gl_draw_line(GLContext *c, GLVertex *p1, GLVertex *p2) { float dx, dy, dz, dw, x1, y1, z1, w1; float tmin, tmax; GLVertex q1, q2; int cc1, cc2; cc1 = p1->clip_code; cc2 = p2->clip_code; if ((cc1 | cc2) == 0) { if (c->render_mode == TGL_SELECT) { gl_add_select1(c, p1->zp.z, p2->zp.z, p2->zp.z); } else { if (c->depth_test) c->fb->fillLineZ(&p1->zp, &p2->zp); else c->fb->fillLine(&p1->zp, &p2->zp); } } else if ((cc1 & cc2) != 0) { return; } else { dx = p2->pc.X - p1->pc.X; dy = p2->pc.Y - p1->pc.Y; dz = p2->pc.Z - p1->pc.Z; dw = p2->pc.W - p1->pc.W; x1 = p1->pc.X; y1 = p1->pc.Y; z1 = p1->pc.Z; w1 = p1->pc.W; tmin = 0; tmax = 1; if (ClipLine1(dx + dw, -x1 - w1, &tmin, &tmax) && ClipLine1(-dx + dw, x1 - w1, &tmin, &tmax) && ClipLine1(dy + dw, -y1 - w1, &tmin, &tmax) && ClipLine1(-dy + dw, y1 - w1, &tmin, &tmax) && ClipLine1(dz + dw, -z1 - w1, &tmin, &tmax) && ClipLine1(-dz + dw, z1 - w1, &tmin, &tmax)) { interpolate(c, &q1, p1, p2, tmin); interpolate(c, &q2, p1, p2, tmax); gl_transform_to_viewport(c, &q1); gl_transform_to_viewport(c, &q2); if (c->depth_test) c->fb->fillLineZ(&q1.zp, &q2.zp); else c->fb->fillLine(&q1.zp, &q2.zp); } } }
static inline void updateTmp(GLContext *c, GLVertex *q, GLVertex *p0, GLVertex *p1, float t) { interpolate_color(c, q, p0, p1, t); if (c->texture_2d_enabled) { // NOTE: This could be implemented with operator overloading, // but i'm not 100% sure that we can completely disregard Z and W components so I'm leaving it like this for now. q->tex_coord.X = (p0->tex_coord.X + (p1->tex_coord.X - p0->tex_coord.X) * t); q->tex_coord.Y = (p0->tex_coord.Y + (p1->tex_coord.Y - p0->tex_coord.Y) * t); } q->clip_code = gl_clipcode(q->pc.X, q->pc.Y, q->pc.Z, q->pc.W); if (q->clip_code == 0) gl_transform_to_viewport(c, q); }
void glopVertex(GLContext * c, GLParam * p) { GLVertex *v; int n, i, cnt; gl_assert(c->in_begin != 0); n = c->vertex_n; cnt = c->vertex_cnt; cnt++; c->vertex_cnt = cnt; /* quick fix to avoid crashes on large polygons */ if (n >= c->vertex_max) { GLVertex *newarray; c->vertex_max <<= 1; /* just double size */ newarray = gl_malloc(sizeof(GLVertex) * c->vertex_max); if (!newarray) { gl_fatal_error("unable to allocate GLVertex array.\n"); } memcpy(newarray, c->vertex, n * sizeof(GLVertex)); gl_free(c->vertex); c->vertex = newarray; } /* 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); } else { v->color = c->current_color; } /* tex coords */ if (c->texture_2d_enabled) { 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(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: if (n == 1) { c->vertex[2] = c->vertex[0]; } else if (n == 2) { gl_draw_line(c, &c->vertex[0], &c->vertex[1]); c->vertex[0] = c->vertex[1]; n = 1; } 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; case GL_POLYGON: break; default: gl_fatal_error("glBegin: type %x not handled\n", c->begin_type); } c->vertex_n = n; }