WIP 3D Engine [v0.06] (v0.07 preview screenie)

User projects written in or related to FreeBASIC.
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

WIP 3D Engine [v0.06] (v0.07 preview screenie)

Postby Hezad » Aug 22, 2008 13:38

Hey !

So after a lot of peregrinations with poly filling, screen buffer access and glitches, here it is : my first Gouraud Shading code !
Once again, thanks to Relsoft for his tutorial (http://www.phatcode.net/articles.php?id=214) and to Counting Pine for having helped me with screen buffer stuff.
This code is everything but optimized ! So I don't know how it'll run on your computer.
I also posted it on DBF/GVY forums.

A screen :
Image

The code :

Code: Select all

#Define Norm(a) sqr(a.x*a.x + a.y*a.y + a.z*a.z)

Const MAX_TRIANGLES_PER_OBJECT = 500
Const MAX_OBJECTS = 10
Const xRes = 640, yRes = 480

Dim shared as integer ptr ScrPtr

Screenres xRes,yRes,32,2

ScrPtr = Screenptr

Type Vector
    as single x,y,z
End Type

Type ColorT
    as integer r,g,b
End Type

Type VertexT
   
    as Vector Pos3d
   
    as Vector Gouraud_Normal
   
    as Vector Pos2d
   
    as ColorT Color
   
End Type

Type TriangleT
   
    as Vector Normal
   
    as integer idZ
   
    as VertexT Vertex(2)
   
End Type

Type ObjectT
   
    as TriangleT Triangle(MAX_TRIANGLES_PER_OBJECT)
   
    as Vector Center
   
    as integer nb_triangles
   
End Type

Type LightT
   
    Pos3d as Vector
   
    Intensity as single
   
End Type

'' 3d Characteristics
Dim shared as single FOV = 256

Sub Sort_Object_Z(obj as ObjectT)
   
    For i as integer = 1 to obj.nb_Triangles
       
        obj.triangle(i).IdZ = i
        if i>1 then
            if obj.triangle(i).vertex(0).pos3d.z + obj.triangle(i).vertex(1).pos3d.z + obj.triangle(i).vertex(2).pos3d.z < obj.triangle(i-1).vertex(0).pos3d.z + obj.triangle(i-1).vertex(1).pos3d.z + obj.triangle(i-1).vertex(2).pos3d.z then

                Swap obj.triangle(i), obj.triangle(i-1)
                i=1
               
            end if
        end if
       
    Next
   
End Sub

Sub Calc_Triangle_2d_ZNormal(Tri as TriangleT)
   
    Tri.Normal.Z = (Tri.Vertex(1).pos2d.x - Tri.Vertex(0).pos2d.x) * (Tri.Vertex(0).pos2d.y - Tri.Vertex(2).pos2d.y) - (Tri.Vertex(1).pos2d.y - Tri.Vertex(0).pos2d.y) * (Tri.Vertex(0).pos2d.x - Tri.Vertex(2).pos2d.x)

End Sub

Sub Calc_Triangle_Normal(Tri as TriangleT)
   
    dim as single ax,bx,ay,by,az,bz,NNorm
   
    ax = Tri.Vertex(1).pos3d.x - Tri.Vertex(0).pos3d.x
    bx = Tri.Vertex(2).pos3d.x - Tri.Vertex(1).pos3d.x
    ay = Tri.Vertex(1).pos3d.y - Tri.Vertex(0).pos3d.y
    by = Tri.Vertex(2).pos3d.y - Tri.Vertex(1).pos3d.y
    az = Tri.Vertex(1).pos3d.z - Tri.Vertex(0).pos3d.z
    bz = Tri.Vertex(2).pos3d.z - Tri.Vertex(1).pos3d.z
   
    Tri.Normal.x = ay * bz - az * by
    Tri.Normal.y = az * bx - ax * bz
    Tri.Normal.z = ax * by - ay * bx
   
    '' Normalize (ouch, not optimized !) :
    NNorm = Norm(Tri.Normal)
   
    Tri.Normal.x /= NNorm
    Tri.Normal.y /= NNorm
    Tri.Normal.z /= NNorm
   
End Sub

Sub Calc_Object_Normals(obj as ObjectT)
   
    for i as integer = 1 to obj.nb_triangles
       
        Calc_Triangle_Normal(obj.Triangle(i))
   
    next
   
End Sub

Function SetLight(x as single,y as single, z as single,intens as single) as LightT
   
    Dim as LightT Tmp
   
    Tmp.pos3d.x = x
    Tmp.pos3d.y = y
    Tmp.pos3d.z = z
   
    Tmp.Intensity = intens
   
    Return Tmp
   
End Function

Sub Project_Object(Obj as ObjectT)
   
    if obj.nb_triangles = 0 then exit Sub
   
    For i as integer = 1 to obj.nb_triangles
       
        For j as integer = 0 to 2
           
            if obj.Center.z + obj.Triangle(i).Vertex(j).pos3d.z = FOV then obj.Triangle(i).Vertex(j).pos3d.z+=1
           
            obj.Triangle(i).Vertex(j).pos2d.x = xRes/2 + FOV * (obj.Center.x + obj.Triangle(i).Vertex(j).pos3d.x) / (FOV - (obj.Center.z + obj.Triangle(i).Vertex(j).pos3d.z))
            obj.Triangle(i).Vertex(j).pos2d.y = yRes/2 - FOV * (obj.Center.y + obj.Triangle(i).Vertex(j).pos3d.y) / (FOV - (obj.Center.z + obj.Triangle(i).Vertex(j).pos3d.z))
       
        Next
       
    Next
   
End Sub

Sub GLine(ByVal x1 as integer,ByVal x2 as integer, y as integer,ByVal r1 as integer,ByVal g1 as integer,ByVal b1 as integer,ByVal r2 as integer,ByVal g2 as integer,ByVal b2 as integer)
   
    dim as single dR,dG,dB
    dim as single R,g,b
   
    dim as integer itx1,itx2
    dim as single sr1,sr2,sg1,sg2,sb1,sb2
   
    if x1<x2 then
        itx1 = x1
        itx2 = x2
        sr1 = r1
        sr2 = r2
        sg1 = g1
        sg2 = g2
        sb1 = b1
        sb2 = b2
    else
        itx1 = x2
        itx2 = x1
        sr1 = r2
        sr2 = r1
        sg1 = g2
        sg2 = g1
        sb1 = b2
        sb2 = b1
    end if
   
    dR = (sr2 - sr1)/(itx2 - itx1)
    dG = (sg2 - sg1)/(itx2 - itx1)
    dB = (sb2 - sb1)/(itx2 - itx1)
   
    r = sr1
    g = sg1
    b = sb1
   
    for i as integer = itx1 to itx2-1

        if y>0 and y<yRes and i>0 and i<xRes then
            ScrPtr[y*xRes+i] = rgb(r,g,b)
        end if

        r += dR
        g += dG
        b += dB
       
    Next
   
End Sub

Sub Gouraud_Fill(ByVal Triangle as TriangleT)
   
    '' Sorting Y values
    if Triangle.Vertex(1).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(1).Pos2d.y,Triangle.Vertex(0).Pos2d.y
        swap Triangle.Vertex(1).Pos2d.x,Triangle.Vertex(0).Pos2d.x
           
        swap Triangle.Vertex(1).Color.r,Triangle.Vertex(0).Color.r
        swap Triangle.Vertex(1).Color.g,Triangle.Vertex(0).Color.g
        swap Triangle.Vertex(1).Color.b,Triangle.Vertex(0).Color.b
    end if
   
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(2).Pos2d.y,Triangle.Vertex(0).Pos2d.y
        swap Triangle.Vertex(2).Pos2d.x,Triangle.Vertex(0).Pos2d.x
           
        swap Triangle.Vertex(2).Color.r,Triangle.Vertex(0).Color.r
        swap Triangle.Vertex(2).Color.g,Triangle.Vertex(0).Color.g
        swap Triangle.Vertex(2).Color.b,Triangle.Vertex(0).Color.b
    end if
   
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(1).Pos2d.y then
        swap Triangle.Vertex(2).Pos2d.y,Triangle.Vertex(1).Pos2d.y
        swap Triangle.Vertex(2).Pos2d.x,Triangle.Vertex(1).Pos2d.x
           
        swap Triangle.Vertex(2).Color.r,Triangle.Vertex(1).Color.r
        swap Triangle.Vertex(2).Color.g,Triangle.Vertex(1).Color.g
        swap Triangle.Vertex(2).Color.b,Triangle.Vertex(1).Color.b
    end if
   
    dim as integer dx1,dy1,dx2,dy2,dx3,dy3
    dim as integer dr1,dg1,db1,dr2,dg2,db2,dr3,dg3,db3
    dim as single Slope1,Slope2,Slope3
    dim as single RSlope1, GSlope1,BSlope1
    dim as single RSlope2, GSlope2,BSlope2
    dim as single RSlope3, GSlope3,BSlope3
   
   
    '' interpolate 0 to 1 (pos + color)
       
    dX1 = Triangle.Vertex(1).pos2d.x - Triangle.Vertex(0).pos2d.x
    dY1 = Triangle.Vertex(1).pos2d.y - Triangle.Vertex(0).pos2d.y
   
    dr1 = Triangle.Vertex(1).color.r - Triangle.Vertex(0).color.r
    dg1 = Triangle.Vertex(1).color.g - Triangle.Vertex(0).color.g
    db1 = Triangle.Vertex(1).color.b - Triangle.Vertex(0).color.b
   
    if dY1 <> 0 then
   
        Slope1 = dX1 / dY1
       
        RSlope1 = dR1 / dY1
        GSlope1 = dG1 / dY1
        BSlope1 = dB1 / dY1
       
    else
       
        Slope1 = 0
       
        RSlope1 = 0
        GSlope1 = 0
        BSlope1 = 0
       
    End if
   
   
    '' interpolate 1 to 2
       
    dX2 = Triangle.Vertex(2).pos2d.x - Triangle.Vertex(1).pos2d.x
    dY2 = Triangle.Vertex(2).pos2d.y - Triangle.Vertex(1).pos2d.y
   
    dr2 = Triangle.Vertex(2).color.r - Triangle.Vertex(1).color.r
    dg2 = Triangle.Vertex(2).color.g - Triangle.Vertex(1).color.g
    db2 = Triangle.Vertex(2).color.b - Triangle.Vertex(1).color.b
   
    if dY2 <> 0 then
   
        Slope2 = dX2 / dY2
       
        RSlope2 = dR2 / dY2
        GSlope2 = dG2 / dY2
        BSlope2 = dB2 / dY2
       
    else
       
        Slope2 = 0
       
        RSlope2 = 0
        GSlope2 = 0
        BSlope2 = 0
       
    End if
   
   
    '' interpolate 0 to 2
       
    dX3 = Triangle.Vertex(0).pos2d.x - Triangle.Vertex(2).pos2d.x
    dY3 = Triangle.Vertex(0).pos2d.y - Triangle.Vertex(2).pos2d.y
   
    dr3 = Triangle.Vertex(0).color.r - Triangle.Vertex(2).color.r
    dg3 = Triangle.Vertex(0).color.g - Triangle.Vertex(2).color.g
    db3 = Triangle.Vertex(0).color.b - Triangle.Vertex(2).color.b
   
    if dY3 <> 0 then
   
        Slope3 = dX3 / dY3
       
        RSlope3 = dR3 / dY3
        GSlope3 = dG3 / dY3
        BSlope3 = dB3 / dY3
       
    else
       
        Slope3 = 0
       
        RSlope3 = 0
        GSlope3 = 0
        BSlope3 = 0
       
    End if
   
   
    '' Drawing
   
    '' Top
    dim as single CurX1=Triangle.Vertex(0).pos2d.x, CurX2=Triangle.Vertex(0).pos2d.x
    dim as single CurR1=Triangle.Vertex(0).Color.r,_
                   CurG1=Triangle.Vertex(0).Color.g,_
                   CurB1=Triangle.Vertex(0).Color.b,_
                   CurR2=Triangle.Vertex(0).Color.r,_
                   CurG2=Triangle.Vertex(0).Color.g,_
                   CurB2=Triangle.Vertex(0).Color.b
   
    'BufferIter = Triangle.Vertex(0).pos2d.y * xRes
   
    For y as integer = Triangle.Vertex(0).pos2d.y to Triangle.Vertex(1).pos2d.y-1
       
        GLine(CurX1,CurX2,y,CurR1,CurG1,CurB1,CurR2,CurG2,CurB2)
       
        CurX1 += Slope1
        CurX2 += Slope3
       
        CurR1 += RSlope1
        CurR2 += RSlope3
        CurG1 += GSlope1
        CurG2 += GSlope3
        CurB1 += BSlope1
        CurB2 += BSlope3
       
        'BufferIter += xRes
       
    Next
   
    '' down
   
    CurX1 = Triangle.Vertex(1).pos2d.x
    CurR1 = Triangle.Vertex(1).color.r
    Curg1 = Triangle.Vertex(1).color.g
    Curb1 = Triangle.Vertex(1).color.b
   
    For y as integer = Triangle.Vertex(1).pos2d.y to Triangle.Vertex(2).pos2d.y-1
       
        GLine(CurX1,CurX2,y,CurR1,CurG1,CurB1,CurR2,CurG2,CurB2)
       
        CurX1 += Slope2
        CurX2 += Slope3
       
        CurR1 += RSlope2
        CurR2 += RSlope3
        CurG1 += GSlope2
        CurG2 += GSlope3
        CurB1 += BSlope2
        CurB2 += BSlope3
       
    Next
   
End Sub

#Define SamePnt(a,b) iif (a.pos3d.x = b.pos3d.x and a.pos3d.y = b.pos3d.y and a.pos3d.z = b.pos3d.z,1,0)
       
Sub Gouraud_Shader(obj_ as objectT,L_ as LightT)
   
    Dim as single Dot1,Dot2,Dot3
   
    Dim as objectT obj = obj_
    Dim as LightT L = L_
   
    dim as single tmpXNorm,TmpYNorm,TmpZNorm
    dim as integer tmpNBfaces
   
    '' "Vertex normals"
    For k as integer = 1 to obj.nb_triangles
        for i as integer = 0 to 2
            TmpXNorm = 0
            TmpYNorm = 0
            TmpZNorm = 0
            tmpNBfaces = 0
       
            for j as integer = 1 to obj.nb_triangles
                if SamePnt(obj.triangle(k).Vertex(0),obj.triangle(j).Vertex(i)) or _
                   SamePnt(obj.triangle(k).Vertex(1),obj.triangle(j).Vertex(i)) or _
                   SamePnt(obj.triangle(k).Vertex(2),obj.triangle(j).Vertex(i)) then
                   
                    TmpXNorm += obj.triangle(j).Normal.x
                    TmpYNorm += obj.triangle(j).Normal.y
                    TmpZNorm += obj.triangle(j).Normal.z
   
                    tmpNBfaces += 1
               
                end if
            next
       
            TmpXNorm /= TmpNBfaces
            TmpYNorm /= TmpNBfaces
            TmpZNorm /= TmpNBfaces
   
            obj.triangle(k).Vertex(i).Gouraud_Normal.x = TmpXNorm
            obj.triangle(k).Vertex(i).Gouraud_Normal.y = TmpyNorm
            obj.triangle(k).Vertex(i).Gouraud_Normal.z = TmpzNorm
       
        next
   
        Dot1 = (obj.triangle(k).Vertex(0).Gouraud_Normal.x * L.pos3d.x) + _
               (obj.triangle(k).Vertex(0).Gouraud_Normal.y * L.pos3d.y) + _
               (obj.triangle(k).Vertex(0).Gouraud_Normal.z * L.pos3d.z)
        if Dot1<0 then Dot1 = 0
        if Dot1>1 then Dot1 = 1
   
        Dot2 = (obj.triangle(k).Vertex(1).Gouraud_Normal.x * L.pos3d.x) + _
               (obj.triangle(k).Vertex(1).Gouraud_Normal.y * L.pos3d.y) + _
               (obj.triangle(k).Vertex(1).Gouraud_Normal.z * L.pos3d.z)
        if Dot2<0 then Dot2 = 0
        if Dot2>1 then Dot2 = 1
       
        Dot3 = (obj.triangle(k).Vertex(2).Gouraud_Normal.x * L.pos3d.x) + _
               (obj.triangle(k).Vertex(2).Gouraud_Normal.y * L.pos3d.y) + _
               (obj.triangle(k).Vertex(2).Gouraud_Normal.z * L.pos3d.z)
        if Dot3<0 then Dot3 = 0
        if Dot3>1 then Dot3 = 1
       
        '' apply new color
        obj_.triangle(k).Vertex(0).Color.r = 255*L.Intensity*Dot1
        obj_.triangle(k).Vertex(0).Color.g = 255*L.Intensity*Dot1
        obj_.triangle(k).Vertex(0).Color.b = 255*L.Intensity*Dot1
       
        obj_.triangle(k).Vertex(1).Color.r = 255*L.Intensity*Dot2
        obj_.triangle(k).Vertex(1).Color.g = 255*L.Intensity*Dot2
        obj_.triangle(k).Vertex(1).Color.b = 255*L.Intensity*Dot2
       
        obj_.triangle(k).Vertex(2).Color.r = 255*L.Intensity*Dot3
        obj_.triangle(k).Vertex(2).Color.g = 255*L.Intensity*Dot3
        obj_.triangle(k).Vertex(2).Color.b = 255*L.Intensity*Dot3
    next
   
   
   
End sub

Sub Rotate(obj as objectT,Tx as single, Ty as single, Tz as single)
   
    dim as single tmpX,tmpY,TmpZ
   
    For i as integer = 1 to obj.NB_triangles
        For j as integer = 0 to 2
           
            TmpY = obj.Triangle(i).Vertex(j).pos3d.y * cos(Tx) - obj.Triangle(i).Vertex(j).pos3d.z * sin(Tx)
            TmpZ = obj.Triangle(i).Vertex(j).pos3d.z * cos(Tx) + obj.Triangle(i).Vertex(j).pos3d.y * sin(Tx)
            obj.Triangle(i).Vertex(j).pos3d.y = TmpY
            obj.Triangle(i).Vertex(j).pos3d.z = TmpZ
           
            TmpZ = obj.Triangle(i).Vertex(j).pos3d.z * cos(Ty) - obj.Triangle(i).Vertex(j).pos3d.x * sin(Ty)
            TmpX = obj.Triangle(i).Vertex(j).pos3d.x * cos(Ty) + obj.Triangle(i).Vertex(j).pos3d.z * sin(Ty)
            obj.Triangle(i).Vertex(j).pos3d.x = TmpX
           
            TmpX = obj.Triangle(i).Vertex(j).pos3d.x * cos(Tz) - obj.Triangle(i).Vertex(j).pos3d.y * sin(Tz)
            TmpY = obj.Triangle(i).Vertex(j).pos3d.y * cos(Tz) + obj.Triangle(i).Vertex(j).pos3d.x * sin(Tz)
           
            obj.Triangle(i).Vertex(j).pos3d.x = TmpX
            obj.Triangle(i).Vertex(j).pos3d.y = TmpY
            obj.Triangle(i).Vertex(j).pos3d.z = TmpZ
           
        Next
    Next
   
End sub










'' Test

'' Loading objects

Dim as ObjectT Pyramid

Pyramid.nb_triangles = 4
Pyramid.Center.z = 1
Pyramid.Center.y = 0
Pyramid.Center.x = 0

For i as integer = 1 to Pyramid.nb_triangles
    for j as integer = 0 to 2
       
        Read Pyramid.triangle(i).Vertex(j).pos3d.x, Pyramid.triangle(i).Vertex(j).pos3d.y, Pyramid.triangle(i).Vertex(j).pos3d.z, Pyramid.triangle(i).Vertex(j).Color.r, Pyramid.triangle(i).Vertex(j).Color.g, Pyramid.triangle(i).Vertex(j).Color.b
   
        Pyramid.triangle(i).Vertex(j).pos3d.x *= 4
        Pyramid.triangle(i).Vertex(j).pos3d.y *= 4
        Pyramid.triangle(i).Vertex(j).pos3d.z *= 4
    next
   
next


dim as single t=.02

Dim as LightT Light

Light = SetLight(1,2,0,1)

Do
   
    Screenlock : cls
   
    Project_object Pyramid
   
    Sort_object_Z Pyramid
   
    Calc_object_normals Pyramid
   
    Gouraud_Shader Pyramid, Light
   
    For i as integer = 1 to Pyramid.nb_triangles
       
        if Pyramid.triangle(i).Normal.Z>0 then
            Gouraud_Fill Pyramid.triangle(i)
        end if
    Next
   
    Rotate(Pyramid,t/2,t/3,t/2)
   
    screenunlock : sleep 1,1
   
loop until multikey(&h01)


'' PYRAMID
'' triangle 1
Data 0,30,0,250,50,50
Data 20,0,-20,50,250,50
Data -20,0,-20,50,50,250

'' triangle 2
Data 0,30,0,250,50,50
Data 0,0,20,250,50,250
Data 20,0,-20,50,250,50

'' triangle 3
Data 0,30,0,250,50,50
Data -20,0,-20,50,50,250
Data 0,0,20,250,50,250

'' triangle 4
Data 20,0,-20,50,250,50
Data 0,0,20,250,50,250
Data -20,0,-20,50,50,250


++ :)
Last edited by Hezad on Nov 20, 2008 11:56, edited 8 times in total.
ssjx
Posts: 34
Joined: Oct 23, 2007 8:51
Contact:

