Skip to content

Commit 1abb5fe

Browse files
author
skywind3000
committed
adjust for clearity
1 parent 25704fd commit 1abb5fe

File tree

1 file changed

+93
-110
lines changed

1 file changed

+93
-110
lines changed

mini3d.c

+93-110
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
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;
308309
typedef struct { float top, bottom; edge_t left, right; } trapezoid_t;
309310
typedef struct { vertex_t v, step; int x, y, w; } scanline_t;
310311

312+
311313
void 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

Comments
 (0)