Author Topic: WIP 3D Engine (Update : v0.07 screenie preview) [v0.06]  (Read 108847 times)

0 Members and 1 Guest are viewing this topic.

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Hello there !

So it's my first post  :updance:

First, just a few words to present myself :
I'm a french (so please excuse me if some of my sentences sound ambiguous !) freebasic user since some years now but I really don't define myself as a programmer ! In fact, I started "coding" on a TO7 and a ZX Spectrum (by "coding", i mean copying the programs listed in the manual and writing some ultra simple stuff). Then I coded a bit on PC with QBasic, I quickly stopped and started to code with GFA Basic on my Atari Mega STE (The only thing I ever really coded with it were a pong) :P
So 1 or 2 years ago, after some years without coding anything, I decided to start again coding and I found an awesome language which was (and IS) freebasic !

Oh and I'm a musician too :) Guitar, saxophone, drums and computer music. Don't ask me if I ever written any demo music, the answer is no :p I tried one or two times but it was catastrophic  :whack:


Well ! So now, about the Gouraud filling :D The relsoft's tutorial (http://www.phatcode.net/articles.php?id=214) helped me a lot since it totally guided me through this small project. Thanks a lot to him for that ! And thanks to Freebasic forum users which helped me a lot to understand Screen buffer access, especially counting_pine (I didn't want to use Pset : even if my code is everything but optimized, I wanted to access the buffer "by myself").

a screenshot :


a Zip with code+Exe :
http://narky00.free.fr/Gouraud.rar

And the code :
Code: [Select]
#Define Norm(a) sqr(a.x*a.x + a.y*a.y + a.z*a.z)

Const MAX_TRIANGLES_PER_OBJECT = 500
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 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

'' 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
   
    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
   
    '' Not normalized for now !! Normalize it if Code shading !
   
End Sub
   
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
       
        'BufferIter += xRes
       
    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

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 single tmpx,tmpz,tmpy
dim as integer j

Do
   
    Screenlock : cls
   
    Project_object Pyramid
   
    Sort_object_Z Pyramid
   
    For i as integer = 1 to Pyramid.nb_triangles
       
        Calc_Triangle_Normal Pyramid.triangle(i)
       
        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)


'' 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

To finish, let me tell you that I red and saw a lot of awesome stuff here, especially ultra optimized stuff, so please excuse the fact that this code is more a proof-that-I-can-do-this than a real compo. The next steps are resolving some glitches, and then, coding a Gouraud shading routine with lights :D

++ !

Hezad *glad to be there*


ps : Code Updated (Not the zip though) : the pyramid was moving a bit too fast :p
« Last Edit: November 20, 2008 by Hezad »

Offline mazemaker

  • C= 64
  • **
  • Posts: 28
  • Karma: 11
    • View Profile
Re: Gouraud Filling + Presentation :D
« Reply #1 on: August 21, 2008 »
this is great!

lights should be easy... you already have triangle normal calc. easy to normalise properly.


Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2757
  • Karma: 493
    • View Profile
    • https://www.rbraz.com/
Re: Gouraud Filling + Presentation :D
« Reply #2 on: August 21, 2008 »
 :hi: a board dude, nice work and keep it up
Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling + Presentation :D
« Reply #3 on: August 22, 2008 »
Thanks :)

Quote
lights should be easy...

I hope so ^^

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling + Presentation :D
« Reply #4 on: August 22, 2008 »
Update !

Here is the Gouraud Shading :)

Code :
Code: [Select]
#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

*Just found how to attach files*

Attached : Screen + Zip(Code+Exe)

If you prefer I to upload it on my FTP instead of here, please tell me :)

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Gouraud Filling (Update : Gouraud Shading)
« Reply #5 on: August 22, 2008 »
Welldone mate and :hi to the forums.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17422
  • Karma: 499
  • evil/good
    • View Profile
    • My Homepage
Re: Gouraud Filling (Update : Gouraud Shading)
« Reply #6 on: August 22, 2008 »
Hi Hezad :)

It's really good to see someone else having a go at software rendering, hats off to you.

Welcome to the forum.

You say that the code is not too optimised, it looks ok to me, nicely set out too. As far as the normals calcs go, you could pre-compute these once at the beginning and just rotate them with the rest of the object, but I really don't think you should lose any sleep over them with an object like a pyramid!

You're only a tiny way away from linear texture mapping with this too. All you'd need to do is have a texture map in memory and where you are interpolating the colour accross the object from the edges, just apply the same method to some UV (texture x and texture y) co-ordinates.

I am sure that you are going to have a lot of fun with your learning, you're already doing fantastic!

So have some good Karma from me and please enjoy the site.

Ps. 2 Things, you are free to attach your files to the posts, don't worry :) Your written English is better than you give yourself credit for.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline benny!

  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4384
  • Karma: 228
  • in this place forever!
    • View Profile
    • bennyschuetz.com - mycroBlog
Re: Gouraud Filling (Update : Gouraud Shading)
« Reply #7 on: August 22, 2008 »
 :hi: Hezad.
[ mycroBLOG - POUET :: whatever keeps us longing - for another breath of air - is getting rare ]

Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Gouraud Shading)
« Reply #8 on: August 22, 2008 »
Thanks everyone :) And thanks for the welcome :D

Quote
You say that the code is not too optimised, it looks ok to me, nicely set out too. As far as the normals calcs go, you could pre-compute these once at the beginning and just rotate them with the rest of the object, but I really don't think you should lose any sleep over them with an object like a pyramid!

hey cool ! I was wondering how I could precalculate the normals since I'd need to update them with the rotation but yeah, I just need to rotate them with the object !!  :inspired: lol I didn't thought about it ! Thanks for this advice !

Quote
You're only a tiny way away from linear texture mapping with this too. All you'd need to do is have a texture map in memory and where you are interpolating the colour accross the object from the edges, just apply the same method to some UV (texture x and texture y) co-ordinates.

lol in fact, I started directly with texture mapping tries but that was catastrophic ^^ So I decided to do Gouraud filling + shading before to make sure I understand. Now, I'll try texture mapping :) I'll try to make a cube with a moving plasma mapped on it :D And I already have some ideas to merge texture mapping and gouraud shading (but will I succeed in this objective?Iit's another question :P)

Quote
I am sure that you are going to have a lot of fun with your learning, you're already doing fantastic!

So have some good Karma from me and please enjoy the site.

I'm pretty sure too concerning the fun :P And thanks a lot for the karma :)

Oh and I already enjoyed the board since I saw awesome productions and/or snippets here and I'm sure I'll continue to enjoy it :D

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Gouraud Shading)
« Reply #9 on: August 23, 2008 »
Update !

The renderer now supports Z-Buffering :D and I ameliorated a bit the lighting routine

Code :

Code: [Select]
''  =======================---. 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

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
   
    as ColorT OriginalColor
   
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_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
    NNorm = 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
            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
       
    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
    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
   
    dR = (sr2 - sr1)/(itx2 - itx1)
    dG = (sg2 - sg1)/(itx2 - itx1)
    dB = (sb2 - sb1)/(itx2 - itx1)
   
    dZ = (zz2 - zz1)/(itx2 - itx1)
   
    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
    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
       
        zSlope1 = dZ1 / dY1
       
        Slope1 = dX1 / dY1
       
        RSlope1 = dR1 / dY1
        GSlope1 = dG1 / dY1
        BSlope1 = dB1 / dY1
       
    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
       
        zSlope2 = dZ2 / dY2
       
        Slope2 = dX2 / dY2
       
        RSlope2 = dR2 / dY2
        GSlope2 = dG2 / dY2
        BSlope2 = dB2 / dY2
       
    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
       
        zSlope3 = dZ3 /dY3
       
        Slope3 = dX3 / dY3
       
        RSlope3 = dR3 / dY3
        GSlope3 = dG3 / dY3
        BSlope3 = dB3 / dY3
       
    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
   
    Dim as objectT obj = obj_
    Dim as LightT L = L_
   
        '' 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

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

#Define Cls_zBuffer For klm as integer =0 to SCREEN_MEM-1 : Zbuffer(klm) = -MAX_Z : next







'' Test

'' Loading objects

Dim as ObjectT Pyramid, Pyramid2

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

Pyramid2.Nb_triangles = 4

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).OriginalColor.r,Pyramid.triangle(i).Vertex(j).OriginalColor.g,Pyramid.triangle(i).Vertex(j).OriginalColor.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(-.9,1,.8,1)

PreCalc_object_normals Pyramid

Set_Camera 0,0,0

Pyramid2 = Pyramid

Pyramid2.Center.x = 50

Do
   
    Screenlock : cls
   
    Paint(0,0),BGND_COLOR
   
    CLS_zBuffer
   
    Project_object Pyramid
    Project_object Pyramid2
   
    '' No Need to sort since there is Z-Buffer now !
    'Sort_object_Z Pyramid
   
    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
            Gouraud_Fill Pyramid2.triangle(i)
        end if
       
    Next
   
    Rotate(Pyramid,t,t/2,t/2)
   
    Rotate(Pyramid2,-t,t/4,-t/2)
   
    screenunlock : sleep 1,1
   
loop until multikey(&h01)


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

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

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

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

Attached : Screenshot + Rar(src + exe)

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Gouraud Filling (Update : Z-Buffer)
« Reply #10 on: August 23, 2008 »
Looks good now.

One thing with the normals is that once you have added all the face normals together you need to re-normalise the result, instead of dividing by the number of faces added.

A small optimisation too.  You do something like
Code: [Select]
dx = x2-x1
dr = (r2-r1) / dx
dg = (g2-g1) / dx
drb= (b2-b1) / dx
It would be quicker to do
Code: [Select]
dx = 1.0/(x2-x1)
dr = (r2-r1) * dx
dg = (g2-g1) * dx
drb= (b2-b1) * dx
But while you're learning we might be better off not talking about optimisation just now and more about algorithms.

Jim
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17422
  • Karma: 499
  • evil/good
    • View Profile
    • My Homepage
Re: Gouraud Filling (Update : Z-Buffer)
« Reply #11 on: August 23, 2008 »
Nice Z-Buffering :)

Now that you have this capability in your renderer you could easily make some really complicated objects with non-convex (overlapping) faces and since you worked out how to interpolate the colours and the Z co-ordinates, texture co-ordinates should be easy for you to do now :)

Looking forward to seeing your first Star wars X-Wing fighter :D
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Z-Buffer)
« Reply #12 on: August 23, 2008 »
Thanks for your replies :)

Jim :

Quote
One thing with the normals is that once you have added all the face normals together you need to re-normalise the result, instead of dividing by the number of faces added.
You must be speaking of the Calc_triangle_2d_normal() sub ? 'cause I don't use it :) I have another sub I use called Calc_triangle_normal() so the first is kinda deprecated :p I should get it off the code.
If you speak about something else, please tell me :)

Quote
But while you're learning we might be better off not talking about optimisation just now and more about algorithms.
Small optimization tips like this one are perfect :) It permits me to learn some basic optimization stuff without recoding everything :D
So thanks.


Shockwave :

Quote
Now that you have this capability in your renderer you could easily make some really complicated objects with non-convex (overlapping) faces and since you worked out how to interpolate the colours and the Z co-ordinates, texture co-ordinates should be easy for you to do now Smiley

Yeah :D Next step : texture mapping ^^


Quote
Looking forward to seeing your first Star wars X-Wing fighter Cheesy
hehe I should write an object importer :p And I don't know in which soft I could modelize it. maybe milkshape 3D ? for now, I don't even think about 3dsmax or those kind of 3d factories ^^

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Gouraud Filling (Update : Z-Buffer)
« Reply #13 on: August 23, 2008 »
The mistake is in PreCalc_Object_Normals

Jim
Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Z-Buffer)
« Reply #14 on: August 23, 2008 »
oh ok :) In fact, the part your talking about (when dividing NbFaces to TmpNorm), is not for faces normals but for Vertex normals (for shading).

Anyway, replacing the division by a normalization looks much better, the light's much better contrasted ! Thanks :)

Some news :
While I was working on Texture Mapping (I'm still on it, there's a problem with the UV projection, but the "pasting" part works for now :) ), I noticed there is a big problem with the way I globally handle my coordinates. I'm so lost I don't know in which sense are organized my axis anymore (especially the Z one ..)

To be continued .. :P

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Z-Buffer)
« Reply #15 on: August 23, 2008 »
Update :

Texture mapping implemented :D

On the other side, I played around with the Light equation part so the Gouraud shading seems jerky  ::) Gotta work on it but still, here is the texture mapping !

I'm really glad, it's the first time I go so far in 3D  :updance: (hm .. I like this smiley)

Code :
Code: [Select]


''  =======================---. 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

Attached : Screenshot + Rar(Exe + Code)

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Texture Mapping)
« Reply #16 on: August 24, 2008 »
Update :D (post copied for fb's forums, lazy to rewrite it ^^)

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.



Download : Rar (Src+Exe+Texture)

Any idea about the glitch ?

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17422
  • Karma: 499
  • evil/good
    • View Profile
    • My Homepage
Re: Gouraud Filling (Update : Texture Mapping)
« Reply #17 on: August 24, 2008 »
Textures are working really nicely, well done :)

For a cube the normals are easy to do, they would either be (X,Y,Z);
(  1,0,0)
(-1,0,0)
(0,1,0)
(0,-1,0)
(0,0,1)
(0,0,-1)

Make sure that the winding order for all the triangles are the same too ie all points in clockwise or all points counter clockwise :)

I am at my parents hose atm and havent been able to look at the code, only the exes :)
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Texture Mapping)
« Reply #18 on: August 24, 2008 »
thanks for your reply :)

Quote
For a cube the normals are easy to do, they would either be (X,Y,Z);
(  1,0,0)
(-1,0,0)
(0,1,0)
(0,-1,0)
(0,0,1)
(0,0,-1)
The point is I don't specify myself the normals, they are all precalculated for each triangle :p

Quote
Make sure that the winding order for all the triangles are the same too ie all points in clockwise or all points counter clockwise

Well here is precisely the problem :p I declared all my vertices in a clockwise order ! I verified all the vertex data but an error in the vertices order could pass through my verification and I don't see what's going on :p

*/me continue to search the error*

Quote
I am at my parents hose atm and havent been able to look at the code, only the exes

no problem :D


edit : err... Wait a minute ...  :inspired: !! I think I inverted the Z-Axis in some vertices data statements !
« Last Edit: August 24, 2008 by Hezad »

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17422
  • Karma: 499
  • evil/good
    • View Profile
    • My Homepage
Re: Gouraud Filling (Update : Texture Mapping)
« Reply #19 on: August 24, 2008 »
edit : err... Wait a minute ...  :inspired: !! I think I inverted the Z-Axis in some vertices data statements !

And therefore the normals will be pointing the wrong way :)
Shockwave ^ Codigos
Challenge Trophies Won: