1111// 2007.7.02 skywind implementate texture and color render
1212// 2008.3.15 skywind fixed a trapezoid issue
1313// 2015.8.09 skywind rewrite with more comment
14+ // 2015.8.12 skywind adjust interfaces for clearity
1415//
1516//=====================================================================
1617#include <stdio.h>
@@ -308,6 +309,7 @@ typedef struct { vertex_t v, v1, v2; } edge_t;
308309typedef struct { float top , bottom ; edge_t left , right ; } trapezoid_t ;
309310typedef struct { vertex_t v , step ; int x , y , w ; } scanline_t ;
310311
312+
311313void vertex_rhw_init (vertex_t * v ) {
312314 float rhw = 1.0f / v -> pos .w ;
313315 v -> rhw = rhw ;
@@ -355,94 +357,90 @@ void vertex_add(vertex_t *y, const vertex_t *x) {
355357 y -> color .b += x -> color .b ;
356358}
357359
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 ;
426392 }
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 ;
427423}
428424
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 );
436433}
437434
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 ;
442440 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 );
446444}
447445
448446
@@ -650,15 +648,15 @@ void device_draw_scanline(device_t *device, scanline_t *scanline) {
650648}
651649
652650// 主渲染函数
653- void device_render_trape (device_t * device , trapezoid_t * trape ) {
651+ void device_render_trap (device_t * device , trapezoid_t * trap ) {
654652 scanline_t scanline ;
655653 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 );
658656 for (j = top ; j < bottom ; j ++ ) {
659657 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 );
662660 device_draw_scanline (device , & scanline );
663661 }
664662 if (j >= device -> height ) break ;
@@ -689,8 +687,10 @@ void device_draw_primitive(device_t *device, const vertex_t *v1,
689687
690688 // 纹理或者色彩绘制
691689 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+
694694 t1 .pos = p1 ;
695695 t2 .pos = p2 ;
696696 t3 .pos = p3 ;
@@ -701,29 +701,12 @@ void device_draw_primitive(device_t *device, const vertex_t *v1,
701701 vertex_rhw_init (& t1 ); // 初始化 w
702702 vertex_rhw_init (& t2 ); // 初始化 w
703703 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 ;
709704
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 );
713707
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 ]);
727710 }
728711
729712 if (render_state & RENDER_STATE_WIREFRAME ) { // 线框绘制
0 commit comments