Postby ssjx » Aug 22, 2008 13:52

That's very cool! Are you planning on using this in a game or anything?

I've taken the lazy approach to 3d and am just using opengl to do all the hard work!

Btw, what are the DBF/GVY forums? I don't recognise the acronyms...
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Postby Hezad » Aug 22, 2008 14:23

That's very cool!


Thanks :)

Are you planning on using this in a game or anything?

Nope :p The point is there is only one object rendered. Rendering more object would need a way better sorting algorithm (I just sort the triangles by the simplest and the more CPU-demanding way :p) and/or a Z-buffer handling.
But more than that, it's reaaally unoptimized lol
Maybe a little demo but nothing more.

I've taken the lazy approach to 3d and am just using opengl to do all the hard work!

When I try(:p) to do 3d usually, I'm in the same case ^^

Btw, what are the DBF/GVY forums? I don't recognise the acronyms...


Well, to be honest, I don't know what the acronym means >< :p but it's a demo coding forum with a freebasic part :
http://dbfinteractive.com/forum/index.php
nkk_kan
Posts: 209
Joined: May 18, 2007 13:01
Location: India
Contact:

Postby nkk_kan » Aug 22, 2008 14:49

dbf = Dark Bit Factory
and gvy = GraVitY

oh and hezad, you should read administrator's PMs =P
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Postby Hezad » Aug 22, 2008 16:34

dbf = Dark Bit Factory
and gvy = GraVitY


Thanks for those precisions !

oh and hezad, you should read administrator's PMs =P

??
1) I have no message telling me I have any PM
2) There's no link from where I can see my PM box
3) Aren't PM's disabled on this board ?

lol Or maybe I missed something ?
nkk_kan
Posts: 209
Joined: May 18, 2007 13:01
Location: India
Contact:

Postby nkk_kan » Aug 22, 2008 21:18

lol...i meant on DBF/GVY forum =P
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Postby Hezad » Aug 22, 2008 22:40

Well ... lol... the point is I haven't any pm's on dbf/gby forum neither ^^
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Postby Hezad » Aug 23, 2008 16:41

Update :D

Now the "engine" supports Z-Buffering and Texture Mapping. I ameliorated the colors and light handling some versions ago but since I played around with it recently, light seems weird : I'm working on it :)

Screens :

Image
Z-Buffer

Image
Texture Mapping


Code :

Code: Select all



''  =======================---. 3D Stuff .---=======================
''
''      Gouraud Shading + Z-Buffer rendering
''
''                      Code : Hezad  [   Hezad0 )at( Gmail.com    ]
''
''
''  Thanks to Relsoft for his awesome tutorial :
''                 [  http://www.phatcode.net/articles.php?id=214  ]
''
''
''  ================================================================


#Define Norm(a) sqr(a.x*a.x + a.y*a.y + a.z*a.z)

Const MAX_TRIANGLES_PER_OBJECT = 500
Const MAX_OBJECTS = 10
Const xRes = 640, yRes = 480

Const SCREEN_MEM = xRes * yRes

Const BGND_COLOR = rgb(50,50,70)

Const MAX_Z = 1000

Dim shared as integer ptr ScrPtr
ReDim shared as integer ZBuffer(SCREEN_MEM)

Screenres xRes,yRes,32,2

ScrPtr = Screenptr

Dim shared as single FPS_t,CurFPS,FPS_counter

Type Vector
    as single x,y,z
End Type

Type ColorT
    as integer r,g,b
End Type

Type TextureT
   
    as vector Size

    as integer ptr GFX
   
End Type

Sub Set_Texture_Size(Text as TextureT, x as integer, y as integer)
   
    If Text.GFX <> 0 then deallocate Text.GFX
   
    Text.Size.x = x
    Text.Size.y = y
   
    Text.GFX = Callocate(x*y,sizeof(integer))
   
End Sub

Type VertexT
   
    as Vector Pos3d
   
    as Vector Gouraud_Normal
   
    as Vector Pos2d
   
    as ColorT Color
   
    as ColorT OriginalColor
   
    as single U,V
   
End Type

Type TriangleT
   
    as Vector Normal
   
    as integer idZ
   
    as VertexT Vertex(2)
   
    as Vector Parent_Center
   
End Type

Type ObjectT
   
    as TriangleT Triangle(MAX_TRIANGLES_PER_OBJECT)
   
    as Vector Center
   
    as integer nb_triangles
   
End Type

Type LightT
   
    Pos3d as Vector
   
    Intensity as single
   
End Type

Type CameraT
   
    Pos as Vector
   
    Angle as Vector
   
End Type

   
Dim shared as single FOV = 256
Dim shared as CameraT Camera

Sub Set_Camera(x as integer, y as integer, z as integer)
   
    Camera.Pos.x = x
    Camera.Pos.y = y
    Camera.Pos.z = z
   
End Sub

Sub Sort_Object_Z(obj as ObjectT)
   
    For i as integer = 1 to obj.nb_Triangles
       
        obj.triangle(i).IdZ = i
        if i>1 then
            if obj.triangle(i).vertex(0).pos3d.z + obj.triangle(i).vertex(1).pos3d.z + obj.triangle(i).vertex(2).pos3d.z < obj.triangle(i-1).vertex(0).pos3d.z + obj.triangle(i-1).vertex(1).pos3d.z + obj.triangle(i-1).vertex(2).pos3d.z then

                Swap obj.triangle(i), obj.triangle(i-1)
                i=1
               
            end if
        end if
       
    Next
   
End Sub

Sub Calc_Triangle_Normal(Tri as TriangleT)
   
    dim as single ax,bx,ay,by,az,bz,NNorm
   
    ax = Tri.Vertex(1).pos3d.x - Tri.Vertex(0).pos3d.x
    bx = Tri.Vertex(2).pos3d.x - Tri.Vertex(1).pos3d.x
    ay = Tri.Vertex(1).pos3d.y - Tri.Vertex(0).pos3d.y
    by = Tri.Vertex(2).pos3d.y - Tri.Vertex(1).pos3d.y
    az = Tri.Vertex(1).pos3d.z - Tri.Vertex(0).pos3d.z
    bz = Tri.Vertex(2).pos3d.z - Tri.Vertex(1).pos3d.z
   
    Tri.Normal.x = ay * bz - az * by
    Tri.Normal.y = az * bx - ax * bz
    Tri.Normal.z = ax * by - ay * bx
   
    '' Normalize
    NNorm = 1/Norm(Tri.Normal)
   
    Tri.Normal.x *= NNorm
    Tri.Normal.y *= NNorm
    Tri.Normal.z *= NNorm
   
End Sub

#Define SamePnt(a,b) iif (a.pos3d.x = b.pos3d.x and a.pos3d.y = b.pos3d.y and a.pos3d.z = b.pos3d.z,1,0)

Sub PreCalc_Object_Normals(obj as ObjectT)
   
    dim as single tmpXNorm,TmpYNorm,TmpZNorm
    dim as integer tmpNBfaces
   
    for k as integer = 1 to obj.nb_triangles
       
        '' face normal
        Calc_Triangle_Normal(obj.Triangle(k))
   
        '' "Vertex normals"
        for i as integer = 0 to 2
            TmpXNorm = 0
            TmpYNorm = 0
            TmpZNorm = 0
       
            for j as integer = 1 to obj.nb_triangles
                if SamePnt(obj.triangle(k).Vertex(0),obj.triangle(j).Vertex(i)) or _
                   SamePnt(obj.triangle(k).Vertex(1),obj.triangle(j).Vertex(i)) or _
                   SamePnt(obj.triangle(k).Vertex(2),obj.triangle(j).Vertex(i)) then
                   
                    TmpXNorm += obj.triangle(j).Normal.x
                    TmpYNorm += obj.triangle(j).Normal.y
                    TmpZNorm += obj.triangle(j).Normal.z
               
                end if
            next
           
            dim as single _Normm = 1/sqr(TmpXNorm*TmpXNorm+TmpYNorm*TmpYNorm+TmpZNorm*TmpZNorm)
           
            TmpXNorm *= _Normm
            TmpYNorm *= _Normm
            TmpZNorm *= _Normm
           
            obj.triangle(k).Vertex(i).Gouraud_Normal.x = TmpXNorm
            obj.triangle(k).Vertex(i).Gouraud_Normal.y = TmpyNorm
            obj.triangle(k).Vertex(i).Gouraud_Normal.z = TmpzNorm
       
        next
       
    next
   
End Sub

Function SetLight(x as single,y as single, z as single,intens as single) as LightT
   
    Dim as LightT Tmp
   
    Tmp.pos3d.x = x
    Tmp.pos3d.y = y
    Tmp.pos3d.z = z
   
    Tmp.Intensity = intens
   
    Return Tmp
   
End Function

Declare Sub Rotate(obj as objectT,Tx as single, Ty as single, Tz as single)

Sub Project_Object(Obj as ObjectT)
   
    dim as single aX,aY,aZ
   
    if obj.nb_triangles = 0 then exit Sub
   
    For i as integer = 1 to obj.nb_triangles
       
        obj.Triangle(i).Parent_Center = obj.Center
       
        For j as integer = 0 to 2
           
            if obj.Triangle(i).Vertex(j).pos3d.z = Camera.pos.z - obj.Center.z + FOV then obj.Triangle(i).Vertex(j).pos3d.z+=.0001
           
            obj.Triangle(i).Vertex(j).pos2d.x = xRes/2 + FOV*(-Camera.pos.x + obj.Center.x + obj.Triangle(i).Vertex(j).pos3d.x) / (FOV - (-Camera.pos.z + obj.Center.z + obj.Triangle(i).Vertex(j).pos3d.z))
            obj.Triangle(i).Vertex(j).pos2d.y = yRes/2 - FOV*(-Camera.pos.y + obj.Center.y + obj.Triangle(i).Vertex(j).pos3d.y) / (FOV - (-Camera.pos.z + obj.Center.z + obj.Triangle(i).Vertex(j).pos3d.z))
           
        Next
       
    Next
   
End Sub

Sub GLine(ByVal x1 as integer,ByVal x2 as integer, y as integer,ByVal r1 as integer,ByVal g1 as integer,ByVal b1 as integer,ByVal r2 as integer,ByVal g2 as integer,ByVal b2 as integer,ByVal z1 as integer,ByVal z2 as integer)
   
    dim as single dR,dG,dB, dZ
    dim as single R,g,b
   
    dim as integer itx1,itx2,zz1,zz2
    Dim as single CurZ,xDiv
    dim as single sr1,sr2,sg1,sg2,sb1,sb2
   
    if x1<x2 then
        zz1 = z1
        zz2 = z2
       
        itx1 = x1
        itx2 = x2
        sr1 = r1
        sr2 = r2
        sg1 = g1
        sg2 = g2
        sb1 = b1
        sb2 = b2
    else
        zz1 = z2
        zz2 = z1
       
        itx1 = x2
        itx2 = x1
        sr1 = r2
        sr2 = r1
        sg1 = g2
        sg2 = g1
        sb1 = b2
        sb2 = b1
    end if
   
    xDiv = 1/(itx2 - itx1)
   
    dR = xDiv * (sr2 - sr1)
    dG = xDiv * (sg2 - sg1)
    dB = xDiv * (sb2 - sb1)
   
    dZ = xDiv * (zz2 - zz1)
   
    r = sr1
    g = sg1
    b = sb1
   
    CurZ = zz1
   
    dim as integer it
   
    for i as integer = itx1 to itx2-1

        if y>0 and y<yRes and i>0 and i<xRes then
           
            it = y*xRes + i
           
            If (FOV - (-Camera.pos.z + CurZ))>0 then
               
                If Curz > ZBuffer(it) then
                   
                    ZBuffer(it) = CurZ
                   
                    ScrPtr[it] = rgb(r,g,b)
                   
                    '' UnComment to show the ZBuffer Gfx :D
                    'dim as integer zBufferCol = 255*cast(single,(abs(ZBuffer(it))/MAX_Z))
                    'ScrPtr[it] = rgb(zBufferCol,zBufferCol,zBufferCol)
                   
                End if
           
            end if
       
        end if
       
        curZ += dZ
       
        r += dR
        g += dG
        b += dB
       
    Next
   
End Sub

Sub Gouraud_Fill(ByVal Triangle as TriangleT)
   
   
    '' Sorting Y values
    if Triangle.Vertex(1).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(1),Triangle.Vertex(0)
        swap Triangle.Vertex(1).Gouraud_Normal,Triangle.Vertex(0).Gouraud_Normal
    end if
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(0)
        swap Triangle.Vertex(1).Gouraud_Normal,Triangle.Vertex(0).Gouraud_Normal
    end if
   
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(1).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(1)
        swap Triangle.Vertex(1).Gouraud_Normal,Triangle.Vertex(0).Gouraud_Normal
    end if
   
    dim as integer dx1,dy1,dx2,dy2,dx3,dy3
    dim as integer dr1,dg1,db1,dr2,dg2,db2,dr3,dg3,db3
    dim as single Slope1,Slope2,Slope3, dYDiv
    dim as single RSlope1, GSlope1,BSlope1
    dim as single RSlope2, GSlope2,BSlope2
    dim as single RSlope3, GSlope3,BSlope3
   
    Dim as integer dz1,dz2,dz3
    Dim as single zSlope1,zSlope2,zSlope3
   
    '' interpolate 0 to 1 (pos + color)
   
    dZ1 = Triangle.Vertex(1).pos3d.z - Triangle.Vertex(0).pos3d.z
   
    dX1 = Triangle.Vertex(1).pos2d.x - Triangle.Vertex(0).pos2d.x
    dY1 = Triangle.Vertex(1).pos2d.y - Triangle.Vertex(0).pos2d.y
   
    dr1 = Triangle.Vertex(1).color.r - Triangle.Vertex(0).color.r
    dg1 = Triangle.Vertex(1).color.g - Triangle.Vertex(0).color.g
    db1 = Triangle.Vertex(1).color.b - Triangle.Vertex(0).color.b
   
    if dY1 <> 0 then
       
        dYDiv = 1/dY1
       
        zSlope1 = dZ1 * dYDiv
       
        Slope1 = dX1 * dYDiv
       
        RSlope1 = dR1 * dYDiv
        GSlope1 = dG1 * dYDiv
        BSlope1 = dB1 * dYDiv
       
    else
       
        zSlope1 = 0
       
        Slope1 = 0
       
        RSlope1 = 0
        GSlope1 = 0
        BSlope1 = 0
       
    End if
   
   
    '' interpolate 1 to 2
   
    dZ2 = Triangle.Vertex(2).pos3d.z - Triangle.Vertex(1).pos3d.z
   
    dX2 = Triangle.Vertex(2).pos2d.x - Triangle.Vertex(1).pos2d.x
    dY2 = Triangle.Vertex(2).pos2d.y - Triangle.Vertex(1).pos2d.y
   
    dr2 = Triangle.Vertex(2).color.r - Triangle.Vertex(1).color.r
    dg2 = Triangle.Vertex(2).color.g - Triangle.Vertex(1).color.g
    db2 = Triangle.Vertex(2).color.b - Triangle.Vertex(1).color.b
   
    if dY2 <> 0 then
       
        dYDiv = 1/dY2
       
        zSlope2 = dZ2 * dYDiv
       
        Slope2 = dX2 * dYDiv
       
        RSlope2 = dR2 * dYDiv
        GSlope2 = dG2 * dYDiv
        BSlope2 = dB2 * dYDiv
       
    else
       
        zSlope2 = 0
       
        Slope2 = 0
       
        RSlope2 = 0
        GSlope2 = 0
        BSlope2 = 0
       
    End if
   
   
    '' interpolate 0 to 2
   
    dZ3 = Triangle.Vertex(0).pos3d.z - Triangle.Vertex(2).pos3d.z
   
    dX3 = Triangle.Vertex(0).pos2d.x - Triangle.Vertex(2).pos2d.x
    dY3 = Triangle.Vertex(0).pos2d.y - Triangle.Vertex(2).pos2d.y
   
    dr3 = Triangle.Vertex(0).color.r - Triangle.Vertex(2).color.r
    dg3 = Triangle.Vertex(0).color.g - Triangle.Vertex(2).color.g
    db3 = Triangle.Vertex(0).color.b - Triangle.Vertex(2).color.b
   
    if dY3 <> 0 then
       
        dYDiv = 1/dY3
       
        zSlope3 = dZ3 * dYDiv
       
        Slope3 = dX3 * dYDiv
       
        RSlope3 = dR3 * dYDiv
        GSlope3 = dG3 * dYDiv
        BSlope3 = dB3 * dYDiv
       
    else
       
        zSlope3 = 0
       
        Slope3 = 0
       
        RSlope3 = 0
        GSlope3 = 0
        BSlope3 = 0
       
    End if
   
   
    '' Drawing
   
    '' Top
    dim as single CurX1=Triangle.Vertex(0).pos2d.x, CurX2=Triangle.Vertex(0).pos2d.x
    dim as single CurR1=Triangle.Vertex(0).Color.r,_
                   CurG1=Triangle.Vertex(0).Color.g,_
                   CurB1=Triangle.Vertex(0).Color.b,_
                   CurR2=Triangle.Vertex(0).Color.r,_
                   CurG2=Triangle.Vertex(0).Color.g,_
                   CurB2=Triangle.Vertex(0).Color.b
   
    dim as single CurZ1=Triangle.Vertex(0).pos3d.z, CurZ2=Triangle.Vertex(0).pos3d.z
   
    CurZ1 += Triangle.Parent_Center.z
    CurZ2 += Triangle.Parent_Center.z
   
    'BufferIter = Triangle.Vertex(0).pos2d.y * xRes
   
    For y as integer = Triangle.Vertex(0).pos2d.y to Triangle.Vertex(1).pos2d.y-1
       
        GLine(CurX1,CurX2,y,CurR1,CurG1,CurB1,CurR2,CurG2,CurB2, CurZ1, CurZ2)
       
        CurZ1 += zSlope1
        CurZ2 += zSlope3
       
        CurX1 += Slope1
        CurX2 += Slope3
       
        CurR1 += RSlope1
        CurR2 += RSlope3
        CurG1 += GSlope1
        CurG2 += GSlope3
        CurB1 += BSlope1
        CurB2 += BSlope3
       
        'BufferIter += xRes
       
    Next
   
    '' down
   
    CurZ1 = Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z
   
    CurX1 = Triangle.Vertex(1).pos2d.x
    CurR1 = Triangle.Vertex(1).color.r
    Curg1 = Triangle.Vertex(1).color.g
    Curb1 = Triangle.Vertex(1).color.b
   
    For y as integer = Triangle.Vertex(1).pos2d.y to Triangle.Vertex(2).pos2d.y-1
       
        GLine(CurX1,CurX2,y,CurR1,CurG1,CurB1,CurR2,CurG2,CurB2, CurZ1, CurZ2)
       
        CurZ1 += zSlope2
        CurZ2 += zSlope3
       
        CurX1 += Slope2
        CurX2 += Slope3
       
        CurR1 += RSlope2
        CurR2 += RSlope3
        CurG1 += GSlope2
        CurG2 += GSlope3
        CurB1 += BSlope2
        CurB2 += BSlope3
       
    Next
   
End Sub
       
Sub Calc_Gouraud_Shader(obj_ as objectT,L_ as LightT)
   
    Dim as single Dot1,Dot2,Dot3,NL
   
    Dim as objectT obj = obj_
    Dim as LightT L = L_
   
   
    '' normalizing Light vector
    NL = 1/Norm(L.pos3d)
   
    L.pos3d.x *= NL
    L.pos3d.y *= NL
    L.pos3d.z *= NL
   
    '' dot products
   
    For k as integer = 1 to obj.nb_triangles
       
        Dot1 = (obj.triangle(k).Vertex(0).Gouraud_Normal.x * L.pos3d.x) + _
               (obj.triangle(k).Vertex(0).Gouraud_Normal.y * L.pos3d.y) + _
               (obj.triangle(k).Vertex(0).Gouraud_Normal.z * L.pos3d.z)
        if Dot1<0 then Dot1 = 0
        if Dot1>1 then Dot1 = 1
       
        Dot2 = (obj.triangle(k).Vertex(1).Gouraud_Normal.x * L.pos3d.x) + _
               (obj.triangle(k).Vertex(1).Gouraud_Normal.y * L.pos3d.y) + _
               (obj.triangle(k).Vertex(1).Gouraud_Normal.z * L.pos3d.z)
        if Dot2<0 then Dot2 = 0
        if Dot2>1 then Dot2 = 1
       
        Dot3 = (obj.triangle(k).Vertex(2).Gouraud_Normal.x * L.pos3d.x) + _
               (obj.triangle(k).Vertex(2).Gouraud_Normal.y * L.pos3d.y) + _
               (obj.triangle(k).Vertex(2).Gouraud_Normal.z * L.pos3d.z)
        if Dot3<0 then Dot3 = 0
        if Dot3>1 then Dot3 = 1
       
        '' apply new color
        obj_.triangle(k).Vertex(0).Color.r = obj_.triangle(k).Vertex(0).OriginalColor.r*L.Intensity*Dot1
        obj_.triangle(k).Vertex(0).Color.g = obj_.triangle(k).Vertex(0).OriginalColor.g*L.Intensity*Dot1
        obj_.triangle(k).Vertex(0).Color.b = obj_.triangle(k).Vertex(0).OriginalColor.b*L.Intensity*Dot1
       
        obj_.triangle(k).Vertex(1).Color.r = obj_.triangle(k).Vertex(1).OriginalColor.r*L.Intensity*Dot2
        obj_.triangle(k).Vertex(1).Color.g = obj_.triangle(k).Vertex(1).OriginalColor.g*L.Intensity*Dot2
        obj_.triangle(k).Vertex(1).Color.b = obj_.triangle(k).Vertex(1).OriginalColor.b*L.Intensity*Dot2
       
        obj_.triangle(k).Vertex(2).Color.r = obj_.triangle(k).Vertex(2).OriginalColor.r*L.Intensity*Dot3
        obj_.triangle(k).Vertex(2).Color.g = obj_.triangle(k).Vertex(2).OriginalColor.g*L.Intensity*Dot3
        obj_.triangle(k).Vertex(2).Color.b = obj_.triangle(k).Vertex(2).OriginalColor.b*L.Intensity*Dot3
    next
   
   
   
End sub


'' texturing
Sub TLine(ByVal x1 as integer,ByVal x2 as integer, y as integer,ByVal U1 as single,ByVal V1 as single,ByVal U2 as single,ByVal V2 as single,ByVal z1 as integer,ByVal z2 as integer,byval Texture as TextureT)
   
    dim as single dU,dV,dZ,U,V



    dim as single Uu1,Vv1,Uu2,Vv2
   
    dim as integer itx1,itx2,zz1,zz2
    Dim as single CurZ,xDiv
   
    if x1<x2 then
        zz1 = z1
        zz2 = z2
       
        itx1 = x1
        itx2 = x2
       
        Uu1 = u1
        Uu2 = u2
        Vv1 = v1
        Vv2 = v2
    else
        zz1 = z2
        zz2 = z1
       
        itx1 = x2
        itx2 = x1
       
        Uu1 = u2
        Uu2 = u1
        Vv1 = v2
        Vv2 = v1
    end if
   
    Uu1 *= Texture.Size.x
    Uu2 *= Texture.Size.x
    Vv1 *= Texture.Size.y
    Vv2 *= Texture.Size.y
   
    xDiv = 1/(itx2 - itx1)
   
    dZ = xDiv * (zz2 - zz1)
   
    dU = xDiv * (Uu2 - Uu1)
    dV = xDiv * (Vv2 - Vv1)
   
    CurZ = zz1
   
    U = Uu1
    V = Vv1
   
    dim as integer it
   
    for i as integer = itx1 to itx2-1

        if y>0 and y<yRes and i>0 and i<xRes then
           
            it = y*xRes + i
           
            If (FOV - (-Camera.pos.z + CurZ))>0 then
               
                If Curz > ZBuffer(it) then
                   
                    ZBuffer(it) = CurZ
                   
                    ScrPtr[it] = Texture.GFX[int(U)+Texture.Size.x*int(V)]
                                       
                End if
           
            end if
       
        end if
       
        U += dU
        V += dV
       
        curZ += dZ
       
    Next
   
End Sub



Sub Texture_Map(ByVal Triangle as TriangleT, _
                ByVal Texture as TextureT)      '' UV's saved in the Triangle.Vertex Type
   
   
    '' Sorting Y values
    if Triangle.Vertex(1).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(1),Triangle.Vertex(0)
    end if
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(0)
    end if
   
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(1).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(1)
    end if
   
    dim as integer dx1,dy1,dx2,dy2,dx3,dy3
    dim as single Slope1,Slope2,Slope3, dYDiv
   
    dim as single dU1,dU2,dU3,dV1,dV2,dV3
    dim as single USlope1,USlope2,USlope3
    dim as single VSlope1,VSlope2,VSlope3
   
    Dim as integer dz1,dz2,dz3
    Dim as single zSlope1,zSlope2,zSlope3
   
    '' interpolate 0 to 1 (pos + color)
   
    dZ1 = Triangle.Vertex(1).pos3d.z - Triangle.Vertex(0).pos3d.z
   
    dX1 = Triangle.Vertex(1).pos2d.x - Triangle.Vertex(0).pos2d.x
    dY1 = Triangle.Vertex(1).pos2d.y - Triangle.Vertex(0).pos2d.y
   
    dU1 = Triangle.Vertex(1).U - Triangle.Vertex(0).U
    dV1 = Triangle.Vertex(1).V - Triangle.Vertex(0).V
   
    if dY1 <> 0 then
       
        dYDiv = 1/dY1
       
        zSlope1 = dZ1 * dYDiv
       
        Slope1 = dX1 * dYDiv
       
        USlope1 = dU1 * dYDiv
        VSlope1 = dV1 * dYDiv
       
    else
       
        zSlope1 = 0
       
        Slope1 = 0
       
        USlope1 = 0
        VSlope1 = 0
       
    End if
   
   
    '' interpolate 1 to 2
   
    dZ2 = Triangle.Vertex(2).pos3d.z - Triangle.Vertex(1).pos3d.z
   
    dX2 = Triangle.Vertex(2).pos2d.x - Triangle.Vertex(1).pos2d.x
    dY2 = Triangle.Vertex(2).pos2d.y - Triangle.Vertex(1).pos2d.y
   
    dU2 = Triangle.Vertex(2).U - Triangle.Vertex(1).U
    dV2 = Triangle.Vertex(2).V - Triangle.Vertex(1).V
   
    if dY2 <> 0 then
       
        dYDiv = 1/dY2
       
        zSlope2 = dZ2 * dYDiv
       
        Slope2 = dX2 * dYDiv
       
        USlope2 = dU2 * dYDiv
        VSlope2 = dV2 * dYDiv
       
    else
       
        zSlope2 = 0
       
        Slope2 = 0
       
        USlope2 = 0
        VSlope2 = 0
       
    End if
   
   
    '' interpolate 0 to 2
   
    dZ3 = Triangle.Vertex(0).pos3d.z - Triangle.Vertex(2).pos3d.z
   
    dX3 = Triangle.Vertex(0).pos2d.x - Triangle.Vertex(2).pos2d.x
    dY3 = Triangle.Vertex(0).pos2d.y - Triangle.Vertex(2).pos2d.y
   
    dU3 = Triangle.Vertex(0).U - Triangle.Vertex(2).U
    dV3 = Triangle.Vertex(0).V - Triangle.Vertex(2).V
   
    if dY3 <> 0 then
       
        dYDiv = 1/dY3
       
        zSlope3 = dZ3 * dYDiv
       
        Slope3 = dX3 * dYDiv
       
        USlope3 = dU3 * dYDiv
        VSlope3 = dV3 * dYDiv
       
    else
       
        zSlope3 = 0
       
        Slope3 = 0
       
        USlope3 = 0
        VSlope3 = 0
       
    End if
   
   
    '' Drawing
   
    '' Top
    dim as single CurX1=Triangle.Vertex(0).pos2d.x, CurX2=Triangle.Vertex(0).pos2d.x
    dim as single CurU1=Triangle.Vertex(0).U, CurU2=Triangle.Vertex(0).U,_
                  CurV1=Triangle.Vertex(0).V, CurV2=Triangle.Vertex(0).V
   
    dim as single CurZ1=Triangle.Vertex(0).pos3d.z, CurZ2=Triangle.Vertex(0).pos3d.z
   
    CurZ1 += Triangle.Parent_Center.z
    CurZ2 += Triangle.Parent_Center.z
   
    'BufferIter = Triangle.Vertex(0).pos2d.y * xRes
   
    For y as integer = Triangle.Vertex(0).pos2d.y to Triangle.Vertex(1).pos2d.y-1
       
        TLine(CurX1,CurX2,y,CurU1,CurV1,CurU2,CurV2, CurZ1, CurZ2, Texture)
       
        CurZ1 += zSlope1
        CurZ2 += zSlope3
       
        CurU1 += USlope1
        CurU2 += USlope3
        CurV1 += VSlope1
        CurV2 += VSlope3
       
        CurX1 += Slope1
        CurX2 += Slope3
       
        'BufferIter += xRes
       
    Next
   
    '' down
   
    CurZ1 = Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z
   
    CurU1 = Triangle.Vertex(1).U
    CurV1 = Triangle.Vertex(1).V
   
    CurX1 = Triangle.Vertex(1).pos2d.x
   
    For y as integer = Triangle.Vertex(1).pos2d.y to Triangle.Vertex(2).pos2d.y-1
       
        TLine(CurX1,CurX2,y,CurU1,CurV1,CurU2,CurV2, CurZ1, CurZ2, Texture)
       
        CurZ1 += zSlope2
        CurZ2 += zSlope3
       
        CurX1 += Slope2
        CurX2 += Slope3
       
        CurU1 += USlope2
        CurU2 += USlope3
        CurV1 += VSlope2
        CurV2 += VSlope3
       
    Next
   
End Sub



Sub Rotate(obj as objectT,Tx as single, Ty as single, Tz as single)
   
    dim as single tmpX,tmpY,TmpZ,normX,normY,normZ
    dim as single VnormX,VnormY,VnormZ
   
    For i as integer = 1 to obj.NB_triangles
        For j as integer = 0 to 2
           
            '' Points
            TmpY = obj.Triangle(i).Vertex(j).pos3d.y * cos(Tx) - obj.Triangle(i).Vertex(j).pos3d.z * sin(Tx)
            TmpZ = obj.Triangle(i).Vertex(j).pos3d.z * cos(Tx) + obj.Triangle(i).Vertex(j).pos3d.y * sin(Tx)
            obj.Triangle(i).Vertex(j).pos3d.y = TmpY
            obj.Triangle(i).Vertex(j).pos3d.z = TmpZ
           
            TmpZ = obj.Triangle(i).Vertex(j).pos3d.z * cos(Ty) - obj.Triangle(i).Vertex(j).pos3d.x * sin(Ty)
            TmpX = obj.Triangle(i).Vertex(j).pos3d.x * cos(Ty) + obj.Triangle(i).Vertex(j).pos3d.z * sin(Ty)
            obj.Triangle(i).Vertex(j).pos3d.x = TmpX
           
            TmpX = obj.Triangle(i).Vertex(j).pos3d.x * cos(Tz) - obj.Triangle(i).Vertex(j).pos3d.y * sin(Tz)
            TmpY = obj.Triangle(i).Vertex(j).pos3d.y * cos(Tz) + obj.Triangle(i).Vertex(j).pos3d.x * sin(Tz)
           
            obj.Triangle(i).Vertex(j).pos3d.x = TmpX
            obj.Triangle(i).Vertex(j).pos3d.y = TmpY
            obj.Triangle(i).Vertex(j).pos3d.z = TmpZ
                   
       
            '' Vertex normals
            VnormY = obj.Triangle(i).Vertex(j).Gouraud_Normal.y * cos(Tx) - obj.Triangle(i).Vertex(j).Gouraud_Normal.z * sin(Tx)
            VnormZ = obj.Triangle(i).Vertex(j).Gouraud_Normal.z * cos(Tx) + obj.Triangle(i).Vertex(j).Gouraud_Normal.y * sin(Tx)
            obj.Triangle(i).Vertex(j).Gouraud_Normal.y = VnormY
            obj.Triangle(i).Vertex(j).Gouraud_Normal.z = VnormZ
           
            VnormZ = obj.Triangle(i).Vertex(j).Gouraud_Normal.z * cos(Ty) - obj.Triangle(i).Vertex(j).Gouraud_Normal.x * sin(Ty)
            VnormX = obj.Triangle(i).Vertex(j).Gouraud_Normal.x * cos(Ty) + obj.Triangle(i).Vertex(j).Gouraud_Normal.z * sin(Ty)
            obj.Triangle(i).Vertex(j).Gouraud_Normal.x = VnormX

            VnormX = obj.Triangle(i).Vertex(j).Gouraud_Normal.x * cos(Tz) - obj.Triangle(i).Vertex(j).Gouraud_Normal.y * sin(Tz)

            VnormY = obj.Triangle(i).Vertex(j).Gouraud_Normal.y * cos(Tz) + obj.Triangle(i).Vertex(j).Gouraud_Normal.x * sin(Tz)
           
            obj.Triangle(i).Vertex(j).Gouraud_Normal.x = VnormX
            obj.Triangle(i).Vertex(j).Gouraud_Normal.y = VnormY
            obj.Triangle(i).Vertex(j).Gouraud_Normal.z = VnormZ
        Next
       
        '' normals
        NormY = obj.Triangle(i).Normal.y * cos(Tx) - obj.Triangle(i).Normal.z * sin(Tx)
        NormZ = obj.Triangle(i).Normal.z * cos(Tx) + obj.Triangle(i).Normal.y * sin(Tx)
        obj.Triangle(i).Normal.y = NormY
        obj.Triangle(i).Normal.z = NormZ
       
        NormZ = obj.Triangle(i).Normal.z * cos(Ty) - obj.Triangle(i).Normal.x * sin(Ty)
        NormX = obj.Triangle(i).Normal.x * cos(Ty) + obj.Triangle(i).Normal.z * sin(Ty)
        obj.Triangle(i).Normal.x = NormX
       
        NormX = obj.Triangle(i).Normal.x * cos(Tz) - obj.Triangle(i).Normal.y * sin(Tz)
        NormY = obj.Triangle(i).Normal.y * cos(Tz) + obj.Triangle(i).Normal.x * sin(Tz)
           
        obj.Triangle(i).Normal.x = NormX
        obj.Triangle(i).Normal.y = NormY
        obj.Triangle(i).Normal.z = NormZ
       
    Next
   
End sub

Function FPS() as integer
   
    dim as integer _curfps
   
    If Timer - FPS_t <= 1 then
       
        FPS_counter += 1
       
        Return -1
       
    else
       
        _CurFPS = FPS_Counter/(Timer - FPS_t)
       
        FPS_counter = 0
        FPS_t = Timer
       
        Return _CurFPS
       
    End if
End Function
       
       
       
#Define Cls_zBuffer For klm as integer =0 to SCREEN_MEM-1 : Zbuffer(klm) = -MAX_Z : next



















'' Test

'' Loading objects

Dim as ObjectT Pyramid, Face

Pyramid.nb_triangles = 4
Pyramid.Center.z = 0
Pyramid.Center.y = 0
Pyramid.Center.x = -100

Face.Nb_triangles = 2
Face.Center.x = 100

For i as integer = 1 to Pyramid.nb_triangles
    for j as integer = 0 to 2
       
        Read Pyramid.triangle(i).Vertex(j).pos3d.x, Pyramid.triangle(i).Vertex(j).pos3d.y, Pyramid.triangle(i).Vertex(j).pos3d.z
        Read Pyramid.triangle(i).Vertex(j).OriginalColor.r, Pyramid.triangle(i).Vertex(j).OriginalColor.g, Pyramid.triangle(i).Vertex(j).OriginalColor.b
        Read Pyramid.triangle(i).Vertex(j).U, Pyramid.triangle(i).Vertex(j).V
       
        Pyramid.triangle(i).Vertex(j).pos3d.x *= 4
        Pyramid.triangle(i).Vertex(j).pos3d.y *= 4
        Pyramid.triangle(i).Vertex(j).pos3d.z *= 4
       
    next
next

For i as integer = 1 to Face.nb_triangles
    for j as integer = 0 to 2
       
        Read Face.triangle(i).Vertex(j).pos3d.x, Face.triangle(i).Vertex(j).pos3d.y, Face.triangle(i).Vertex(j).pos3d.z
        Read Face.triangle(i).Vertex(j).OriginalColor.r, Face.triangle(i).Vertex(j).OriginalColor.g, Face.triangle(i).Vertex(j).OriginalColor.b
        Read Face.triangle(i).Vertex(j).U, Face.triangle(i).Vertex(j).V
       
        Face.triangle(i).Vertex(j).pos3d.x *= 4
        Face.triangle(i).Vertex(j).pos3d.y *= 4
        Face.triangle(i).Vertex(j).pos3d.z *= 4
       
    next
next

'' Setting Light and stuff, Precalculating normals

dim as single t=.02

Dim as LightT Light

Light = SetLight(1,0,0,1)

PreCalc_object_normals Pyramid

Set_Camera 0,0,0



'' Texture loading for texture mapping
Dim as TextureT PlasmaTexture

Set_Texture_Size PlasmaTexture,50,50

dim as integer colorexp

For i as integer = 0 to 49
    For j as integer = 0 to 49
       
        colorexp = 125+125*sin((sqr(((25-i)/2)^2+((25-j)/3)^2))*cos(i/20+j/20))
       
        PlasmaTexture.GFX[i+j*PlasmaTexture.Size.x] = rgb(colorexp,colorexp,colorexp)

    Next
Next


Do
   
    Screenlock : cls
   
    Paint(0,0),BGND_COLOR
   
    CLS_zBuffer
   
    Project_object Pyramid
    Project_object Face
   
    Calc_Gouraud_Shader Pyramid, Light
    'Calc_Gouraud_Shader Pyramid2, Light
   
    For i as integer = 1 to Pyramid.nb_triangles
       
        'if Pyramid.triangle(i).Normal.Z>0 then
            Gouraud_Fill Pyramid.triangle(i)
        'end if
       
        'if Pyramid2.triangle(i).Normal.Z>0 then
            Texture_Map Face.triangle(i),PlasmaTexture
        'end if
       
    Next
   
    Rotate(Pyramid,t/2,t,0)
    Rotate(Face,0,-t,0)
   
    '' DEBUG : Show Texture
    For i as integer = 0 to 49
        For j as integer = 0 to 49
           
            ScrPtr[i+j*xRes] = PlasmaTexture.GFX[i+j*PlasmaTexture.Size.x]
   
        Next
    Next
   
    '' DEBGU : Show FPS
    CurFPS = FPS
    If CurFPS <> -1 and CurFPS <>0 then
        WindowTitle "["+str(CurFPS)+" FPS] 3D stuff"
    elseIf CurFPS = 0 then
        WindowTitle "3D Stuff"
    End if
   
    screenunlock : sleep 1,1
   
loop until multikey(&h01)


'' PYRAMID
'' triangle 1
Data 0,30,0,250,50,50,0,0
Data 20,0,-20,250,50,50,1,1
Data -20,0,-20,250,50,50,0,1

'' triangle 2
Data 0,30,0,250,50,250,0,0
Data 0,0,20,250,50,250,1,1
Data 20,0,-20,250,50,250,0,1

'' triangle 3
Data 0,30,0,50,50,250,0,0
Data -20,0,-20,50,50,250,1,1
Data 0,0,20,50,50,250,0,1

'' triangle 4
Data 20,0,-20,50,250,50,0,0
Data 0,0,20,50,250,50,1,1
Data -20,0,-20,50,250,50,0,1


'' Face
'' triangle 1
Data -20,20,0,250,250,250,0,0
Data 20,20,0,250,250,250,1,0
Data -20,-20,0,250,250,250,0,1

'' triangle 2
Data 20,20,0,250,250,250,1,0
Data 20,-20,0,250,250,250,1,1
Data -20,-20,0,250,250,250,0,1


Download : <exe + src>
1000101
Posts: 2556
Joined: Jun 13, 2005 23:14
Location: SK, Canada

Postby 1000101 » Aug 23, 2008 17:55

Your calculations seem to be off or you are using a very wide field of view. The tetrahedron seems a little distorted.
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Postby Hezad » Aug 23, 2008 21:23

Yep, right ! In fact, as I said, I played around with the light equation but I also played around with camera handling. And I did the opposite of ameliorating the code :p

But I'm working on it :) This "release" was just to show the texture mapping part.
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Postby Hezad » Aug 24, 2008 13:29

Little Update :)

Well, I decided to test my stuff on cubes instead of pyramids, it's way more easy to see if something's wrong in the lighting/shading/texture mapping !

I think light and projection are now better but there are glitches on the right cube (non textured to test the shading). I guess it's a problem with inversed normals on some triangles but I tried to rearrange those triangles points without any amelioration :S I'm on it.

Image

Download : Rar (Src+Exe+Texture)

Any idea about the glitch ?


edit : Glitch fixed, cube normally rendered :D
Image
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Postby Hezad » Aug 25, 2008 12:56

Update !

Now Texture mapped objects support Gouraud shading :D

Image



Download : Rar (Src + Texture + Exe)


Code :

Code: Select all



''  =======================---. 3D Stuff .---=======================
''
''      Gouraud Shading + Z-Buffer rendering
''
''                      Code : Hezad  [   Hezad0 )at( Gmail.com    ]
''
''
''  Thanks to Relsoft for his awesome tutorial :
''                 [  http://www.phatcode.net/articles.php?id=214  ]
''
''
''  ================================================================


#Define Norm(a) sqr(a.x*a.x + a.y*a.y + a.z*a.z)

Const MAX_TRIANGLES_PER_OBJECT = 500
Const MAX_OBJECTS = 10
Const xRes = 640, yRes = 480

Const SCREEN_MEM = xRes * yRes

Const BGND_COLOR = rgb(50,50,70)

Const FOV = 512, ZOOM = 512

Const MAX_Z = 1000

Const PI = 3.1415926535897932384626
Const PIx2 = 2*PI

Const ToRad = PIx2/360
Const ToDeg = 360/PIx2



Dim shared as integer ptr ScrPtr
ReDim shared as integer ZBuffer(SCREEN_MEM)

Screenres xRes,yRes,32,2

ScrPtr = Screenptr

Dim shared as single FPS_t,CurFPS,FPS_counter

Type Vector
    as single x,y,z
End Type

Type ColorT
    as integer r,g,b
End Type

Type TextureT
   
    as vector Size

    as integer ptr GFX
   
End Type

Sub Set_Texture_Size(Text as TextureT, x as integer, y as integer)
   
    If Text.GFX <> 0 then deallocate Text.GFX
   
    Text.Size.x = x
    Text.Size.y = y-1
   
    Text.GFX = Callocate(x*y,sizeof(integer))
   
End Sub

Type VertexT
   
    as Vector Pos3d
   
    as Vector Gouraud_Normal
   
    as Vector Pos2d
   
    as ColorT Color
   
    as ColorT OriginalColor
   
    as single U,V
   
End Type

Type TriangleT
   
    as Vector Normal
   
    as integer idZ
   
    as VertexT Vertex(2)
   
    as Vector Parent_Center
   
End Type

Type ObjectT
   
    as TriangleT Triangle(MAX_TRIANGLES_PER_OBJECT)
   
    as Vector Center
   
    as integer nb_triangles
   
End Type

Type LightT
   
    Pos3d as Vector
   
    Intensity as single
   
End Type

Type CameraT
   
    Pos as Vector
   
    Angle as Vector
   
End Type


Dim shared as CameraT Camera

Sub Set_Camera(x as integer, y as integer, z as integer)
   
    Camera.Pos.x = x
    Camera.Pos.y = y
    Camera.Pos.z = z
   
End Sub

Sub Sort_Object_Z(obj as ObjectT)
   
    For i as integer = 1 to obj.nb_Triangles
       
        obj.triangle(i).IdZ = i
        if i>1 then
            if obj.triangle(i).vertex(0).pos3d.z + obj.triangle(i).vertex(1).pos3d.z + obj.triangle(i).vertex(2).pos3d.z < obj.triangle(i-1).vertex(0).pos3d.z + obj.triangle(i-1).vertex(1).pos3d.z + obj.triangle(i-1).vertex(2).pos3d.z then

                Swap obj.triangle(i), obj.triangle(i-1)
                i=1
               
            end if
        end if
       
    Next
   
End Sub

Sub Calc_Triangle_Normal(Tri as TriangleT)
   
    dim as single ax,bx,ay,by,az,bz,NNorm
   
    ax = Tri.Vertex(1).pos3d.x - Tri.Vertex(0).pos3d.x
    bx = Tri.Vertex(2).pos3d.x - Tri.Vertex(1).pos3d.x
    ay = Tri.Vertex(1).pos3d.y - Tri.Vertex(0).pos3d.y
    by = Tri.Vertex(2).pos3d.y - Tri.Vertex(1).pos3d.y
    az = Tri.Vertex(1).pos3d.z - Tri.Vertex(0).pos3d.z
    bz = Tri.Vertex(2).pos3d.z - Tri.Vertex(1).pos3d.z
   
    Tri.Normal.x = ay * bz - az * by
    Tri.Normal.y = az * bx - ax * bz
    Tri.Normal.z = ax * by - ay * bx
   
    '' Normalize
    NNorm = 1/Norm(Tri.Normal)
   
    Tri.Normal.x *= NNorm
    Tri.Normal.y *= NNorm
    Tri.Normal.z *= NNorm
   
End Sub

#Define SamePnt(a,b) iif ((a.pos3d.x = b.pos3d.x) and (a.pos3d.y = b.pos3d.y) and (a.pos3d.z = b.pos3d.z),1,0)

Sub PreCalc_Object_Normals(obj as ObjectT)
   
    dim as single tmpXNorm,TmpYNorm,TmpZNorm
   
    For k as integer = 1 to obj.nb_triangles
        '' face normal
        Calc_Triangle_Normal(obj.Triangle(k))
   
    Next
   
    for k as integer = 1 to obj.nb_triangles
       
        '' "Vertex normals"
        for i as integer = 0 to 2
            TmpXNorm = 0
            TmpYNorm = 0
            TmpZNorm = 0
           
            for j as integer = 1 to obj.nb_triangles
                if SamePnt(obj.triangle(k).Vertex(i),obj.triangle(j).Vertex(0)) or _
                    SamePnt(obj.triangle(k).Vertex(i),obj.triangle(j).Vertex(1)) or _
                    SamePnt(obj.triangle(k).Vertex(i),obj.triangle(j).Vertex(2)) then
                   
                    TmpXNorm += obj.triangle(j).Normal.x
                    TmpYNorm += obj.triangle(j).Normal.y
                    TmpZNorm += obj.triangle(j).Normal.z
                   
                end if
            next
               
            dim as single _Normm = 1/sqr(TmpXNorm*TmpXNorm+TmpYNorm*TmpYNorm+TmpZNorm*TmpZNorm)
           
            TmpXNorm *= _Normm
            TmpYNorm *= _Normm
            TmpZNorm *= _Normm
           
            obj.triangle(k).Vertex(i).Gouraud_Normal.x = TmpXNorm
            obj.triangle(k).Vertex(i).Gouraud_Normal.y = TmpyNorm
            obj.triangle(k).Vertex(i).Gouraud_Normal.z = TmpzNorm
           
        next
       
    next
   
End Sub

Function SetLight(x as single,y as single, z as single,intens as single) as LightT
   
    Dim as LightT Tmp
   
    Tmp.pos3d.x = x
    Tmp.pos3d.y = y
    Tmp.pos3d.z = z
   
    Tmp.Intensity = intens
   
    Return Tmp
   
End Function

Declare Sub Rotate(obj as objectT,Tx as single, Ty as single, Tz as single)


'' Projection ============================

Sub Project_Object(Obj as ObjectT)
   
    dim as single aX,aY,aZ
   
    if obj.nb_triangles = 0 then exit Sub
   
    For i as integer = 1 to obj.nb_triangles
       
        obj.Triangle(i).Parent_Center = obj.Center
       
        For j as integer = 0 to 2
           
            if obj.Triangle(i).Vertex(j).pos3d.z = Camera.pos.z - obj.Center.z + FOV then obj.Triangle(i).Vertex(j).pos3d.z+=.0001
           
            obj.Triangle(i).Vertex(j).pos2d.x = xRes/2 + (FOV * (-Camera.pos.x + obj.Center.x + obj.Triangle(i).Vertex(j).pos3d.x)) / (ZOOM - (Camera.pos.z + obj.Center.z + obj.Triangle(i).Vertex(j).pos3d.z))
            obj.Triangle(i).Vertex(j).pos2d.y = yRes/2 - (FOV * (-Camera.pos.y + obj.Center.y + obj.Triangle(i).Vertex(j).pos3d.y)) / (ZOOM - (Camera.pos.z + obj.Center.z + obj.Triangle(i).Vertex(j).pos3d.z))
           
        Next
       
    Next
   
End Sub

'' ========================================

Sub GLine(ByVal x1 as integer,ByVal x2 as integer, y as integer,ByVal r1 as integer,ByVal g1 as integer,ByVal b1 as integer,ByVal r2 as integer,ByVal g2 as integer,ByVal b2 as integer,ByVal z1 as integer,ByVal z2 as integer)
   
    dim as single dR,dG,dB, dZ
    dim as single R,g,b
   
    dim as integer itx1,itx2,zz1,zz2
    Dim as single CurZ,xDiv
    dim as single sr1,sr2,sg1,sg2,sb1,sb2
   
    if x1<x2 then
        zz1 = z1
        zz2 = z2
       
        itx1 = x1
        itx2 = x2
        sr1 = r1
        sr2 = r2
        sg1 = g1
        sg2 = g2
        sb1 = b1
        sb2 = b2
    else
        zz1 = z2
        zz2 = z1
       
        itx1 = x2
        itx2 = x1
        sr1 = r2
        sr2 = r1
        sg1 = g2
        sg2 = g1
        sb1 = b2
        sb2 = b1
    end if
   
    xDiv = 1/(itx2 - itx1)
   
    dR = xDiv * (sr2 - sr1)
    dG = xDiv * (sg2 - sg1)
    dB = xDiv * (sb2 - sb1)
   
    dZ = xDiv * (zz2 - zz1)
   
    r = sr1
    g = sg1
    b = sb1
   
    CurZ = zz1
   
    dim as integer it
   
    for i as integer = itx1 to itx2-1

        if y>0 and y<yRes and i>0 and i<xRes then
           
            it = y*xRes + i
           
            If (FOV - (-Camera.pos.z + CurZ))>0 then
               
                If Curz > ZBuffer(it) then
                   
                    ZBuffer(it) = CurZ
                   
                    ScrPtr[it] = rgb(r,g,b)
                   
                    '' UnComment to show the ZBuffer Gfx :D
                    'dim as integer zBufferCol = 255*cast(single,(abs(ZBuffer(it))/MAX_Z))
                    'ScrPtr[it] = rgb(zBufferCol,zBufferCol,zBufferCol)
                   
                End if
           
            end if
       
        end if
       
        curZ += dZ
       
        r += dR
        g += dG
        b += dB
       
    Next
   
End Sub

Sub Gouraud_Fill(ByVal Triangle as TriangleT)
   
   
    '' Sorting Y values
    if Triangle.Vertex(1).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(1),Triangle.Vertex(0)
    end if
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(0)
    end if
   
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(1).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(1)
    end if
   
    dim as integer dx1,dy1,dx2,dy2,dx3,dy3
    dim as integer dr1,dg1,db1,dr2,dg2,db2,dr3,dg3,db3
    dim as single Slope1,Slope2,Slope3, dYDiv
    dim as single RSlope1, GSlope1,BSlope1
    dim as single RSlope2, GSlope2,BSlope2
    dim as single RSlope3, GSlope3,BSlope3
   
    Dim as integer dz1,dz2,dz3
    Dim as single zSlope1,zSlope2,zSlope3
   
    '' interpolate 0 to 1 (pos + color)
   
    dZ1 = Triangle.Vertex(1).pos3d.z - Triangle.Vertex(0).pos3d.z
   
    dX1 = Triangle.Vertex(1).pos2d.x - Triangle.Vertex(0).pos2d.x
    dY1 = Triangle.Vertex(1).pos2d.y - Triangle.Vertex(0).pos2d.y
   
    dr1 = Triangle.Vertex(1).color.r - Triangle.Vertex(0).color.r
    dg1 = Triangle.Vertex(1).color.g - Triangle.Vertex(0).color.g
    db1 = Triangle.Vertex(1).color.b - Triangle.Vertex(0).color.b
   
    if dY1 <> 0 then
       
        dYDiv = 1/dY1
       
        zSlope1 = dZ1 * dYDiv
       
        Slope1 = dX1 * dYDiv
       
        RSlope1 = dR1 * dYDiv
        GSlope1 = dG1 * dYDiv
        BSlope1 = dB1 * dYDiv
       
    else
       
        zSlope1 = 0
       
        Slope1 = 0
       
        RSlope1 = 0
        GSlope1 = 0
        BSlope1 = 0
       
    End if
   
   
    '' interpolate 1 to 2
   
    dZ2 = Triangle.Vertex(2).pos3d.z - Triangle.Vertex(1).pos3d.z
   
    dX2 = Triangle.Vertex(2).pos2d.x - Triangle.Vertex(1).pos2d.x
    dY2 = Triangle.Vertex(2).pos2d.y - Triangle.Vertex(1).pos2d.y
   
    dr2 = Triangle.Vertex(2).color.r - Triangle.Vertex(1).color.r
    dg2 = Triangle.Vertex(2).color.g - Triangle.Vertex(1).color.g
    db2 = Triangle.Vertex(2).color.b - Triangle.Vertex(1).color.b
   
    if dY2 <> 0 then
       
        dYDiv = 1/dY2
       
        zSlope2 = dZ2 * dYDiv
       
        Slope2 = dX2 * dYDiv
       
        RSlope2 = dR2 * dYDiv
        GSlope2 = dG2 * dYDiv
        BSlope2 = dB2 * dYDiv
       
    else
       
        zSlope2 = 0
       
        Slope2 = 0
       
        RSlope2 = 0
        GSlope2 = 0
        BSlope2 = 0
       
    End if
   
   
    '' interpolate 0 to 2
   
    dZ3 = Triangle.Vertex(0).pos3d.z - Triangle.Vertex(2).pos3d.z
   
    dX3 = Triangle.Vertex(0).pos2d.x - Triangle.Vertex(2).pos2d.x
    dY3 = Triangle.Vertex(0).pos2d.y - Triangle.Vertex(2).pos2d.y
   
    dr3 = Triangle.Vertex(0).color.r - Triangle.Vertex(2).color.r
    dg3 = Triangle.Vertex(0).color.g - Triangle.Vertex(2).color.g
    db3 = Triangle.Vertex(0).color.b - Triangle.Vertex(2).color.b
   
    if dY3 <> 0 then
       
        dYDiv = 1/dY3
       
        zSlope3 = dZ3 * dYDiv
       
        Slope3 = dX3 * dYDiv
       
        RSlope3 = dR3 * dYDiv
        GSlope3 = dG3 * dYDiv
        BSlope3 = dB3 * dYDiv
       
    else
       
        zSlope3 = 0
       
        Slope3 = 0
       
        RSlope3 = 0
        GSlope3 = 0
        BSlope3 = 0
       
    End if
   
   
    '' Drawing
   
    '' Top
    dim as single CurX1=Triangle.Vertex(0).pos2d.x, CurX2=Triangle.Vertex(0).pos2d.x
    dim as single CurR1=Triangle.Vertex(0).Color.r,_
                   CurG1=Triangle.Vertex(0).Color.g,_
                   CurB1=Triangle.Vertex(0).Color.b,_
                   CurR2=Triangle.Vertex(0).Color.r,_
                   CurG2=Triangle.Vertex(0).Color.g,_
                   CurB2=Triangle.Vertex(0).Color.b
   
    dim as single CurZ1=Triangle.Vertex(0).pos3d.z, CurZ2=Triangle.Vertex(0).pos3d.z
   
    CurZ1 += Triangle.Parent_Center.z
    CurZ2 += Triangle.Parent_Center.z
   
    'BufferIter = Triangle.Vertex(0).pos2d.y * xRes
   
    For y as integer = Triangle.Vertex(0).pos2d.y to Triangle.Vertex(1).pos2d.y-1
       
        GLine(CurX1,CurX2,y,CurR1,CurG1,CurB1,CurR2,CurG2,CurB2, CurZ1, CurZ2)
       
        CurZ1 += zSlope1
        CurZ2 += zSlope3
       
        CurX1 += Slope1
        CurX2 += Slope3
       
        CurR1 += RSlope1
        CurR2 += RSlope3
        CurG1 += GSlope1
        CurG2 += GSlope3
        CurB1 += BSlope1
        CurB2 += BSlope3
       
        'BufferIter += xRes
       
    Next
   
    '' down
   
    CurZ1 = Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z
   
    CurX1 = Triangle.Vertex(1).pos2d.x
    CurR1 = Triangle.Vertex(1).color.r
    Curg1 = Triangle.Vertex(1).color.g
    Curb1 = Triangle.Vertex(1).color.b
   
    For y as integer = Triangle.Vertex(1).pos2d.y to Triangle.Vertex(2).pos2d.y-1
       
        GLine(CurX1,CurX2,y,CurR1,CurG1,CurB1,CurR2,CurG2,CurB2, CurZ1, CurZ2)
       
        CurZ1 += zSlope2
        CurZ2 += zSlope3
       
        CurX1 += Slope2
        CurX2 += Slope3
       
        CurR1 += RSlope2
        CurR2 += RSlope3
        CurG1 += GSlope2
        CurG2 += GSlope3
        CurB1 += BSlope2
        CurB2 += BSlope3
       
    Next
   
End Sub
       
Sub Calc_Gouraud_Shader(obj_ as objectT,L_ as LightT)
   
    Dim as single Dot1,Dot2,Dot3,NL
   
    Dim as objectT obj = obj_
    Dim as LightT L = L_
   
   
    '' normalizing Light vector
    NL = 1/Norm(L.pos3d)
   
    L.pos3d.x *= NL
    L.pos3d.y *= NL
    L.pos3d.z *= NL
   
    '' dot products
   
    For k as integer = 1 to obj.nb_triangles
       
        Dot1 = (obj.triangle(k).Vertex(0).Gouraud_Normal.x * L.pos3d.x) + _
               (obj.triangle(k).Vertex(0).Gouraud_Normal.y * L.pos3d.y) + _
               (obj.triangle(k).Vertex(0).Gouraud_Normal.z * L.pos3d.z)
        if Dot1<0 then Dot1 = 0
        if Dot1>1 then Dot1 = 1
       
        Dot2 = (obj.triangle(k).Vertex(1).Gouraud_Normal.x * L.pos3d.x) + _
               (obj.triangle(k).Vertex(1).Gouraud_Normal.y * L.pos3d.y) + _
               (obj.triangle(k).Vertex(1).Gouraud_Normal.z * L.pos3d.z)
        if Dot2<0 then Dot2 = 0
        if Dot2>1 then Dot2 = 1
       
        Dot3 = (obj.triangle(k).Vertex(2).Gouraud_Normal.x * L.pos3d.x) + _
               (obj.triangle(k).Vertex(2).Gouraud_Normal.y * L.pos3d.y) + _
               (obj.triangle(k).Vertex(2).Gouraud_Normal.z * L.pos3d.z)
        if Dot3<0 then Dot3 = 0
        if Dot3>1 then Dot3 = 1
       
        '' apply new color
        obj_.triangle(k).Vertex(0).Color.r = obj_.triangle(k).Vertex(0).OriginalColor.r*L.Intensity*Dot1
        obj_.triangle(k).Vertex(0).Color.g = obj_.triangle(k).Vertex(0).OriginalColor.g*L.Intensity*Dot1
        obj_.triangle(k).Vertex(0).Color.b = obj_.triangle(k).Vertex(0).OriginalColor.b*L.Intensity*Dot1
       
        obj_.triangle(k).Vertex(1).Color.r = obj_.triangle(k).Vertex(1).OriginalColor.r*L.Intensity*Dot2
        obj_.triangle(k).Vertex(1).Color.g = obj_.triangle(k).Vertex(1).OriginalColor.g*L.Intensity*Dot2
        obj_.triangle(k).Vertex(1).Color.b = obj_.triangle(k).Vertex(1).OriginalColor.b*L.Intensity*Dot2
       
        obj_.triangle(k).Vertex(2).Color.r = obj_.triangle(k).Vertex(2).OriginalColor.r*L.Intensity*Dot3
        obj_.triangle(k).Vertex(2).Color.g = obj_.triangle(k).Vertex(2).OriginalColor.g*L.Intensity*Dot3
        obj_.triangle(k).Vertex(2).Color.b = obj_.triangle(k).Vertex(2).OriginalColor.b*L.Intensity*Dot3
    next
   
   
   
End sub


'' texturing
Sub TLine(ByVal x1 as integer,ByVal x2 as integer, y as integer,ByVal U1 as single,ByVal V1 as single,ByVal U2 as single,ByVal V2 as single,ByVal z1 as integer,ByVal z2 as integer,byval Texture as TextureT)
   
    dim as single dU,dV,dZ,U,V
    dim as single Uu1,Vv1,Uu2,Vv2
   
    dim as integer itx1,itx2,zz1,zz2
    Dim as single CurZ,xDiv
   
    if x1<x2 then
        zz1 = z1
        zz2 = z2
       
        itx1 = x1
        itx2 = x2
       
        Uu1 = u1
        Uu2 = u2
        Vv1 = v1
        Vv2 = v2
    else
        zz1 = z2
        zz2 = z1
       
        itx1 = x2
        itx2 = x1
       
        Uu1 = u2
        Uu2 = u1
        Vv1 = v2
        Vv2 = v1
    end if
   
    Uu1 *= Texture.Size.x
    Uu2 *= Texture.Size.x
    Vv1 *= Texture.Size.y
    Vv2 *= Texture.Size.y
   
    xDiv = 1/(itx2 - itx1)
   
    dZ = xDiv * (zz2 - zz1)
   
    dU = xDiv * (Uu2 - Uu1)
    dV = xDiv * (Vv2 - Vv1)
   
    CurZ = zz1
   
    U = Uu1
    V = Vv1
   
    dim as integer it
   
    for i as integer = itx1 to itx2-1

        if y>0 and y<yRes and i>0 and i<xRes then
           
            it = y*xRes + i
           
            If (FOV - (-Camera.pos.z + CurZ))>0 then
               
                If Curz > ZBuffer(it) then
                   
                    ZBuffer(it) = CurZ
                   
                    ScrPtr[it] = Texture.GFX[int(U)+Texture.Size.x*int(V)]
                                       
                End if
           
            end if
       
        end if
       
        U += dU
        V += dV
       
        curZ += dZ
       
    Next
   
End Sub



Sub Texture_Map(ByVal Triangle as TriangleT, _
                ByVal Texture as TextureT)      '' UV's saved in the Triangle.Vertex Type
   
   
    '' Sorting Y values
    if Triangle.Vertex(1).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(1),Triangle.Vertex(0)
    end if
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(0)
    end if
   
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(1).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(1)
    end if
   
    dim as integer dx1,dy1,dx2,dy2,dx3,dy3
    dim as single Slope1,Slope2,Slope3, dYDiv
   
    dim as single dU1,dU2,dU3,dV1,dV2,dV3
    dim as single USlope1,USlope2,USlope3
    dim as single VSlope1,VSlope2,VSlope3
   
    Dim as integer dz1,dz2,dz3
    Dim as single zSlope1,zSlope2,zSlope3
   
    '' interpolate 0 to 1 (pos + color)
   
    dZ1 = Triangle.Vertex(1).pos3d.z - Triangle.Vertex(0).pos3d.z
   
    dX1 = Triangle.Vertex(1).pos2d.x - Triangle.Vertex(0).pos2d.x
    dY1 = Triangle.Vertex(1).pos2d.y - Triangle.Vertex(0).pos2d.y
   
    dU1 = Triangle.Vertex(1).U - Triangle.Vertex(0).U
    dV1 = Triangle.Vertex(1).V - Triangle.Vertex(0).V
   
    if dY1 <> 0 then
       
        dYDiv = 1/dY1
       
        zSlope1 = dZ1 * dYDiv
       
        Slope1 = dX1 * dYDiv
       
        USlope1 = dU1 * dYDiv
        VSlope1 = dV1 * dYDiv
       
    else
       
        zSlope1 = 0
       
        Slope1 = 0
       
        USlope1 = 0
        VSlope1 = 0
       
    End if
   
   
    '' interpolate 1 to 2
   
    dZ2 = Triangle.Vertex(2).pos3d.z - Triangle.Vertex(1).pos3d.z
   
    dX2 = Triangle.Vertex(2).pos2d.x - Triangle.Vertex(1).pos2d.x
    dY2 = Triangle.Vertex(2).pos2d.y - Triangle.Vertex(1).pos2d.y
   
    dU2 = Triangle.Vertex(2).U - Triangle.Vertex(1).U
    dV2 = Triangle.Vertex(2).V - Triangle.Vertex(1).V
   
    if dY2 <> 0 then
       
        dYDiv = 1/dY2
       
        zSlope2 = dZ2 * dYDiv
       
        Slope2 = dX2 * dYDiv
       
        USlope2 = dU2 * dYDiv
        VSlope2 = dV2 * dYDiv
       
    else
       
        zSlope2 = 0
       
        Slope2 = 0
       
        USlope2 = 0
        VSlope2 = 0
       
    End if
   
   
    '' interpolate 0 to 2
   
    dZ3 = Triangle.Vertex(0).pos3d.z - Triangle.Vertex(2).pos3d.z
   
    dX3 = Triangle.Vertex(0).pos2d.x - Triangle.Vertex(2).pos2d.x
    dY3 = Triangle.Vertex(0).pos2d.y - Triangle.Vertex(2).pos2d.y
   
    dU3 = Triangle.Vertex(0).U - Triangle.Vertex(2).U
    dV3 = Triangle.Vertex(0).V - Triangle.Vertex(2).V
   
    if dY3 <> 0 then
       
        dYDiv = 1/dY3
       
        zSlope3 = dZ3 * dYDiv
       
        Slope3 = dX3 * dYDiv
       
        USlope3 = dU3 * dYDiv
        VSlope3 = dV3 * dYDiv
       
    else
       
        zSlope3 = 0
       
        Slope3 = 0
       
        USlope3 = 0
        VSlope3 = 0
       
    End if
   
   
    '' Drawing
   
    '' Top
    dim as single CurX1=Triangle.Vertex(0).pos2d.x, CurX2=Triangle.Vertex(0).pos2d.x
    dim as single CurU1=Triangle.Vertex(0).U, CurU2=Triangle.Vertex(0).U,_
                  CurV1=Triangle.Vertex(0).V, CurV2=Triangle.Vertex(0).V
   
    dim as single CurZ1=Triangle.Vertex(0).pos3d.z, CurZ2=Triangle.Vertex(0).pos3d.z
   
    CurZ1 += Triangle.Parent_Center.z
    CurZ2 += Triangle.Parent_Center.z
   
    'BufferIter = Triangle.Vertex(0).pos2d.y * xRes
   
    For y as integer = Triangle.Vertex(0).pos2d.y to Triangle.Vertex(1).pos2d.y-1
       
        TLine(CurX1,CurX2,y,CurU1,CurV1,CurU2,CurV2, CurZ1, CurZ2, Texture)
       
        CurZ1 += zSlope1
        CurZ2 += zSlope3
       
        CurU1 += USlope1
        CurU2 += USlope3
        CurV1 += VSlope1
        CurV2 += VSlope3
       
        CurX1 += Slope1
        CurX2 += Slope3
       
        'BufferIter += xRes
       
    Next
   
    '' down
   
    CurZ1 = Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z
   
    CurU1 = Triangle.Vertex(1).U
    CurV1 = Triangle.Vertex(1).V
   
    CurX1 = Triangle.Vertex(1).pos2d.x
   
    For y as integer = Triangle.Vertex(1).pos2d.y to Triangle.Vertex(2).pos2d.y-1
       
        TLine(CurX1,CurX2,y,CurU1,CurV1,CurU2,CurV2, CurZ1, CurZ2, Texture)
       
        CurZ1 += zSlope2
        CurZ2 += zSlope3
       
        CurX1 += Slope2
        CurX2 += Slope3
       
        CurU1 += USlope2
        CurU2 += USlope3
        CurV1 += VSlope2
        CurV2 += VSlope3
       
    Next
   
End Sub


'' Texture Mapping + Gouraud shader
'' texturing
Sub TSLine(ByVal x1 as integer,ByVal x2 as integer, y as integer,ByVal U1 as single,ByVal V1 as single,ByVal U2 as single,ByVal V2 as single,ByVal z1 as integer,ByVal z2 as integer,byval Texture as TextureT, r1 as integer,r2 as integer,g1 as integer,g2 as integer,b1 as integer,b2 as integer)
   
    dim as single dR,dG,dB
    dim as single R,g,b
   
    dim as single sr1,sr2,sg1,sg2,sb1,sb2
   
    dim as single dU,dV,dZ,U,V
    dim as single Uu1,Vv1,Uu2,Vv2
   
    dim as integer itx1,itx2,zz1,zz2
    Dim as single CurZ,xDiv
   
    if x1<x2 then
        zz1 = z1
        zz2 = z2
       
        itx1 = x1
        itx2 = x2
       
        Uu1 = u1
        Uu2 = u2
        Vv1 = v1
        Vv2 = v2
       
        sr1 = r1
        sr2 = r2
        sg1 = g1
        sg2 = g2
        sb1 = b1
        sb2 = b2
    else
        zz1 = z2
        zz2 = z1
       
        itx1 = x2
        itx2 = x1
       
        Uu1 = u2
        Uu2 = u1
        Vv1 = v2
        Vv2 = v1
       
        sr1 = r2
        sr2 = r1
        sg1 = g2
        sg2 = g1
        sb1 = b2
        sb2 = b1
    end if
   
    Uu1 *= Texture.Size.x
    Uu2 *= Texture.Size.x
    Vv1 *= Texture.Size.y
    Vv2 *= Texture.Size.y
   
    xDiv = 1/(itx2 - itx1)
   
    dR = xDiv * (sr2 - sr1)
    dG = xDiv * (sg2 - sg1)
    dB = xDiv * (sb2 - sb1)
   
    dZ = xDiv * (zz2 - zz1)
   
    dU = xDiv * (Uu2 - Uu1)
    dV = xDiv * (Vv2 - Vv1)
   
    CurZ = zz1
   
    U = Uu1
    V = Vv1
   
    r = sr1
    g = sg1
    b = sb1
   
    dim as integer it
    Dim as integer CurTex,Cr,Cg,Cb
   
    for i as integer = itx1 to itx2-1

        if y>0 and y<yRes and i>0 and i<xRes then
           
            it = y*xRes + i
           
            If (FOV - (-Camera.pos.z + CurZ))>0 then
               
                If Curz > ZBuffer(it) then
                   
                    ZBuffer(it) = CurZ
                   
                    CurTex = Texture.GFX[int(U)+Texture.Size.x*int(V)]
                   
                    dim as single _255 = 1/255
                   
                    Cb = CurTex and 255
                    Cg = (CurTex shr 8) and 255
                    Cr = (CurTex shr 16) and 255
                   
                    ScrPtr[it] = rgb(r*Cr*_255,g*Cg*_255,b*Cb*_255)
                                       
                End if
           
            end if
       
        end if
       
        U += dU
        V += dV
       
        r += dR
        g += dG
        b += dB
       
        curZ += dZ
       
    Next
   
End Sub

Sub Texture_Map_Shaded(ByVal Triangle as TriangleT, _
                       ByVal Texture as TextureT)      '' UV's saved in the Triangle.Vertex Type
   
   
    '' Sorting Y values
    if Triangle.Vertex(1).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(1),Triangle.Vertex(0)
    end if
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(0)
    end if
   
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(1).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(1)
    end if
   
    dim as integer dx1,dy1,dx2,dy2,dx3,dy3
    dim as single Slope1,Slope2,Slope3, dYDiv
   
    dim as single dU1,dU2,dU3,dV1,dV2,dV3
    dim as single USlope1,USlope2,USlope3
    dim as single VSlope1,VSlope2,VSlope3
   
    Dim as integer dz1,dz2,dz3
    Dim as single zSlope1,zSlope2,zSlope3
   
    dim as integer dr1,dg1,db1,dr2,dg2,db2,dr3,dg3,db3
    dim as single RSlope1, GSlope1,BSlope1
    dim as single RSlope2, GSlope2,BSlope2
    dim as single RSlope3, GSlope3,BSlope3
   
    '' interpolate 0 to 1 (pos + color)
   
    dZ1 = Triangle.Vertex(1).pos3d.z - Triangle.Vertex(0).pos3d.z
   
    dX1 = Triangle.Vertex(1).pos2d.x - Triangle.Vertex(0).pos2d.x
    dY1 = Triangle.Vertex(1).pos2d.y - Triangle.Vertex(0).pos2d.y
   
    dU1 = Triangle.Vertex(1).U - Triangle.Vertex(0).U
    dV1 = Triangle.Vertex(1).V - Triangle.Vertex(0).V
   
    dr1 = Triangle.Vertex(1).color.r - Triangle.Vertex(0).color.r
    dg1 = Triangle.Vertex(1).color.g - Triangle.Vertex(0).color.g
    db1 = Triangle.Vertex(1).color.b - Triangle.Vertex(0).color.b
   
    if dY1 <> 0 then
       
        dYDiv = 1/dY1
       
        zSlope1 = dZ1 * dYDiv
       
        Slope1 = dX1 * dYDiv
       
        USlope1 = dU1 * dYDiv
        VSlope1 = dV1 * dYDiv
       
        RSlope1 = dR1 * dYDiv
        GSlope1 = dG1 * dYDiv
        BSlope1 = dB1 * dYDiv
       
    else
       
        zSlope1 = 0
       
        Slope1 = 0
       
        USlope1 = 0
        VSlope1 = 0
       
        RSlope1 = 0
        GSlope1 = 0
        BSlope1 = 0
    End if
   
   
    '' interpolate 1 to 2
   
    dZ2 = Triangle.Vertex(2).pos3d.z - Triangle.Vertex(1).pos3d.z
   
    dX2 = Triangle.Vertex(2).pos2d.x - Triangle.Vertex(1).pos2d.x
    dY2 = Triangle.Vertex(2).pos2d.y - Triangle.Vertex(1).pos2d.y
   
    dU2 = Triangle.Vertex(2).U - Triangle.Vertex(1).U
    dV2 = Triangle.Vertex(2).V - Triangle.Vertex(1).V

    dr2 = Triangle.Vertex(2).color.r - Triangle.Vertex(1).color.r
    dg2 = Triangle.Vertex(2).color.g - Triangle.Vertex(1).color.g
    db2 = Triangle.Vertex(2).color.b - Triangle.Vertex(1).color.b

    if dY2 <> 0 then
       
        dYDiv = 1/dY2
       
        zSlope2 = dZ2 * dYDiv
       
        Slope2 = dX2 * dYDiv
       
        USlope2 = dU2 * dYDiv
        VSlope2 = dV2 * dYDiv
       
        RSlope2 = dR2 * dYDiv
        GSlope2 = dG2 * dYDiv
        BSlope2 = dB2 * dYDiv
       
    else
       
        zSlope2 = 0
       
        Slope2 = 0
       
        USlope2 = 0
        VSlope2 = 0
       
        RSlope2 = 0
        GSlope2 = 0
        BSlope2 = 0
    End if
   
   
    '' interpolate 0 to 2
   
    dZ3 = Triangle.Vertex(0).pos3d.z - Triangle.Vertex(2).pos3d.z
   
    dX3 = Triangle.Vertex(0).pos2d.x - Triangle.Vertex(2).pos2d.x
    dY3 = Triangle.Vertex(0).pos2d.y - Triangle.Vertex(2).pos2d.y
   
    dU3 = Triangle.Vertex(0).U - Triangle.Vertex(2).U
    dV3 = Triangle.Vertex(0).V - Triangle.Vertex(2).V

    dr3 = Triangle.Vertex(0).color.r - Triangle.Vertex(2).color.r
    dg3 = Triangle.Vertex(0).color.g - Triangle.Vertex(2).color.g
    db3 = Triangle.Vertex(0).color.b - Triangle.Vertex(2).color.b

    if dY3 <> 0 then
       
        dYDiv = 1/dY3
       
        zSlope3 = dZ3 * dYDiv
       
        Slope3 = dX3 * dYDiv
       
        USlope3 = dU3 * dYDiv
        VSlope3 = dV3 * dYDiv
       
        RSlope3 = dR3 * dYDiv
        GSlope3 = dG3 * dYDiv
        BSlope3 = dB3 * dYDiv
       
    else
       
        zSlope3 = 0
       
        Slope3 = 0
       
        USlope3 = 0
        VSlope3 = 0
       
        RSlope3 = 0
        GSlope3 = 0
        BSlope3 = 0
       
    End if
   
   
    '' Drawing
   
    '' Top
    dim as single CurX1=Triangle.Vertex(0).pos2d.x, CurX2=Triangle.Vertex(0).pos2d.x
    dim as single CurU1=Triangle.Vertex(0).U, CurU2=Triangle.Vertex(0).U,_
                  CurV1=Triangle.Vertex(0).V, CurV2=Triangle.Vertex(0).V
   
    dim as single CurR1=Triangle.Vertex(0).Color.r,_
                   CurG1=Triangle.Vertex(0).Color.g,_
                   CurB1=Triangle.Vertex(0).Color.b,_
                   CurR2=Triangle.Vertex(0).Color.r,_
                   CurG2=Triangle.Vertex(0).Color.g,_
                   CurB2=Triangle.Vertex(0).Color.b
   
    dim as single CurZ1=Triangle.Vertex(0).pos3d.z, CurZ2=Triangle.Vertex(0).pos3d.z
   
    CurZ1 += Triangle.Parent_Center.z
    CurZ2 += Triangle.Parent_Center.z
   
    'BufferIter = Triangle.Vertex(0).pos2d.y * xRes
   
    For y as integer = Triangle.Vertex(0).pos2d.y to Triangle.Vertex(1).pos2d.y-1
       
        TSLine(CurX1,CurX2,y,CurU1,CurV1,CurU2,CurV2, CurZ1, CurZ2, Texture,CurR1,CurR2,CurG1,CurG2,CurB1,CurB2)
       
        CurZ1 += zSlope1
        CurZ2 += zSlope3
       
        CurU1 += USlope1
        CurU2 += USlope3
        CurV1 += VSlope1
        CurV2 += VSlope3
       
        CurX1 += Slope1
        CurX2 += Slope3
       
        CurR1 += RSlope1
        CurR2 += RSlope3
        CurG1 += GSlope1
        CurG2 += GSlope3
        CurB1 += BSlope1
        CurB2 += BSlope3
       
        'BufferIter += xRes
       
    Next
   
    '' down
   
    CurZ1 = Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z
   
    CurU1 = Triangle.Vertex(1).U
    CurV1 = Triangle.Vertex(1).V
   
    CurX1 = Triangle.Vertex(1).pos2d.x
   
    CurR1 = Triangle.Vertex(1).color.r
    Curg1 = Triangle.Vertex(1).color.g
    Curb1 = Triangle.Vertex(1).color.b
   
    For y as integer = Triangle.Vertex(1).pos2d.y to Triangle.Vertex(2).pos2d.y-1
       
        TSLine(CurX1,CurX2,y,CurU1,CurV1,CurU2,CurV2, CurZ1, CurZ2, Texture,CurR1,CurR2,CurG1,CurG2,CurB1,CurB2)
       
        CurZ1 += zSlope2
        CurZ2 += zSlope3
       
        CurX1 += Slope2
        CurX2 += Slope3
       
        CurU1 += USlope2
        CurU2 += USlope3
        CurV1 += VSlope2
        CurV2 += VSlope3
       
        CurR1 += RSlope2
        CurR2 += RSlope3
        CurG1 += GSlope2
        CurG2 += GSlope3
        CurB1 += BSlope2
        CurB2 += BSlope3
       
    Next
   
End Sub

Sub Rotate(obj as objectT,Tx as single, Ty as single, Tz as single)
   
    dim as single tmpX,tmpY,TmpZ,normX,normY,normZ
    dim as single VnormX,VnormY,VnormZ
   
    For i as integer = 1 to obj.NB_triangles
        For j as integer = 0 to 2
           
            '' Points
            TmpY = obj.Triangle(i).Vertex(j).pos3d.y * cos(Tx) - obj.Triangle(i).Vertex(j).pos3d.z * sin(Tx)
            TmpZ = obj.Triangle(i).Vertex(j).pos3d.z * cos(Tx) + obj.Triangle(i).Vertex(j).pos3d.y * sin(Tx)
            obj.Triangle(i).Vertex(j).pos3d.y = TmpY
            obj.Triangle(i).Vertex(j).pos3d.z = TmpZ
           
            TmpZ = obj.Triangle(i).Vertex(j).pos3d.z * cos(Ty) - obj.Triangle(i).Vertex(j).pos3d.x * sin(Ty)
            TmpX = obj.Triangle(i).Vertex(j).pos3d.x * cos(Ty) + obj.Triangle(i).Vertex(j).pos3d.z * sin(Ty)
            obj.Triangle(i).Vertex(j).pos3d.x = TmpX
           
            TmpX = obj.Triangle(i).Vertex(j).pos3d.x * cos(Tz) - obj.Triangle(i).Vertex(j).pos3d.y * sin(Tz)
            TmpY = obj.Triangle(i).Vertex(j).pos3d.y * cos(Tz) + obj.Triangle(i).Vertex(j).pos3d.x * sin(Tz)
           
            obj.Triangle(i).Vertex(j).pos3d.x = TmpX
            obj.Triangle(i).Vertex(j).pos3d.y = TmpY
            obj.Triangle(i).Vertex(j).pos3d.z = TmpZ
                   
       
            '' Vertex normals
            VnormY = obj.Triangle(i).Vertex(j).Gouraud_Normal.y * cos(Tx) - obj.Triangle(i).Vertex(j).Gouraud_Normal.z * sin(Tx)
            VnormZ = obj.Triangle(i).Vertex(j).Gouraud_Normal.z * cos(Tx) + obj.Triangle(i).Vertex(j).Gouraud_Normal.y * sin(Tx)
            obj.Triangle(i).Vertex(j).Gouraud_Normal.y = VnormY
            obj.Triangle(i).Vertex(j).Gouraud_Normal.z = VnormZ
           
            VnormZ = obj.Triangle(i).Vertex(j).Gouraud_Normal.z * cos(Ty) - obj.Triangle(i).Vertex(j).Gouraud_Normal.x * sin(Ty)
            VnormX = obj.Triangle(i).Vertex(j).Gouraud_Normal.x * cos(Ty) + obj.Triangle(i).Vertex(j).Gouraud_Normal.z * sin(Ty)
            obj.Triangle(i).Vertex(j).Gouraud_Normal.x = VnormX

            VnormX = obj.Triangle(i).Vertex(j).Gouraud_Normal.x * cos(Tz) - obj.Triangle(i).Vertex(j).Gouraud_Normal.y * sin(Tz)
            VnormY = obj.Triangle(i).Vertex(j).Gouraud_Normal.y * cos(Tz) + obj.Triangle(i).Vertex(j).Gouraud_Normal.x * sin(Tz)
           
            obj.Triangle(i).Vertex(j).Gouraud_Normal.x = VnormX
            obj.Triangle(i).Vertex(j).Gouraud_Normal.y = VnormY
            obj.Triangle(i).Vertex(j).Gouraud_Normal.z = VnormZ
        Next
       
        '' normals
        NormY = obj.Triangle(i).Normal.y * cos(Tx) - obj.Triangle(i).Normal.z * sin(Tx)
        NormZ = obj.Triangle(i).Normal.z * cos(Tx) + obj.Triangle(i).Normal.y * sin(Tx)
        obj.Triangle(i).Normal.y = NormY
        obj.Triangle(i).Normal.z = NormZ
       
        NormZ = obj.Triangle(i).Normal.z * cos(Ty) - obj.Triangle(i).Normal.x * sin(Ty)
        NormX = obj.Triangle(i).Normal.x * cos(Ty) + obj.Triangle(i).Normal.z * sin(Ty)
        obj.Triangle(i).Normal.x = NormX
       
        NormX = obj.Triangle(i).Normal.x * cos(Tz) - obj.Triangle(i).Normal.y * sin(Tz)
        NormY = obj.Triangle(i).Normal.y * cos(Tz) + obj.Triangle(i).Normal.x * sin(Tz)
           
        obj.Triangle(i).Normal.x = NormX
        obj.Triangle(i).Normal.y = NormY
        obj.Triangle(i).Normal.z = NormZ
       
    Next
   
End sub

Function FPS() as integer
   
    dim as integer _curfps
   
    If Timer - FPS_t <= 1 then
       
        FPS_counter += 1
       
        Return -1
       
    else
       
        _CurFPS = FPS_Counter/(Timer - FPS_t)
       
        FPS_counter = 0
        FPS_t = Timer
       
        Return _CurFPS
       
    End if
End Function

Function GenerateCube(x0 as integer,y0 as integer,z0 as integer,Size as integer) as objectT
   
    Dim as ObjectT obj
    Dim as Single Size_2 = Size/2
   
    obj.Center.x=x0
    obj.Center.y=y0
    obj.Center.z=z0
   
    obj.nb_triangles = 12 '' 12 !
   
    '' Defining color white/grey
    For i as integer = 1 to obj.nb_triangles
        for j as integer = 0 to 2
            obj.triangle(i).Vertex(j).originalColor.r = 255
            obj.triangle(i).Vertex(j).originalColor.g = 255
            obj.triangle(i).Vertex(j).originalColor.b = 255
        next
    next
   
   
    '' Face 1
    obj.triangle(1).Vertex(0).U = 1
    obj.triangle(1).Vertex(0).V = 0
    obj.triangle(1).Vertex(0).pos3d.x = Size_2
    obj.triangle(1).Vertex(0).pos3d.y = Size_2
    obj.triangle(1).Vertex(0).pos3d.z = Size_2
   
    obj.triangle(1).Vertex(2).U = 0
    obj.triangle(1).Vertex(2).V = 0
    obj.triangle(1).Vertex(2).pos3d.x = -Size_2
    obj.triangle(1).Vertex(2).pos3d.y = Size_2
    obj.triangle(1).Vertex(2).pos3d.z = Size_2
   
    obj.triangle(1).Vertex(1).U = 0
    obj.triangle(1).Vertex(1).V = 1
    obj.triangle(1).Vertex(1).pos3d.x = -Size_2
    obj.triangle(1).Vertex(1).pos3d.y = -Size_2
    obj.triangle(1).Vertex(1).pos3d.z = Size_2
   
   
    obj.triangle(2).Vertex(0).U = 0
    obj.triangle(2).Vertex(0).V = 1
    obj.triangle(2).Vertex(0).pos3d.x = -Size_2
    obj.triangle(2).Vertex(0).pos3d.y = -Size_2
    obj.triangle(2).Vertex(0).pos3d.z = Size_2
   
    obj.triangle(2).Vertex(2).U = 1
    obj.triangle(2).Vertex(2).V = 1
    obj.triangle(2).Vertex(2).pos3d.x = Size_2
    obj.triangle(2).Vertex(2).pos3d.y = -Size_2
    obj.triangle(2).Vertex(2).pos3d.z = Size_2
   
    obj.triangle(2).Vertex(1).U = 1
    obj.triangle(2).Vertex(1).V = 0
    obj.triangle(2).Vertex(1).pos3d.x = Size_2
    obj.triangle(2).Vertex(1).pos3d.y = Size_2
    obj.triangle(2).Vertex(1).pos3d.z = Size_2
   

    '' Face 2
    for i as integer = 3 to 4
        For j as integer = 0 to 2
           
            obj.triangle(i).Vertex(j).U = obj.triangle(i-2).Vertex(j).U
            obj.triangle(i).Vertex(j).V = obj.triangle(i-2).Vertex(j).V
           
            obj.triangle(i).Vertex(j).pos3d.x = obj.triangle(i-2).Vertex(j).pos3d.z
            obj.triangle(i).Vertex(j).pos3d.y = obj.triangle(i-2).Vertex(j).pos3d.y
            obj.triangle(i).Vertex(j).pos3d.z = -obj.triangle(i-2).Vertex(j).pos3d.x
   
        next
    next
   
    '' Face 3
    for i as integer = 5 to 6
        For j as integer = 0 to 2
           
            obj.triangle(i).Vertex(j).U = obj.triangle(i-2).Vertex(j).U
            obj.triangle(i).Vertex(j).V = obj.triangle(i-2).Vertex(j).V
           
            obj.triangle(i).Vertex(j).pos3d.x = obj.triangle(i-2).Vertex(j).pos3d.z
            obj.triangle(i).Vertex(j).pos3d.y = obj.triangle(i-2).Vertex(j).pos3d.y
            obj.triangle(i).Vertex(j).pos3d.z = -obj.triangle(i-2).Vertex(j).pos3d.x
   
        next
    next
   
    '' Face 4
    for i as integer = 7 to 8
        For j as integer = 0 to 2
           
            obj.triangle(i).Vertex(j).U = obj.triangle(i-2).Vertex(j).U
            obj.triangle(i).Vertex(j).V = obj.triangle(i-2).Vertex(j).V
           
            obj.triangle(i).Vertex(j).pos3d.x = obj.triangle(i-2).Vertex(j).pos3d.z
            obj.triangle(i).Vertex(j).pos3d.y = obj.triangle(i-2).Vertex(j).pos3d.y
            obj.triangle(i).Vertex(j).pos3d.z = -obj.triangle(i-2).Vertex(j).pos3d.x
   
        next
    next
   
    '' Face 5
    for i as integer = 9 to 10
        For j as integer = 0 to 2
           
            obj.triangle(i).Vertex(j).U = obj.triangle(i-2).Vertex(j).U
            obj.triangle(i).Vertex(j).V = obj.triangle(i-2).Vertex(j).V
           
            obj.triangle(i).Vertex(j).pos3d.x = -obj.triangle(i-2).Vertex(j).pos3d.y
            obj.triangle(i).Vertex(j).pos3d.y = obj.triangle(i-2).Vertex(j).pos3d.x
            obj.triangle(i).Vertex(j).pos3d.z = obj.triangle(i-2).Vertex(j).pos3d.z
   
        next
    next
   
    '' Face 6
    for i as integer = 11 to 12
        For j as integer = 0 to 2
           
            obj.triangle(i).Vertex(j).U = obj.triangle(i-4).Vertex(j).U
            obj.triangle(i).Vertex(j).V = obj.triangle(i-4).Vertex(j).V
           
            obj.triangle(i).Vertex(j).pos3d.x = obj.triangle(i-4).Vertex(j).pos3d.y
            obj.triangle(i).Vertex(j).pos3d.y = -obj.triangle(i-4).Vertex(j).pos3d.x
            obj.triangle(i).Vertex(j).pos3d.z = obj.triangle(i-4).Vertex(j).pos3d.z
   
        next
    next
   
    Return obj
   
End Function
       
#Define Cls_zBuffer For klm as integer =0 to SCREEN_MEM-1 : Zbuffer(klm) = -MAX_Z : next



















'' Test

'' Loading objects

Dim as ObjectT Face2

Face2 = GenerateCube(0,0,0,120) '' x,y,z,sidesize

'' Setting Light and stuff, Precalculating normals

dim as single t=.02

Dim as LightT Light

Light = SetLight(1,-1,-1,1)

PreCalc_object_normals Face2

Set_Camera 0,0,0



'' Texture loading for texture mapping
Dim as TextureT PlasmaTexture

Set_Texture_Size PlasmaTexture,64,64

Bload "Texture_Shader.bmp",PlasmaTexture.GFX-8


Do
   
    Screenlock : cls
   
    Paint(0,0),BGND_COLOR
   
    CLS_zBuffer
   
    Project_object Face2
   
    Calc_Gouraud_Shader face2, Light
   
    For i as integer = 1 to Face2.nb_triangles
       
        Texture_Map_Shaded Face2.triangle(i),PlasmaTexture
       
    Next
   
   
    Rotate(face2,t/2,t,0)
   
    '' DEBGUG : Show FPS
    CurFPS = FPS
    If CurFPS <> -1 and CurFPS <>0 then
        WindowTitle "["+str(CurFPS)+" FPS] 3D stuff"
    elseIf CurFPS = 0 then
        WindowTitle "3D Stuff"
    End if
   
    screenunlock : sleep 1,1
   
loop until multikey(&h01)

Eclipzer
Posts: 432
Joined: Oct 01, 2005 10:50
Location: Maryland
Contact:

Postby Eclipzer » Aug 25, 2008 17:46

Yeah, that looks pretty slick. Now you just need to improve the speed. I also noticed that your textures are slipping a bit, are you using perspective correct texture mapping?
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Postby Hezad » Aug 25, 2008 18:24

Thanks :) And you're right, the texture mapping is affine. I should code a perspective correct one !

Concerning the speed, yeah, I need to optimize it. In fact the backface culling is not working here since I can't use world-z axis. I need to set up the camera to know the correct z-axis to use for. And there are some stuff I need to optimize like incremental rendering (I loop through the screen buffer by multiplications for now ...)

I generated cos and sin tables but It doesn't seem to have a big impact on the speed (well, there are just 12 triangles in the scene, maybe I need to put more to "benchmark" the app.)

While i'm here : a funny glitch I had by working on a generateSphere() sub :

Image

:)
cha0s
Site Admin
Posts: 5317
Joined: May 27, 2005 6:42
Location: Illinois
Contact:

Postby cha0s » Aug 25, 2008 23:13

Nice. :)

And that sphere looks like a Christmas ornament....

Return to “Projects”

Who is online

Users browsing this forum: No registered users and 4 guests