Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 3D Engine code release
Index -> Programming, Turing -> Turing Submissions
View previous topic Printable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
MihaiG




PostPosted: Mon Nov 24, 2008 6:37 pm   Post subject: 3D Engine code release

So i decided to release the code to my 3d engine, personally i was fairly pleased at what i did in the allotted time in which i coded the program,
but the way i actually developed the program set up roadblocks in doing zsorting and shading

so here is the code

code:

View.Set ("offscreenonly")
setscreen ("graphics:max;max")
var zoom : int := 400
var zshift := 3.0
var xshift := 0.0
var yshift := 0.0
var chars : array char of boolean
var pointsize := 1
var perspective := 1
procedure rotz (var x, y : real, theta : real)
    var xt, yt : real
    xt := x
    yt := y
    x := xt * cosd (theta) + yt * sind (theta)
    y := yt * cosd (theta) - xt * sind (theta)
end rotz
var fileNo : int
open : fileNo, "<filename>", get
var polycount : string
get : fileNo, polycount
var px : array 1 .. strint (polycount), 1 .. 3 of real
var py : array 1 .. strint (polycount), 1 .. 3 of real
var pz : array 1 .. strint (polycount), 1 .. 3 of real
var draw : array 1 .. strint (polycount) of boolean
for i : 1 .. strint (polycount)
    draw (i) := true
end for
var t : string
for face : 1 .. strint (polycount)
    for point : 1 .. 3
        get : fileNo, t
        px (face, point) := strreal (t)
        get : fileNo, t
        py (face, point) := strreal (t)
        get : fileNo, t
        pz (face, point) := strreal (t)
    end for
end for
const xdsip := maxx / 2
const ydsip := maxy / 2
proc drawpoint (x, y, z : real)
    Draw.FillOval (round (((x - xshift) / (z * perspective - zshift)) * zoom + xdsip), round (((y - yshift) / (z * perspective - zshift)) * zoom + ydsip), pointsize, pointsize, red)
end drawpoint
proc facedraw (x1, x2, x3, y1, y2, y3, z1, z2, z3 : real)
    var fx : array 1 .. 3 of int
    var fy : array 1 .. 3 of int
    fx (1) := round (((x1 - xshift) / (z1 * perspective - zshift)) * zoom + xdsip)
    fx (2) := round (((x2 - xshift) / (z2 * perspective - zshift)) * zoom + xdsip)
    fx (3) := round (((x3 - xshift) / (z3 * perspective - zshift)) * zoom + xdsip)
    fy (1) := round (((y1 - yshift) / (z1 * perspective - zshift)) * zoom + ydsip)
    fy (2) := round (((y2 - yshift) / (z2 * perspective - zshift)) * zoom + ydsip)
    fy (3) := round (((y3 - yshift) / (z3 * perspective - zshift)) * zoom + ydsip)
    Draw.Polygon (fx, fy, 3, 7)
    for i : 1 .. 3
        Draw.FillOval (round (fx (i)), round (fy (i)), pointsize, pointsize, red)
    end for
end facedraw
proc updatescreen
    for face : 1 .. strint ((polycount))
        facedraw (px (round (face), 1), px (round (face), 2), px (round (face), 3), py (round (face), 1), py (round (face), 2),
            py (round (face), 3), pz (round (face), 1), pz (round (face), 2), pz (round (face), 3))
    end for
end updatescreen
var change := true
cls
updatescreen
loop
    if change = true then
        cls
    end if
    change := false
    Input.KeyDown (chars)
    for face : 1 .. strint (polycount)
        for point : 1 .. 3
            if chars ('e') then
                rotz (px (face, point), py (face, point), 2)
                change := true
            elsif chars ('z') then
                rotz (px (face, point), py (face, point), -2)
                change := true
            end if
            if chars ('x') then
                rotz (py (face, point), pz (face, point), 2)
                change := true
            elsif chars ('w') then
                rotz (py (face, point), pz (face, point), -2)
                change := true
            end if
            if chars ('d') then
                rotz (pz (face, point), px (face, point), 2)
                change := true
            elsif chars ('a') then
                rotz (pz (face, point), px (face, point), -2)
                change := true
            end if
            if chars ('q') then
                rotz (px (face, point), py (face, point), 1)
                rotz (py (face, point), pz (face, point), 1.5)
                rotz (pz (face, point), px (face, point), 2)
                change := true
            elsif chars ('`') then
                quit
            end if
        end for
    end for
    if change = true then
        updatescreen
        View.Update
    end if
end loop


some tips
the file formating is listed above
to create a model
i just used blender, and imported a model and then used the export function and exported as raw faces using the default values

so just a brief overview of the initial parameters of the program

zoom : basically zooms in its best to have values over 300
zshift moves the object back (sortoff like zoom)
xshift : moves to the right/left
yshift : moves pictures updown
point size defines the size of the vertex of each face
perspective is basically the strength of the camera, so basically having a perspective of 0 will make it have no perspective point, the higher the value, the closer it is to the camera

enjoy

-mihai
Sponsor
Sponsor
Sponsor
sponsor
A.J




PostPosted: Mon Nov 24, 2008 6:50 pm   Post subject: Re: 3D Engine code release

so.......do u have an input file that I can use?
MihaiG




PostPosted: Mon Nov 24, 2008 9:11 pm   Post subject: Re: 3D Engine code release

***************NOTE*****************
this is a wireframe only engine
i couldnt get surfaces to work properly
i will be making a completley new engine after winter break
****************************

sorry i forgot to mention,
the input files are on my original submission of the program its just an zip that has the exe inside

http://compsci.ca/v3/viewtopic.php?t=19304

its the second last post in the topic has a bunch of models
you can read that topic as how the data is stored in the files

also

` is quit
w&x are rotation on the x axis
e&z are rotation on the y
a&d are rotation on the z axis
Zren




PostPosted: Mon Nov 24, 2008 9:26 pm   Post subject: Re: 3D Engine code release

There's a more efficient way to do 3D polygons in data files. You see here for 1 box you'd have to re write EVERY Point on each polygon. You'd have a 109-line long file. (Example file attached.)

A much number crunching file would be to do as so.

Make two input types: Vertice (Points) and Polygons.
Load the total number of points and polygons (2 lines).
load the vertices. (x,y,z) (3 lines)
Load the polygons (the data here would be the number for the vertice.) (3 lines)

Now, for a basic cube that consists of 8 vertices, and is broken down into 12 polygons:
(2 lines) total numbers
(8*3) points
(12*3) polygons
=62 lines total

A better explanation with pictures is here.



cube.txt
 Description:
Cube file for

Download
 Filename:  cube.txt
 Filesize:  380 Bytes
 Downloaded:  190 Time(s)

MihaiG




PostPosted: Mon Nov 24, 2008 11:17 pm   Post subject: Re: 3D Engine code release

thanks but i probably wont be doing any work on this engine anymore since im having some issues based on the way i developed it

the code is there, so if you want to implement it, be my guest Smile
A.J




PostPosted: Mon Nov 24, 2008 11:35 pm   Post subject: Re: 3D Engine code release

good job MihaiG!

I am doing a similar thing but in C++ (for my FP. I am making a 3D Game)

good job!
MihaiG




PostPosted: Tue Dec 09, 2008 4:53 pm   Post subject: Re: 3D Engine code release major update

hey guys, im adding a new major update to the code

i now have zsorting so you will draw poly from furthest to closet, i did using saad's quicksort
i also added a kind of pseudo-shading

code:

View.Set ("offscreenonly")
setscreen ("graphics:max;max")
var zoom : int := 200
var zshift := 3.0
var xshift := 0.0
var yshift := 0.0
var chars : array char of boolean
var pointsize := 1
var perspective := 0.1
var camrate := 0.00005
var ma := 0.0
var mn := 10000.0
var av := 0.0
var rotspeed := 3
procedure rotz (var x, y : real, theta : real)
    var xt, yt : real
    xt := x
    yt := y
    x := xt * cosd (theta) + yt * sind (theta)
    y := yt * cosd (theta) - xt * sind (theta)
end rotz
var fileNo : int
open : fileNo, "helmet.ply", get
var polycount : string
get : fileNo, polycount
var px : array 1 .. strint (polycount), 1 .. 3 of real
var py : array 1 .. strint (polycount), 1 .. 3 of real
var pz : array 1 .. strint (polycount), 1 .. 3 of real
var draw : array 1 .. strint (polycount) of boolean
for i : 1 .. strint (polycount)
    draw (i) := true
end for
var t : string
for face : 1 .. strint (polycount)
    for point : 1 .. 3
        get : fileNo, t
        px (face, point) := strreal (t)
        get : fileNo, t
        py (face, point) := strreal (t)
        get : fileNo, t
        pz (face, point) := strreal (t)
    end for
end for
const xdsip := maxx / 2
const ydsip := maxy / 2
proc drawpoint (x, y, z : real)
    Draw.FillOval (round (((x - xshift) / (z * perspective - zshift)) * zoom + xdsip), round (((y - yshift) / (z * perspective - zshift)) * zoom + ydsip), pointsize, pointsize, red)
end drawpoint


var dis, order : array 1 .. strint (polycount) of real
proc res ()
    for i : 1 .. strint (polycount)
        order (i) := i
    end for
end res
res


proc Swap (var num1, num2 : real)
    var tnum := num1
    num1 := num2
    num2 := tnum
end Swap

proc Quick_Sort (var num : array 1 .. * of real, start, finish : int, var order : array 1 .. * of real)
    if start < finish then
        var pivot := num (start)
        var up := start
        var down := finish
        loop
            exit when up >= down
            loop
                exit when up > finish or num (up) > pivot
                up += 1
            end loop
            loop
                exit when down < start or num (down) <= pivot
                down -= 1
            end loop
            if (up < down) then
                Swap (num (up), num (down))
                Swap (order (up), order (down))
            elsif (up > down) then
                Swap (num (start), num (down))
                Swap (order (start), order (down))
                Quick_Sort (num, start, down - 1, order)
                Quick_Sort (num, down + 1, finish, order)
            end if
        end loop
    end if
end Quick_Sort


proc facedraw (x1, x2, x3, y1, y2, y3, z1, z2, z3 : real)
    var fx : array 1 .. 3 of int
    var fy : array 1 .. 3 of int
    var ax, ay, az : real
    var dist : real
    ax := (x1 + x2 + x3) / 3
    ay := (y1 + y2 + y3) / 3
    az := (z1 + z2 + z3) / 3
    fx (1) := round (((x1 - xshift) / (z1 * perspective - zshift)) * zoom + xdsip)
    fx (2) := round (((x2 - xshift) / (z2 * perspective - zshift)) * zoom + xdsip)
    fx (3) := round (((x3 - xshift) / (z3 * perspective - zshift)) * zoom + xdsip)
    fy (1) := round (((y1 - yshift) / (z1 * perspective - zshift)) * zoom + ydsip)
    fy (2) := round (((y2 - yshift) / (z2 * perspective - zshift)) * zoom + ydsip)
    fy (3) := round (((y3 - yshift) / (z3 * perspective - zshift)) * zoom + ydsip)
    dist := sqrt ((ax + xshift) ** 2 + (ay + yshift) ** 2 + (az + zshift) ** 2)
    Draw.FillPolygon (fx, fy, 3, round ((16 + (dist - mn) / (ma-mn) * (32 - 17))))
    Draw.Polygon (fx, fy, 3, 7)

end facedraw
proc updatescreen
    for face : 1 .. strint (polycount)
        facedraw (px (round (order (face)), 1), px (round (order (face)), 2), px (round (order (face)), 3), py (round (order (face)), 1), py (round (order (face)), 2),
            py (round (order (face)), 3), pz (round (order (face)), 1), pz (round (order (face)), 2), pz (round (order (face)), 3))
    end for
end updatescreen
var change := true
proc avg
    var ax, ay, az : real
    mn := 1000
    ma := 0
    av := 0
    for face : 1 .. strint (polycount)
        ax := (px (face, 1) + px (face, 2) + px (face, 3)) / 3
        az := (pz (face, 1) + pz (face, 2) + pz (face, 3)) / 3
        ay := (py (face, 1) + py (face, 2) + py (face, 3)) / 3
        dis (face) := sqrt ((ax + xshift) ** 2 + (ay + yshift) ** 2 + (az + zshift) ** 2)
        if dis (face) < mn then
            mn := dis (face)
        end if
        if dis (face) > ma then
            ma := dis (face)
        end if
        av += dis(face)
    end for
    av :=av/ strint(polycount)
    res
    Quick_Sort (dis, 1, upper (dis), order)

end
avg
updatescreen
loop
    if change then
        cls
    end if
    change := false
    Input.KeyDown (chars)
    for face : 1 .. strint (polycount)
        for point : 1 .. 3
            if chars ('e') then
                rotz (px (face, point), py (face, point), rotspeed)
                change := true
            elsif chars ('z') then
                rotz (px (face, point), py (face, point), -1 * rotspeed)
                change := true
            end if
            if chars ('x') then
                rotz (py (face, point), pz (face, point), rotspeed)
                change := true
            elsif chars ('w') then
                rotz (py (face, point), pz (face, point), -1 * rotspeed)
                change := true
            end if
            if chars ('d') then
                rotz (pz (face, point), px (face, point), rotspeed)
                change := true
            elsif chars ('a') then
                rotz (pz (face, point), px (face, point), -1 * rotspeed)
                change := true
            end if
            if chars ('i') then
                yshift += camrate
                change := true
            elsif chars ('m') then
                yshift -= camrate
                change := true
            end if
            if chars ('h') then
                xshift += camrate
                change := true
            elsif chars ('k') then
                xshift -= camrate
                change := true
            end if
            if chars ('u') then
                zshift += camrate
                change := true
            elsif chars ('n') then
                zshift -= camrate
                change := true
            end if

            if chars ('r') then
                xshift := 0
                yshift := 0
                change := true
            end if
            if chars ('q') then
                rotz (px (face, point), py (face, point), 3*rotspeed)
                rotz (py (face, point), pz (face, point), 1.5 * rotspeed)
                rotz (pz (face, point), px (face, point), 2 * rotspeed)
                change := true
            elsif chars ('`') then
                exit
            end if
        end for
    end for
    if change = true then
        avg
        updatescreen
        View.Update
    end if
end loop
Homer_simpson




PostPosted: Wed Dec 10, 2008 4:08 pm   Post subject: Re: 3D Engine code release

i like it...+ bits
Sponsor
Sponsor
Sponsor
sponsor
MihaiG




PostPosted: Wed Dec 10, 2008 7:32 pm   Post subject: Re: 3D Engine code release

thanks homer

it achieves around 20+fps on 500 polygon models, my assumption is that if you use low detail polygons.
i know that i didn't document much, but if you need any clarification with what code does feel free to send me an email at
mihail[dot]gheorghe[at]gmail[dot]com
i should respond within a day.

also, id like to thank saad again for letting me steal his quicksort code ;P
if anyone is interested in how i did the shading here it is..

when i found the distance to each face, i store a max and a min

then when calculating the color
i took the actual distance and subtracted the min which gave me the delta, i then divided that by the difference between the max and the min, which essential means that, the farther away the darker it is the closer the lighter, this is a bit buggy cause if you have disproportionate models, you will have an "uneven" lighting system,

if someone figures out a more consistant way to do realistic lighting, remember light intensity is proportional to the inverse of the sqaure of the distance Razz

anyways, i know there are many places efficiency can be imroved probably using taylor series for some of the functions (ill try to implement that now)
A.J




PostPosted: Wed Dec 10, 2008 11:28 pm   Post subject: Re: 3D Engine code release

where can i find helmet.ply?
MihaiG




PostPosted: Thu Dec 11, 2008 10:49 am   Post subject: Re: 3D Engine code release

hey i attached the helmet.ply below
its not a wel designed model cause there are erroneous polygons inside the helmet :/
the helmet probably gives the best result with the 3d engine

note you need to change the file extension back to ply, compsci.ca doesnt allow *.ply uploads Confused, i know its listed as a jpg, your gonna have to right click and save target as ....



helmet.jpg
 Description:
 Filesize:  44.19 KB
 Viewed:  5022 Time(s)

helmet.jpg


Homer_simpson




PostPosted: Thu Dec 11, 2008 12:31 pm   Post subject: Re: 3D Engine code release

for proper lighting effect you need to find the normal to each face and find the angle between your face normal to your light source and calculate the color based on that.
you can look at the code off my old engine, i had normal calculations in there.
http://compsci.ca/v3/viewtopic.php?t=6503
MihaiG




PostPosted: Thu Dec 11, 2008 1:20 pm   Post subject: Re: 3D Engine code release

homer,
i understand as to how to calculate the normal to a plane in 3d space, but how do i know which side it would be facing? because there would be "two' normals that spring of any plane?
or would the correct vector be calculated assuming each polygon's verticies are stored in the same order? ie CW or CCW?

**edit**
ya ifigured it out, i also read up on backface culling if anyone is interested

http://www.cubic.org/docs/backcull.htm

ie. if the normal of a polygon is facing away (ie if the Z value is less than 0) we can skip drawing it
Display posts from previous:   
   Index -> Programming, Turing -> Turing Submissions
View previous topic Tell A FriendPrintable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 13 Posts ]
Jump to:   


Style:  
Search: