0

Note: q is the azimuthal angle, and j is the polar angle.

Here is my code so far:

from math import pi, sin, cos, sqrt, acos
from pynput.mouse import Button, Controller
import pyautogui
import cv2
import numpy as np
import sympy as sp

zoom = 0.5
d = 200
q = 0
j = pi / 2
win = '3D'
side = 1000
unitsPerPixelJ = pi / side
unitsPerPixelQ = 2 * pi / side

cv2.namedWindow(win)
cv2.moveWindow(win, 0, 0)
mat = np.zeros((side, side, 3))

# A(d * cos(q) * sin(j), d * sin(q) * sin(j), d * cos(j)): d units in front of viewer's eyes
# B(x * t, y * t, z * t): intersection of line, from (x, y, z) to (0, 0, 0), and plane of vision
# C(d * cos(q) * sin(j) + r * sin(q), d * sin(q) * sin(j) - r * cos(q), d * cos(j)): point of reference to find an angle needed later

def RGBtoLAB(RGB):
    return (RGB[2] / 255, RGB[1] / 255, RGB[0] / 255)

# maps a point (x, y, z) to the screen as a point (x, y)
def point(x, y, z):
    # t: constant value required to find point B
    t = d / (x * cos(q) * sin(j) + y * sin(q) * sin(j) + z * cos(j))
    # r: distance from point A to point B
    r = sqrt((d * cos(q) * sin(j) - x * t) ** 2 + (d * sin(q) * sin(j) - y * t) ** 2 + (d * cos(j) - z * t) ** 2)
    BminusA = (x * t - d * cos(q) * sin(j), y * t - d * sin(q) * sin(j), z * t - d * cos(j))
    CminusA = (r * sin(q), - r * cos(q), 0)
    angleBAC = acos((BminusA[0] * CminusA[0] + BminusA[1] * CminusA[1]) / r ** 2)
    return (round(zoom * r * cos(angleBAC) + side / 2), round(zoom * r * sin(angleBAC) + side / 2))

#(z != 0 and (abs(z) / z) or 1) * 

def fillPoly(xLst, yLst, zLst, color = (255, 255, 255)):
    xLst2D = []
    yLst2D = []
    for item in range(len(xLst)):
        pt = point(xLst[item], yLst[item], zLst[item])
        xLst2D += [pt[0]]
        yLst2D += [pt[1]]
    ptLst = []
    for item in range(len(xLst2D)):
        ptLst += [[xLst2D[item], yLst2D[item]]]
    ptLst = np.array(ptLst)
    cv2.fillPoly(mat, np.int32([ptLst]), RGBtoLAB(color))
    print(ptLst)

pyautogui.moveTo(side / 2 + 8, side / 2 + 31)

mouse = Controller()
col = mouse.position[0]
row = mouse.position[1]
fillPoly([1, -1, -1, 1], [1, 1, -1, -1], [1, 1, 1, 1])
cv2.imshow(win, mat)

while True:
    colNew = mouse.position[0]
    rowNew = mouse.position[1]

    if (col != colNew) or (row != rowNew):
        fillPoly([1, -1, -1, 1], [1, 1, -1, -1], [1, 1, 1, 1], (0, 0, 0))
        print('q = ' + str(q))
        print('j = ' + str(j))
        q += (col - colNew) * unitsPerPixelQ
        j += (row - rowNew) * unitsPerPixelJ
        col = colNew
        row = rowNew
        fillPoly([1, -1, -1, 1], [1, 1, -1, -1], [1, 1, 1, 1])
        
        cv2.imshow(win, mat)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

My end goal is to make a 3D renderer, where you can input a point in (x, y, z) into a function that returns a point in (x, y). How would I go about doing this?

Is my point(x, y, z) function inaccurate?

Thank you in advance.

  • Without a definition of your coordinate systems, this question is unanswerable. – Han-Kwang Nienhuys Jun 25 '20 at 18:19
  • Can you further explain what you mean by definition of coordinate systems? I have 1000 rows and columns (in pixels) in my graphics window. I differentiate between rows, columns, and (x,y) coordinates by using these formulas: row=-y+500 y=-row+500 column=x+500 x=column-500 – Logan Tischler Jun 27 '20 at 01:25
  • https://en.wikipedia.org/wiki/3D_projection#Mathematical_formula – Han-Kwang Nienhuys Jun 27 '20 at 11:40

0 Answers0