Drawing a perspective grid (Solved)

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
Star Crunch
Prole
Posts: 33
Joined: Sun Feb 15, 2009 12:13 am
Location: Monterrey, MX
Contact:

Re: Drawing a perspective grid (Solved)

Post by Star Crunch » Mon Mar 09, 2009 6:43 am

Well, if you're done with this, just move along, I guess. But here's an off-the-cuff trig idea.

A useful mental model here is to compare the grid against a "real" object, which for your purposes is probably a rectangular grid, with left and right sides at fixed x-values (say GRID_BOTTOM_XI and GRID_BOTTOM_XF) and at a fixed y-value (say, GRID_BOTTOM_YI), and using one-point perspective.

You'll need to say how far the back points are from the front ones, which will be easiest here with a depth, dz.

In the link above, in the railroad tracks picture, you can see how the tracks form a triangle with the edges of the image. This is similar to what goes on with the reference grid.

You get these relationships:

Image
Image

So you have x = z * tan(θ) = z * (dx / dz) and y = z * tan(φ) = z * (dy / dz).

dx: GRID_TOP_XI - GRID_BOTTOM_XI (symmetry should give you the right side)
dy: GRID_TOP_XI - GRID_BOTTOM_YI
dz: Set this to something that looks good

And then your values would be:

left x: GRID_BOTTOM_XI + x
right x: GRID_BOTTOM_XF - x
y: GRID_BOTTOM_YI + y

*Tries program out*

Okay, I looked at your results and sort of guessed that the spacing between cells was about 4/5 of the previous one. Using that, you can put this somewhere at the beginning:

Code: Select all

local DX = GRID_TOP_XI - GRID_BOTTOM_XI
local DY = GRID_TOP_YI - GRID_BOTTOM_YI
local DZ = 30                -- Tune this
local DZ_SCALE = .8      -- and this
local DZ_BASE = 0
local XCOEFF = DX / DZ
local YCOEFF = DY / DZ

-- Accumulate 1 + scale + scale * scale + ...
-- Find the base that we need to start from.
for i = 0, GRID_SIZE - 1 do
	DZ_BASE = DZ_BASE + DZ_SCALE^i
end

DZ_BASE = DZ / DZ_BASE
and try this at the horizontal lines part:

Code: Select all

    -- Horizontal lines
    local z, dz = 0, DZ_BASE

    for i = 0, GRID_SIZE
    do
        --local y = (i * STEP) + GRID_TOP_YI
--[[
        local y = (GRID_HORIZ_FUNC_A * (i^2)) + (GRID_HORIZ_FUNC_B * i)
          + GRID_TOP_YI

        local xi = (y - GRID_RIGHT_SLOPE_ADD) / GRID_RIGHT_SLOPE
        local xf = (y - GRID_LEFT_SLOPE_ADD) / GRID_LEFT_SLOPE
--]]
---[[
	local dx = XCOEFF * z
	local xi = GRID_BOTTOM_XI + dx
	local xf = GRID_BOTTOM_XF - dx
	local y = GRID_BOTTOM_YI + YCOEFF * z

	z, dz = z + dz, dz * DZ_SCALE
--]]
        love.graphics.line(xi, y, xf, y)
    end
It gets pretty close, and the math is easier.

osuf oboys
Party member
Posts: 215
Joined: Sun Jan 18, 2009 8:03 pm

Re: Drawing a perspective grid (Solved)

Post by osuf oboys » Mon Mar 09, 2009 7:05 am

Very instructive :nyu:
Star Crunch wrote: [...] So you have x = z * tan(θ) = z * (dx / dz) and y = z * tan(φ) = z * (dy / dz). [...]
If the x is the screen x-coordinate, then it should be x = c * θ =~ c * (dx / dz) (well, I would call it dx / dy). That's for small theta, however. Using theta instead of dx / dz should look better.

Just a small note: 'y' and 'z' in the previous post may have to be switched occasionally. In most 3d apps, 'y' is upwards and 'z' is depth. In LÖVE and "2.5D", typically 'y' is depth and 'z' is height.
If I haven't written anything else, you may assume that my work is released under the LPC License - the LÖVE Community. See http://love2d.org/wiki/index.php?title=LPC_License.

User avatar
Star Crunch
Prole
Posts: 33
Joined: Sun Feb 15, 2009 12:13 am
Location: Monterrey, MX
Contact:

Re: Drawing a perspective grid (Solved)

Post by Star Crunch » Mon Mar 09, 2009 1:57 pm

It actually occurred to me now, as I groggily awoke, that all the DZ parts of the code cancel with one another, and so that part is superfluous. Then the above snippets become:

Code: Select all

local DX = GRID_TOP_XI - GRID_BOTTOM_XI
local DY = GRID_TOP_YI - GRID_BOTTOM_YI
local SCALE = .8 -- Tune just this
local BASE = 0

for i = 0, GRID_SIZE - 1 do
   BASE = BASE + SCALE^i
end

BASE = 1 / BASE
and

Code: Select all

-- Horizontal lines
local z, dz = 0, BASE

for i = 0, GRID_SIZE
do
   local dx = DX * z
   local xi = GRID_BOTTOM_XI + dx
   local xf = GRID_BOTTOM_XF - dx
   local y = GRID_BOTTOM_YI + DY * z

   z, dz = z + dz, dz * SCALE

   love.graphics.line(xi, y, xf, y)
end
Modify what coordinate is what as desired. :)

Post Reply

Who is online

Users browsing this forum: No registered users and 29 guests