ref: d29ae2940e7f7145c6f36426647e5cf462cfeae6
parent: 522b4cd3a8ecf8bd0833a7d41daa408c6493829f
author: David <gek@katherine>
date: Wed Feb 24 04:49:51 EST 2021
Performance fix
--- a/config.mk
+++ b/config.mk
@@ -4,7 +4,7 @@
CC= gcc
#CFLAGS= -Wall -w -O3 -g -std=c99 -mtune=native -DNDEBUG
#CFLAGS= -Wall -w -O3 -g -std=c99 -march=native -DNDEBUG
-CFLAGS= -Wall -w -O3 -g -std=c99 -DNDEBUG
+CFLAGS= -Wall -O3 -g -std=c99 -DNDEBUG
#CFLAGS= -Wall -O1 -g -std=c99 -Wno-undef -DNDEBUG
LFLAGS=
--- a/src/clip.c
+++ b/src/clip.c
@@ -10,8 +10,48 @@
#define CLIP_ZMIN (1 << 4)
#define CLIP_ZMAX (1 << 5)
+static inline void gl_transform_to_viewport_clip_c(GLContext* c, GLVertex* v) { //MARK: NOT_INLINED_IN_OG
+ /* coordinates */
+ {
+ 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);
+ }
+ /* color */
+ 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;
+ /* texture */
+
+ 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
+ }
+}
+
+/*
+//MARK <POSSIBLE_PERF_BONUS>
+#define clip_func(name, sign, dir, dir1, dir2) GLfloat name(V4* c, V4* a, V4* b);
+//MARK <POSSIBLE_PERF_BONUS>
+clip_func(clip_xmin, -, X, Y, Z)
+
+ clip_func(clip_xmax, +, X, Y, Z)
+
+ clip_func(clip_ymin, -, Y, X, Z)
+
+ clip_func(clip_ymax, +, Y, X, Z)
+//MARK <POSSIBLE_PERF_BONUS>
+ clip_func(clip_zmin, -, Z, X, Y)
+
+ clip_func(clip_zmax, +, Z, X, Y)
+
+extern GLfloat (*clip_proc[6])(V4*, V4*, V4*);// = {clip_xmin, clip_xmax, clip_ymin, clip_ymax, clip_zmin, clip_zmax};
+
+*/
+
#define clip_funcdef(name, sign, dir, dir1, dir2) \
GLfloat name(V4* c, V4* a, V4* b) { \
GLfloat t, dX, dY, dZ, dW, den; \
@@ -45,9 +85,32 @@
GLfloat (*clip_proc[6])(V4*, V4*, V4*) = {clip_xmin, clip_xmax, clip_ymin, clip_ymax, clip_zmin, clip_zmax};
/* point */
+static void gl_add_select1(GLContext* c, GLint z1, GLint z2, GLint z3) {
+ GLint min, max;
+ min = max = z1;
+ if (z2 < min)
+ min = z2;
+ if (z3 < min)
+ min = z3;
+ if (z2 > max)
+ max = z2;
+ if (z3 > max)
+ max = z3;
+ gl_add_select(c, 0xffffffff - min, 0xffffffff - max);
+}
+void gl_draw_point(GLContext* c, GLVertex* p0) {
+ if (p0->clip_code == 0) {
+ if (c->render_mode == GL_SELECT) {
+ gl_add_select(c, p0->zp.z, p0->zp.z);
+ }else if (c->render_mode == GL_FEEDBACK){
+ gl_add_feedback(c,GL_POINT_TOKEN,p0,NULL,NULL,0);
+ } else {
+ ZB_plot(c->zb, &p0->zp);
+ }
+ }
+}
-
/* line */
//Used only for lines.
@@ -56,8 +119,276 @@
* Line Clipping
*/
+
+
+
+
+
+static inline void GLinterpolate(GLVertex* q, GLVertex* p0, GLVertex* p1, GLfloat t) { //MARK: INLINED_IN_OG
+ q->pc.X = p0->pc.X + (p1->pc.X - p0->pc.X) * t;
+ q->pc.Y = p0->pc.Y + (p1->pc.Y - p0->pc.Y) * t;
+ q->pc.Z = p0->pc.Z + (p1->pc.Z - p0->pc.Z) * t;
+ q->pc.W = p0->pc.W + (p1->pc.W - p0->pc.W) * t;
+
+ for(int i = 0; i < 3; i++)
+ q->color.v[i] = p0->color.v[i] + (p1->color.v[i] - p0->color.v[i]) * t;
+}
+
/* Line Clipping algorithm from 'Computer Graphics', Principles and
Practice */
+static inline GLint ClipLine1(GLfloat denom, GLfloat num, GLfloat* tmin, GLfloat* tmax) {
+ GLfloat t;
+
+ if (denom > 0) {
+ t = num / denom;
+ if (t > *tmax)
+ return 0;
+ if (t > *tmin)
+ *tmin = t;
+ } else if (denom < 0) {
+ t = num / denom;
+ if (t < *tmin)
+ return 0;
+ if (t < *tmax)
+ *tmax = t;
+ } else if (num > 0)
+ return 0;
+ return 1;
+}
+void gl_draw_line(GLContext* c, GLVertex* p1, GLVertex* p2) {
+ GLfloat dx, dy, dz, dw, x1, y1, z1, w1;
+
+ GLVertex q1, q2;
+ GLint cc1, cc2;
+
+ cc1 = p1->clip_code;
+ cc2 = p2->clip_code;
+
+ if ((cc1 | cc2) == 0) {
+ if (c->render_mode == GL_SELECT) {
+ gl_add_select1(c, p1->zp.z, p2->zp.z, p2->zp.z);
+ }else if (c->render_mode == GL_FEEDBACK){
+ gl_add_feedback(
+ c, GL_LINE_TOKEN,
+ p1,
+ p2,
+ NULL,
+ 0
+ );
+ } else {
+ if (c->zb->depth_test)
+ ZB_line_z(c->zb, &p1->zp, &p2->zp);
+ else
+ ZB_line(c->zb, &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;
+
+ GLfloat tmin = 0;
+ GLfloat 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)) {
+
+ GLinterpolate(&q1, p1, p2, tmin);
+ GLinterpolate(&q2, p1, p2, tmax);
+ gl_transform_to_viewport_clip_c(c, &q1);
+ gl_transform_to_viewport_clip_c(c, &q2);
+
+ if (c->zb->depth_test)
+ ZB_line_z(c->zb, &q1.zp, &q2.zp);
+ else
+ ZB_line(c->zb, &q1.zp, &q2.zp);
+ }
+ }
+}
+
+//inline void gl_draw_point(GLContext* c, GLVertex* p0);
+
+
+/*Triangles*/
+
+static inline void updateTmp(GLContext* c, GLVertex* q, GLVertex* p0, GLVertex* p1, GLfloat t) { //MARK: INLINED_IN_OG
+ {
+
+
+ q->color.v[0] = p0->color.v[0] + (p1->color.v[0] - p0->color.v[0]) * t;
+ q->color.v[1] = p0->color.v[1] + (p1->color.v[1] - p0->color.v[1]) * t;
+ q->color.v[2] = p0->color.v[2] + (p1->color.v[2] - p0->color.v[2]) * t;
+ }
+ // */
+ if (c->texture_2d_enabled) {
+ 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_clip_c(c, q);
+}
+//DO NOT INLINE!!! DO NOT INLINE!!! DO NOT INLINE!!!
+static void gl_draw_triangle_clip(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2, GLint clip_bit);//MARK: NOT_INLINED_IN_OG
+
+void gl_draw_triangle(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2) {
+ GLint co, cc[3], front;
+
+
+ cc[0] = p0->clip_code;
+ cc[1] = p1->clip_code;
+ cc[2] = p2->clip_code;
+
+ co = cc[0] | cc[1] | cc[2];
+
+ /* we handle the non clipped case here to go faster */
+ if (co == 0) {
+ GLfloat norm;
+ norm = (GLfloat)(p1->zp.x - p0->zp.x) * (GLfloat)(p2->zp.y - p0->zp.y) - (GLfloat)(p2->zp.x - p0->zp.x) * (GLfloat)(p1->zp.y - p0->zp.y);
+
+ if (norm == 0) //MARK <POSSIBLE_PERF_BONUS>
+ return;
+
+ front = norm < 0.0;
+ front = front ^ c->current_front_face; //I don't know how this works, but it does, GL_CCW is 0x901 and CW is 900.
+
+ /* back face culling */
+ if (c->cull_face_enabled) {
+ /* most used case first */
+ if (c->current_cull_face == GL_BACK) {
+ if (front == 0)
+ return;
+ c->draw_triangle_front(c, p0, p1, p2);
+ } else if (c->current_cull_face == GL_FRONT) {
+ if (front != 0)
+ return;
+ c->draw_triangle_back(c, p0, p1, p2);
+ } else {
+ return;
+ }
+ } else {
+ /* no culling */
+ if (front) {
+ c->draw_triangle_front(c, p0, p1, p2);
+ } else {
+ c->draw_triangle_back(c, p0, p1, p2);
+ }
+ }
+ } else {
+ //GLint c_and = cc[0] & cc[1] & cc[2];
+ if ((cc[0] & cc[1] & cc[2]) == 0) { // Don't draw a triangle with no points
+ gl_draw_triangle_clip(c, p0, p1, p2, 0);
+ }
+ }
+}
+
+
+static void gl_draw_triangle_clip(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2, GLint clip_bit) {
+ GLint co, c_and, co1, cc[3], edge_flag_tmp, clip_mask;
+ //GLVertex tmp1, tmp2, *q[3];
+ GLVertex *q[3];
+
+
+ cc[0] = p0->clip_code;
+ cc[1] = p1->clip_code;
+ cc[2] = p2->clip_code;
+
+ co = cc[0] | cc[1] | cc[2];
+ if (co == 0) {
+ gl_draw_triangle(c, p0, p1, p2);
+ } else {
+
+ c_and = cc[0] & cc[1] & cc[2];
+ /* the triangle is completely outside */
+ if (c_and != 0)
+ return;
+
+ /* find the next direction to clip */
+ while (clip_bit < 6 && (co & (1 << clip_bit)) == 0) {
+ clip_bit++;
+ }
+
+ /* this test can be true only in case of rounding errors */
+ if (clip_bit == 6) { //The 2 bit and the 4 bit.
+#if 0
+ tgl_warning("Error:\n");tgl_warning("%f %f %f %f\n",p0->pc.X,p0->pc.Y,p0->pc.Z,p0->pc.W);tgl_warning("%f %f %f %f\n",p1->pc.X,p1->pc.Y,p1->pc.Z,p1->pc.W);tgl_warning("%f %f %f %f\n",p2->pc.X,p2->pc.Y,p2->pc.Z,p2->pc.W);
+#endif
+ return;
+ }
+
+ clip_mask = 1 << clip_bit;
+ co1 = (cc[0] ^ cc[1] ^ cc[2]) & clip_mask;
+
+ if (co1) {
+ /* one point outside */
+
+ if (cc[0] & clip_mask) {
+ q[0] = p0;
+ q[1] = p1;
+ q[2] = p2;
+ } else if (cc[1] & clip_mask) {
+ q[0] = p1;
+ q[1] = p2;
+ q[2] = p0;
+ } else {
+ q[0] = p2;
+ q[1] = p0;
+ q[2] = p1;
+ }
+ {GLVertex tmp1, tmp2;GLfloat tt;
+ tt = clip_proc[clip_bit](&tmp1.pc, &q[0]->pc, &q[1]->pc);
+ updateTmp(c, &tmp1, q[0], q[1], tt);
+
+ tt = clip_proc[clip_bit](&tmp2.pc, &q[0]->pc, &q[2]->pc);
+ updateTmp(c, &tmp2, q[0], q[2], tt);
+
+ tmp1.edge_flag = q[0]->edge_flag;
+ edge_flag_tmp = q[2]->edge_flag;
+ q[2]->edge_flag = 0;
+ gl_draw_triangle_clip(c, &tmp1, q[1], q[2], clip_bit + 1);
+
+ tmp2.edge_flag = 1;
+ tmp1.edge_flag = 0;
+ q[2]->edge_flag = edge_flag_tmp;
+ gl_draw_triangle_clip(c, &tmp2, &tmp1, q[2], clip_bit + 1);
+ }
+ } else {
+ /* two points outside */
+
+ if ((cc[0] & clip_mask) == 0) {
+ q[0] = p0;
+ q[1] = p1;
+ q[2] = p2;
+ } else if ((cc[1] & clip_mask) == 0) {
+ q[0] = p1;
+ q[1] = p2;
+ q[2] = p0;
+ } else {
+ q[0] = p2;
+ q[1] = p0;
+ q[2] = p1;
+ }
+ {GLVertex tmp1, tmp2;GLfloat tt;
+ tt = clip_proc[clip_bit](&tmp1.pc, &q[0]->pc, &q[1]->pc);
+ updateTmp(c, &tmp1, q[0], q[1], tt);
+
+ tt = clip_proc[clip_bit](&tmp2.pc, &q[0]->pc, &q[2]->pc);
+ updateTmp(c, &tmp2, q[0], q[2], tt);
+
+ tmp1.edge_flag = 1;
+ tmp2.edge_flag = q[2]->edge_flag;
+ gl_draw_triangle_clip(c, q[0], &tmp1, &tmp2, clip_bit + 1);
+ }
+ }
+ }
+}
+
--- a/src/vertex.c
+++ b/src/vertex.c
@@ -133,7 +133,7 @@
}
}
}
-/*
+
static inline void gl_transform_to_viewport_vertex_c(GLContext* c, GLVertex* v) {
@@ -155,7 +155,7 @@
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;
@@ -274,7 +274,7 @@
}
/* precompute the mapping to the viewport */
if (v->clip_code == 0)
- gl_transform_to_viewport_clip_c(c, v);
+ gl_transform_to_viewport_vertex_c(c, v);
/* edge flag */
v->edge_flag = c->current_edge_flag;
--- a/src/zgl.h
+++ b/src/zgl.h
@@ -387,27 +387,7 @@
return a;
}
-static inline void gl_transform_to_viewport_clip_c(GLContext* c, GLVertex* v) {
- /* coordinates */
- {
- 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);
- }
- /* color */
- 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;
-
- /* texture */
-
- 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
- }
-}
//void gl_transform_to_viewport(GLContext* c, GLVertex* v);
//inline void gl_draw_triangle(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2);
@@ -421,309 +401,15 @@
* We compute the point 'c' of GLintersection and the value of the parameter 't'
* of the GLintersection if x=a+t(b-a).
*/
-//MARK <POSSIBLE_PERF_BONUS>
-#define clip_func(name, sign, dir, dir1, dir2) GLfloat name(V4* c, V4* a, V4* b);
-//MARK <POSSIBLE_PERF_BONUS>
-clip_func(clip_xmin, -, X, Y, Z)
- clip_func(clip_xmax, +, X, Y, Z)
- clip_func(clip_ymin, -, Y, X, Z)
- clip_func(clip_ymax, +, Y, X, Z)
-//MARK <POSSIBLE_PERF_BONUS>
- clip_func(clip_zmin, -, Z, X, Y)
-
- clip_func(clip_zmax, +, Z, X, Y)
-
-extern GLfloat (*clip_proc[6])(V4*, V4*, V4*);// = {clip_xmin, clip_xmax, clip_ymin, clip_ymax, clip_zmin, clip_zmax};
-
-static inline void updateTmp(GLContext* c, GLVertex* q, GLVertex* p0, GLVertex* p1, GLfloat t) {
- {
-
-
- q->color.v[0] = p0->color.v[0] + (p1->color.v[0] - p0->color.v[0]) * t;
- q->color.v[1] = p0->color.v[1] + (p1->color.v[1] - p0->color.v[1]) * t;
- q->color.v[2] = p0->color.v[2] + (p1->color.v[2] - p0->color.v[2]) * t;
- }
- // */
- if (c->texture_2d_enabled) {
- 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_clip_c(c, q);
-}
-
//inline void gl_draw_triangle_clip(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2, GLint clip_bit);
-static inline void gl_draw_triangle_clip(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2, GLint clip_bit);
+void gl_draw_triangle(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2);
+void gl_draw_line(GLContext* c, GLVertex* p0, GLVertex* p1);
+void gl_draw_point(GLContext* c, GLVertex* p0);
-static inline void gl_draw_triangle(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2) {
- GLint co, cc[3], front;
-
-
- cc[0] = p0->clip_code;
- cc[1] = p1->clip_code;
- cc[2] = p2->clip_code;
-
- co = cc[0] | cc[1] | cc[2];
-
- /* we handle the non clipped case here to go faster */
- if (co == 0) {
- GLfloat norm;
- norm = (GLfloat)(p1->zp.x - p0->zp.x) * (GLfloat)(p2->zp.y - p0->zp.y) - (GLfloat)(p2->zp.x - p0->zp.x) * (GLfloat)(p1->zp.y - p0->zp.y);
-
- if (norm == 0) //MARK <POSSIBLE_PERF_BONUS>
- return;
-
- front = norm < 0.0;
- front = front ^ c->current_front_face; //I don't know how this works, but it does, GL_CCW is 0x901 and CW is 900.
-
- /* back face culling */
- if (c->cull_face_enabled) {
- /* most used case first */
- if (c->current_cull_face == GL_BACK) {
- if (front == 0)
- return;
- c->draw_triangle_front(c, p0, p1, p2);
- } else if (c->current_cull_face == GL_FRONT) {
- if (front != 0)
- return;
- c->draw_triangle_back(c, p0, p1, p2);
- } else {
- return;
- }
- } else {
- /* no culling */
- if (front) {
- c->draw_triangle_front(c, p0, p1, p2);
- } else {
- c->draw_triangle_back(c, p0, p1, p2);
- }
- }
- } else {
- //GLint c_and = cc[0] & cc[1] & cc[2];
- if ((cc[0] & cc[1] & cc[2]) == 0) { // Don't draw a triangle with no points
- gl_draw_triangle_clip(c, p0, p1, p2, 0);
- }
- }
-}
-
-
-static inline void gl_draw_triangle_clip(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2, GLint clip_bit) {
- GLint co, c_and, co1, cc[3], edge_flag_tmp, clip_mask;
- //GLVertex tmp1, tmp2, *q[3];
- GLVertex *q[3];
-
-
- cc[0] = p0->clip_code;
- cc[1] = p1->clip_code;
- cc[2] = p2->clip_code;
-
- co = cc[0] | cc[1] | cc[2];
- if (co == 0) {
- gl_draw_triangle(c, p0, p1, p2);
- } else {
-
- c_and = cc[0] & cc[1] & cc[2];
- /* the triangle is completely outside */
- if (c_and != 0)
- return;
-
- /* find the next direction to clip */
- while (clip_bit < 6 && (co & (1 << clip_bit)) == 0) {
- clip_bit++;
- }
-
- /* this test can be true only in case of rounding errors */
- if (clip_bit == 6) { //The 2 bit and the 4 bit.
-#if 0
- tgl_warning("Error:\n");tgl_warning("%f %f %f %f\n",p0->pc.X,p0->pc.Y,p0->pc.Z,p0->pc.W);tgl_warning("%f %f %f %f\n",p1->pc.X,p1->pc.Y,p1->pc.Z,p1->pc.W);tgl_warning("%f %f %f %f\n",p2->pc.X,p2->pc.Y,p2->pc.Z,p2->pc.W);
-#endif
- return;
- }
-
- clip_mask = 1 << clip_bit;
- co1 = (cc[0] ^ cc[1] ^ cc[2]) & clip_mask;
-
- if (co1) {
- /* one point outside */
-
- if (cc[0] & clip_mask) {
- q[0] = p0;
- q[1] = p1;
- q[2] = p2;
- } else if (cc[1] & clip_mask) {
- q[0] = p1;
- q[1] = p2;
- q[2] = p0;
- } else {
- q[0] = p2;
- q[1] = p0;
- q[2] = p1;
- }
- {GLVertex tmp1, tmp2;GLfloat tt;
- tt = clip_proc[clip_bit](&tmp1.pc, &q[0]->pc, &q[1]->pc);
- updateTmp(c, &tmp1, q[0], q[1], tt);
-
- tt = clip_proc[clip_bit](&tmp2.pc, &q[0]->pc, &q[2]->pc);
- updateTmp(c, &tmp2, q[0], q[2], tt);
-
- tmp1.edge_flag = q[0]->edge_flag;
- edge_flag_tmp = q[2]->edge_flag;
- q[2]->edge_flag = 0;
- gl_draw_triangle_clip(c, &tmp1, q[1], q[2], clip_bit + 1);
-
- tmp2.edge_flag = 1;
- tmp1.edge_flag = 0;
- q[2]->edge_flag = edge_flag_tmp;
- gl_draw_triangle_clip(c, &tmp2, &tmp1, q[2], clip_bit + 1);
- }
- } else {
- /* two points outside */
-
- if ((cc[0] & clip_mask) == 0) {
- q[0] = p0;
- q[1] = p1;
- q[2] = p2;
- } else if ((cc[1] & clip_mask) == 0) {
- q[0] = p1;
- q[1] = p2;
- q[2] = p0;
- } else {
- q[0] = p2;
- q[1] = p0;
- q[2] = p1;
- }
- {GLVertex tmp1, tmp2;GLfloat tt;
- tt = clip_proc[clip_bit](&tmp1.pc, &q[0]->pc, &q[1]->pc);
- updateTmp(c, &tmp1, q[0], q[1], tt);
-
- tt = clip_proc[clip_bit](&tmp2.pc, &q[0]->pc, &q[2]->pc);
- updateTmp(c, &tmp2, q[0], q[2], tt);
-
- tmp1.edge_flag = 1;
- tmp2.edge_flag = q[2]->edge_flag;
- gl_draw_triangle_clip(c, q[0], &tmp1, &tmp2, clip_bit + 1);
- }
- }
- }
-}
-
-//inline void gl_draw_line(GLContext* c, GLVertex* p0, GLVertex* p1);
-static inline void gl_add_select1(GLContext* c, GLint z1, GLint z2, GLint z3) {
- GLint min, max;
- min = max = z1;
- if (z2 < min)
- min = z2;
- if (z3 < min)
- min = z3;
- if (z2 > max)
- max = z2;
- if (z3 > max)
- max = z3;
-
- gl_add_select(c, 0xffffffff - min, 0xffffffff - max);
-}
-static inline void GLinterpolate(GLVertex* q, GLVertex* p0, GLVertex* p1, GLfloat t) {
- q->pc.X = p0->pc.X + (p1->pc.X - p0->pc.X) * t;
- q->pc.Y = p0->pc.Y + (p1->pc.Y - p0->pc.Y) * t;
- q->pc.Z = p0->pc.Z + (p1->pc.Z - p0->pc.Z) * t;
- q->pc.W = p0->pc.W + (p1->pc.W - p0->pc.W) * t;
-
- for(int i = 0; i < 3; i++)
- q->color.v[i] = p0->color.v[i] + (p1->color.v[i] - p0->color.v[i]) * t;
-}
-static inline GLint ClipLine1(GLfloat denom, GLfloat num, GLfloat* tmin, GLfloat* tmax) {
- GLfloat t;
-
- if (denom > 0) {
- t = num / denom;
- if (t > *tmax)
- return 0;
- if (t > *tmin)
- *tmin = t;
- } else if (denom < 0) {
- t = num / denom;
- if (t < *tmin)
- return 0;
- if (t < *tmax)
- *tmax = t;
- } else if (num > 0)
- return 0;
- return 1;
-}
-static inline void gl_draw_line(GLContext* c, GLVertex* p1, GLVertex* p2) {
- GLfloat dx, dy, dz, dw, x1, y1, z1, w1;
-
- GLVertex q1, q2;
- GLint cc1, cc2;
-
- cc1 = p1->clip_code;
- cc2 = p2->clip_code;
-
- if ((cc1 | cc2) == 0) {
- if (c->render_mode == GL_SELECT) {
- gl_add_select1(c, p1->zp.z, p2->zp.z, p2->zp.z);
- }else if (c->render_mode == GL_FEEDBACK){
- gl_add_feedback(
- c, GL_LINE_TOKEN,
- p1,
- p2,
- NULL,
- 0
- );
- } else {
- if (c->zb->depth_test)
- ZB_line_z(c->zb, &p1->zp, &p2->zp);
- else
- ZB_line(c->zb, &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;
-
- GLfloat tmin = 0;
- GLfloat 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)) {
-
- GLinterpolate(&q1, p1, p2, tmin);
- GLinterpolate(&q2, p1, p2, tmax);
- gl_transform_to_viewport_clip_c(c, &q1);
- gl_transform_to_viewport_clip_c(c, &q2);
-
- if (c->zb->depth_test)
- ZB_line_z(c->zb, &q1.zp, &q2.zp);
- else
- ZB_line(c->zb, &q1.zp, &q2.zp);
- }
- }
-}
-
-//inline void gl_draw_point(GLContext* c, GLVertex* p0);
-inline void gl_draw_point(GLContext* c, GLVertex* p0) {
- if (p0->clip_code == 0) {
- if (c->render_mode == GL_SELECT) {
- gl_add_select(c, p0->zp.z, p0->zp.z);
- }else if (c->render_mode == GL_FEEDBACK){
- gl_add_feedback(c,GL_POINT_TOKEN,p0,NULL,NULL,0);
- } else {
- ZB_plot(c->zb, &p0->zp);
- }
- }
-}
void gl_draw_triangle_point(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2); //MUST BE FUNCTION POINTER
void gl_draw_triangle_line(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2); //MUST BE FUNCTION POINTER