11
11
// 2007.7.02 skywind implementate texture and color render
12
12
// 2008.3.15 skywind fixed a trapezoid issue
13
13
// 2015.8.09 skywind rewrite with more comment
14
+ // 2015.8.12 skywind adjust interfaces for clearity
14
15
//
15
16
//=====================================================================
16
17
#include <stdio.h>
@@ -308,6 +309,7 @@ typedef struct { vertex_t v, v1, v2; } edge_t;
308
309
typedef struct { float top , bottom ; edge_t left , right ; } trapezoid_t ;
309
310
typedef struct { vertex_t v , step ; int x , y , w ; } scanline_t ;
310
311
312
+
311
313
void vertex_rhw_init (vertex_t * v ) {
312
314
float rhw = 1.0f / v -> pos .w ;
313
315
v -> rhw = rhw ;
@@ -355,94 +357,90 @@ void vertex_add(vertex_t *y, const vertex_t *x) {
355
357
y -> color .b += x -> color .b ;
356
358
}
357
359
358
- // 1
359
- // 2 3
360
- void trapezoid_init_edge_up (trapezoid_t * trape ,
361
- const vertex_t * v1 , const vertex_t * v2 , const vertex_t * v3 ) {
362
- const vertex_t * v ;
363
- if (v2 -> pos .x > v3 -> pos .x ) v = v2 , v2 = v3 , v3 = v ;
364
- trape -> top = v1 -> pos .y ;
365
- trape -> bottom = v2 -> pos .y ;
366
- trape -> left .v = * v1 ;
367
- trape -> right .v = * v1 ;
368
- trape -> left .v1 = * v1 ;
369
- trape -> left .v2 = * v2 ;
370
- trape -> right .v1 = * v1 ;
371
- trape -> right .v2 = * v3 ;
372
- }
373
-
374
- // 1 2
375
- // 3
376
- void trapezoid_init_edge_down (trapezoid_t * trape ,
377
- const vertex_t * v1 , const vertex_t * v2 , const vertex_t * v3 ) {
378
- const vertex_t * v ;
379
- if (v1 -> pos .x > v2 -> pos .x ) v = v1 , v1 = v2 , v2 = v ;
380
- trape -> top = v1 -> pos .y ;
381
- trape -> bottom = v3 -> pos .y ;
382
- trape -> left .v = * v1 ;
383
- trape -> right .v = * v2 ;
384
- trape -> left .v1 = * v1 ;
385
- trape -> left .v2 = * v3 ;
386
- trape -> right .v1 = * v2 ;
387
- trape -> right .v2 = * v3 ;
388
- }
389
-
390
- // 1 1
391
- // 2 or 2
392
- // (t) 3 3 (t)
393
- void trapezoid_init_edges (trapezoid_t * up , trapezoid_t * down ,
394
- const vertex_t * v1 , const vertex_t * v2 , const vertex_t * v3 ) {
395
- float f = (v3 -> pos .y - v1 -> pos .y ) / (v2 -> pos .y - v1 -> pos .y );
396
- vertex_t t1 = * v1 ;
397
- vertex_t t2 = * v2 ;
398
- vertex_t t3 = * v3 ;
399
- vertex_t t ;
400
-
401
- up -> top = t1 .pos .y ;
402
- up -> bottom = t2 .pos .y ;
403
- down -> top = t2 .pos .y ;
404
- down -> bottom = t3 .pos .y ;
405
-
406
- vertex_interp (& t , & t1 , & t2 , f );
407
-
408
- if (t .pos .x <= t3 .pos .x ) {
409
- up -> left .v1 = t1 ;
410
- up -> left .v2 = t2 ;
411
- up -> right .v1 = t1 ;
412
- up -> right .v2 = t3 ;
413
- down -> left .v1 = t2 ;
414
- down -> left .v2 = t3 ;
415
- down -> right .v1 = t1 ;
416
- down -> right .v2 = t3 ;
417
- } else {
418
- up -> left .v1 = t1 ;
419
- up -> left .v2 = t3 ;
420
- up -> right .v1 = t1 ;
421
- up -> right .v2 = t2 ;
422
- down -> left .v1 = t1 ;
423
- down -> left .v2 = t3 ;
424
- down -> right .v1 = t2 ;
425
- down -> right .v2 = t3 ;
360
+ // 根据三角形生成 0-2 个梯形,并且返回合法梯形的数量
361
+ int trapezoid_init_triangle (trapezoid_t * trap , const vertex_t * p1 ,
362
+ const vertex_t * p2 , const vertex_t * p3 ) {
363
+ const vertex_t * p ;
364
+ float k , x ;
365
+
366
+ if (p1 -> pos .y > p2 -> pos .y ) p = p1 , p1 = p2 , p2 = p ;
367
+ if (p1 -> pos .y > p3 -> pos .y ) p = p1 , p1 = p3 , p3 = p ;
368
+ if (p2 -> pos .y > p3 -> pos .y ) p = p2 , p2 = p3 , p3 = p ;
369
+ if (p1 -> pos .y == p2 -> pos .y && p1 -> pos .y == p3 -> pos .y ) return 0 ;
370
+ if (p1 -> pos .x == p2 -> pos .x && p1 -> pos .x == p3 -> pos .x ) return 0 ;
371
+
372
+ if (p1 -> pos .y == p2 -> pos .y ) { // triangle down
373
+ if (p1 -> pos .x > p2 -> pos .x ) p = p1 , p1 = p2 , p2 = p ;
374
+ trap [0 ].top = p1 -> pos .y ;
375
+ trap [0 ].bottom = p3 -> pos .y ;
376
+ trap [0 ].left .v1 = * p1 ;
377
+ trap [0 ].left .v2 = * p3 ;
378
+ trap [0 ].right .v1 = * p2 ;
379
+ trap [0 ].right .v2 = * p3 ;
380
+ return (trap [0 ].top < trap [0 ].bottom )? 1 : 0 ;
381
+ }
382
+
383
+ if (p2 -> pos .y == p3 -> pos .y ) { // triangle up
384
+ if (p2 -> pos .x > p3 -> pos .x ) p = p2 , p2 = p3 , p3 = p ;
385
+ trap [0 ].top = p1 -> pos .y ;
386
+ trap [0 ].bottom = p3 -> pos .y ;
387
+ trap [0 ].left .v1 = * p1 ;
388
+ trap [0 ].left .v2 = * p2 ;
389
+ trap [0 ].right .v1 = * p1 ;
390
+ trap [0 ].right .v2 = * p3 ;
391
+ return (trap [0 ].top < trap [0 ].bottom )? 1 : 0 ;
426
392
}
393
+
394
+ trap [0 ].top = p1 -> pos .y ;
395
+ trap [0 ].bottom = p2 -> pos .y ;
396
+ trap [1 ].top = p2 -> pos .y ;
397
+ trap [1 ].bottom = p3 -> pos .y ;
398
+
399
+ k = (p3 -> pos .y - p1 -> pos .y ) / (p2 -> pos .y - p1 -> pos .y );
400
+ x = p1 -> pos .x + (p2 -> pos .x - p1 -> pos .x ) * k ;
401
+
402
+ if (x <= p3 -> pos .x ) { // triangle left
403
+ trap [0 ].left .v1 = * p1 ;
404
+ trap [0 ].left .v2 = * p2 ;
405
+ trap [0 ].right .v1 = * p1 ;
406
+ trap [0 ].right .v2 = * p3 ;
407
+ trap [1 ].left .v1 = * p2 ;
408
+ trap [1 ].left .v2 = * p3 ;
409
+ trap [1 ].right .v1 = * p1 ;
410
+ trap [1 ].right .v2 = * p3 ;
411
+ } else { // triangle right
412
+ trap [0 ].left .v1 = * p1 ;
413
+ trap [0 ].left .v2 = * p3 ;
414
+ trap [0 ].right .v1 = * p1 ;
415
+ trap [0 ].right .v2 = * p2 ;
416
+ trap [1 ].left .v1 = * p1 ;
417
+ trap [1 ].left .v2 = * p3 ;
418
+ trap [1 ].right .v1 = * p2 ;
419
+ trap [1 ].right .v2 = * p3 ;
420
+ }
421
+
422
+ return 2 ;
427
423
}
428
424
429
- void trapezoid_edge_interp (trapezoid_t * trape , float y ) {
430
- float s1 = trape -> left .v2 .pos .y - trape -> left .v1 .pos .y ;
431
- float s2 = trape -> right .v2 .pos .y - trape -> right .v1 .pos .y ;
432
- float t1 = (y - trape -> left .v1 .pos .y ) / s1 ;
433
- float t2 = (y - trape -> right .v1 .pos .y ) / s2 ;
434
- vertex_interp (& trape -> left .v , & trape -> left .v1 , & trape -> left .v2 , t1 );
435
- vertex_interp (& trape -> right .v , & trape -> right .v1 , & trape -> right .v2 , t2 );
425
+ // 按照 Y 坐标计算出左右两条边纵坐标等于 Y 的顶点
426
+ void trapezoid_edge_interp (trapezoid_t * trap , float y ) {
427
+ float s1 = trap -> left .v2 .pos .y - trap -> left .v1 .pos .y ;
428
+ float s2 = trap -> right .v2 .pos .y - trap -> right .v1 .pos .y ;
429
+ float t1 = (y - trap -> left .v1 .pos .y ) / s1 ;
430
+ float t2 = (y - trap -> right .v1 .pos .y ) / s2 ;
431
+ vertex_interp (& trap -> left .v , & trap -> left .v1 , & trap -> left .v2 , t1 );
432
+ vertex_interp (& trap -> right .v , & trap -> right .v1 , & trap -> right .v2 , t2 );
436
433
}
437
434
438
- void trapezoid_init_scan_line (const trapezoid_t * trape , scanline_t * scanline , int y ) {
439
- float width = trape -> right .v .pos .x - trape -> left .v .pos .x ;
440
- scanline -> x = (int )(trape -> left .v .pos .x + 0.5f );
441
- scanline -> w = (int )(trape -> right .v .pos .x + 0.5f ) - scanline -> x ;
435
+ // 根据左右两边的端点,初始化计算出扫描线的起点和步长
436
+ void trapezoid_init_scan_line (const trapezoid_t * trap , scanline_t * scanline , int y ) {
437
+ float width = trap -> right .v .pos .x - trap -> left .v .pos .x ;
438
+ scanline -> x = (int )(trap -> left .v .pos .x + 0.5f );
439
+ scanline -> w = (int )(trap -> right .v .pos .x + 0.5f ) - scanline -> x ;
442
440
scanline -> y = y ;
443
- scanline -> v = trape -> left .v ;
444
- if (trape -> left .v .pos .x >= trape -> right .v .pos .x ) scanline -> w = 0 ;
445
- vertex_division (& scanline -> step , & trape -> left .v , & trape -> right .v , width );
441
+ scanline -> v = trap -> left .v ;
442
+ if (trap -> left .v .pos .x >= trap -> right .v .pos .x ) scanline -> w = 0 ;
443
+ vertex_division (& scanline -> step , & trap -> left .v , & trap -> right .v , width );
446
444
}
447
445
448
446
@@ -650,15 +648,15 @@ void device_draw_scanline(device_t *device, scanline_t *scanline) {
650
648
}
651
649
652
650
// 主渲染函数
653
- void device_render_trape (device_t * device , trapezoid_t * trape ) {
651
+ void device_render_trap (device_t * device , trapezoid_t * trap ) {
654
652
scanline_t scanline ;
655
653
int j , top , bottom ;
656
- top = (int )(trape -> top + 0.5f );
657
- bottom = (int )(trape -> bottom + 0.5f );
654
+ top = (int )(trap -> top + 0.5f );
655
+ bottom = (int )(trap -> bottom + 0.5f );
658
656
for (j = top ; j < bottom ; j ++ ) {
659
657
if (j >= 0 && j < device -> height ) {
660
- trapezoid_edge_interp (trape , (float )j + 0.5f );
661
- trapezoid_init_scan_line (trape , & scanline , j );
658
+ trapezoid_edge_interp (trap , (float )j + 0.5f );
659
+ trapezoid_init_scan_line (trap , & scanline , j );
662
660
device_draw_scanline (device , & scanline );
663
661
}
664
662
if (j >= device -> height ) break ;
@@ -689,8 +687,10 @@ void device_draw_primitive(device_t *device, const vertex_t *v1,
689
687
690
688
// 纹理或者色彩绘制
691
689
if (render_state & (RENDER_STATE_TEXTURE | RENDER_STATE_COLOR )) {
692
- trapezoid_t trape1 , trape2 ;
693
- vertex_t t1 = * v1 , t2 = * v2 , t3 = * v3 , t ;
690
+ vertex_t t1 = * v1 , t2 = * v2 , t3 = * v3 ;
691
+ trapezoid_t traps [2 ];
692
+ int n ;
693
+
694
694
t1 .pos = p1 ;
695
695
t2 .pos = p2 ;
696
696
t3 .pos = p3 ;
@@ -701,29 +701,12 @@ void device_draw_primitive(device_t *device, const vertex_t *v1,
701
701
vertex_rhw_init (& t1 ); // 初始化 w
702
702
vertex_rhw_init (& t2 ); // 初始化 w
703
703
vertex_rhw_init (& t3 ); // 初始化 w
704
-
705
- // 三角形排序,从上到下 t1, t2, t3
706
- if (t1 .pos .y > t2 .pos .y ) t = t1 , t1 = t2 , t2 = t ;
707
- if (t1 .pos .y > t3 .pos .y ) t = t1 , t1 = t3 , t3 = t ;
708
- if (t2 .pos .y > t3 .pos .y ) t = t2 , t2 = t3 , t3 = t ;
709
704
710
- if (t1 .pos .y == t2 .pos .y && t1 .pos .y == t3 .pos .y ) { // 调过 0高度
711
- return ;
712
- }
705
+ // 拆分三角形为0-2个梯形,并且返回可用梯形数量
706
+ n = trapezoid_init_triangle (traps , & t1 , & t2 , & t3 );
713
707
714
- if (t1 .pos .y == t2 .pos .y ) { // t1 在上,t2, t3 在一条水平线上
715
- trapezoid_init_edge_down (& trape1 , & t1 , & t2 , & t3 );
716
- device_render_trape (device , & trape1 ); // 渲染梯形
717
- }
718
- else if (t2 .pos .y == t3 .pos .y ) { // t1, t2同水平线,t3在下
719
- trapezoid_init_edge_up (& trape2 , & t1 , & t2 , & t3 );
720
- device_render_trape (device , & trape2 ); // 渲染梯形
721
- }
722
- else { // t1上,t2中,t3下,计算一个中点 t 使得分成上下两三角形
723
- trapezoid_init_edges (& trape1 , & trape2 , & t1 , & t2 , & t3 );
724
- device_render_trape (device , & trape1 ); // 渲染上部分梯形
725
- device_render_trape (device , & trape2 ); // 渲染下部分梯形
726
- }
708
+ if (n >= 1 ) device_render_trap (device , & traps [0 ]);
709
+ if (n >= 2 ) device_render_trap (device , & traps [1 ]);
727
710
}
728
711
729
712
if (render_state & RENDER_STATE_WIREFRAME ) { // 线框绘制
0 commit comments