02-15-2024, 09:10 PM
hello B+,
there are two options, the easiest is parallel projection and the trickier but more realistic one is perspective projection
say you have 3D coord variables x, y, z and you wish to convert them to 2D coords, lets call them p, q
for parallel:
p = x + 0.7*z
q = y + 0.7*z
where 0.7 is a kind of arbitrary number which you can mod until it looks right
for perspective
p = x * d/z
q = y * d/z
where d is like a field of vision value that corresponds to the relative distance between your eye and the monitor (the plane of projection) and getting these values correct requires a bit of math or a lot of modding -- consider an offset to prevent negative z or a division by zero. I usually use the former to do something like a quick plot to get an idea and will mod my way to the latter for more serious mods.
see SUB proj in the following example
you can also use the same procedure to convert 4D coordinates into 2D! first project them down to 3D, then again down to 2D (see also example and SUB proj in this useful JB thread https://justbasiccom.proboards.com/threa...e-question )
speaking of maptriangle, its been on my backburner to translate that over to QBJS but I ran into a few brick walls due to my lack of JS (not JB) knowledge, mainly the image loading and webGL stuff, and kinda lost interest, but there has been some renewed interest in webGL in one of the math communities i'm into so I may give that another shot in the near future. I was able to at least find the formula to match 3D to 2D coordinates 1:1 with QB64's maptri and can share that mod if there's interest
there are two options, the easiest is parallel projection and the trickier but more realistic one is perspective projection
say you have 3D coord variables x, y, z and you wish to convert them to 2D coords, lets call them p, q
for parallel:
p = x + 0.7*z
q = y + 0.7*z
where 0.7 is a kind of arbitrary number which you can mod until it looks right
for perspective
p = x * d/z
q = y * d/z
where d is like a field of vision value that corresponds to the relative distance between your eye and the monitor (the plane of projection) and getting these values correct requires a bit of math or a lot of modding -- consider an offset to prevent negative z or a division by zero. I usually use the former to do something like a quick plot to get an idea and will mod my way to the latter for more serious mods.
see SUB proj in the following example
Code: (Select All)
defdbl a-z
const d = 300
const z0 = 550
const oy = 00
dim shared pi
pi = 4*atn(1)
dim x(5), y(5), z(5)
x( 0) = 0: y( 0) = 70: z( 0) = 0
x( 1) = 70: y( 1) =-70: z( 1) = 70
x( 2) =-70: y( 2) =-70: z( 2) = 70
x( 3) =-70: y( 3) =-70: z( 3) =-70
x( 4) = 70: y( 4) =-70: z( 4) =-70
x( 5) = 70: y( 5) =-70: z( 5) = 70
zoom = 4
sw = 640
sh = 480
screen _newimage(sw,sh,32)
a = 0
do
cls
a = a + 0.01
xx = x(0)
yy = y(0)
zz = z(0)
rot yy, zz, a
rot xx, zz, a
proj p0, q0, xx, yy, zz
'draw all triangles
for i=1 to 4
x1 = x(i)
y1 = y(i)
z1 = z(i)
rot y1, z1, a
rot x1, z1, a
x2 = x(i + 1)
y2 = y(i + 1)
z2 = z(i + 1)
rot y2, z2, a
rot x2, z2, a
c = _rgb(35,35,35)
proj p, q, x1, y1, z1
pset (sw/2 + zoom*p0, sh/2 - zoom*q0 + oy), c
line -(sw/2 + zoom*p, sh/2 - zoom*q + oy), c
proj p, q, x2, y2, z2
line -(sw/2 + zoom*p, sh/2 - zoom*q + oy), c
line -(sw/2 + zoom*p0, sh/2 - zoom*q0 + oy), c
next
'draw the visible triangles
for i=1 to 4
x1 = x(i)
y1 = y(i)
z1 = z(i)
rot y1, z1, a
rot x1, z1, a
x2 = x(i + 1)
y2 = y(i + 1)
z2 = z(i + 1)
rot y2, z2, a
rot x2, z2, a
'vector cross product
cz = (x1 - xx)*(y2 - yy) - (y1 - yy)*(x2 - xx)
if cz > 0 then
c = _rgb(255,255,255)
proj p, q, x1, y1, z1
pset (sw/2 + zoom*p0, sh/2 - zoom*q0 + oy), c
line -(sw/2 + zoom*p, sh/2 - zoom*q + oy), c
proj p, q, x2, y2, z2
line -(sw/2 + zoom*p, sh/2 - zoom*q + oy), c
line -(sw/2 + zoom*p0, sh/2 - zoom*q0 + oy), c
end if
next
'draw the base
xx = x(1)
yy = y(1)
zz = z(1)
rot yy, zz, a
rot xx, zz, a
x1 = x(2)
y1 = y(2)
z1 = z(2)
rot y1, z1, a
rot x1, z1, a
x2 = x(3)
y2 = y(3)
z2 = z(3)
rot y2, z2, a
rot x2, z2, a
cz = (x1 - xx)*(y2 - yy) - (y1 - yy)*(x2 - xx)
if cz < 0 then
c = _rgb(255,255,255)
proj p0, q0, xx, yy, zz
pset (sw/2 + zoom*p0, sh/2 - zoom*q0 + oy), c
for i=2 to 5
xx = x(i)
yy = y(i)
zz = z(i)
rot yy, zz, a
rot xx, zz, a
proj p, q, xx, yy, zz
line -(sw/2 + zoom*p, sh/2 - zoom*q + oy), c
next
end if
_display
_limit 30
loop until _keyhit = 27
sleep
system
'rotate
sub rot(x, y, a)
xx = x*cos(a) - y*sin(a)
yy = x*sin(a) + y*cos(a)
x = xx
y = yy
end sub
'perspective projection
sub proj(p, q, x, y, z)
dz = z0 + z
p = x*d/dz
q = y*d/dz
end sub
speaking of maptriangle, its been on my backburner to translate that over to QBJS but I ran into a few brick walls due to my lack of JS (not JB) knowledge, mainly the image loading and webGL stuff, and kinda lost interest, but there has been some renewed interest in webGL in one of the math communities i'm into so I may give that another shot in the near future. I was able to at least find the formula to match 3D to 2D coordinates 1:1 with QB64's maptri and can share that mod if there's interest