3 /* fill triangle profile */
6 #define CLIP_XMIN (1<<0)
7 #define CLIP_XMAX (1<<1)
8 #define CLIP_YMIN (1<<2)
9 #define CLIP_YMAX (1<<3)
10 #define CLIP_ZMIN (1<<4)
11 #define CLIP_ZMAX (1<<5)
13 void gl_transform_to_viewport(GLContext
*c
,GLVertex
*v
)
19 v
->zp
.x
= (int) ( v
->pc
.X
* winv
* c
->viewport
.scale
.X
20 + c
->viewport
.trans
.X
);
21 v
->zp
.y
= (int) ( v
->pc
.Y
* winv
* c
->viewport
.scale
.Y
22 + c
->viewport
.trans
.Y
);
23 v
->zp
.z
= (int) ( v
->pc
.Z
* winv
* c
->viewport
.scale
.Z
24 + c
->viewport
.trans
.Z
);
26 if (c
->lighting_enabled
) {
27 v
->zp
.r
=(int)(v
->color
.v
[0] * (ZB_POINT_RED_MAX
- ZB_POINT_RED_MIN
)
29 v
->zp
.g
=(int)(v
->color
.v
[1] * (ZB_POINT_GREEN_MAX
- ZB_POINT_GREEN_MIN
)
30 + ZB_POINT_GREEN_MIN
);
31 v
->zp
.b
=(int)(v
->color
.v
[2] * (ZB_POINT_BLUE_MAX
- ZB_POINT_BLUE_MIN
)
34 /* no need to convert to integer if no lighting : take current color */
35 v
->zp
.r
= c
->longcurrent_color
[0];
36 v
->zp
.g
= c
->longcurrent_color
[1];
37 v
->zp
.b
= c
->longcurrent_color
[2];
42 if (c
->texture_2d_enabled
) {
43 v
->zp
.s
=(int)(v
->tex_coord
.X
* (ZB_POINT_S_MAX
- ZB_POINT_S_MIN
)
45 v
->zp
.t
=(int)(v
->tex_coord
.Y
* (ZB_POINT_T_MAX
- ZB_POINT_T_MIN
)
51 static void gl_add_select1(GLContext
*c
,int z1
,int z2
,int z3
)
60 gl_add_select(c
,0xffffffff-min
,0xffffffff-max
);
65 void gl_draw_point(GLContext
*c
,GLVertex
*p0
)
67 if (p0
->clip_code
== 0) {
68 if (c
->render_mode
== GL_SELECT
) {
69 gl_add_select(c
,p0
->zp
.z
,p0
->zp
.z
);
71 ZB_plot(c
->zb
,&p0
->zp
);
78 static inline void interpolate(GLVertex
*q
,GLVertex
*p0
,GLVertex
*p1
,float t
)
80 q
->pc
.X
=p0
->pc
.X
+(p1
->pc
.X
-p0
->pc
.X
)*t
;
81 q
->pc
.Y
=p0
->pc
.Y
+(p1
->pc
.Y
-p0
->pc
.Y
)*t
;
82 q
->pc
.Z
=p0
->pc
.Z
+(p1
->pc
.Z
-p0
->pc
.Z
)*t
;
83 q
->pc
.W
=p0
->pc
.W
+(p1
->pc
.W
-p0
->pc
.W
)*t
;
85 q
->color
.v
[0]=p0
->color
.v
[0] + (p1
->color
.v
[0]-p0
->color
.v
[0])*t
;
86 q
->color
.v
[1]=p0
->color
.v
[1] + (p1
->color
.v
[1]-p0
->color
.v
[1])*t
;
87 q
->color
.v
[2]=p0
->color
.v
[2] + (p1
->color
.v
[2]-p0
->color
.v
[2])*t
;
94 /* Line Clipping algorithm from 'Computer Graphics', Principles and
96 static inline int ClipLine1(float denom
,float num
,float *tmin
,float *tmax
)
102 if (t
>*tmax
) return 0;
103 if (t
>*tmin
) *tmin
=t
;
104 } else if (denom
<0) {
106 if (t
<*tmin
) return 0;
107 if (t
<*tmax
) *tmax
=t
;
108 } else if (num
>0) return 0;
112 void gl_draw_line(GLContext
*c
,GLVertex
*p1
,GLVertex
*p2
)
114 float dx
,dy
,dz
,dw
,x1
,y1
,z1
,w1
;
122 if ( (cc1
| cc2
) == 0) {
123 if (c
->render_mode
== GL_SELECT
) {
124 gl_add_select1(c
,p1
->zp
.z
,p2
->zp
.z
,p2
->zp
.z
);
127 ZB_line_z(c
->zb
,&p1
->zp
,&p2
->zp
);
129 ZB_line(c
->zb
,&p1
->zp
,&p2
->zp
);
131 } else if ( (cc1
&cc2
) != 0 ) {
134 dx
=p2
->pc
.X
-p1
->pc
.X
;
135 dy
=p2
->pc
.Y
-p1
->pc
.Y
;
136 dz
=p2
->pc
.Z
-p1
->pc
.Z
;
137 dw
=p2
->pc
.W
-p1
->pc
.W
;
145 if (ClipLine1(dx
+dw
,-x1
-w1
,&tmin
,&tmax
) &&
146 ClipLine1(-dx
+dw
,x1
-w1
,&tmin
,&tmax
) &&
147 ClipLine1(dy
+dw
,-y1
-w1
,&tmin
,&tmax
) &&
148 ClipLine1(-dy
+dw
,y1
-w1
,&tmin
,&tmax
) &&
149 ClipLine1(dz
+dw
,-z1
-w1
,&tmin
,&tmax
) &&
150 ClipLine1(-dz
+dw
,z1
-w1
,&tmin
,&tmax
)) {
152 interpolate(&q1
,p1
,p2
,tmin
);
153 interpolate(&q2
,p1
,p2
,tmax
);
154 gl_transform_to_viewport(c
,&q1
);
155 gl_transform_to_viewport(c
,&q2
);
158 ZB_line_z(c
->zb
,&q1
.zp
,&q2
.zp
);
160 ZB_line(c
->zb
,&q1
.zp
,&q2
.zp
);
172 /* We clip the segment [a,b] against the 6 planes of the normal volume.
173 * We compute the point 'c' of intersection and the value of the parameter 't'
174 * of the intersection if x=a+t(b-a).
177 #define clip_func(name,sign,dir,dir1,dir2) \
178 static float name(V4 *c,V4 *a,V4 *b) \
180 float t,dX,dY,dZ,dW,den;\
185 den = -(sign d ## dir) + dW;\
187 else t = ( sign a->dir - a->W) / den;\
188 c->dir1 = a->dir1 + t * d ## dir1;\
189 c->dir2 = a->dir2 + t * d ## dir2;\
190 c->W = a->W + t * dW;\
196 clip_func(clip_xmin
,-,X
,Y
,Z
)
198 clip_func(clip_xmax
,+,X
,Y
,Z
)
200 clip_func(clip_ymin
,-,Y
,X
,Z
)
202 clip_func(clip_ymax
,+,Y
,X
,Z
)
204 clip_func(clip_zmin
,-,Z
,X
,Y
)
206 clip_func(clip_zmax
,+,Z
,X
,Y
)
209 float (*clip_proc
[6])(V4
*,V4
*,V4
*)= {
215 static inline void updateTmp(GLContext
*c
,
216 GLVertex
*q
,GLVertex
*p0
,GLVertex
*p1
,float t
)
218 if (c
->current_shade_model
== GL_SMOOTH
) {
219 q
->color
.v
[0]=p0
->color
.v
[0] + (p1
->color
.v
[0]-p0
->color
.v
[0])*t
;
220 q
->color
.v
[1]=p0
->color
.v
[1] + (p1
->color
.v
[1]-p0
->color
.v
[1])*t
;
221 q
->color
.v
[2]=p0
->color
.v
[2] + (p1
->color
.v
[2]-p0
->color
.v
[2])*t
;
223 q
->color
.v
[0]=p0
->color
.v
[0];
224 q
->color
.v
[1]=p0
->color
.v
[1];
225 q
->color
.v
[2]=p0
->color
.v
[2];
228 if (c
->texture_2d_enabled
) {
229 q
->tex_coord
.X
=p0
->tex_coord
.X
+ (p1
->tex_coord
.X
-p0
->tex_coord
.X
)*t
;
230 q
->tex_coord
.Y
=p0
->tex_coord
.Y
+ (p1
->tex_coord
.Y
-p0
->tex_coord
.Y
)*t
;
233 q
->clip_code
=gl_clipcode(q
->pc
.X
,q
->pc
.Y
,q
->pc
.Z
,q
->pc
.W
);
235 gl_transform_to_viewport(c
,q
);
238 static void gl_draw_triangle_clip(GLContext
*c
,
239 GLVertex
*p0
,GLVertex
*p1
,GLVertex
*p2
,int clip_bit
);
241 void gl_draw_triangle(GLContext
*c
,
242 GLVertex
*p0
,GLVertex
*p1
,GLVertex
*p2
)
244 int co
,c_and
,cc
[3],front
;
251 co
=cc
[0] | cc
[1] | cc
[2];
253 /* we handle the non clipped case here to go faster */
256 norm
=(float)(p1
->zp
.x
-p0
->zp
.x
)*(float)(p2
->zp
.y
-p0
->zp
.y
)-
257 (float)(p2
->zp
.x
-p0
->zp
.x
)*(float)(p1
->zp
.y
-p0
->zp
.y
);
259 if (norm
== 0) return;
262 front
= front
^ c
->current_front_face
;
264 /* back face culling */
265 if (c
->cull_face_enabled
) {
266 /* most used case first */
267 if (c
->current_cull_face
== GL_BACK
) {
268 if (front
== 0) return;
269 c
->draw_triangle_front(c
,p0
,p1
,p2
);
270 } else if (c
->current_cull_face
== GL_FRONT
) {
271 if (front
!= 0) return;
272 c
->draw_triangle_back(c
,p0
,p1
,p2
);
279 c
->draw_triangle_front(c
,p0
,p1
,p2
);
281 c
->draw_triangle_back(c
,p0
,p1
,p2
);
285 c_and
=cc
[0] & cc
[1] & cc
[2];
287 gl_draw_triangle_clip(c
,p0
,p1
,p2
,0);
292 static void gl_draw_triangle_clip(GLContext
*c
,
293 GLVertex
*p0
,GLVertex
*p1
,GLVertex
*p2
,int clip_bit
)
295 int co
,c_and
,co1
,cc
[3],edge_flag_tmp
,clip_mask
;
296 GLVertex tmp1
,tmp2
,*q
[3];
303 co
=cc
[0] | cc
[1] | cc
[2];
305 gl_draw_triangle(c
,p0
,p1
,p2
);
307 c_and
=cc
[0] & cc
[1] & cc
[2];
308 /* the triangle is completely outside */
309 if (c_and
!=0) return;
311 /* find the next direction to clip */
312 while (clip_bit
< 6 && (co
& (1 << clip_bit
)) == 0) {
316 /* this test can be true only in case of rounding errors */
320 printf("%f %f %f %f\n",p0
->pc
.X
,p0
->pc
.Y
,p0
->pc
.Z
,p0
->pc
.W
);
321 printf("%f %f %f %f\n",p1
->pc
.X
,p1
->pc
.Y
,p1
->pc
.Z
,p1
->pc
.W
);
322 printf("%f %f %f %f\n",p2
->pc
.X
,p2
->pc
.Y
,p2
->pc
.Z
,p2
->pc
.W
);
327 clip_mask
= 1 << clip_bit
;
328 co1
=(cc
[0] ^ cc
[1] ^ cc
[2]) & clip_mask
;
331 /* one point outside */
333 if (cc
[0] & clip_mask
) { q
[0]=p0
; q
[1]=p1
; q
[2]=p2
; }
334 else if (cc
[1] & clip_mask
) { q
[0]=p1
; q
[1]=p2
; q
[2]=p0
; }
335 else { q
[0]=p2
; q
[1]=p0
; q
[2]=p1
; }
337 tt
=clip_proc
[clip_bit
](&tmp1
.pc
,&q
[0]->pc
,&q
[1]->pc
);
338 updateTmp(c
,&tmp1
,q
[0],q
[1],tt
);
340 tt
=clip_proc
[clip_bit
](&tmp2
.pc
,&q
[0]->pc
,&q
[2]->pc
);
341 updateTmp(c
,&tmp2
,q
[0],q
[2],tt
);
343 tmp1
.edge_flag
=q
[0]->edge_flag
;
344 edge_flag_tmp
=q
[2]->edge_flag
;
346 gl_draw_triangle_clip(c
,&tmp1
,q
[1],q
[2],clip_bit
+1);
350 q
[2]->edge_flag
=edge_flag_tmp
;
351 gl_draw_triangle_clip(c
,&tmp2
,&tmp1
,q
[2],clip_bit
+1);
353 /* two points outside */
355 if ((cc
[0] & clip_mask
)==0) { q
[0]=p0
; q
[1]=p1
; q
[2]=p2
; }
356 else if ((cc
[1] & clip_mask
)==0) { q
[0]=p1
; q
[1]=p2
; q
[2]=p0
; }
357 else { q
[0]=p2
; q
[1]=p0
; q
[2]=p1
; }
359 tt
=clip_proc
[clip_bit
](&tmp1
.pc
,&q
[0]->pc
,&q
[1]->pc
);
360 updateTmp(c
,&tmp1
,q
[0],q
[1],tt
);
362 tt
=clip_proc
[clip_bit
](&tmp2
.pc
,&q
[0]->pc
,&q
[2]->pc
);
363 updateTmp(c
,&tmp2
,q
[0],q
[2],tt
);
366 tmp2
.edge_flag
=q
[2]->edge_flag
;
367 gl_draw_triangle_clip(c
,q
[0],&tmp1
,&tmp2
,clip_bit
+1);
373 void gl_draw_triangle_select(GLContext
*c
,
374 GLVertex
*p0
,GLVertex
*p1
,GLVertex
*p2
)
376 gl_add_select1(c
,p0
->zp
.z
,p1
->zp
.z
,p2
->zp
.z
);
380 int count_triangles
,count_triangles_textured
,count_pixels
;
383 void gl_draw_triangle_fill(GLContext
*c
,
384 GLVertex
*p0
,GLVertex
*p1
,GLVertex
*p2
)
389 assert(p0
->zp
.x
>= 0 && p0
->zp
.x
< c
->zb
->xsize
);
390 assert(p0
->zp
.y
>= 0 && p0
->zp
.y
< c
->zb
->ysize
);
391 assert(p1
->zp
.x
>= 0 && p1
->zp
.x
< c
->zb
->xsize
);
392 assert(p1
->zp
.y
>= 0 && p1
->zp
.y
< c
->zb
->ysize
);
393 assert(p2
->zp
.x
>= 0 && p2
->zp
.x
< c
->zb
->xsize
);
394 assert(p2
->zp
.y
>= 0 && p2
->zp
.y
< c
->zb
->ysize
);
396 norm
=(p1
->zp
.x
-p0
->zp
.x
)*(p2
->zp
.y
-p0
->zp
.y
)-
397 (p2
->zp
.x
-p0
->zp
.x
)*(p1
->zp
.y
-p0
->zp
.y
);
398 count_pixels
+=abs(norm
)/2;
403 if (c
->texture_2d_enabled
) {
405 count_triangles_textured
++;
407 ZB_setTexture(c
->zb
,c
->current_texture
->images
[0].pixmap
);
408 ZB_fillTriangleMappingPerspective(c
->zb
,&p0
->zp
,&p1
->zp
,&p2
->zp
);
409 } else if (c
->current_shade_model
== GL_SMOOTH
) {
410 ZB_fillTriangleSmooth(c
->zb
,&p0
->zp
,&p1
->zp
,&p2
->zp
);
412 ZB_fillTriangleFlat(c
->zb
,&p0
->zp
,&p1
->zp
,&p2
->zp
);
416 /* Render a clipped triangle in line mode */
418 void gl_draw_triangle_line(GLContext
*c
,
419 GLVertex
*p0
,GLVertex
*p1
,GLVertex
*p2
)
422 if (p0
->edge_flag
) ZB_line_z(c
->zb
,&p0
->zp
,&p1
->zp
);
423 if (p1
->edge_flag
) ZB_line_z(c
->zb
,&p1
->zp
,&p2
->zp
);
424 if (p2
->edge_flag
) ZB_line_z(c
->zb
,&p2
->zp
,&p0
->zp
);
426 if (p0
->edge_flag
) ZB_line(c
->zb
,&p0
->zp
,&p1
->zp
);
427 if (p1
->edge_flag
) ZB_line(c
->zb
,&p1
->zp
,&p2
->zp
);
428 if (p2
->edge_flag
) ZB_line(c
->zb
,&p2
->zp
,&p0
->zp
);
434 /* Render a clipped triangle in point mode */
435 void gl_draw_triangle_point(GLContext
*c
,
436 GLVertex
*p0
,GLVertex
*p1
,GLVertex
*p2
)
438 if (p0
->edge_flag
) ZB_plot(c
->zb
,&p0
->zp
);
439 if (p1
->edge_flag
) ZB_plot(c
->zb
,&p1
->zp
);
440 if (p2
->edge_flag
) ZB_plot(c
->zb
,&p2
->zp
);