I am very new to coding and decided to start with a 3D engine in python. I followed OLC's tutorial and adapted it for python. However, my translation matrix doesn't seem to be affecting how the model is rendered. Any advice at all, from code improvements, to telling me how bad I am would be much appreciated.
I have tried to re-do the vector multiplication in all sorts of ways, and all kinds of reformatting and re-trying, but I am not even sure what I am looking for in this case. Any help would be much appreciated
As I am new, I apologize for any poor etiquette I may have done on this site.
import math, numpy as np, pygame, sys, os, random, string
from pygame.locals import *
pygame.init()
width,height = 1600,900;cx,cy = width//2,height//2
screen = pygame.display.set_mode((width,height))
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
pygame.display.set_caption('3D Graphics')
def loadObj(filename):
tris = []
verts = []
try:
fp = open(filename, "r")
except:
print("File: "+filename+" not found")
sys.exit(1)
for line in fp:
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'v':
#v = vec3(float(values[1]), float(values[2]), float(values[3]))
#verts.append(vec3(int(values[1]), int(values[2]), int(values[3])))
verts.append(vec3(float(values[1]), float(values[2]), float(values[3]), 0 ))
#verts.append(v)
elif values[0] == 'f':
p = []
for v in values[1:]:
w = v.split("/")
p.append(int(w[0]))
#print(p)
#print(verts[-185])
triTemp = triangle(verts[p[0] - 1], verts[p[1] - 1], verts[p[2]- 1])
tris.append(triTemp)
fp.close()
return tris
class vec3(): #Possibly Obsolete
__slots__ = ['x','y','z','w']
def __init__(self, x, y, z, w):
self.x = x
self.y = y
self.z = z
self.w = w
class triangle():
__slots__ = ['vec1','vec2','vec3']
def __init__(self, vec1, vec2, vec3):
self.vec1 = vec1
self.vec2 = vec2
self.vec3 = vec3
def matrixMakeTranslation(x, y, z):
matrix = np.zeros((4,4))
matrix[0,0] = 1.0
matrix[1,1] = 1.0
matrix[2,2] = 1.0
matrix[3,3] = 1.0
matrix[3,0] = x
matrix[3,1] = y
matrix[3,2] = z
return matrix
def Matrix_MakeRotationX(fAngleRad):
matrix = np.zeros((4,4))
matrix[0,0] = 1.0
matrix[1,1] = (math.cos(fAngleRad * 0.5))
matrix[1,2] = (math.sin(fAngleRad * 0.5))
matrix[2,1] = (-math.sin(fAngleRad * 0.5))
matrix[2,2] = (math.cos(fAngleRad * 0.5))
matrix[3,3] = 1.0
return matrix
def Matrix_MakeRotationZ(fAngleRad):
matrix = np.zeros((4,4))
matrix[0,0] = (math.cos(fAngleRad))
matrix[0,1] = (math.sin(fAngleRad))
matrix[1,0] = (-math.sin(fAngleRad))
matrix[1,1] = (math.cos(fAngleRad))
matrix[2,2] = 1.0
matrix[3,3] = 1.0
return matrix
fNear = float(0.1) #Create the Projection Matrix
fFar = float(1000.0)
fFov = float(90.0)
fAspectRatio = float(height/width)
fFovRad = 1/math.tan(fFov * 0.5 / 180 * math.pi)
projectionMatrix = np.zeros((4,4))
projectionMatrix[0,0] = fAspectRatio * fFovRad
projectionMatrix[1,1] = fFovRad
projectionMatrix[2,2] = fFar / (fFar - fNear)
projectionMatrix[3,2] = float((-fFar * fNear) / (fFar - fNear))
projectionMatrix[2,3] = 1.0
projectionMatrix[3,3] = 0.0
meshname = "teapot.obj" #Load the mesh
tris = loadObj(meshname)
vCamera = np.array([0,0,0,0])
fAngleRad = 0
colour = (255,255,255)
colour2 = (0,0,0)
triProjected = triangle(np.array([0,0,0,0]),np.array([0,0,0,0]),np.array([0,0,0,0])) #These are used later
triTranslalted = triangle(np.array([0,0,0,0]),np.array([0,0,0,0]),np.array([0,0,0,0]))
triTransformed= triangle(np.array([0,0,0,0]),np.array([0,0,0,0]),np.array([0,0,0,0]))
while True: #Begin Loop
for event in pygame.event.get(): #Quit
if event.type == pygame.QUIT: pygame.quit(); sys.exit()
dt = clock.tick()/1000
pygame.display.set_caption('3D Graphics - FPS: %.2f'%int(dt))
print("fps:", clock.get_fps()) #Framerate and caption
pygame.display.update()
screen.fill((0,0,0))
fAngleRad += 0.1
matRotZ = Matrix_MakeRotationZ(fAngleRad * 0.5) #Set up matricies
matRotX = Matrix_MakeRotationX(fAngleRad)
matTrans = matrixMakeTranslation(0.0,0.0,50.0)
matWorld = np.identity(4)
matWorld = matRotZ # matRotX
matWorld = matWorld # matTrans #Seems to be broken. idk why.
for i in tris: #For triangle in all triangles
reDo1 = np.array([i.vec1.x, i.vec1.y, i.vec1.z, i.vec1.w])
reDo2 = np.array([i.vec2.x, i.vec2.y, i.vec2.z, i.vec2.w])
reDo3 = np.array([i.vec3.x, i.vec3.y, i.vec3.z, i.vec3.w])
triTransformed.vec1 = np.matmul(matWorld, reDo1)
triTransformed.vec2 = np.matmul(matWorld, reDo2)
triTransformed.vec3 = np.matmul(matWorld, reDo3)
triProjected.vec1 = np.matmul(projectionMatrix, triTransformed.vec1)
triProjected.vec2 = np.matmul(projectionMatrix, triTransformed.vec2)
triProjected.vec3 = np.matmul(projectionMatrix, triTransformed.vec3)
#Scale Into View
triProjected.vec1[0] += 1.0
triProjected.vec1[1] += 1.0
triProjected.vec2[0] += 1.0
triProjected.vec2[1] += 1.0
triProjected.vec3[0] += 1.0
triProjected.vec3[1] += 1.0
triProjected.vec1[0] *= 0.5 * width
triProjected.vec1[1] *= 0.5 * height
triProjected.vec2[0] *= 0.5 * width
triProjected.vec2[1] *= 0.5 * height
triProjected.vec3[0] *= 0.5 * width
triProjected.vec3[1] *= 0.5 * height
pygame.draw.polygon(screen, colour, [(triProjected.vec1[0], triProjected.vec1[1]),(triProjected.vec2[0], triProjected.vec2[1]),(triProjected.vec3[0], triProjected.vec3[1])])
You are using Homogenious Coordinates to represent the vertices of your model. So the W component must be 1.
When you load your model you are setting W to 0.
verts.append(vec3(float(values[1]), float(values[2]), float(values[3]), 0 ))
By setting W=0 you are creating a Homogenious Vector (a.k.a "point at infinity" or "ideal point") and by setting W=1 you are creating a Homogeneous Point.
Points can be translated but vectors cannot.
https://en.m.wikipedia.org/wiki/Homogeneous_coordinates
Related
I made a simple ray tracer python program that takes xml file as input and creates a png image file.
In the python file, I used xml.etree.ElementTree as extension and implemented parser to read the xml file.
I'm trying to run the program on cmd like:
c:\WINDOWS\system32>python3 rayTracer.py scenes/one-sphere.xml
However, it doesn't create an image.
Did I use wrong command on cmd?
(one-sphere.xml file is in the scenes file)
this is main
def main():
#parser
tree = ET.parse(sys.argv[1])
root = tree.getroot()
viewPoint = np.array([0, 0, 0]).astype(np.float)
viewDir = np.array([0, 0, -1]).astype(np.float)
viewUp = np.array([0, 1, 0]).astype(np.float)
viewProjNormal = -1 * viewDir
viewWidth = 1.0
viewHeight = 1.0
projDistance = 1.0
intensity = np.array([1, 1, 1]).astype(np.float) # how bright the light is.
imgSize = np.array(root.findtext('image').split()).astype(np.int)
list = []
light = []
for c in root.findall('camera'):
viewPoint = np.array(c.findtext('viewPoint').split()).astype(np.float)
viewDir = np.array(c.findtext('viewDir').split()).astype(np.float)
if (c.findtext('projNormal')):
viewProjNormal = np.array(c.findtext('projNormal').split()).astype(np.float)
viewUp = np.array(c.findtext('viewUp').split()).astype(np.float)
if (c.findtext('projDistance')):
projDistance = np.array(c.findtext('projDistance').split()).astype(np.float)
viewWidth = np.array(c.findtext('viewWidth').split()).astype(np.float)
viewHeight = np.array(c.findtext('viewHeight').split()).astype(np.float)
view = View(viewPoint, viewDir, viewUp, viewProjNormal, viewWidth, viewHeight, projDistance, intensity)
for c in root.findall('surface'):
type_c = c.get('type')
if type_c == 'Sphere':
center_c = np.array(c.findtext('center').split()).astype(np.float)
radius_c = np.array(c.findtext('radius')).astype(np.float)
ref = ''
for child in c:
if child.tag == 'shader':
ref = child.get('ref')
for d in root.findall('shader'):
if d.get('name') == ref:
diffuse_d = np.array(d.findtext('diffuseColor').split()).astype(np.float)
type_d = d.get('type')
for c in root.findall('light'):
position_c = np.array(c.findtext('position').split()).astype(np.float)
intensity_c = np.array(c.findtext('intensity').split()).astype(np.float)
light.append(Light(position_c, intensity_c))
# Create an empty image
channels = 3
img = np.zeros((imgSize[1], imgSize[0], channels), dtype=np.uint8)
img[:, :] = 0
pixel_x = view.viewWidth / imgSize[0]
pixel_y = view.viewHeight / imgSize[1]
w = view.viewDir
u = np.cross(w, view.viewUp)
v = np.cross(w, u)
w_unit = w / np.sqrt(np.sum(w * w))
u_unit = u / np.sqrt(np.sum(u * u))
v_unit = v / np.sqrt(np.sum(v * v))
start = w_unit * view.projDistance - u_unit * pixel_x * ((imgSize[0]/2) + 1/2) - v_unit * pixel_y * ((imgSize[1]/2) + 1/2)
for x in np.arange(imgSize[0]):
for y in np.arange(imgSize[1]):
ray = start + u_unit * x * pixel_x + pixel_y * y * v_unit
tmp = raytrace(list, ray, view.viewPoint)
img[y][x] = shade(tmp[0], ray, view, list, tmp[1], light)
rawimg = Image.fromarray(img, 'RGB')
rawimg.save(sys.argv[1] + '.png')
if __name__ == "__main__":
main()
I'm trying to import these on Jupyter, however I got an error when I run these code that say ModuleNotFoundError: No module named 'anna_phog'. I have another python file named as 'anna_phog'. How do I fix this?
below is 'anna_phog_demo.py' where I got the error
from anna_phog import anna_phog
import imageio
import matplotlib.pyplot as plt
image_path = "image_0058.jpg"
S = 8
angle = 360
Level = 3
roi = [1,225,1,300]
save=True
Image = imageio.imread(image_path)
p = anna_phog(Image, bin, angle, Level, roi)
print("P: \n{}".format(p))
print(len(p), type(p))
And below is the 'anna_phog.py' code
import numpy as np
import imageio
import cv2
import matplotlib.pyplot as plt
def anna_phog(Img, bin, angle, L, roi):
if Img.shape[2] == 3:
G = cv2.cvtColor(Img, cv2.COLOR_BGR2GRAY)
else:
G = Img
if np.sum(G) > 100:
# apply automatic Canny edge detection using the computed median
sigma = 0.33
v = np.median(G)
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
E = cv2.Canny(G,lower,upper) #high and low treshold
GradientX, GradientY = np.gradient(G)
GradientYY = np.gradient(GradientY, axis=1)
Gr = np.sqrt(np.square(GradientX)+np.square(GradientY))
index = GradientX == 0
GradientX[index] = 1e-5 #maybe another value
YX = GradientY*GradientX
if angle == 180: A = ((np.arctan(YX)+(np.pi/2))*180)/np.pi
if angle == 360: A = ((np.arctan2(GradientY,GradientX)+np.pi)*180)/np.pi
bh, bv = anna_BinMatrix(A,E,Gr,angle,bin)
else:
bh = np.zeros(Img.shape)
bv = np.zeros(Img.shape)
bh_roi = bh[roi[0]:roi[1], roi[2]:roi[3]]
bv_roi = bv[roi[0]:roi[1], roi[2]:roi[3]]
p = anna_PhogDescriptor(bh_roi,bv_roi,L,bin)
return p
def anna_BinMatrix(A,E,G,angle,bin):
n, contorns = cv2.connectedComponents(E, connectivity=8)
X = E.shape[1]
Y = E.shape[0]
bm = np.zeros(shape=(Y,X))
bv = np.zeros(shape=(Y,X))
nAngle = angle/bin
for i in range(n):
posY, posX = np.where(contorns==i)
for j in range(posY.shape[0]):
pos_x = posX[j]
pos_y = posY[j]
b = np.ceil(A[pos_y,pos_x]/nAngle)
if b==0: bin=1
if G[pos_y,pos_x]>0:
bm[pos_y,pos_x] = b
bv[pos_y,pos_x] = G[pos_y,pos_x]
return (bm, bv)
def anna_PhogDescriptor(bh,bv,L,bin):
p = np.array([])
#level 0
for b in range(bin):
ind = bh==b
p = np.append(p, np.sum(bv[ind]))
#higher levels
for l in range(1, L+1):
x = int(np.trunc(bh.shape[1]/(2**l)))
y = int(np.trunc(bh.shape[0]/(2**l)))
for xx in range(0, bh.shape[1]-x+1, x):
for yy in range(0, bh.shape[0]-y+1, y):
print(l)
bh_cella = bh[yy:yy+y, xx:xx+x]
bv_cella = bv[yy:yy+y, xx:xx+x]
for b in range(bin):
ind = bh_cella==b
p = np.append(p, np.sum(bv_cella[ind], axis=0))
if np.sum(p)!=0:
p = p/np.sum(p)
return p
Below is the screenshot of the folder where I put these file
folder path
Doing a project for physics class. vPython documentation is not very good I think and it's a bit confusing. I need to move a ball, which currently is being moved by mouse, but I need to make this work with 2 players, so I need to use keyboard events.
Currently this is the code:
#GlowScript 2.7 VPython
scene.range = 30
scene.forward = vec(0,-0.25,-1)
#red side of the field
redField = box()
redField.size = vec(40,1,60)
redField.pos= vec(-20,0,0)
redField.color = color.red
#blue side of the field
redField = box()
redField.size = vec(40,1,60)
redField.pos= vec(20,0,0)
redField.color = color.blue
cueBall = sphere()
cueBall.radius = 1.5
cueBall.pos = vec(0,2,0)
cueBall.vel = vec(3,0,0) # velocity in m/s
cueBall.mass = 2.0
blueBall = sphere()
blueBall.radius = 1.5
blueBall.pos = vec(4,2,0)
blueBall.color = color.blue
blueBall.mass = 1.5
blueBall.vel = vec(0,0,0)
blueBall.force = arrow(axis = vec(0,0,0), color = color.blue)
rail1 = box()
rail1.texture = {'file': "https://i.imgur.com/ss5OcnL.jpg"}
rail1.size = vec(3,3,55)
rail1.pos = vec(-39,1,0)
rail2 = box()
rail2.texture = {'file': "https://i.imgur.com/ss5OcnL.jpg"}
rail2.size = vec(3,3,55)
rail2.pos = vec(39,1,0)
rail3 = box()
rail3.texture = {'file': "https://i.imgur.com/ss5OcnL.jpg"}
rail3.size = vec(80,3,3)
rail3.pos = vec(0,1,29)
rail4 = box()
rail4.texture = {'file': "https://i.imgur.com/ss5OcnL.jpg"}
rail4.size = vec(80,3,3)
rail4.pos = vec(0,1,-29)
redBall = sphere()
redBall.radius = 1.5
redBall.pos = vec(-3,2,0)
redBall.color = color.red
redBall.force = arrow(axis = vec(0,0,0), color = color.red)
redBall.vel = vec(0,0,0)
redBall.mass = 1.5
yBall = sphere()
yBall.radius = 1.5
yBall.pos = vec(-9,2,0)
yBall.color = color.yellow
yBall.vel = vec(0,0,0)
yBall.mass = 1.5
yBall.force = arrow(axis = vec(0,0,0), color = color.yellow)
rail = []
rail.append(rail1, rail2, rail3, rail4)
ball = []
ball.append(cueBall, blueBall, redBall, yBall)
ball[0].force = arrow(axis = vec(0,0,0), color = color.white)
drag = False
chosenObject = None
scene.bind("mousedown", down)
scene.bind("mousemove", move)
scene.bind("mouseup", up)
def down():
nonlocal drag, chosenObject
chosenObject = scene.mouse.pick()
drag = True
def move():
nonlocal drag, chosenObject
if (drag == True):
chosenObject.force.axis = scene.mouse.pos - chosenObject.pos
chosenObject.force.pos = chosenObject.pos
chosenObject.force.axis.y = 0
def up():
nonlocal drag, chosenObject
chosenObject.force.axis = vec(0,0,0)
chosenObject = None
drag = False
elasticConst = 500
dt = 0.01
time = 0
while (True):
rate(1/dt)
for i in range(len(ball)):
ball[i].vel = ball[i].vel + ( ball[i].force.axis * dt / ball[i].mass )
ball[i].force.pos = ball[i].pos
for i in range(len(ball)):
for j in range(len(ball)):
if (i == j): continue
separation = ball[i].pos - ball[j].pos
contactSeparation = separation.norm() * (ball[i].radius + ball[j].radius)
if (separation.mag < contactSeparation.mag):
elasticForce = - elasticConst * (separation - contactSeparation)
ball[i].vel = ball[i].vel + (elasticForce / ball[i].mass) * dt
for i in range(len(ball)):
if ( ball[i].pos.x < rail1.pos.x + 2):
ball[i].pos.x = rail1.pos.x + 2
ball[i].vel.x = - ball[i].vel.x
if ( ball[i].pos.x > rail2.pos.x - 2):
ball[i].pos.x = rail2.pos.x - 2
ball[i].vel.x = - ball[i].vel.x
if ( ball[i].pos.z > rail3.pos.z - 2):
ball[i].pos.z = rail3.pos.z - 2
ball[i].vel.z = - ball[i].vel.z
if ( ball[i].pos.z < rail4.pos.z + 2):
ball[i].pos.z = rail4.pos.z + 2
ball[i].vel.z = - ball[i].vel.z
## for i in range(len(ball)):
# for j in range(len(hole)):
# if ((ball[i].pos - hole[j].pos).mag < ball[i].radius + hole[j].radius):
# ball[i].visible = False
for i in range(len(ball)):
ball[i].pos = ball[i].pos + ball[i].vel * dt
If you could help me understand how I could increment the position variables on keyboard.
When I run this code I get an error "Error: Property 'pos' must be a vector." Do I have to write another vector somewhere? Because I wrote vector at
grav_force = vector(0,-object.mass*grav_field,0)
This is my whole code
GlowScript 2.7 VPython
from visual import *
display(width = 1300, height = 1000)
projectile = sphere(pos = (-5,0,0),
radius = 0.1,
color = color.red,
make_trail = True)
projectile.speed = 3.2 # Initial speed.
projectile.angle = 75*3.141459/180 # Initial angle, from the +x-axis.
projectile.velocity = vector(projectile.speed*cos(projectile.angle),
projectile.speed*sin(projectile.angle),
0)
projectile.mass = 1.0
grav_field = 1.0
dt = 0.01
time = 0
while (projectile.pos.y >=0):
rate(100)
# Calculate the force.
grav_force = vector(0,-projectile.mass*grav_field,0)
force = grav_force
# Update velocity.
projectile.velocity = projectile.velocity + force/projectile.mass * dt
# Update position.
projectile.pos = projectile.pos + projectile.velocity * dt
# Update time.
time = time + dt
Change
projectile = sphere(pos = (-5,0,0), radius = 0.1,color = color.red, make_trail = True)
to
projectile = sphere(pos = vector(-5,0,0), radius = 0.1, color = color.red, make_trail = True)
See documentation
http://www.glowscript.org/docs/VPythonDocs/sphere.html
also from documentation
How GlowScript VPython and VPython 7 differ from Classic VPython 6
· Vectors must be represented as vector(x,y,z) or vec(x,y,z), not as (x,y,z).
I've tried searching but none of the other questions seem to be like mine. I'm more or less experimenting with perspective projection and rotation in python, and have run into a snag. I'm sure my projection equations are accurate, as well as my rotation equations; however, when I run it, the rotation starts normal, but begins to swirl inwards until the vector is in the same position as the Z axis (the axis I am rotating over).
''' Imports '''
from tkinter import Tk, Canvas, TclError
from threading import Thread
from math import cos, sin, radians, ceil
from time import sleep
''' Points class '''
class pPoint:
def __init__(self, fPoint, wWC, wHC):
self.X = 0
self.Y = 0
self.Z = 0
self.xP = 0
self.yP = 0
self.fPoint = fPoint
self.wWC = wWC
self.wHC = wHC
def pProject(self):
self.xP = (self.fPoint * (self.X + self.wWC)) / (self.fPoint + self.Z)
self.yP = (self.fPoint * (self.Y + self.wHC)) / (self.fPoint + self.Z)
''' Main class '''
class Main:
def __init__(self):
''' Declarations '''
self.wWidth = 640
self.wHeight = 480
self.fPoint = 256
''' Generated declarations '''
self.wWC = self.wWidth / 2
self.wHC = self.wHeight / 2
''' Misc declarations '''
self.gWin = Tk()
self.vPoint = pPoint(self.fPoint, self.wWC, self.wHC)
self.vPoint.X = 50
self.vPoint.Y = 60
self.vPoint.Z = -25
self.vPoint.pProject()
self.ang = 0
def initWindow(self):
self.gWin.minsize(self.wWidth, self.wHeight)
self.gWin.maxsize(self.wWidth, self.wHeight)
''' Create canvas '''
self.gCan = Canvas(self.gWin, width = self.wWidth, height = self.wHeight, background = "black")
self.gCan.pack()
def setAxis(self):
''' Create axis points '''
self.pXax = pPoint(self.fPoint, self.wWC, self.wHC)
self.pXbx = pPoint(self.fPoint, self.wWC, self.wHC)
self.pYax = pPoint(self.fPoint, self.wWC, self.wHC)
self.pYbx = pPoint(self.fPoint, self.wWC, self.wHC)
self.pZax = pPoint(self.fPoint, self.wWC, self.wHC)
self.pZbx = pPoint(self.fPoint, self.wWC, self.wHC)
''' Set axis points '''
self.pXax.X = -(self.wWC)
self.pXax.Y = 0
self.pXax.Z = 1
self.pXbx.X = self.wWC
self.pXbx.Y = 0
self.pXbx.Z = 1
self.pYax.X = 0
self.pYax.Y = -(self.wHC)
self.pYax.Z = 1
self.pYbx.X = 0
self.pYbx.Y = self.wHC
self.pYbx.Z = 1
self.pZax.X = 0
self.pZax.Y = 0
self.pZax.Z = -(self.fPoint) / 2
self.pZbx.X = 0
self.pZbx.Y = 0
self.pZbx.Z = (self.fPoint * self.wWC) - self.fPoint
def projAxis(self):
''' Project the axis '''
self.pXax.pProject()
self.pXbx.pProject()
self.pYax.pProject()
self.pYbx.pProject()
self.pZax.pProject()
self.pZbx.pProject()
def drawAxis(self):
''' Draw the axis '''
self.gCan.create_line(self.pXax.xP, self.pXax.yP, self.pXbx.xP, self.pXbx.yP, fill = "white")
self.gCan.create_line(self.pYax.xP, self.pYax.yP, self.pYbx.xP, self.pYbx.yP, fill = "white")
self.gCan.create_line(self.pZax.xP, self.pZax.yP, self.pZbx.xP, self.pZbx.yP, fill = "white")
def prePaint(self):
self.vA = self.gCan.create_line(self.wWC, self.wHC, self.vPoint.xP, self.vPoint.yP, fill = "red")
def paintCanvas(self):
try:
while True:
self.ang += 1
if self.ang >= 361:
self.ang = 0
self.vPoint.X = (self.vPoint.X * cos(radians(self.ang))) - (self.vPoint.Y * sin(radians(self.ang)))
self.vPoint.Y = (self.vPoint.X * sin(radians(self.ang))) + (self.vPoint.Y * cos(radians(self.ang)))
self.vPoint.pProject()
self.gCan.coords(self.vA, self.wWC, self.wHC, self.vPoint.xP, self.vPoint.yP)
self.gWin.update_idletasks()
self.gWin.update()
sleep(0.1)
except TclError:
pass
mMain = Main()
mMain.initWindow()
mMain.setAxis()
mMain.projAxis()
mMain.drawAxis()
mMain.prePaint()
mMain.paintCanvas()
Thank you for any input :)
EDIT: Sorry, I just realized I forgot to put my question. I just want to know why it is gravitating inward, and not just rotating "normally"?
This section is wrong:
self.ang += 1
if self.ang >= 361:
self.ang = 0
self.vPoint.X = (self.vPoint.X * cos(radians(self.ang))
- self.vPoint.Y * sin(radians(self.ang)))
self.vPoint.Y = (self.vPoint.X * sin(radians(self.ang))
+ self.vPoint.Y * cos(radians(self.ang)))
self.vPoint.pProject()
For two reasons:
self.ang will take integers in the open range [0 - 360], which means the angle 360 (== 0) is repeated.
In each iteration, you rotate the point from the previous iteration by the angle. As a result, your first frame is at 1 degree, your second at 1+2 = 3, the third at 1 + 2 + 3... You should either be:
rotating the point from the previous iteration by a constant angle each time (1°). This suffers from the problem mentioned in my comment
rotating the initial point by the current angle of rotation each time
Not actualy related to your problem, but I strongly suggest you to use Numpy to perform geometric transformations, specially if it involves 3D points.
Below, I post a sample snippet, I hope it helps:
import numpy
from math import radians, cos, sin
## suppose you have a Nx3 cloudpoint (it might even be a single row of x,y,z coordinates)
cloudpoint = give_me_a_cloudpoint()
## this will be a rotation around Y azis:
yrot = radians(some_angle_in_degrees)
## let's create a rotation matrix using a numpy array
yrotmatrix = numpy.array([[cos(yrot), 0, -sin(yrot)],
[0, 1, 0],
[sin(yrot), 0, cos(yrot)]], dtype=float)
## apply the rotation via dot multiplication
rotatedcloud = numpy.dot(yrotmatrix, pointcloud.T).T # .T means transposition