Author Topic: Software fixed point triangle renderer?  (Read 7262 times)

0 Members and 1 Guest are viewing this topic.

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Software fixed point triangle renderer?
« on: October 05, 2006 »
Can anyone point me to some C source code that does fixed point triangle rendering in software, preferably with textures? Even better with mip-maps.
I'd like it free of licenses if possible...

Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17414
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Software fixed point triangle renderer?
« Reply #1 on: October 05, 2006 »
I can make you one if you like but it would be in freebasic so you'd have to convert it.
Mip mapping is where you have several versions of a texture in memory, depending on the area of the triangle you are rendering, you use the texture that fits the size of the triangle the best, speeds things up a lot and helps get rid of jumping pixels.

This is a link that helped me a lot;

http://www.whisqu.com/per/docs/graphics16.htm It contains pseudo code.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #2 on: October 06, 2006 »
Shockwave thanks a lot, but dotn go to the trouble of writing the code. This is for a work project and it wouldnt be right for you to do that without us paying and as I'm doing this "skunk works" style (without managment approval) I can't pay you. I'll keep looking for some license free code or I'll find time and write it myself.

Challenge Trophies Won:

Offline relsoft

  • DBF Aficionado
  • ******
  • Posts: 3303
  • Karma: 47
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #3 on: October 06, 2006 »
DOS:ASM (PASCAL/BASIC) calling...


From Rellib. My old Dos sofware QB library.

Code: [Select]
;;;Fix point Textured triangle routine. :*)
;;;Call with:
;;;Declare sub (Byval Layer%, Byval x1%, Byval y1%,Byval u1%,Byval v1%, Byval x2%,_
;;; Byval y2%,Byval u2%,Byval v2%, Byval x3%, Byval y3%,Byval u3%,Byval v3%, Byval TSEG%, Byval TOFF%)

.Model Medium, BASIC
.386
.Code

align 2

;;*****************Near procedure for preclipped Textured Hline*****************************************
HTline     Proc  near\
            x1:word, x2:word, y:word, lu:dword, ru:dword, lv:dword, rv:dword, Tsize:word

Local udelta:   dword
Local vdelta:   dword
Local u: dword
Local v: dword
Local dy: word
Local TsizeM1: word
Local Toff: word
Local wid: word

;GS = Xshift


    mov ax, x1
    mov bx, x2
    cmp ax,bx
    jle Short @Postswapx
    xchg ax, bx
    mov ecx, lu
    mov edx, ru
    xchg ecx, edx
    mov x1, ax
    mov x2, bx
    mov eax, lv
    mov ebx, rv
    xchg eax, ebx
    mov lu, ecx
    mov ru, edx
    mov lv, eax
    mov rv, ebx
@PostSwapX:



mov ecx, lu
mov edx, lv
mov u, ecx
mov v, edx
;U
    mov ax, x1
    mov bx, x2
    mov edx, ru
    mov ecx, lu
    ;Gdx% = (Gx2% - Gx1%) + 1       'Get Xdelta(+1) for the Div by 0 error
    ;Cdx& = Clr2& - Clr1&           'Color delta    ;deltac& = Cdx& \ Gdx%          'Interpolate
    ;col& = Clr1&                   'save orig color to be safe
    sub edx, ecx

    sub bx, ax
    jz  @NolineH
    mov dy, bx ;save ydelta
    mov ax, bx
    cwde ;eax = gdx
    mov ecx, edx ;ecx = cdx
    xchg eax, ecx ;eax = cdx  : ecx = gdx
    cdq ;eax:edx = cdx

    idiv ecx                 ;eax = edxedx\ecx
    mov udelta, eax


;V
mov edx, rv
    mov ecx, lv
    ;Gdx% = (Gx2% - Gx1%) + 1       'Get Xdelta(+1) for the Div by 0 error
    ;Cdx& = Clr2& - Clr1&           'Color delta    ;deltac& = Cdx& \ Gdx%          'Interpolate
    ;col& = Clr1&                   'save orig color to be safe
    sub edx, ecx
    mov ax, dy
    cwde ;eax = gdx
    mov ecx, edx ;ecx = cdx
    xchg eax, ecx ;eax = cdx  : ecx = gdx
    cdq ;eax:edx = cdx

    idiv ecx                 ;eax = edxedx\ecx
    mov vdelta, eax



    mov ax, x1
    mov bx, x2


;;;;;;;;;;
    cmp ax,319
    jg @NolineH
    cmp ax,0
    jl  @clipLeft
@PostclipLeft:
    cmp bx,0
    jl  @NolineH
    cmp bx,319
    jg  @clipRight
@PostclipRight:



