A Basic 3D Wireframe Implementation in LÖVE

Showcase your libraries, tools and other projects that help your fellow love users.
Post Reply
rexjericho
Prole
Posts: 44
Joined: Sat Dec 15, 2012 7:55 am

A Basic 3D Wireframe Implementation in LÖVE

Post by rexjericho »

Here's a project that I've sort of given up on. I attempted to implement a wireframe renderer using this guide:
http://www.kmjn.org/notes/3d_rendering_intro.html

Unfortunately my implementation is super horribly innefficient, but it works for simple shapes. I may revisit/redo this project in the future. There are so many things I would change.

I've attached a demo love file of a cube rotating about a random axis. Check it out. Let me know if you have any questions/criticisms. If you take a peek at the source, pretty much all the magic happens in the project() function and the camera table. Knowing a bit about vector/matrix math and 3d geometry may help.
Ink89.png
Ink89.png (32.23 KiB) Viewed 347 times
usage:
move camera side to side, up/down, in/out:
w,a,s,d,r,f

rotate camera on it's own x,y,z axis:
up, left, down, right, lshift, enter
Attachments
wireframe.love
(61.4 KiB) Downloaded 290 times
User avatar
Jasoco
Inner party member
Posts: 3726
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: A Basic 3D Wireframe Implementation in LÖVE

Post by Jasoco »

Interesting. I don't really understand the matrix stuff. My 3D stuff just uses simple math to do the same thing. It runs through every single visible point every frame and calculates its 2D location every frame and is capable of doing this...
ss.png
ss.png (61.88 KiB) Viewed 3422 times
Without slowdown.

Code: Select all

function point3d(x, y, z, cam)
	local cam = cam or camera 

	--3D Calculations are done here!!!!
	local xy, xz, yz, yx, zx, zy, scale, dist, rx, ry, rz

	rx = cam.x + x
	ry = cam.y + y
	rz = cam.z + z

	xy = cx*ry - sx*rz
	xz = sx*ry + cx*rz
	yz = cy*xz - sy*rx
	yx = sy*xz + cy*rx
	zx = cz*yx - sz*xy
	zy = sz*yx + cz*xy

	scale = focal/(focal + yz)
	rx = zx*scale
	ry = zy*scale
	dist = yz

	return rx, ry, dist, scale
end
You basically use this to find out where each visible triangle is on screen, sort them by their distance and loop through them.
rexjericho
Prole
Posts: 44
Joined: Sat Dec 15, 2012 7:55 am

Re: A Basic 3D Wireframe Implementation in LÖVE

Post by rexjericho »

Thanks! This helped a lot. I didn't realize that the calculations were actually so simple. Multiplying the matrices together was the super innefficient part, so I ended up expanding them out by hand, and only calculating what was needed. This got rid of a tonne of unnecessary calculations that were being performed by the matrix multiplications

Code: Select all

    -- vertex coordinates
    local x = point.x
    local y = point.y
    local z = point.z
    
    -- for camera perspective transform
    local A11 = 2*cam.near/cam.width
    local A22 = 2*cam.near/cam.height
    local A33 = -(cam.far + cam.near)/(cam.far - cam.near)
    local A34 = -(2*cam.far*cam.near)/(cam.far - cam.near)
    
    -- for camera look transform
    local B11 = cam.u.x   -- camera's x axis
    local B12 = cam.u.y
    local B13 = cam.u.z
    local B21 = cam.v.x   -- camera's y axis
    local B22 = cam.v.y
    local B23 = cam.v.z
    local B31 = cam.n.x   -- camera's z axis
    local B32 = cam.n.y
    local B33 = cam.n.z
    
    -- for camera perspective transform
    local C14 = -cam.position.x
    local C24 = -cam.position.y
    local C34 = -cam.position.z
    
    -- calculate vertex view space
    local newx = A11*B11*x + A11*B12*y + A11*B13*z + A11*B11*C14 + A11*B12*C24 + A11*B13*C34
    local newy = A22*B21*x + A22*B22*y + A22*B23*z + A22*B21*C14 + A22*B22*C24 + A22*B23*C34
    local newz = A33*B31*x + A33*B32*y + A33*B33*z + A33*B31*C14 + A33*B32*C24 + A33*B33*C34 + A34
    local neww = 1 - B31*x - B32*y - B33*z - B31*C14 - B32*C24 - B33*C34

    -- normalize coordinates by dividing by homogenous coordinate neww
    local wr = 1/neww
    local newx = newx*wr
    local newy = newy*wr
    local newz = newz*wr
    
    -- projected x and y coordinates
    local projx = 0.5*newx*cam.width + 0.5*cam.width
    local projy = 0.5*newy*cam.height + 0.5*cam.height
I went from being able to get 3 cubes on screen to 216! 18 rectangle draws to 1296, a massive improvement. I know there is still so much more that I can do to optimize my code, so I'll have to work on that for a while.
V9qyN.png
V9qyN.png (55.68 KiB) Viewed 345 times
arundel
Prole
Posts: 31
Joined: Tue Sep 21, 2010 8:49 pm
Location: The Netherlands

Re: A Basic 3D Wireframe Implementation in LÖVE

Post by arundel »

Wow, this 3d wireframe and cube renderer looks promising. Good job. :3
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests