_TITLE "3D Render 2" ' B+ started 2019-10-20 (as Vector Math) ' Based on notes provided to QB64 forum by William F Barnes, on 2019-10-19
' https://www.qb64.org/forum/index.php?topic=1782.0
' A vector's dimension is the number of components it has.
' Here is code for processing 2 and 3 dimension vectors.
'2019-11-20 add STxAxTIC's conversion code for new sub screenXY
' Nice cube corners maker and nice wireframe cube
'2019-11-22 3D render 2, Upon STxAxTIC's advice crank up the FOVD,
' I did and found a nice range of cube like cubes, I also have a check
' for xyz to see if it is viewable, which we will test with FOVD.
' Oddly I had to make FOVD negative in order to get the numbers in the
' correct quadrants. When the cube center crosses into positive,
' the quadrants will flip-flop, but still a nice cube is drawn.
' When the cube center is at z=0 you will see a big X across screen!
CONST sxmax
= 700, symax
= 700 CONST tlx
= -100, tly
= 100, brx
= 100, bry
= -100 ' Cartesian Coordinate System corners for WINDOW command ' to convert mouse coordinates to WINDOW after call look up PMAP
' notation 0 w/arrowHat (no way of telling if 2, 3 or more dimensions)
v2zero.x = 0: v2zero.y = 0
v3zero.x = 0: v3zero.y = 0: v3zero.z = 0
'Basis Vectors, isolate components e sub x Dot V w/arrowHat = V sub x
v2e(1).x = 1: v2e(1).y = 0
v2e(2).x = 0: v2e(2).y = 1
v3e(1).x = 1: v3e(1).y = 0: v3e(1).z = 0
v3e(2).x = 0: v3e(2).y = 1: v3e(2).z = 0
v3e(3).x = 0: v3e(3).y = 0: v3e(3).z = 1
fovd = -200 '???
DIM SHARED zmin
, zmax
, xmin
, xmax
, ymin
, ymax
zmin = -250: zmax = -1
xmin = -50: xmax = 50
ymin = -50: ymax = 50
'==================================================================================== test area 2019-11-20
WINDOW (tlx
, tly
)-(brx
, bry
) ' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< get a Cartesian Coordinate System started ' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> to convert mouse coordinates to WINDOW after call look up PMAP
'all z's must be negative!!!! there seems a flip flop mirror upside down image passing zero top pos hit inf at 0!!!!!!!!!
newCube x, y, z - pushBack, 1, testCube()
'FOR i = 0 TO 7
' PRINT v3$(testCube(i))
'NEXT
'good! now convert these to screen projection points
screenXY testCube(i), screenTest(i)
'PRINT screenTest(i).x, screenTest(i).y
drawWireCube screenTest()
_TITLE "Testing only cubes with sides = 1 whatever units. Predicting what is viewable and what is not = BEEP with new function."
PRINT "Press any to wakeup from sleep, esc to quit..." z = irnd(-10, 5) 'ok now testing in and outside view numbers
x = irnd(.5 * z, -.5 * z)
y = irnd(.5 * z, -.5 * z)
setV3 x, y, z, testPt
newCube x, y, z, 1, testCube()
'good! now convert these to screen projection points
screenXY testCube(i), screenTest(i)
PRINT screenTest
(i
).x
, screenTest
(i
).y
drawWireCube screenTest()
newCube x, y, z, 1, testCube()
'good! now convert these to screen projection points
screenXY testCube(i), screenTest(i)
PRINT screenTest
(i
).x
, screenTest
(i
).y
drawWireCube screenTest()
'this code decides if x,y,z on real map is in square cone of vision
'DIM SHARED zmin, zmax, xmin, xmax, ymin, ymax 'move to top
'zmin = -50: zmax = -1
'xmin = -50: xmax = 50
'ymin = -50: ymax = 50
'bring this in for testing xyzInView
FUNCTION irnd%
(n1
, n2
) 'return an integer between 2 numbers IF n1
> n2
THEN l%
= n2: h%
= n1
ELSE l%
= n1: h%
= n2
irnd%
= INT(RND * (h%
- l%
+ 1)) + l%
' ========================================================================= 2019-11-20 code
SUB drawWireCube
(corners
() AS xyType
) 'front face
LINE (corners
(0).x
, corners
(0).y
)-(corners
(1).x
, corners
(1).y
) LINE -(corners
(2).x
, corners
(2).y
) LINE -(corners
(3).x
, corners
(3).y
) LINE -(corners
(0).x
, corners
(0).y
) 'back face
LINE (corners
(4).x
, corners
(4).y
)-(corners
(5).x
, corners
(5).y
) LINE -(corners
(6).x
, corners
(6).y
) LINE -(corners
(7).x
, corners
(7).y
) LINE -(corners
(4).x
, corners
(4).y
) 'connect from to back
LINE (corners
(0).x
, corners
(0).y
)-(corners
(4).x
, corners
(4).y
) LINE (corners
(1).x
, corners
(1).y
)-(corners
(5).x
, corners
(5).y
) LINE (corners
(2).x
, corners
(2).y
)-(corners
(6).x
, corners
(6).y
) LINE (corners
(3).x
, corners
(3).y
)-(corners
(7).x
, corners
(7).y
)
SUB newCube
(cx
, cy
, cz
, side
, cubeCorners
() AS xyzType
) DIM sd2
, lx
, rx
, ty
, by
, fz
, bz
sd2 = side / 2
rx = cx + sd2: lx = cx - sd2
ty = cy + sd2: by = cy - sd2
fz = cz + sd2: bz = cz - sd2
cubeCorners(0).x = lx: cubeCorners(0).y = ty: cubeCorners(0).z = fz
cubeCorners(1).x = rx: cubeCorners(1).y = ty: cubeCorners(1).z = fz
cubeCorners(2).x = rx: cubeCorners(2).y = by: cubeCorners(2).z = fz
cubeCorners(3).x = lx: cubeCorners(3).y = by: cubeCorners(3).z = fz
cubeCorners(4).x = lx: cubeCorners(4).y = ty: cubeCorners(4).z = bz
cubeCorners(5).x = rx: cubeCorners(5).y = ty: cubeCorners(5).z = bz
cubeCorners(6).x = rx: cubeCorners(6).y = by: cubeCorners(6).z = bz
cubeCorners(7).x = lx: cubeCorners(7).y = by: cubeCorners(7).z = bz
' project (x, y, z) point in real space to screenXY of user's eye-line
SUB screenXY
(xyzReal
AS xyzType
, xyScreen
AS xyType
) 'convert STxAxTIC's code to my code here
' https://www.qb64.org/forum/index.php?topic=1904.msg111304#msg111304
' vec3Ddotnhat = vec(i, 1) * nhat(1) + vec(i, 2) * nhat(2) + vec(i, 3) * nhat(3)
' vec2D(i, 1) = (vec(i, 1) * uhat(1) + vec(i, 2) * uhat(2) + vec(i, 3) * uhat(3)) * fovd / vec3Ddotnhat
' vec2D(i, 2) = (vec(i, 1) * vhat(1) + vec(i, 2) * vhat(2) + vec(i, 3) * vhat(3)) * fovd / vec3Ddotnhat
'my comments and conversion
'fovd seems like a variable that should be globally shared, maybe constant?
vec3Ddotnhat = v3DotProduct(xyzReal, v3e(3))
xyScreen.x = v3DotProduct(xyzReal, v3e(1)) * fovd / vec3Ddotnhat
xyScreen.y = v3DotProduct(xyzReal, v3e(2)) * fovd / vec3Ddotnhat
'================================================= subs and fuctions from Vector Math.bas 2019-10-20
SUB setV3
(x
, y
, z
, setMe
AS xyzType
) setMe.x = x: setMe.y = y: setMe.z = z
v3$ = "[" + ts$(showMeInnards.x) + ", " + ts$(showMeInnards.y) + ", " + ts$(showMeInnards.z) + "]"
'notation UppercaseLetter w/arrowhat + uppercase Letter w/arrowHat
SUB v2Add
(A
AS xyType
, B
AS xyType
, Sum
AS xyType
) Sum.x = A.x + B.x
Sum.y = A.y + B.y
SUB v3Add
(A
AS xyzType
, B
AS xyzType
, Sum
AS xyzType
) Sum.x = A.x + B.x
Sum.y = A.y + B.y
Sum.z = A.z + B.z
'notation UppercaseLetter w/arrowHat - UppercaseLetter w/arrowHat
SUB v2Subtr
(A
AS xyType
, B
AS xyType
, Sum
AS xyType
) Sum.x = A.x - B.x
Sum.y = A.y - B.y
SUB v3Subtr
(A
AS xyzType
, B
AS xyzType
, Sum
AS xyzType
) Sum.x = A.x - B.x
Sum.y = A.y - B.y
Sum.z = A.z - B.z
'notation lowercaseletter (for a number next to (times)) UppercaseLetter w/arrowHat
Scale.x = mult * A.x
Scale.y = mult * A.y
Scale.x = mult * A.x
Scale.y = mult * A.y
Scale.z = mult * A.z
'notation the inverse of A w/arrowHat is -A w/arrowHat
SUB v2Inverse
(A
AS xyType
, Inverse
AS xyType
) ' A + InverseOfA = 0 Inverse.x = -A.x
Inverse.y = -A.y
SUB v3Inverse
(A
AS xyzType
, Inverse
AS xyzType
) ' A + InverseOfA = 0 Inverse.x = -A.x
Inverse.y = -A.y
Inverse.z = -A.z
'notation: A w/arrowHat Dot B w/arrowHat v2 Dot Product is a number, v3 Dot Product is a vector
FUNCTION v2DotProduct
(A
AS xyType
, B
AS xyType
) 'shadow or projection if A Dot B = 0 then A , B are perpendicular v2DotProduct = A.x * B.x + A.y * B.y
FUNCTION v3DotProduct
(A
AS xyzType
, B
AS xyzType
) 'shadow or projection if A Dot B = 0 then A , B are perpendicular v3DotProduct = A.x * B.x + A.y * B.y + A.z * B.z
'notation absolute value bars about A w/arrowHat OR just an UppercaseLetter (with no hat), its just a number
FUNCTION v2Magnitude
(A
AS xyType
) 'hypotenuse of right triangle v2Magnitude
= SQR(v2DotProduct
(A
, A
))FUNCTION v3Magnitude
(A
AS xyzType
) 'hypotenuse of cube v3Magnitude
= SQR(v3DotProduct
(A
, A
))
'notation: A w/arrowHat X B w/arrowHat, X is a Cross get it?
FUNCTION v2CrossProduct
(A
AS xyType
, B
AS xyType
) ' a vector perpendicular to both A and B, v2 is a magnitude v2CrossProduct = A.x * B.y - A.y * B.x
SUB v3CrossProduct
(A
AS xyzType
, B
AS xyzType
, Cross
AS xyzType
) ' v3 cross product is a 3d vector perpendicular to A and B 'notice x has no x components, y no y componets, z no z components
Cross.x = A.y * B.z - A.z * B.y
Cross.y = A.z * B.x - A.x * B.z
Cross.z = A.x * B.y - A.y * B.x
'notation: A w/caratHat = A w/arrowHat divided by A (UppercaseLetter) or scaled by 1/A magnitude (no hats)
SUB v2Unit
(A
AS xyType
, Unit
AS xyType
) m = v2Magnitude(A)
v2Scale 1 / m, A, Unit
SUB v3Unit
(A
AS xyzType
, Unit
AS xyzType
) m = v3Magnitude(A)
v3Scale 1 / m, A, Unit