mov cx, Tsize
    mov dx, bx ;dx = (bx - ax)+1
    inc dx
    dec cx
    mov TsizeM1, cx
    sub dx, ax
    jz   @NolineH
    mov cx, y ;put in y value
    xchg ch, cl ;y = y *256 ;di& = cx * 320& + ax
    mov di, cx ;di = 256
    shr di, 2 ;di = 64
    add di, cx ;di = 256+64 = 320
    add di, ax ;di = y*320+x


    ;FOR l% = Gx1% TO Gx2%                   'Rasterizer loop
    ;    PSET (l%, yy%), col& \ FIXPOINT     'Use poke for speed
    ;    col& = col& + deltac&               'DDA
    ;NEXT l%


;;xloop okay
Mov Toff, fs
mov bx, dx ;do divide
cmp bx, 4
jle @Less4
and bl, 3
shr dx, 2
mov ch, bl ;odd pixels I used dy to conserve mem. :*)
mov wid, dx
mov ax, gs ;shift counter
mov cl, al ;use cl
mov ebx, u ;save u and v
mov edx, v

@xloop:
;1.
;;v
    mov eax, edx
    shr eax, 16
    and ax, TsizeM1
    shl ax, cl
    mov si, ax
    add si, Toff
    ;;u
    mov eax, ebx
    shr eax, 16
    and ax, TsizeM1
    add si, ax
    mov al,[si+4]
    mov es:[di], al
    add ebx, udelta
    add edx, vdelta
    ;2.
;;v
    mov eax, edx
    shr eax, 16
    and ax, TsizeM1
    shl ax, cl
    mov si, ax
    add si, Toff
    ;;u
    mov eax, ebx
    shr eax, 16
    and ax, TsizeM1
    add si, ax
    mov al,[si+4]
    mov es:[di+1], al
    add ebx, udelta
    add edx, vdelta
    ;3.
;;v
    mov eax, edx
    shr eax, 16
    and ax, TsizeM1
    shl ax, cl
    mov si, ax
    add si, Toff
    ;;u
    mov eax, ebx
    shr eax, 16
    and ax, TsizeM1
    add si, ax
    mov al,[si+4]
    mov es:[di+2], al
    add ebx, udelta
    add edx, vdelta
    ;4.
;;v
    mov eax, edx
    shr eax, 16
    and ax, TsizeM1
    shl ax, cl
    mov si, ax
    add si, Toff
    ;;u
    mov eax, ebx
    shr eax, 16
    and ax, TsizeM1
    add si, ax
    mov al,[si+4]
    mov es:[di+3], al
    add ebx, udelta
    add edx, vdelta
    add di, 4
    dec wid
    jnz @xloop

test ch,ch
jz short @NolineH
@xloop2:
;1.
;;v
    mov eax, edx
    shr eax, 16
    and ax, TsizeM1
    shl ax, cl
    mov si, ax
    add si, Toff
    ;;u
    mov eax, ebx
    shr eax, 16
    and ax, TsizeM1
    add si, ax
    mov al,[si+4]
    mov es:[di], al
    add ebx, udelta
    add edx, vdelta
    inc di
    dec ch
    jnz @xloop2

@NolineH:

Ret

@clipLeft:
mov cx, ax ;save in cx
neg cx ;cx = clipped width
    mov dx,bx
    sub dx,ax
    add ax,dx
    cmp ax,0
    jl short @NolineH
    xor eax, eax
    mov ax, cx
    imul eax, udelta ;eax=wid*udelta
    add u, eax     ;add to u to clip
        xor eax,eax
        mov ax, cx
        imul eax, vdelta ;eax=wid*vdelta
    add v, eax ;add to v to clip
    xor eax,eax
    Jmp  @PostclipLeft

@clipRight:
    mov bx,319
    Jmp  @PostclipRight


;Less then 4
@Less4:
mov wid, dx
mov ax, gs ;shift counter
mov cl, al ;use cl
mov ebx, u ;save u and v
mov edx, v

@xloopLess4:
;;v
    mov eax, edx
    shr eax, 16
    and ax, TsizeM1
    shl ax, cl
    mov si, ax
    add si, Toff
    ;;u
    mov eax, ebx
    shr eax, 16
    and ax, TsizeM1
    add si, ax
    mov al,[si+4]
    mov es:[di], al
    add ebx, udelta
    add edx, vdelta
    inc di
    dec wid
    jnz short @xloopLess4
Ret

EndP


;;*****************Procedure for Textured Triangle Filler**************************************************

Public  RelTriT
RelTriT     Proc  Uses es di ds si,\
            Layer:word, x1:word, y1:word, u1:word, v1:word, x2:word, y2:word, u2:word, v2:word,\
            x3:word, y3:word, u3:word, v3:word, Tseg: word, Toff: word

            Local delta1:   dword
            Local delta2:   dword
            Local delta3:   dword
            Local Lx:       dword
            Local Rx:       dword
            Local udelta1:  dword
            Local udelta2:  dword
            Local udelta3:  dword
            Local Lu:       dword
            Local Ru:       dword
            Local vdelta1:  dword
            Local vdelta2:  dword
            Local vdelta3:  dword
            Local Lv:       dword
            Local Rv:       dword
            Local ycounter: word
            Local Tsize: word
            Local xshift: word

mov ax, y1
mov bx, y2
cmp bx, ax ;cmp y2, y1
jge short @noswapy1
xchg ax, bx ;xchg y1, y2
mov cx, x1
mov dx, x2
xchg cx, dx ;xchg x1, x2
mov y1, ax
mov y2, bx
mov x1, cx
mov x2, dx
mov cx, u1
mov dx, u2
xchg cx, dx
mov u1, cx
mov u2, dx
mov cx, v1
mov dx, v2
xchg cx, dx
mov v1, cx
mov v2, dx
@noswapy1:


mov ax, y3
mov bx, y1
cmp ax, bx ;cmp y3, y1
jge short @noswapy2
xchg ax, bx ;xchg y3, y1
mov cx, x3
mov dx, x1
xchg cx, dx ;xchg x3, x1
mov y3, ax
mov y1, bx
mov x3, cx
mov x1, dx
mov cx, u3
mov dx, u1
xchg cx, dx
mov u3, cx
mov u1, dx
mov cx, v3
mov dx, v1
xchg cx, dx
mov v3, cx
mov v1, dx
@noswapy2:


mov ax, y3
mov bx, y2
cmp ax, bx ;cmp y3, y2
jge short @noswapy3
xchg ax, bx ;xchg y3, y2
mov cx, x3
mov dx, x2
xchg cx, dx ;xchg x3, x2
mov y3, ax
mov y2, bx
mov x3, cx
mov x2, dx
mov cx, u3
mov dx, u2
xchg cx, dx
mov u3, cx
mov u2, dx
mov cx, v3
mov dx, v2
xchg cx, dx
mov v3, cx
mov v2, dx
@noswapy3:

mov delta1, 0
mov udelta1, 0
mov vdelta1, 0

mov bx, y2 ;bx = y2
sub bx, y1 ;bx = bx - y1

jz short @delta1_is_zero ;IF bx <> 0 THEN
    mov ax, x2 ;ax = x2
    sub ax, x1 ;ax = ax - x1

    shl eax, 16 ;eax& = eax& * FIXPOINT
    cdq ;edx& = eax&
    ;edxeax& = edx&

    movsx ecx, bx ;ecx& = bx
    idiv ecx ;delta1& = edxeax& \ ecx&
    mov delta1, eax

    ;uDelta1& = du1 * FIXPOINT \ dy1
    mov ax, u2 ;ax = u2
    sub ax, u1 ;ax = ax - u1

    shl eax, 16 ;eax& = eax& * FIXPOINT
    cdq ;edx& = eax&
    ;edxeax& = edx&
    idiv ecx ;delta1& = edxeax& \ ecx&
    mov udelta1, eax

    ;vDelta1& = dv1 * FIXPOINT \ dy1
    mov ax, v2 ;ax = u2
    sub ax, v1 ;ax = ax - u1

    shl eax, 16 ;eax& = eax& * FIXPOINT
    cdq ;edx& = eax&
    ;edxeax& = edx&
    idiv ecx ;delta1& = edxeax& \ ecx&
    mov vdelta1, eax

@delta1_is_zero:



mov delta2, 0
mov udelta2, 0
mov vdelta2, 0

mov bx, y3 ;bx = y3
sub bx, y2 ;bx = bx - y2

jz short @delta2_is_zero ;IF bx <> 0 THEN
    mov ax, x3 ;ax = x3
    sub ax, x2 ;ax = ax - x2

    shl eax, 16 ;eax& = eax& * FIXPOINT
    cdq ;edx& = eax&
    ;edxeax& = edx&

    movsx ecx, bx ;ecx& = bx
    idiv ecx ;delta1& = edxeax& \ ecx&
    mov delta2, eax

        ;uDelta1& = du2 * FIXPOINT \ dy2
    mov ax, u3 ;ax = u3
    sub ax, u2 ;ax = ax - u3

    shl eax, 16 ;eax& = eax& * FIXPOINT
    cdq ;edx& = eax&
    ;edxeax& = edx&
    idiv ecx ;delta1& = edxeax& \ ecx&
    mov udelta2, eax

            ;vDelta1& = dv2 * FIXPOINT \ dy2
    mov ax, v3 ;ax = v3
    sub ax, v2 ;ax = ax - v3

    shl eax, 16 ;eax& = eax& * FIXPOINT
    cdq ;edx& = eax&
    ;edxeax& = edx&
    idiv ecx ;delta1& = edxeax& \ ecx&
    mov vdelta2, eax


@delta2_is_zero:


mov delta3, 0
mov udelta3, 0
mov vdelta3, 0

mov bx, y1 ;bx = y1
sub bx, y3 ;bx = bx - y3

jz short @delta3_is_zero ;IF bx <> 0 THEN
    mov ax, x1 ;ax = x1
    sub ax, x3 ;ax = ax - x3

    shl eax, 16 ;eax& = eax& * FIXPOINT
    cdq ;edx& = eax&
    ;edxeax& = edx&

    movsx ecx, bx ;ecx& = bx
    idiv ecx ;delta1& = edxeax& \ ecx&
    mov delta3, eax

        ;uDelta1& = du3 * FIXPOINT \ dy3
    mov ax, u1 ;ax = u1
    sub ax, u3 ;ax = ax - u3

    shl eax, 16 ;eax& = eax& * FIXPOINT
    cdq ;edx& = eax&
    ;edxeax& = edx&
    idiv ecx ;delta1& = edxeax& \ ecx&
    mov udelta3, eax

        ;vDelta1& = dv3 * FIXPOINT \ dy3
    mov ax, v1 ;ax = v1
    sub ax, v3 ;ax = ax - v3

    shl eax, 16 ;eax& = eax& * FIXPOINT
    cdq ;edx& = eax&
    ;edxeax& = edx&
    idiv ecx ;delta1& = edxeax& \ ecx&
    mov vdelta3, eax

@delta3_is_zero:


Mov es, Layer
Mov ds, TSEG
mov ax, TOFF
mov fs, ax
mov si, ax
mov bx, [si]
shr bx,3 ;width
mov Tsize, bx


;calculate shifts

mov ax, bx
    cmp ax, 2
    jne short @xpow4
        mov bx, 1
        jmp short @SizeOK
@xpow4:
    cmp ax, 4
    jne short @xpow8
        mov bx, 2
        jmp short @SizeOK
@xpow8:
    cmp ax, 8
    jne short @xpow16
        mov bx, 3
        jmp short @SizeOK
@xpow16:
    cmp ax, 16
    jne short @xpow32
        mov bx, 4
        jmp short @SizeOK
@xpow32:
    cmp ax, 32
    jne short @xpow64
        mov bx, 5
        jmp short @SizeOK
@xpow64:
    cmp ax, 64
    jne short @xpow128
        mov bx, 6
        jmp short @SizeOK
@xpow128:
    cmp ax, 128
    jne short @xpow256
        mov bx, 7
        jmp short @SizeOK
@xpow256:
    cmp ax, 256
    jne @exit
    mov bx, 8


@SizeOK:
;Flat bottom
;Top part of triangle

mov gs, bx ;save xshift

mov ax, x1 ;ax = x1
cwde ;eax& = ax
sal eax, 16 ;eax& = eax& * FIXPOINT
mov ebx, eax ;ebx& = eax&
mov lx, eax
mov rx, ebx

mov ax, u1 ;ax = u1
cwde ;eax& = ax
sal eax, 16 ;eax& = eax& * FIXPOINT
mov ebx, eax ;ebx& = eax&
mov lu, eax
mov ru, ebx

mov ax, v1 ;ax = v1
cwde ;eax& = ax
sal eax, 16 ;eax& = eax& * FIXPOINT
mov ebx, eax ;ebx& = eax&
mov lv, eax
mov rv, ebx



mov cx, y1 ;cx = y1
mov ycounter, cx
@Loop1:
cmp ycounter, 0
    jl short @Noline1
    cmp ycounter, 199
    jg short @Noline1
    mov eax, lx
    mov ebx, rx
    sar eax, 16 ;ax = eax& \ FIXPOINT
    sar ebx, 16 ;bx = ebx& \ FIXPOINT
    Push ax ;x1
    push bx     ;x2
    mov ecx, lu ;u1
    mov edx, ru             ;u2
    mov ax, ycounter
    push ax
    Push ecx ;Lu
    push edx ;Ru
    mov eax, lv
    mov ebx, rv
    Push eax ;Lv
    push ebx ;Rv
    mov cx, Tsize
    push cx


    call HTline

@Noline1:
    mov eax, delta1
    mov ebx, delta3
    mov ecx, udelta1
    mov edx, udelta3

    add lx, eax ;eax& = eax& + delta1&
    add rx, ebx ;ebx& = ebx& + delta3&
    add lu, ecx ;eax& = eax& + udelta1&
    add ru, edx ;ebx& = ebx& + udelta3&

    mov eax, vdelta1
    mov ebx, vdelta3
    add lv, eax ;eax& = eax& + vdelta1&
    add rv, ebx ;ebx& = ebx& + vdelta3&


    inc ycounter
    mov cx, ycounter
    cmp cx, y2
    jle short @Loop1

    mov ebx, delta3
    sub rx, ebx  ;subtexel accuracy
    mov edx, udelta3
    sub ru, edx
    mov eax, vdelta3
    sub rv, eax


;Flat top
;Lower part of triangle

mov ax, x2 ;ax = x2
cwde ;eax& = ax
sal eax, 16 ;eax& = eax& * FIXPOINT
mov lx, eax

mov ax, u2 ;ax = u2
cwde ;eax& = ax
sal eax, 16 ;eax& = eax& * FIXPOINT
mov lu, eax

mov ax, v2 ;ax = v2
cwde ;eax& = ax
sal eax, 16 ;eax& = eax& * FIXPOINT
mov lv, eax


mov cx, y2 ;cx = y2
mov ycounter, cx
@Loop2:
cmp ycounter, 0
    jl short @Noline2
    cmp ycounter, 199
    jg short @Noline2
    mov eax, lx
    mov ebx, rx
    sar eax, 16 ;ax = eax& \ FIXPOINT
    sar ebx, 16 ;bx = ebx& \ FIXPOINT
    Push ax     ;x1
    push bx ;x2
    mov ecx, lu ;u1
    mov edx, ru             ;u2
    mov ax, ycounter
    push ax
    Push ecx ;Lu
    push edx ;Ru
    mov eax, lv
    mov ebx, rv
    Push eax ;Lv
    push ebx ;Rv

    mov cx, Tsize
    push cx


    call HTline

@Noline2:
    mov eax, delta2
    mov ebx, delta3
    mov ecx, udelta2
    mov edx, udelta3

    add lx, eax ;eax& = eax& + delta2&
    add rx, ebx ;ebx& = ebx& + delta3&
    add lu, ecx ;eax& = eax& + udelta2&
    add ru, edx ;ebx& = ebx& + udelta3&

    mov eax, vdelta2
    mov ebx, vdelta3
    add lv, eax ;eax& = eax& + vdelta2&
    add rv, ebx ;ebx& = ebx& + vdelta3&


    inc ycounter
    mov cx, ycounter
    cmp cx, y3
    jl short @Loop2

@exit:
Ret

EndP

End

For what it's worth here's how it works....

http://rel.betterwebber.com/mytutes/3dtutes/chapter3/chapter3.htm

BTW, you may have to scroll below (way below).

;*)

Challenge Trophies Won:

Offline relsoft

  • DBF Aficionado
  • ******
  • Posts: 3303
  • Karma: 47
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #4 on: October 06, 2006 »
Ooops!!! You wanted C code.

You accept TurboC? Never did sofware In devcpp.

http://rel.betterwebber.com/junk.php?id=37

Challenge Trophies Won:

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #5 on: October 06, 2006 »
Yeah unfortunately the processor is not an i386 so the ams is no use but the C code could very very useful. I'll check it out. Thanks relsoft, have some chicken karma.

Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #6 on: October 06, 2006 »
heres a gba fixed point affine c routine excluding the gba stuff it should work with windows just fine note the only thing ive excluded from the source is the giant texture array which was a raw 16 bit bmp.
 
Code: [Select]
#define SHIFT 8
#define SCALE (1<<SHIFT)
#define TWOPOINTFIVE (0x280<<(SHIFT-8))

typedef struct
{
        s32 x;
        s32 u;
        s32 v;
} EDGE;

s32 zin[360];
s32 coz[360];

typedef struct
{
        s32 x,y,z;
} VECTOR;

typedef s32 MATRIX[3][3];
typedef struct
{
        u16 face;
        s32 z;
} SORTER;

// uv stuff
typedef struct
{
        u8 point_index;
        s16 u, v;
} VERTEX;

typedef struct
{
        VERTEX pt[3];
} FACE;

#define N_FACES 12
#define N_POINTS 8

FACE faces[N_FACES]=
{
        {
                {{0,0,0},
                {2,TEX_X-1,0},
                {6,TEX_X-1,TEX_Y-1}},
        },
        {
                {{0,0,0},
                {6,TEX_X-1,TEX_Y-1},
                {4,0,TEX_Y-1}}
        },
                {
                        {{0,0,0},
                        {1,TEX_X-1,0},
                        {3,TEX_X-1,TEX_Y-1}}
                },
        {
                {{0,0,0},
                {3,TEX_X-1,TEX_Y-1},
                {2,0,TEX_Y-1}}
        },
                {
                        {{4,0,0},
                        {6,TEX_X-1,0},
                        {7,TEX_X-1,TEX_Y-1}}
                },
        {
                {{4,0,0},
                {7,TEX_X-1,TEX_Y-1},
                {5,0,TEX_Y-1}}
        },
                {
                        {{1,0,0},
                        {0,TEX_X-1,0},
                        {4,TEX_X-1,TEX_Y-1}}
                },
        {
                {{1,0,0},
                {4,TEX_X-1,TEX_Y-1},
                {5,0,TEX_Y-1}}
        },
                {
                        {{2,0,0},
                        {3,TEX_X-1,0},
                        {7,TEX_X-1,TEX_Y-1}}
                },
        {
                {{2,0,0},
                {7,TEX_X-1,TEX_Y-1},
                {6,0,TEX_Y-1}}
        },
                {
                        {{5,0,0},
                        {1,TEX_X-1,0},
                        {3,TEX_X-1,TEX_Y-1}}
                },
        {
                {{5,0,0},
                {3,TEX_X-1,TEX_Y-1},
                {7,0,TEX_Y-1}}
        }
};

const VECTOR points[N_POINTS]=
{
        {1<<SHIFT,1<<SHIFT,1<<SHIFT},
        {1<<SHIFT,1<<SHIFT,-1<<SHIFT},
        {1<<SHIFT,-1<<SHIFT,1<<SHIFT},
        {1<<SHIFT,-1<<SHIFT,-1<<SHIFT},
        {-1<<SHIFT,1<<SHIFT,1<<SHIFT},
        {-1<<SHIFT,1<<SHIFT,-1<<SHIFT},
        {-1<<SHIFT,-1<<SHIFT,1<<SHIFT},
        {-1<<SHIFT,-1<<SHIFT,-1<<SHIFT},
};

VECTOR rotated[N_POINTS];
SORTER sorter[N_FACES];

MATRIX matrix;
u32 count,xbegin,xend;
s32 x_scale = 40<<SHIFT;
s32 y_scale = 40<<SHIFT;
s32 z_scale = 1<<SHIFT;

u16 tilt=0,turn=0,roll=0;
#define SCREENX 160
#define SCREENY 128
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))

void plotsprite(u16 xpos,u16 ypos);
u8 gnewframe;
u16 *frameptr;

void filltriangle(FACE *);

void vblFunc();
void setup();
int main(void)
{
        u8 swap;
        s32 z;
        s32 A,B,C,D,E,F,AD,BD;

        u16 p,f,j;
        ham_Init();
        ham_SetBgMode(5);
        ham_RotBgEx(2, 0, 0, 0, 0, 0, (256*GFX_MODE5_WIDTH)/GBA_SCREEN_WIDTH,      //make  width fullscreen
                (256*GFX_MODE5_HEIGHT)/GBA_SCREEN_HEIGHT);   // make height fullscreen
        ham_StartIntHandler(INT_TYPE_VBL,(void *)&vblFunc);

        setup();
        while(TRUE)
        {
                if (gnewframe)
                {
                        u8 buffer = ham_GetBGBuffer();
                        if (buffer==1) frameptr=(u16*)0x6000000;
                        else frameptr=(u16*)0x600a000;

                        plotsprite(0,0);
                        //rem prepare the rotation matrix
                        if (tilt > 359){tilt = 0;}
                        if (turn > 359){turn = 0;}
                        if (roll > 359){roll = 0;}

                        A=coz[tilt];B=zin[tilt];
                        C=coz[turn];D=zin[turn];
                        E=coz[roll];F=zin[roll];
                        AD=(A*D)>>SHIFT;
                        BD=(B*D)>>SHIFT;
                        matrix[0][0]=(C*E)>>SHIFT;
                        matrix[1][0]=(-C*F)>>SHIFT;
                        matrix[2][0]=D;
                        matrix[0][1]=((BD*E)+(A*F))>>SHIFT;
                        matrix[1][1]=((-BD*F)+(A*E))>>SHIFT;
                        matrix[2][1]=(-B*C)>>SHIFT;
                        matrix[0][2]=((-AD*E)+(B*F))>>SHIFT;
                        matrix[1][2]=((AD*F)+(B*E))>>SHIFT;
                        matrix[2][2]=(A*C)>>SHIFT;

                        //rem rotate all the points using the matrix

                        for (p=0;p<N_POINTS; p++)
                        {
                                rotated[p].x = ((matrix[0][0] * points[p].x)>>SHIFT) + ((matrix[0][1] * points[p].y)>>SHIFT) + ((matrix[0][2] * points[p].z)>>SHIFT);
                                rotated[p].x = (rotated[p].x * x_scale)>>SHIFT;
                                rotated[p].y = ((matrix[1][0] * points[p].x)>>SHIFT) + ((matrix[1][1] * points[p].y)>>SHIFT) + ((matrix[1][2] * points[p].z)>>SHIFT);
                                rotated[p].y = (rotated[p].y * y_scale)>>SHIFT;
                                rotated[p].z = ((matrix[2][0] * points[p].x)>>SHIFT) + ((matrix[2][1] * points[p].y)>>SHIFT) + ((matrix[2][2] * points[p].z)>>SHIFT);

                                //rem now do the perspective calculation
                                z = ((1L<<SHIFT)<<SHIFT)/(rotated[p].z + TWOPOINTFIVE);
                                rotated[p].x = ((SCREENX/2)<<SHIFT) + ((rotated[p].x * z)>>SHIFT);
                                rotated[p].y = ((SCREENY/2)<<SHIFT) - ((rotated[p].y * z)>>SHIFT);
                        }

                        //rem set up the sorting array
                        for (f=0;f<N_FACES;f++)
                        {
                                s32 z0,z1,z2;
                                u8 p0,p1,p2;

                                p0 = faces[f].pt[0].point_index;
                                p1 = faces[f].pt[1].point_index;
                                p2 = faces[f].pt[2].point_index;

                                z0 = rotated[p0].z;
                                z1 = rotated[p1].z;
                                z2 = rotated[p2].z;

                                sorter[f].face = f;
                                //near z
                                //sorter[f].z = max(z0,max(z1,z2));
                                //far z
                                //sorter[f].z = min(z0,min(z1,z2));
                                //ave z
                                sorter[f].z = (z0+z1+z2);
                        }

                        do
                        {
                                swap= 0;
                                for (j=0;j<N_FACES-1;j++)
                                {
                                        if (sorter[j+1].z > sorter[j].z)
                                        {
                                                SORTER tmp;
                                                tmp = sorter[j+1];
                                                sorter[j+1]=sorter[j];
                                                sorter[j]=tmp;
                                                swap = 1;
                                        }
                                }
                        } while (swap);

                        for (f=0;f<N_FACES;f++)
                        {
                                u16 face;
                                face = sorter[f].face;
                                filltriangle(&faces[face]);

                                //just plot the corners
                                /*
                                u16 p0,p1,p2;
                                p0 = faces[face].pt[0].point_index;
                                p1 = faces[face].pt[1].point_index;
                                p2 = faces[face].pt[2].point_index;
                                ham_PutPixel(rotated[p0].x, rotated[p0].y, 0x7fff);
                                ham_PutPixel(rotated[p1].x, rotated[p1].y, 0x7fff);
                                ham_PutPixel(rotated[p2].x, rotated[p2].y, 0x7fff);
                                */
                        }

                        tilt = tilt+5;
                        turn = turn+6;
                        roll = roll+7;
                        //rem flip and the screens
                        ham_FlipBGBuffer();
                        ham_ClearBackBuffer(0);
                        gnewframe=0;
                }
        }
        return 0;
}

void setup()
{
        s32 coza;
        for(coza=0;coza<359;coza++)
        {
                zin[coza] = sin(coza/180.0*3.14159)*SCALE;
                coz[coza] = cos(coza/180.0*3.14159)*SCALE;
        }
}

void vblFunc()
{
        gnewframe=1;
}


void plotsprite(u16 xpos ,u16 ypos)
{
        /*
        u16 texptr=0;
        s16 x,y;
        for (y=0;y<SCREENY;y++)
        {
        for (x=0;x<SCREENX;x++)
        {
        *frameptr++=bground5[texptr++];
        }
        frameptr+=SCREENX-SCREENX;
        }
        u8 buffer = ham_GetBGBuffer();
        if (buffer==1) frameptr=(u16*)0x6000000;
        else frameptr=(u16*)0x600a000;
        */

        u16 *src = bground5;
        u16 *dst = frameptr;
        u16 x,y;

        for (y = 0; y < SCREENY; y++)
        {
                for (x = 0; x < SCREENX; x++)
                        *dst++ = *src++;
        }
}


#define FSHIFT 16
#define FSCALE (1L<<FSHIFT)

void scan(EDGE *L,EDGE *R, s32 y)
{
        s32 x0,x1,u,v,du,dv,dx;
        u16 *screenptr16;

        if (y<0 || y>=160) return;

        if (L->x > R->x)
        {
                EDGE *t=L;
                L=R;
                R=t;
        }

        x0=L->x>>FSHIFT;
        x1=R->x>>FSHIFT;

        dx = x1-x0;
        if (!dx) return;

        if (x0>=SCREENY)
                return;
        else if (x0<0)
                x0=0;

        if (x1<0)
                return;
        else if (x1>=SCREENX)
                x1=SCREENX;

        u=L->u;
        v=L->v;

        du = (R->u - L->u) / dx;
        dv = (R->v - L->v) / dx;

        screenptr16 = frameptr + x0 + y * SCREENX;
        while (dx--)
        {
                *screenptr16++ = texture[(u>>FSHIFT)+TEX_X*(v>>FSHIFT)];
                u+=du;
                v+=dv;
        }
}

void filltriangle(FACE *face)
{
        s32 xx[3], yy[3];
        u8 i0,i1,i2;

        s32 dyL, dyT, dyB;
        s32 rdyL,rdyT,rdyB;
        s32 Y;
        s32 dxL, dxT, dxB;

        s32 duL, duT, duB;
        s32 dvL, dvT, dvB;
        EDGE L,R;

        yy[0]=rotated[face->pt[0].point_index].y>>SHIFT;
        yy[1]=rotated[face->pt[1].point_index].y>>SHIFT;
        yy[2]=rotated[face->pt[2].point_index].y>>SHIFT;

        xx[0]=rotated[face->pt[0].point_index].x>>SHIFT;
        xx[1]=rotated[face->pt[1].point_index].x>>SHIFT;
        xx[2]=rotated[face->pt[2].point_index].x>>SHIFT;

        i0 = 0;
        i1 = 1;
        i2 = 2;

        if (yy[0]<=yy[1] && yy[0]<=yy[2])
        {
                //y0 is smallest
                if (yy[1]>yy[2])
                {
                        //y1 is largest
                        i1 = 2;
                        i2 = 1;
                }
                else
                {
                        //y2 is largest
                }
        }
        else if (yy[1]<=yy[0] && yy[1]<=yy[2])
        {
                i0 = 1;
                //y1 is smallest
                if (yy[0]<yy[2])
                {
                        //y2 is largest
                        i1 = 0;
                }
                else
                {
                        //y0 is largest
                        i1 = 2;
                        i2 = 0;
                }
        }
        else
        {
                i0 = 2;
                //y2 is smallest
                if (yy[1]<yy[0])
                {
                        //y0 is largest
                        i2 = 0;
                }
                else
                {
                        //y1 is largest
                        i2 = 1;
                        i1 = 0;
                }
        }

        dyL = yy[i2]-yy[i0];

        if (dyL==0) return;
        rdyL = FSCALE / dyL;
        dxL = (xx[i2]-xx[i0]) * rdyL;
        duL = (face->pt[i2].u-face->pt[i0].u) * rdyL;
        dvL = (face->pt[i2].v-face->pt[i0].v) * rdyL;
        dyT = yy[i1]-yy[i0];
        L.x=xx[i0]<<FSHIFT;
        Y=yy[i0];
        L.u=face->pt[i0].u<<FSHIFT;
        L.v=face->pt[i0].v<<FSHIFT;

        if (dyT!=0)
        {
                rdyT = FSCALE / dyT;
                dxT = (xx[i1]-xx[i0]) * rdyT;
                duT = (face->pt[i1].u-face->pt[i0].u) * rdyT;
                dvT = (face->pt[i1].v-face->pt[i0].v) * rdyT;
                R=L;


                while (Y < yy[i1])
                {
                        scan(&L,&R,Y);
                        Y++;
                        L.x+=dxL;
                        R.x+=dxT;
                        L.u+=duL;
                        L.v+=dvL;
                        R.u+=duT;
                        R.v+=dvT;
                }
        }
        //bottom
        R.x=xx[i1]<<FSHIFT;
        R.u=face->pt[i1].u<<FSHIFT;
        R.v=face->pt[i1].v<<FSHIFT;
        dyB = yy[i2]-yy[i1];
        if (dyB!=0)
        {
                rdyB = FSCALE / dyB;
                dxB = (xx[i2]-xx[i1]) * rdyB;
                duB = (face->pt[i2].u-face->pt[i1].u) * rdyB;
                dvB = (face->pt[i2].v-face->pt[i1].v) * rdyB;

                while (Y < yy[i2])
                {
                        scan(&L,&R,Y);
                        Y++;
                        L.x+=dxL;
                        R.x+=dxB;
                        L.u+=duL;
                        L.v+=dvL;
                        R.u+=duB;
                        R.v+=dvB;
                }
        }
}
Challenge Trophies Won:

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #7 on: October 06, 2006 »
and again, thanks a lot! Karma up!
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17414
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Software fixed point triangle renderer?
« Reply #8 on: October 06, 2006 »
:) Looks like you're innundated with softrenderers!
Shockwave ^ Codigos
Challenge Trophies Won:

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #9 on: October 06, 2006 »
But none do mipmapping yet ...
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #10 on: October 06, 2006 »
->nino - you should probably credit that code, especially since you're giving it away...
->Taj,
Mipmapping's a separate problem from drawing textured triangles - you just have to pick the right sized texture first.  One way of doing this is looking at the z of the triangle and picking smaller textures for far away z, but a far better way is to work out the area of the triangle being rendered in pixels (ie. use a 2d cross product on the screen coordinates) and how many texels it needs (ie. use a 2d cross on the vertex uv's) and work out which texture supplies roughly the right number of texels for that screen area (division, and a lookup).

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #11 on: October 07, 2006 »
woops sorry jim yeah its jims code for an old project me him and sg did on or old forum, i credited you over on my gba tuts for the render so thought that would be ok sorry for that :-X


if youd like jim i could change the above peice of code with one of my own renders when i dig it out and also remove the demo from my gba tut?
« Last Edit: October 07, 2006 by ninogenio »
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #12 on: October 07, 2006 »
Just a simple credit is fine.  I have absolutely no problem with people using my code, otherwise I wouldn't post it :D

Jim
Challenge Trophies Won:

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Re: Software fixed point triangle renderer?
« Reply #13 on: October 08, 2006 »
thanks jim
Challenge Trophies Won: